FuncRoutine.hs 1.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
{- sv2v
 - Author: Zachary Snow <zach@zachjs.com>
 -
 - SystemVerilog allows functions to be called without using their result. For
 - example, if `f` is a function, one may write `f();` or `void'(f());`, causing
 - any side effects of `f` to occur in each case. Verilog-2005 does not allow
 - functions to be called as though they were tasks in this way. This conversion
 - creates a dummy variable to store the result of the function.
 -}

module Convert.FuncRoutine (convert) where

13
import Control.Monad.Writer.Strict
14 15 16 17 18 19 20 21 22 23 24
import qualified Data.Set as Set

import Convert.Traverse
import Language.SystemVerilog.AST

type Idents = Set.Set Identifier

convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription

convertDescription :: Description -> Description
25
convertDescription description@Part{} =
26 27 28 29 30
    traverseModuleItems traverseModuleItem description
    where
        traverseModuleItem =
            traverseStmts $ traverseNestedStmts $ convertStmt functions
        functions = execWriter $
31 32 33 34
            collectModuleItemsM collectFunctionsM description
convertDescription other = other

collectFunctionsM :: ModuleItem -> Writer Idents ()
35
collectFunctionsM (MIPackageItem (Function _ Void _ _ _)) = return ()
36 37 38 39 40 41 42 43 44 45 46 47
collectFunctionsM (MIPackageItem (Function _ _ f _ _)) =
    tell $ Set.singleton f
collectFunctionsM _ = return ()

convertStmt :: Idents -> Stmt -> Stmt
convertStmt functions (Subroutine (Ident func) args) =
    if Set.member func functions
        then Block Seq "" [decl] []
        else Subroutine (Ident func) args
    where
        t = TypeOf e
        e = Call (Ident func) args
Zachary Snow committed
48
        decl = Variable Local t "sv2v_void" [] e
49
convertStmt _ other = other