mirror of https://github.com/zachjs/sv2v.git
improved handling of genvars
This commit is contained in:
parent
da087cc2c1
commit
dd9f040f1f
|
|
@ -14,6 +14,7 @@ import qualified Convert.AsgnOp
|
|||
import qualified Convert.Assertion
|
||||
import qualified Convert.BlockDecl
|
||||
import qualified Convert.DimensionQuery
|
||||
import qualified Convert.DuplicateGenvar
|
||||
import qualified Convert.EmptyArgs
|
||||
import qualified Convert.Enum
|
||||
import qualified Convert.ForDecl
|
||||
|
|
@ -56,6 +57,7 @@ phases excludes =
|
|||
, Convert.NamedBlock.convert
|
||||
, Convert.Assertion.convert
|
||||
, Convert.BlockDecl.convert
|
||||
, Convert.DuplicateGenvar.convert
|
||||
, selectExclude (Job.Logic , Convert.Logic.convert)
|
||||
, Convert.FuncRet.convert
|
||||
, Convert.FuncRoutine.convert
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion to remove duplicate genvar declarations
|
||||
-}
|
||||
|
||||
module Convert.DuplicateGenvar (convert) where
|
||||
|
||||
import Control.Monad.State
|
||||
import qualified Data.Set as Set
|
||||
|
||||
import Convert.Traverse
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
type IdentSet = Set.Set Identifier
|
||||
|
||||
convert :: [AST] -> [AST]
|
||||
convert = map $ traverseDescriptions traverseDescription
|
||||
|
||||
traverseDescription :: Description -> Description
|
||||
traverseDescription (part @ Part{}) =
|
||||
Part attrs extern kw lifetime name ports items'
|
||||
where
|
||||
Part attrs extern kw lifetime name ports items = part
|
||||
-- intentionally only looks at top level module items
|
||||
items' = evalState (mapM traverseModuleItemM items) Set.empty
|
||||
traverseDescription other = other
|
||||
|
||||
traverseModuleItemM :: ModuleItem -> State IdentSet ModuleItem
|
||||
traverseModuleItemM (Genvar x) = do
|
||||
alreadyExists <- gets $ Set.member x
|
||||
if alreadyExists
|
||||
then return $ Generate []
|
||||
else do
|
||||
modify $ Set.insert x
|
||||
return $ Genvar x
|
||||
traverseModuleItemM (Generate items) = do
|
||||
s <- get
|
||||
items' <- traverseItems items
|
||||
s' <- get
|
||||
items'' <- traverseItems items'
|
||||
let genvarDecls = map (GenModuleItem . Genvar) $
|
||||
Set.toList $ Set.difference s' s
|
||||
return $ Generate (genvarDecls ++ items'')
|
||||
where traverseItems = mapM $ traverseNestedGenItemsM traverseGenItemM
|
||||
traverseModuleItemM other = return other
|
||||
|
||||
traverseGenItemM :: GenItem -> State IdentSet GenItem
|
||||
traverseGenItemM (GenModuleItem item) = do
|
||||
item' <- traverseModuleItemM item
|
||||
return $ GenModuleItem item'
|
||||
traverseGenItemM other = return other
|
||||
|
|
@ -2,11 +2,10 @@
|
|||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Verilog-2005 requires that for loops have have exactly one assignment in the
|
||||
- initialization section. For generate for loops, we move any genvar
|
||||
- declarations to a wrapping generate block. For procedural for loops, we pull
|
||||
- the declarations out to a wrapping block, and convert all but one assignment
|
||||
- to a preceding statement. If a for loop has no assignments or declarations, a
|
||||
- dummy declaration is generated.
|
||||
- initialization section. For procedural for loops, we pull the declarations
|
||||
- out to a wrapping block, and convert all but one assignment to a preceding
|
||||
- statement. If a for loop has no assignments or declarations, a dummy
|
||||
- declaration is generated.
|
||||
-}
|
||||
|
||||
module Convert.ForDecl (convert) where
|
||||
|
|
@ -17,35 +16,7 @@ import Language.SystemVerilog.AST
|
|||
convert :: [AST] -> [AST]
|
||||
convert =
|
||||
map $ traverseDescriptions $ traverseModuleItems $
|
||||
( traverseStmts convertStmt
|
||||
. traverseGenItems convertGenItem
|
||||
)
|
||||
|
||||
convertGenItem :: GenItem -> GenItem
|
||||
convertGenItem (GenFor (True, _, _) _ _ GenNull) = GenNull
|
||||
convertGenItem (GenFor (True, _, _) _ _ (GenBlock _ [])) = GenNull
|
||||
convertGenItem (GenFor (True, x, e) a b c) =
|
||||
GenBlock "" genItems
|
||||
where
|
||||
bx = case c of
|
||||
GenBlock name _ -> name
|
||||
_ -> ""
|
||||
x' = if null bx then x else bx ++ "_" ++ x
|
||||
Generate genItems =
|
||||
traverseNestedModuleItems converter $ Generate $
|
||||
[ GenModuleItem $ Genvar x'
|
||||
, GenFor (False, x, e) a b c
|
||||
]
|
||||
converter =
|
||||
(traverseExprs $ traverseNestedExprs convertExpr) .
|
||||
(traverseLHSs $ traverseNestedLHSs convertLHS )
|
||||
prefix :: String -> String
|
||||
prefix ident = if ident == x then x' else ident
|
||||
convertExpr (Ident ident) = Ident $ prefix ident
|
||||
convertExpr other = other
|
||||
convertLHS (LHSIdent ident) = LHSIdent $ prefix ident
|
||||
convertLHS other = other
|
||||
convertGenItem other = other
|
||||
traverseStmts convertStmt
|
||||
|
||||
convertStmt :: Stmt -> Stmt
|
||||
convertStmt (For (Left []) cc asgns stmt) =
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ module Convert.Traverse
|
|||
, traverseGenItemsM
|
||||
, traverseGenItems
|
||||
, collectGenItemsM
|
||||
, traverseNestedGenItemsM
|
||||
, traverseAsgnsM
|
||||
, traverseAsgns
|
||||
, collectAsgnsM
|
||||
|
|
@ -633,11 +634,11 @@ traverseExprsM' strat exprMapper = moduleItemMapper
|
|||
a'' <- traverseAssertionExprsM exprMapper a'
|
||||
return $ AssertionItem (mx, a'')
|
||||
|
||||
genItemMapper (GenFor (n1, x1, e1) cc (x2, op2, e2) subItem) = do
|
||||
genItemMapper (GenFor (x1, e1) cc (x2, op2, e2) subItem) = do
|
||||
e1' <- exprMapper e1
|
||||
e2' <- exprMapper e2
|
||||
cc' <- exprMapper cc
|
||||
return $ GenFor (n1, x1, e1') cc' (x2, op2, e2') subItem
|
||||
return $ GenFor (x1, e1') cc' (x2, op2, e2') subItem
|
||||
genItemMapper (GenIf e i1 i2) = do
|
||||
e' <- exprMapper e
|
||||
return $ GenIf e' i1 i2
|
||||
|
|
@ -762,12 +763,12 @@ traverseLHSsM' strat mapper item =
|
|||
items' <- mapM (traverseNestedGenItemsM traverGenItemLHSsM) items
|
||||
return $ Generate items'
|
||||
traverseModuleItemLHSsM other = return other
|
||||
traverGenItemLHSsM (GenFor (n1, x1, e1) cc (x2, op2, e2) subItem) = do
|
||||
wrapped_x1' <- (if n1 then return else mapper) $ LHSIdent x1
|
||||
traverGenItemLHSsM (GenFor (x1, e1) cc (x2, op2, e2) subItem) = do
|
||||
wrapped_x1' <- mapper $ LHSIdent x1
|
||||
wrapped_x2' <- mapper $ LHSIdent x2
|
||||
let LHSIdent x1' = wrapped_x1'
|
||||
let LHSIdent x2' = wrapped_x2'
|
||||
return $ GenFor (n1, x1', e1) cc (x2', op2, e2) subItem
|
||||
return $ GenFor (x1', e1) cc (x2', op2, e2) subItem
|
||||
traverGenItemLHSsM other = return other
|
||||
|
||||
traverseLHSs' :: TFStrategy -> Mapper LHS -> Mapper ModuleItem
|
||||
|
|
@ -956,12 +957,18 @@ traverseNestedGenItemsM mapper = fullMapper
|
|||
fullMapper stmt =
|
||||
mapper stmt >>= traverseSinglyNestedGenItemsM fullMapper
|
||||
|
||||
flattenGenBlocks :: GenItem -> [GenItem]
|
||||
flattenGenBlocks (GenBlock "" items) = items
|
||||
flattenGenBlocks (GenFor _ _ _ GenNull) = []
|
||||
flattenGenBlocks GenNull = []
|
||||
flattenGenBlocks other = [other]
|
||||
|
||||
traverseSinglyNestedGenItemsM :: Monad m => MapperM m GenItem -> MapperM m GenItem
|
||||
traverseSinglyNestedGenItemsM fullMapper = gim
|
||||
where
|
||||
gim (GenBlock x subItems) = do
|
||||
subItems' <- mapM fullMapper subItems
|
||||
return $ GenBlock x (concatMap flattenBlocks subItems')
|
||||
return $ GenBlock x (concatMap flattenGenBlocks subItems')
|
||||
gim (GenFor a b c subItem) = do
|
||||
subItem' <- fullMapper subItem
|
||||
return $ GenFor a b c subItem'
|
||||
|
|
@ -976,9 +983,6 @@ traverseSinglyNestedGenItemsM fullMapper = gim
|
|||
gim (GenModuleItem moduleItem) =
|
||||
return $ GenModuleItem moduleItem
|
||||
gim (GenNull) = return GenNull
|
||||
flattenBlocks :: GenItem -> [GenItem]
|
||||
flattenBlocks (GenBlock "" items) = items
|
||||
flattenBlocks other = [other]
|
||||
|
||||
traverseAsgnsM' :: Monad m => TFStrategy -> MapperM m (LHS, Expr) -> MapperM m ModuleItem
|
||||
traverseAsgnsM' strat mapper = moduleItemMapper
|
||||
|
|
@ -1024,10 +1028,8 @@ collectStmtAsgnsM = collectify traverseStmtAsgnsM
|
|||
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
|
||||
traverseNestedModuleItemsM mapper = fullMapper
|
||||
where
|
||||
fullMapper (Generate [GenBlock "" genItems]) =
|
||||
mapM fullGenItemMapper genItems >>= mapper . Generate
|
||||
fullMapper (Generate genItems) = do
|
||||
let genItems' = filter (/= GenNull) genItems
|
||||
let genItems' = concatMap flattenGenBlocks genItems
|
||||
mapM fullGenItemMapper genItems' >>= mapper . Generate
|
||||
fullMapper (MIAttr attr mi) =
|
||||
fullMapper mi >>= mapper . MIAttr attr
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem)
|
|||
data GenItem
|
||||
= GenBlock Identifier [GenItem]
|
||||
| GenCase Expr [GenCase]
|
||||
| GenFor (Bool, Identifier, Expr) Expr (Identifier, AsgnOp, Expr) GenItem
|
||||
| GenFor (Identifier, Expr) Expr (Identifier, AsgnOp, Expr) GenItem
|
||||
| GenIf Expr GenItem GenItem
|
||||
| GenNull
|
||||
| GenModuleItem ModuleItem
|
||||
|
|
@ -39,9 +39,8 @@ instance Show GenItem where
|
|||
where bodyStr = indent $ unlines' $ map showGenCase cs
|
||||
show (GenIf e a GenNull) = printf "if (%s) %s" (show e) (show a)
|
||||
show (GenIf e a b ) = printf "if (%s) %s\nelse %s" (show e) (show a) (show b)
|
||||
show (GenFor (new, x1, e1) c (x2, o2, e2) s) =
|
||||
printf "for (%s%s = %s; %s; %s %s %s) %s"
|
||||
(if new then "genvar " else "")
|
||||
show (GenFor (x1, e1) c (x2, o2, e2) s) =
|
||||
printf "for (%s = %s; %s; %s %s %s) %s"
|
||||
x1 (show e1)
|
||||
(show c)
|
||||
x2 (show o2) (show e2)
|
||||
|
|
|
|||
|
|
@ -1238,7 +1238,7 @@ ConditionalGenerateConstruct :: { GenItem }
|
|||
| "if" "(" Expr ")" GenItemOrNull %prec NoElse { GenIf $3 $5 GenNull }
|
||||
| "case" "(" Expr ")" GenCases "endcase" { GenCase $3 $5 }
|
||||
LoopGenerateConstruct :: { GenItem }
|
||||
: "for" "(" GenvarInitialization ";" Expr ";" GenvarIteration ")" GenItem { GenFor $3 $5 $7 $9 }
|
||||
: "for" "(" GenvarInitialization ";" Expr ";" GenvarIteration ")" GenItem { $3 $5 $7 $9 }
|
||||
|
||||
GenBlock :: { (Identifier, [GenItem]) }
|
||||
: "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) }
|
||||
|
|
@ -1250,9 +1250,9 @@ GenCase :: { GenCase }
|
|||
: Exprs ":" GenItemOrNull { ($1, $3) }
|
||||
| "default" opt(":") GenItemOrNull { ([], $3) }
|
||||
|
||||
GenvarInitialization :: { (Bool, Identifier, Expr) }
|
||||
: "genvar" Identifier "=" Expr { (True , $2, $4) }
|
||||
| Identifier "=" Expr { (False, $1, $3) }
|
||||
GenvarInitialization :: { Expr -> (Identifier, AsgnOp, Expr) -> GenItem -> GenItem }
|
||||
: "genvar" Identifier "=" Expr { \a b c -> GenBlock "" [GenModuleItem (Genvar $2), GenFor ($2, $4) a b c] }
|
||||
| Identifier "=" Expr { GenFor ($1, $3) }
|
||||
|
||||
GenvarIteration :: { (Identifier, AsgnOp, Expr) }
|
||||
: Identifier AsgnOp Expr { ($1, $2, $3) }
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ executable sv2v
|
|||
Convert.Assertion
|
||||
Convert.BlockDecl
|
||||
Convert.DimensionQuery
|
||||
Convert.DuplicateGenvar
|
||||
Convert.EmptyArgs
|
||||
Convert.Enum
|
||||
Convert.ForDecl
|
||||
|
|
|
|||
Loading…
Reference in New Issue