{- sv2v - Author: Zachary Snow <zach@zachjs.com> - - Conversion for tasks and functions to contain only one top-level statement, - as required in Verilog-2005. This conversion also hoists data declarations to - the task or function level for greater portability. -} module Convert.TFBlock (convert) where import Data.List (isPrefixOf) import Convert.Traverse import Language.SystemVerilog.AST convert :: [AST] -> [AST] convert = map $ traverseDescriptions $ traverseModuleItems convertModuleItem convertModuleItem :: ModuleItem -> ModuleItem convertModuleItem (MIPackageItem packageItem) = MIPackageItem $ convertPackageItem packageItem convertModuleItem other = other convertPackageItem :: PackageItem -> PackageItem convertPackageItem (Function ml t f decls stmts) = Function ml t f decls' stmts' where (decls', stmts') = convertTFBlock decls stmts convertPackageItem (Task ml f decls stmts) = Task ml f decls' stmts' where (decls', stmts') = convertTFBlock decls stmts convertPackageItem other = other convertTFBlock :: [Decl] -> [Stmt] -> ([Decl], [Stmt]) convertTFBlock decls stmts = (decls', [stmtsToStmt stmts']) where (decls', stmts') = flattenOuterBlocks $ Block Seq "" decls stmts stmtsToStmt :: [Stmt] -> Stmt stmtsToStmt [stmt] = stmt stmtsToStmt stmts = Block Seq "" [] stmts flattenOuterBlocks :: Stmt -> ([Decl], [Stmt]) flattenOuterBlocks (Block Seq "" declsA [stmt]) = (declsA ++ declsB, stmtsB) where (declsB, stmtsB) = flattenOuterBlocks stmt flattenOuterBlocks (Block Seq "" declsA (Block Seq name declsB stmtsA : stmtsB)) = flattenOuterBlocks $ Block Seq name (declsA ++ declsB) (stmtsA ++ stmtsB) flattenOuterBlocks (Block Seq name decls stmts) | notscope name = (decls, stmts) | otherwise = ([], [Block Seq name decls stmts]) flattenOuterBlocks stmt = ([], [stmt]) notscope :: Identifier -> Bool notscope "" = True notscope name = "sv2v_autoblock_" `isPrefixOf` name