Commit dd9f040f by Zachary Snow

improved handling of genvars

parent da087cc2
......@@ -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
......
{- 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
......
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