Commit 22d6ba49 by Zachary Snow

support evaluating functions as statements

parent 2bd24b60
...@@ -19,6 +19,7 @@ import qualified Convert.Enum ...@@ -19,6 +19,7 @@ import qualified Convert.Enum
import qualified Convert.ForDecl import qualified Convert.ForDecl
import qualified Convert.Foreach import qualified Convert.Foreach
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.FuncRoutine
import qualified Convert.Inside import qualified Convert.Inside
import qualified Convert.Interface import qualified Convert.Interface
import qualified Convert.IntTypes import qualified Convert.IntTypes
...@@ -58,6 +59,7 @@ phases excludes = ...@@ -58,6 +59,7 @@ phases excludes =
, selectExclude (Job.Logic , Convert.Logic.convert) , selectExclude (Job.Logic , Convert.Logic.convert)
, Convert.ForDecl.convert , Convert.ForDecl.convert
, Convert.FuncRet.convert , Convert.FuncRet.convert
, Convert.FuncRoutine.convert
, Convert.EmptyArgs.convert , Convert.EmptyArgs.convert
, Convert.Inside.convert , Convert.Inside.convert
, Convert.IntTypes.convert , Convert.IntTypes.convert
......
{- 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
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
...@@ -941,6 +941,7 @@ StmtNonBlock :: { Stmt } ...@@ -941,6 +941,7 @@ StmtNonBlock :: { Stmt }
| AttributeInstance Stmt { StmtAttr $1 $2 } | AttributeInstance Stmt { StmtAttr $1 $2 }
| ProceduralAssertionStatement { Assertion $1 } | ProceduralAssertionStatement { Assertion $1 }
| IncOrDecOperator LHS ";" { AsgnBlk (AsgnOp $1) $2 (Number "1") } | IncOrDecOperator LHS ";" { AsgnBlk (AsgnOp $1) $2 (Number "1") }
| "void" "'" "(" Expr CallArgs ")" ";" { Subroutine $4 $5 }
BlockKWPar :: { BlockKW } BlockKWPar :: { BlockKW }
: "fork" { Par } : "fork" { Par }
......
...@@ -66,6 +66,7 @@ executable sv2v ...@@ -66,6 +66,7 @@ executable sv2v
Convert.ForDecl Convert.ForDecl
Convert.Foreach Convert.Foreach
Convert.FuncRet Convert.FuncRet
Convert.FuncRoutine
Convert.Inside Convert.Inside
Convert.Interface Convert.Interface
Convert.IntTypes Convert.IntTypes
......
...@@ -4,6 +4,10 @@ module top; ...@@ -4,6 +4,10 @@ module top;
f = 1'b1 ^ x; f = 1'b1 ^ x;
$display("f(%b) called", x); $display("f(%b) called", x);
endfunction endfunction
task t;
input x;
$display("t(%b) called", x);
endtask
initial begin initial begin
type(f(0)) x = f(0); type(f(0)) x = f(0);
...@@ -11,5 +15,8 @@ module top; ...@@ -11,5 +15,8 @@ module top;
$display("%b", $bits(x)); $display("%b", $bits(x));
$display("%b", $bits(type(x))); $display("%b", $bits(type(x)));
$display("%b", $bits(logic [0:1+$bits(type(x))])); $display("%b", $bits(logic [0:1+$bits(type(x))]));
f(1);
void'(f(0));
t(1);
end end
endmodule endmodule
...@@ -6,6 +6,10 @@ module top; ...@@ -6,6 +6,10 @@ module top;
$display("f(%b) called", x); $display("f(%b) called", x);
end end
endfunction endfunction
task t;
input x;
$display("t(%b) called", x);
endtask
initial begin : block initial begin : block
reg x; reg x;
...@@ -14,5 +18,8 @@ module top; ...@@ -14,5 +18,8 @@ module top;
$display("%b", 32'd1); $display("%b", 32'd1);
$display("%b", 32'd1); $display("%b", 32'd1);
$display("%b", 32'd3); $display("%b", 32'd3);
x = f(1);
x = f(0);
t(1);
end end
endmodule endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment