Commit 6743725c by Zachary Snow

support partial packing of multidimensional unpacked arrays

parent 3955c47e
{-# LANGUAGE FlexibleInstances #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for any unpacked array which must be packed because it is: A) a
- port; B) is bound to a port; C) is assigned a value in a single assignment;
- or D) is assigned to an unpacked array which itself must be packed.
-
- The scoped nature of declarations makes this challenging. While scoping is
- obeyed in general, if any of a set of *equivalent* declarations within a
- module is packed, all of the declarations are packed. This is because we only
- record the declaration that needs to be packed when a relevant usage is
- encountered.
- or D) is assigned to an unpacked array which itself must be packed. The
- conversion allows for an array to be partially packed if all flat usages of
- the array explicitly specify some of the unpacked dimensions.
-}
module Convert.UnpackedArray (convert) where
import Control.Monad.State.Strict
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import Convert.Scoper
import Convert.Traverse
import Language.SystemVerilog.AST
type Location = [Identifier]
type Locations = Set.Set Location
type Locations = Map.Map Location Int
type ST = ScoperT Decl (State Locations)
convert :: [AST] -> [AST]
......@@ -30,7 +27,7 @@ convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription (description @ (Part _ _ Module _ _ ports _)) =
evalState (operation description) Set.empty
evalState (operation description) Map.empty
where
operation = partScoperT
(traverseDeclM ports) traverseModuleItemM noop traverseStmtM >=>
......@@ -57,13 +54,14 @@ rewriteDeclM (decl @ (Variable d t x a e)) = do
details <- lookupElemM x
let Just (accesses, _, _) = details
let location = map accessName accesses
usedAsPacked <- lift $ gets $ Set.member location
if usedAsPacked
then do
usedAsPacked <- lift $ gets $ Map.lookup location
case usedAsPacked of
Just depth -> do
let (tf, rs) = typeRanges t
let t' = tf $ a ++ rs
return $ Variable d t' x [] e
else return decl
let (shifted, rest) = splitAt (length a - depth) a
let t' = tf $ shifted ++ rs
return $ Variable d t' x rest e
Nothing -> return decl
rewriteDeclM other = return other
traverseModuleItemM :: ModuleItem -> ST ModuleItem
......@@ -109,11 +107,32 @@ traverseAsgnM (x, y) = do
flatUsageM y
return (x, y)
flatUsageM :: ScopeKey e => e -> ST ()
flatUsageM x = do
details <- lookupElemM x
class ScopeKey t => Key t where
unbit :: t -> (t, Int)
instance Key Expr where
unbit (Bit e _) = (e', n + 1)
where (e', n) = unbit e
unbit (Range e _ _) = (e', n)
where (e', n) = unbit e
unbit e = (e, 0)
instance Key LHS where
unbit (LHSBit e _) = (e', n + 1)
where (e', n) = unbit e
unbit (LHSRange e _ _) = (e', n)
where (e', n) = unbit e
unbit e = (e, 0)
instance Key Identifier where
unbit x = (x, 0)
flatUsageM :: Key k => k -> ST ()
flatUsageM k = do
let (k', depth) = unbit k
details <- lookupElemM k'
case details of
Just (accesses, _, _) -> do
let location = map accessName accesses
lift $ modify $ Set.insert location
lift $ modify $ Map.insertWith min location depth
Nothing -> return ()
module example(
input wire [7:0] inp,
output wire [7:0] out
);
assign out = ~inp;
endmodule
module top;
reg arr1 [7:0][1:0];
reg arr2 [7:0][1:0][1:0];
wire [7:0] out1, out2;
example e1(arr1[0], out1);
example e2(arr2[0][0], out2);
initial begin
#1 arr1[0] = 8'hAD;
#1 arr2[0][0] = 8'h42;
end
endmodule
module example(
input wire [7:0] inp,
output wire [7:0] out
);
assign out = ~inp;
endmodule
module top;
reg [7:0] arr1 [1:0];
reg [7:0] arr2 [1:0][1:0];
wire [7:0] out1, out2;
example e1(arr1[0], out1);
example e2(arr2[0][0], out2);
initial begin
#1 arr1[0] = 8'hAD;
#1 arr2[0][0] = 8'h42;
end
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment