Commit dd9f040f by Zachary Snow

improved handling of genvars

parent da087cc2
...@@ -14,6 +14,7 @@ import qualified Convert.AsgnOp ...@@ -14,6 +14,7 @@ import qualified Convert.AsgnOp
import qualified Convert.Assertion import qualified Convert.Assertion
import qualified Convert.BlockDecl import qualified Convert.BlockDecl
import qualified Convert.DimensionQuery import qualified Convert.DimensionQuery
import qualified Convert.DuplicateGenvar
import qualified Convert.EmptyArgs import qualified Convert.EmptyArgs
import qualified Convert.Enum import qualified Convert.Enum
import qualified Convert.ForDecl import qualified Convert.ForDecl
...@@ -56,6 +57,7 @@ phases excludes = ...@@ -56,6 +57,7 @@ phases excludes =
, Convert.NamedBlock.convert , Convert.NamedBlock.convert
, Convert.Assertion.convert , Convert.Assertion.convert
, Convert.BlockDecl.convert , Convert.BlockDecl.convert
, Convert.DuplicateGenvar.convert
, selectExclude (Job.Logic , Convert.Logic.convert) , selectExclude (Job.Logic , Convert.Logic.convert)
, Convert.FuncRet.convert , Convert.FuncRet.convert
, Convert.FuncRoutine.convert , Convert.FuncRoutine.convert
......
{- 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 @@ ...@@ -2,11 +2,10 @@
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
- Verilog-2005 requires that for loops have have exactly one assignment in the - Verilog-2005 requires that for loops have have exactly one assignment in the
- initialization section. For generate for loops, we move any genvar - initialization section. For procedural for loops, we pull the declarations
- declarations to a wrapping generate block. For procedural for loops, we pull - out to a wrapping block, and convert all but one assignment to a preceding
- the declarations out to a wrapping block, and convert all but one assignment - statement. If a for loop has no assignments or declarations, a dummy
- to a preceding statement. If a for loop has no assignments or declarations, a - declaration is generated.
- dummy declaration is generated.
-} -}
module Convert.ForDecl (convert) where module Convert.ForDecl (convert) where
...@@ -17,35 +16,7 @@ import Language.SystemVerilog.AST ...@@ -17,35 +16,7 @@ import Language.SystemVerilog.AST
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert =
map $ traverseDescriptions $ traverseModuleItems $ map $ traverseDescriptions $ traverseModuleItems $
( traverseStmts convertStmt 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
convertStmt :: Stmt -> Stmt convertStmt :: Stmt -> Stmt
convertStmt (For (Left []) cc asgns stmt) = convertStmt (For (Left []) cc asgns stmt) =
......
...@@ -63,6 +63,7 @@ module Convert.Traverse ...@@ -63,6 +63,7 @@ module Convert.Traverse
, traverseGenItemsM , traverseGenItemsM
, traverseGenItems , traverseGenItems
, collectGenItemsM , collectGenItemsM
, traverseNestedGenItemsM
, traverseAsgnsM , traverseAsgnsM
, traverseAsgns , traverseAsgns
, collectAsgnsM , collectAsgnsM
...@@ -633,11 +634,11 @@ traverseExprsM' strat exprMapper = moduleItemMapper ...@@ -633,11 +634,11 @@ traverseExprsM' strat exprMapper = moduleItemMapper
a'' <- traverseAssertionExprsM exprMapper a' a'' <- traverseAssertionExprsM exprMapper a'
return $ AssertionItem (mx, 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 e1' <- exprMapper e1
e2' <- exprMapper e2 e2' <- exprMapper e2
cc' <- exprMapper cc 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 genItemMapper (GenIf e i1 i2) = do
e' <- exprMapper e e' <- exprMapper e
return $ GenIf e' i1 i2 return $ GenIf e' i1 i2
...@@ -762,12 +763,12 @@ traverseLHSsM' strat mapper item = ...@@ -762,12 +763,12 @@ traverseLHSsM' strat mapper item =
items' <- mapM (traverseNestedGenItemsM traverGenItemLHSsM) items items' <- mapM (traverseNestedGenItemsM traverGenItemLHSsM) items
return $ Generate items' return $ Generate items'
traverseModuleItemLHSsM other = return other traverseModuleItemLHSsM other = return other
traverGenItemLHSsM (GenFor (n1, x1, e1) cc (x2, op2, e2) subItem) = do traverGenItemLHSsM (GenFor (x1, e1) cc (x2, op2, e2) subItem) = do
wrapped_x1' <- (if n1 then return else mapper) $ LHSIdent x1 wrapped_x1' <- mapper $ LHSIdent x1
wrapped_x2' <- mapper $ LHSIdent x2 wrapped_x2' <- mapper $ LHSIdent x2
let LHSIdent x1' = wrapped_x1' let LHSIdent x1' = wrapped_x1'
let LHSIdent x2' = wrapped_x2' 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 traverGenItemLHSsM other = return other
traverseLHSs' :: TFStrategy -> Mapper LHS -> Mapper ModuleItem traverseLHSs' :: TFStrategy -> Mapper LHS -> Mapper ModuleItem
...@@ -956,12 +957,18 @@ traverseNestedGenItemsM mapper = fullMapper ...@@ -956,12 +957,18 @@ traverseNestedGenItemsM mapper = fullMapper
fullMapper stmt = fullMapper stmt =
mapper stmt >>= traverseSinglyNestedGenItemsM fullMapper 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 :: Monad m => MapperM m GenItem -> MapperM m GenItem
traverseSinglyNestedGenItemsM fullMapper = gim traverseSinglyNestedGenItemsM fullMapper = gim
where where
gim (GenBlock x subItems) = do gim (GenBlock x subItems) = do
subItems' <- mapM fullMapper subItems subItems' <- mapM fullMapper subItems
return $ GenBlock x (concatMap flattenBlocks subItems') return $ GenBlock x (concatMap flattenGenBlocks subItems')
gim (GenFor a b c subItem) = do gim (GenFor a b c subItem) = do
subItem' <- fullMapper subItem subItem' <- fullMapper subItem
return $ GenFor a b c subItem' return $ GenFor a b c subItem'
...@@ -976,9 +983,6 @@ traverseSinglyNestedGenItemsM fullMapper = gim ...@@ -976,9 +983,6 @@ traverseSinglyNestedGenItemsM fullMapper = gim
gim (GenModuleItem moduleItem) = gim (GenModuleItem moduleItem) =
return $ GenModuleItem moduleItem return $ GenModuleItem moduleItem
gim (GenNull) = return GenNull 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' :: Monad m => TFStrategy -> MapperM m (LHS, Expr) -> MapperM m ModuleItem
traverseAsgnsM' strat mapper = moduleItemMapper traverseAsgnsM' strat mapper = moduleItemMapper
...@@ -1024,10 +1028,8 @@ collectStmtAsgnsM = collectify traverseStmtAsgnsM ...@@ -1024,10 +1028,8 @@ collectStmtAsgnsM = collectify traverseStmtAsgnsM
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
traverseNestedModuleItemsM mapper = fullMapper traverseNestedModuleItemsM mapper = fullMapper
where where
fullMapper (Generate [GenBlock "" genItems]) =
mapM fullGenItemMapper genItems >>= mapper . Generate
fullMapper (Generate genItems) = do fullMapper (Generate genItems) = do
let genItems' = filter (/= GenNull) genItems let genItems' = concatMap flattenGenBlocks genItems
mapM fullGenItemMapper genItems' >>= mapper . Generate mapM fullGenItemMapper genItems' >>= mapper . Generate
fullMapper (MIAttr attr mi) = fullMapper (MIAttr attr mi) =
fullMapper mi >>= mapper . MIAttr attr fullMapper mi >>= mapper . MIAttr attr
......
...@@ -22,7 +22,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem) ...@@ -22,7 +22,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem)
data GenItem data GenItem
= GenBlock Identifier [GenItem] = GenBlock Identifier [GenItem]
| GenCase Expr [GenCase] | GenCase Expr [GenCase]
| GenFor (Bool, Identifier, Expr) Expr (Identifier, AsgnOp, Expr) GenItem | GenFor (Identifier, Expr) Expr (Identifier, AsgnOp, Expr) GenItem
| GenIf Expr GenItem GenItem | GenIf Expr GenItem GenItem
| GenNull | GenNull
| GenModuleItem ModuleItem | GenModuleItem ModuleItem
...@@ -39,9 +39,8 @@ instance Show GenItem where ...@@ -39,9 +39,8 @@ instance Show GenItem where
where bodyStr = indent $ unlines' $ map showGenCase cs where bodyStr = indent $ unlines' $ map showGenCase cs
show (GenIf e a GenNull) = printf "if (%s) %s" (show e) (show a) 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 (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) = show (GenFor (x1, e1) c (x2, o2, e2) s) =
printf "for (%s%s = %s; %s; %s %s %s) %s" printf "for (%s = %s; %s; %s %s %s) %s"
(if new then "genvar " else "")
x1 (show e1) x1 (show e1)
(show c) (show c)
x2 (show o2) (show e2) x2 (show o2) (show e2)
......
...@@ -1238,7 +1238,7 @@ ConditionalGenerateConstruct :: { GenItem } ...@@ -1238,7 +1238,7 @@ ConditionalGenerateConstruct :: { GenItem }
| "if" "(" Expr ")" GenItemOrNull %prec NoElse { GenIf $3 $5 GenNull } | "if" "(" Expr ")" GenItemOrNull %prec NoElse { GenIf $3 $5 GenNull }
| "case" "(" Expr ")" GenCases "endcase" { GenCase $3 $5 } | "case" "(" Expr ")" GenCases "endcase" { GenCase $3 $5 }
LoopGenerateConstruct :: { GenItem } LoopGenerateConstruct :: { GenItem }
: "for" "(" GenvarInitialization ";" Expr ";" GenvarIteration ")" GenItem { GenFor $3 $5 $7 $9 } : "for" "(" GenvarInitialization ";" Expr ";" GenvarIteration ")" GenItem { $3 $5 $7 $9 }
GenBlock :: { (Identifier, [GenItem]) } GenBlock :: { (Identifier, [GenItem]) }
: "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) } : "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) }
...@@ -1250,9 +1250,9 @@ GenCase :: { GenCase } ...@@ -1250,9 +1250,9 @@ GenCase :: { GenCase }
: Exprs ":" GenItemOrNull { ($1, $3) } : Exprs ":" GenItemOrNull { ($1, $3) }
| "default" opt(":") GenItemOrNull { ([], $3) } | "default" opt(":") GenItemOrNull { ([], $3) }
GenvarInitialization :: { (Bool, Identifier, Expr) } GenvarInitialization :: { Expr -> (Identifier, AsgnOp, Expr) -> GenItem -> GenItem }
: "genvar" Identifier "=" Expr { (True , $2, $4) } : "genvar" Identifier "=" Expr { \a b c -> GenBlock "" [GenModuleItem (Genvar $2), GenFor ($2, $4) a b c] }
| Identifier "=" Expr { (False, $1, $3) } | Identifier "=" Expr { GenFor ($1, $3) }
GenvarIteration :: { (Identifier, AsgnOp, Expr) } GenvarIteration :: { (Identifier, AsgnOp, Expr) }
: Identifier AsgnOp Expr { ($1, $2, $3) } : Identifier AsgnOp Expr { ($1, $2, $3) }
......
...@@ -63,6 +63,7 @@ executable sv2v ...@@ -63,6 +63,7 @@ executable sv2v
Convert.Assertion Convert.Assertion
Convert.BlockDecl Convert.BlockDecl
Convert.DimensionQuery Convert.DimensionQuery
Convert.DuplicateGenvar
Convert.EmptyArgs Convert.EmptyArgs
Convert.Enum Convert.Enum
Convert.ForDecl Convert.ForDecl
......
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