Commit a8f2cbbe by Zachary Snow

struct conversion supports complex shadowing

parent 05b7bdb9
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
- Conversion for `packed struct` - Conversion for `struct packed`
-} -}
module Convert.Struct (convert) where module Convert.Struct (convert) where
...@@ -10,6 +10,7 @@ import Data.Hashable (hash) ...@@ -10,6 +10,7 @@ import Data.Hashable (hash)
import Data.Maybe (fromJust, isJust) import Data.Maybe (fromJust, isJust)
import Data.List (elemIndex, sortOn) import Data.List (elemIndex, sortOn)
import Data.Tuple (swap) import Data.Tuple (swap)
import Control.Monad.State
import Control.Monad.Writer import Control.Monad.Writer
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set import qualified Data.Set as Set
...@@ -28,21 +29,15 @@ convert = traverseDescriptions convertDescription ...@@ -28,21 +29,15 @@ convert = traverseDescriptions convertDescription
convertDescription :: Description -> Description convertDescription :: Description -> Description
convertDescription (description @ (Part _ _ _ _ _ _)) = convertDescription (description @ (Part _ _ _ _ _ _)) =
traverseModuleItems (traverseTypes $ convertType structs) $
Part extern kw lifetime name ports (items ++ funcs) Part extern kw lifetime name ports (items ++ funcs)
where where
description' @ (Part extern kw lifetime name ports items) = description' @ (Part extern kw lifetime name ports items) =
traverseModuleItems (traverseExprs $ traverseNestedExprs $ convertOnlyExpr structs types) $ scopedConversion traverseDeclM traverseModuleItemM traverseStmtM
traverseModuleItems (traverseTypes $ convertType structs) $ Map.empty description
traverseModuleItems (traverseAsgns $ convertAsgn structs types) $
description
-- collect information about this description -- collect information about this description
structs = execWriter $ collectModuleItemsM structs = execWriter $ collectModuleItemsM
(collectTypesM collectType) description (collectTypesM collectType) description
typesA = execWriter $ collectModuleItemsM
(collectDeclsM collectDecl) description
typesB = execWriter $ collectModuleItemsM
collectFunction description
types = Map.union typesA typesB
-- determine which of the packer functions we actually need -- determine which of the packer functions we actually need
calledFuncs = execWriter $ collectModuleItemsM calledFuncs = execWriter $ collectModuleItemsM
(collectExprsM $ collectNestedExprsM collectCalls) description' (collectExprsM $ collectNestedExprsM collectCalls) description'
...@@ -51,6 +46,17 @@ convertDescription (description @ (Part _ _ _ _ _ _)) = ...@@ -51,6 +46,17 @@ convertDescription (description @ (Part _ _ _ _ _ _)) =
funcs = map packerFn usedStructs funcs = map packerFn usedStructs
usedStructs = filter (isNeeded . fst) $ Map.toList structs usedStructs = filter (isNeeded . fst) $ Map.toList structs
isNeeded tf = Set.member (packerFnName tf) calledPackedFuncs isNeeded tf = Set.member (packerFnName tf) calledPackedFuncs
-- helpers for the scoped traversal
traverseModuleItemM :: ModuleItem -> State Types ModuleItem
traverseModuleItemM item =
traverseExprsM traverseExprM item >>=
traverseAsgnsM traverseAsgnM
traverseStmtM :: Stmt -> State Types Stmt
traverseStmtM stmt =
traverseStmtExprsM traverseExprM stmt >>=
traverseStmtAsgnsM traverseAsgnM
traverseExprM = traverseNestedExprsM $ stately $ convertOnlyExpr structs
traverseAsgnM = stately $ convertAsgn structs
convertDescription other = other convertDescription other = other
-- writes down the names of called functions -- writes down the names of called functions
...@@ -137,22 +143,14 @@ convertType structs t1 = ...@@ -137,22 +143,14 @@ convertType structs t1 =
where (tf1, rs1) = typeRanges t1 where (tf1, rs1) = typeRanges t1
-- write down the type a declarations -- write down the types of declarations
collectDecl :: Decl -> Writer Types () traverseDeclM :: Decl -> State Types Decl
collectDecl (Variable _ (Implicit _ []) _ _ _) = return () traverseDeclM origDecl = do
collectDecl (Variable _ t x a _) = case origDecl of
-- We add the unpacked dimensions to the type so that our type traversal can Variable _ t x _ _ -> modify $ Map.insert x t
-- correctly match-off the dimensions whenever we see a `Bit` or `Range` Parameter t x _ -> modify $ Map.insert x t
-- expression. Localparam t x _ -> modify $ Map.insert x t
tell $ Map.singleton x (tf $ rs ++ a) return origDecl
where (tf, rs) = typeRanges t
collectDecl (Parameter t x _) = tell $ Map.singleton x t
collectDecl (Localparam t x _) = tell $ Map.singleton x t
-- write down the return type of a function
collectFunction :: ModuleItem -> Writer Types ()
collectFunction (MIPackageItem (Function _ t f _ _)) = tell $ Map.singleton f t
collectFunction _ = return ()
-- returns a "unique" name for the packer for a given struct type -- returns a "unique" name for the packer for a given struct type
packerFnName :: TypeFunc -> Identifier packerFnName :: TypeFunc -> Identifier
......
...@@ -59,6 +59,9 @@ module Convert.Traverse ...@@ -59,6 +59,9 @@ module Convert.Traverse
, traverseAsgnsM' , traverseAsgnsM'
, traverseAsgns' , traverseAsgns'
, collectAsgnsM' , collectAsgnsM'
, traverseStmtAsgnsM
, traverseStmtAsgns
, collectStmtAsgnsM
, traverseNestedModuleItemsM , traverseNestedModuleItemsM
, traverseNestedModuleItems , traverseNestedModuleItems
, collectNestedModuleItemsM , collectNestedModuleItemsM
...@@ -824,13 +827,7 @@ traverseAsgnsM' strat mapper = moduleItemMapper ...@@ -824,13 +827,7 @@ traverseAsgnsM' strat mapper = moduleItemMapper
miMapperA other = return other miMapperA other = return other
miMapperB = traverseStmtsM' strat stmtMapper miMapperB = traverseStmtsM' strat stmtMapper
stmtMapper (AsgnBlk op lhs expr) = do stmtMapper = traverseStmtAsgnsM mapper
(lhs', expr') <- mapper (lhs, expr)
return $ AsgnBlk op lhs' expr'
stmtMapper (Asgn mt lhs expr) = do
(lhs', expr') <- mapper (lhs, expr)
return $ Asgn mt lhs' expr'
stmtMapper other = return other
traverseAsgns' :: TFStrategy -> Mapper (LHS, Expr) -> Mapper ModuleItem traverseAsgns' :: TFStrategy -> Mapper (LHS, Expr) -> Mapper ModuleItem
traverseAsgns' strat = unmonad $ traverseAsgnsM' strat traverseAsgns' strat = unmonad $ traverseAsgnsM' strat
...@@ -844,6 +841,22 @@ traverseAsgns = traverseAsgns' IncludeTFs ...@@ -844,6 +841,22 @@ traverseAsgns = traverseAsgns' IncludeTFs
collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem
collectAsgnsM = collectAsgnsM' IncludeTFs collectAsgnsM = collectAsgnsM' IncludeTFs
traverseStmtAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m Stmt
traverseStmtAsgnsM mapper = stmtMapper
where
stmtMapper (AsgnBlk op lhs expr) = do
(lhs', expr') <- mapper (lhs, expr)
return $ AsgnBlk op lhs' expr'
stmtMapper (Asgn mt lhs expr) = do
(lhs', expr') <- mapper (lhs, expr)
return $ Asgn mt lhs' expr'
stmtMapper other = return other
traverseStmtAsgns :: Mapper (LHS, Expr) -> Mapper Stmt
traverseStmtAsgns = unmonad traverseStmtAsgnsM
collectStmtAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m Stmt
collectStmtAsgnsM = collectify traverseStmtAsgnsM
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
traverseNestedModuleItemsM mapper item = do traverseNestedModuleItemsM mapper item = do
converted <- converted <-
...@@ -888,14 +901,15 @@ traverseScopesM declMapper moduleItemMapper stmtMapper = ...@@ -888,14 +901,15 @@ traverseScopesM declMapper moduleItemMapper stmtMapper =
fullModuleItemMapper fullModuleItemMapper
where where
fullStmtMapper stmt = stmtMapper stmt >>= traverseSinglyNestedStmtsM cs nestedStmtMapper stmt =
cs (Block name decls stmts) = do stmtMapper stmt >>= traverseSinglyNestedStmtsM fullStmtMapper
fullStmtMapper (Block name decls stmts) = do
prevState <- get prevState <- get
decls' <- mapM declMapper decls decls' <- mapM declMapper decls
block <- fullStmtMapper $ Block name decls' stmts block <- nestedStmtMapper $ Block name decls' stmts
put prevState put prevState
return block return block
cs other = fullStmtMapper other fullStmtMapper other = nestedStmtMapper other
redirectModuleItem (MIPackageItem (Function ml t x decls stmts)) = do redirectModuleItem (MIPackageItem (Function ml t x decls stmts)) = do
prevState <- get prevState <- get
......
typedef struct packed { logic w, x, y; } StructA;
typedef struct packed { logic w, y, x; } StructB;
typedef struct packed { logic x, w, y; } StructC;
typedef struct packed { logic y, w, x; } StructD;
typedef struct packed { logic x, y, w; } StructE;
typedef struct packed { logic y, x, w; } StructF;
module top;
integer i, j, k;
StructA a;
StructB b;
StructC c;
StructD d;
StructE e;
StructF f;
initial begin
for (i = 0; i < 2; i++) begin
for (j = 0; j < 2; j++) begin
for (k = 0; k < 2; k++) begin
a = '{ w:i, x:j, y:k };
b = '{ w:i, x:j, y:k };
c = '{ w:i, x:j, y:k };
d = '{ w:i, x:j, y:k };
e = '{ w:i, x:j, y:k };
f = '{ w:i, x:j, y:k };
$display("A: %1d%1d%1d -> ", i,j,k, a,b,c,d,e,f);
end
end
end
end
initial begin
integer i, j, k;
StructB a;
StructC b;
StructD c;
StructE d;
StructF e;
StructA f;
for (i = 0; i < 2; i++) begin
for (j = 0; j < 2; j++) begin
for (k = 0; k < 2; k++) begin
a = '{ w:i, x:j, y:k };
b = '{ w:i, x:j, y:k };
c = '{ w:i, x:j, y:k };
d = '{ w:i, x:j, y:k };
e = '{ w:i, x:j, y:k };
f = '{ w:i, x:j, y:k };
$display("B: %1d%1d%1d -> ", i,j,k, a,b,c,d,e,f);
end
end
end
begin
integer i, j, k;
StructC a;
StructD b;
StructE c;
StructF d;
StructA e;
StructB f;
for (i = 0; i < 2; i++) begin
for (j = 0; j < 2; j++) begin
for (k = 0; k < 2; k++) begin
a = '{ w:i, x:j, y:k };
b = '{ w:i, x:j, y:k };
c = '{ w:i, x:j, y:k };
d = '{ w:i, x:j, y:k };
e = '{ w:i, x:j, y:k };
f = '{ w:i, x:j, y:k };
$display("C: %1d%1d%1d -> ", i,j,k, a,b,c,d,e,f);
end
end
end
end
end
task foo;
integer i, j, k;
StructD a;
StructE b;
StructF c;
StructA d;
StructB e;
StructC f;
for (i = 0; i < 2; i++) begin
for (j = 0; j < 2; j++) begin
for (k = 0; k < 2; k++) begin
a = '{ w:i, x:j, y:k };
b = '{ w:i, x:j, y:k };
c = '{ w:i, x:j, y:k };
d = '{ w:i, x:j, y:k };
e = '{ w:i, x:j, y:k };
f = '{ w:i, x:j, y:k };
$display("D: %1d%1d%1d -> ", i,j,k, a,b,c,d,e,f);
end
end
end
endtask
initial foo();
endmodule
// While this might look silly, you'll notice that the sections are actually
// different. We are ensuring that the correct struct definitions are being used
// in each scope.
module top;
reg [2:0] a = 3'b111;
reg [2:0] b = 3'b111;
reg [2:0] c = 3'b111;
reg [2:0] d = 3'b111;
reg [2:0] e = 3'b111;
reg [2:0] f = 3'b111;
integer i = 2;
integer j = 2;
integer k = 2;
initial begin
$display("A: 000 -> 000000");
$display("A: 001 -> 121424");
$display("A: 010 -> 214142");
$display("A: 011 -> 335566");
$display("A: 100 -> 442211");
$display("A: 101 -> 563635");
$display("A: 110 -> 656353");
$display("A: 111 -> 777777");
$display("B: 000 -> 000000");
$display("B: 001 -> 214241");
$display("B: 010 -> 141422");
$display("B: 011 -> 355663");
$display("B: 100 -> 422114");
$display("B: 101 -> 636355");
$display("B: 110 -> 563536");
$display("B: 111 -> 777777");
$display("C: 000 -> 000000");
$display("C: 001 -> 142412");
$display("C: 010 -> 414221");
$display("C: 011 -> 556633");
$display("C: 100 -> 221144");
$display("C: 101 -> 363556");
$display("C: 110 -> 635365");
$display("C: 111 -> 777777");
$display("D: 000 -> 000000");
$display("D: 001 -> 424121");
$display("D: 010 -> 142214");
$display("D: 011 -> 566335");
$display("D: 100 -> 211442");
$display("D: 101 -> 635563");
$display("D: 110 -> 353656");
$display("D: 111 -> 777777");
end
endmodule
// intentionally empty
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