support evaluating functions as statements

This commit is contained in:
Zachary Snow 2020-01-11 21:06:09 -05:00
parent 2bd24b6086
commit 22d6ba4927
6 changed files with 63 additions and 0 deletions

View File

@ -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 =
, 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

View File

@ -0,0 +1,45 @@
{- 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

View File

@ -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 }

View File

@ -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

View File

@ -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;
$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

View File

@ -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;
$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