TFBlock.hs 2.26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
{- 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

Zachary Snow committed
11
import Data.List (intersect)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

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])
34 35
convertTFBlock decls [CommentStmt c, stmt] =
    convertTFBlock (decls ++ [CommentDecl c]) [stmt]
36 37 38 39 40 41 42 43 44 45
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]) =
46 47 48
    if canCombine declsA declsB
        then (declsA ++ declsB, stmtsB)
        else (declsA, [stmt])
49 50
    where (declsB, stmtsB) = flattenOuterBlocks stmt
flattenOuterBlocks (Block Seq name decls stmts)
Zachary Snow committed
51
    | null name = (decls, stmts)
52 53 54
    | otherwise = ([], [Block Seq name decls stmts])
flattenOuterBlocks stmt = ([], [stmt])

55 56 57 58 59 60 61 62 63 64 65
canCombine :: [Decl] -> [Decl] -> Bool
canCombine [] _ = True
canCombine _ [] = True
canCombine declsA declsB =
    null $ intersect (declNames declsA) (declNames declsB)

declNames :: [Decl] -> [Identifier]
declNames = filter (not . null) . map declName

declName :: Decl -> Identifier
declName (Variable _ _ x _ _) = x
66
declName (Net  _ _ _ _ x _ _) = x
67 68 69
declName (Param _ _ x _) = x
declName (ParamType _ x _) = x
declName CommentDecl{} = ""