{- sv2v - 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. -} module Convert.ForDecl (convert) where import Convert.Traverse import Language.SystemVerilog.AST convert :: [AST] -> [AST] convert = map $ traverseDescriptions $ traverseModuleItems $ ( traverseStmts convertStmt . traverseGenItems convertGenItem ) convertGenItem :: GenItem -> GenItem convertGenItem (GenFor (True, x, e) a b bx c) = GenBlock "" genItems where x' = if null bx then x else bx ++ "_" ++ x Generate genItems = traverseNestedModuleItems converter $ Generate $ [ GenModuleItem $ Genvar x' , GenFor (False, x, e) a b bx 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 (For (Left []) cc asgns stmt) = convertStmt $ For (Right []) cc asgns stmt convertStmt (For (Right []) cc asgns stmt) = convertStmt $ For inits cc asgns stmt where inits = Left [dummyDecl (Just $ Number "0")] convertStmt (orig @ (For (Right [_]) _ _ _)) = orig convertStmt (For (Left inits) cc asgns stmt) = Block Seq "" decls $ initAsgns ++ [For (Right [(lhs, expr)]) cc asgns stmt] where splitDecls = map splitDecl inits decls = map fst splitDecls initAsgns = map asgnStmt $ init $ map snd splitDecls (lhs, expr) = snd $ last splitDecls convertStmt (For (Right origPairs) cc asgns stmt) = Block Seq "" [] $ initAsgns ++ [For (Right [(lhs, expr)]) cc asgns stmt] where (lhs, expr) = last origPairs initAsgns = map asgnStmt $ init origPairs convertStmt other = other splitDecl :: Decl -> (Decl, (LHS, Expr)) splitDecl (Variable d t ident a (Just e)) = (Variable d t ident a Nothing, (LHSIdent ident, e)) splitDecl other = error $ "invalid for loop decl: " ++ show other asgnStmt :: (LHS, Expr) -> Stmt asgnStmt = uncurry $ AsgnBlk AsgnOpEq dummyDecl :: Maybe Expr -> Decl dummyDecl = Variable Local (IntegerAtom TInteger Unspecified) "_sv2v_dummy" []