mirror of https://github.com/zachjs/sv2v.git
struct conversion supports complex shadowing
This commit is contained in:
parent
05b7bdb99c
commit
a8f2cbbe29
|
|
@ -1,7 +1,7 @@
|
||||||
{- 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)
|
||||||
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
|
||||||
|
|
||||||
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 _ _ _ _ _ _)) =
|
||||||
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 =
|
||||||
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
|
||||||
, traverseAsgnsM'
|
, traverseAsgnsM'
|
||||||
, traverseAsgns'
|
, traverseAsgns'
|
||||||
, collectAsgnsM'
|
, collectAsgnsM'
|
||||||
|
, traverseStmtAsgnsM
|
||||||
|
, traverseStmtAsgns
|
||||||
|
, collectStmtAsgnsM
|
||||||
, traverseNestedModuleItemsM
|
, traverseNestedModuleItemsM
|
||||||
, traverseNestedModuleItems
|
, traverseNestedModuleItems
|
||||||
, collectNestedModuleItemsM
|
, collectNestedModuleItemsM
|
||||||
|
|
@ -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
|
||||||
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 =
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
// intentionally empty
|
||||||
Loading…
Reference in New Issue