diff --git a/src/Convert.hs b/src/Convert.hs index a6809ae..2123740 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -19,6 +19,7 @@ import qualified Convert.Enum import qualified Convert.ForDecl import qualified Convert.Foreach import qualified Convert.FuncRet +import qualified Convert.FuncRoutine import qualified Convert.Inside import qualified Convert.Interface import qualified Convert.IntTypes @@ -58,6 +59,7 @@ phases excludes = , selectExclude (Job.Logic , Convert.Logic.convert) , Convert.ForDecl.convert , Convert.FuncRet.convert + , Convert.FuncRoutine.convert , Convert.EmptyArgs.convert , Convert.Inside.convert , Convert.IntTypes.convert diff --git a/src/Convert/FuncRoutine.hs b/src/Convert/FuncRoutine.hs new file mode 100644 index 0000000..0c92e5d --- /dev/null +++ b/src/Convert/FuncRoutine.hs @@ -0,0 +1,45 @@ +{- sv2v + - Author: Zachary Snow + - + - 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 + +import Control.Monad.Writer +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 +convertDescription (description @ Part{}) = + traverseModuleItems (traverseStmts $ convertStmt functions) description + where functions = execWriter $ + collectModuleItemsM collectFunctionsM description +convertDescription other = other + +collectFunctionsM :: ModuleItem -> Writer Idents () +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 + decl = Variable Local t "sv2v_void" [] (Just e) +convertStmt _ other = other diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index 6029ab5..42f3b4c 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -941,6 +941,7 @@ StmtNonBlock :: { Stmt } | AttributeInstance Stmt { StmtAttr $1 $2 } | ProceduralAssertionStatement { Assertion $1 } | IncOrDecOperator LHS ";" { AsgnBlk (AsgnOp $1) $2 (Number "1") } + | "void" "'" "(" Expr CallArgs ")" ";" { Subroutine $4 $5 } BlockKWPar :: { BlockKW } : "fork" { Par } diff --git a/sv2v.cabal b/sv2v.cabal index 720007a..eace236 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -66,6 +66,7 @@ executable sv2v Convert.ForDecl Convert.Foreach Convert.FuncRet + Convert.FuncRoutine Convert.Inside Convert.Interface Convert.IntTypes diff --git a/test/basic/typeof.sv b/test/basic/typeof.sv index 9cbb3cb..fb1b39f 100644 --- a/test/basic/typeof.sv +++ b/test/basic/typeof.sv @@ -4,6 +4,10 @@ module top; f = 1'b1 ^ x; $display("f(%b) called", x); endfunction + task t; + input x; + $display("t(%b) called", x); + endtask initial begin type(f(0)) x = f(0); @@ -11,5 +15,8 @@ module top; $display("%b", $bits(x)); $display("%b", $bits(type(x))); $display("%b", $bits(logic [0:1+$bits(type(x))])); + f(1); + void'(f(0)); + t(1); end endmodule diff --git a/test/basic/typeof.v b/test/basic/typeof.v index 7ff8b66..74c95f3 100644 --- a/test/basic/typeof.v +++ b/test/basic/typeof.v @@ -6,6 +6,10 @@ module top; $display("f(%b) called", x); end endfunction + task t; + input x; + $display("t(%b) called", x); + endtask initial begin : block reg x; @@ -14,5 +18,8 @@ module top; $display("%b", 32'd1); $display("%b", 32'd1); $display("%b", 32'd3); + x = f(1); + x = f(0); + t(1); end endmodule