Commit 2e499dbd by Zachary Snow

support case inside with basic side effects

parent e471d37e
...@@ -19,6 +19,7 @@ module Convert.Inside (convert) where ...@@ -19,6 +19,7 @@ module Convert.Inside (convert) where
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
import Control.Monad.Writer
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
...@@ -54,12 +55,19 @@ convertStmt (Case u kw expr items) = ...@@ -54,12 +55,19 @@ convertStmt (Case u kw expr items) =
Case u kw expr items Case u kw expr items
else if kw /= CaseN then else if kw /= CaseN then
error $ "cannot use inside with " ++ show kw error $ "cannot use inside with " ++ show kw
else if hasSideEffects expr then
Block Seq "" [decl] [stmt]
else else
foldr ($) defaultStmt $ foldr ($) defaultStmt $
map (uncurry $ If NoCheck) $ map (uncurry $ If NoCheck) $
zip comps stmts zip comps stmts
where where
exprs = map fst items exprs = map fst items
-- evaluate expressions with side effects once
tmp = "sv2v_temp_" ++ shortHash expr
decl = Variable Local (TypeOf expr) tmp [] expr
stmt = convertStmt (Case u kw (Ident tmp) items)
-- underlying inside case elaboration
itemsNonDefault = filter (not . null . fst) items itemsNonDefault = filter (not . null . fst) items
isSpecialInside :: [Expr] -> Bool isSpecialInside :: [Expr] -> Bool
isSpecialInside [Inside Nil _] = True isSpecialInside [Inside Nil _] = True
...@@ -71,3 +79,11 @@ convertStmt (Case u kw expr items) = ...@@ -71,3 +79,11 @@ convertStmt (Case u kw expr items) =
stmts = map snd itemsNonDefault stmts = map snd itemsNonDefault
defaultStmt = fromMaybe Null (lookup [] items) defaultStmt = fromMaybe Null (lookup [] items)
convertStmt other = other convertStmt other = other
hasSideEffects :: Expr -> Bool
hasSideEffects expr =
getAny $ execWriter $ collectNestedExprsM write expr
where
write :: Expr -> Writer Any ()
write Call{} = tell $ Any True
write _ = return ()
module top; module top;
function integer sideEffect;
input integer inp;
$display("sideEffect(%b)", inp);
sideEffect = inp;
endfunction
initial initial
for (logic [1:0] a = 0; a < 3; a++) begin for (logic [1:0] a = 0; a < 3; a++) begin
if (a inside {2'b01, 2'b00}) if (a inside {2'b01, 2'b00})
...@@ -13,6 +19,9 @@ module top; ...@@ -13,6 +19,9 @@ module top;
initial $display("C", 3'bz11 inside {3'b011}); initial $display("C", 3'bz11 inside {3'b011});
initial $display("D", 3'bz11 inside {3'b1?1, 3'b011}); initial $display("D", 3'bz11 inside {3'b1?1, 3'b011});
initial $display("E", 3'bz11 inside {3'b?01, 3'b011}); initial $display("E", 3'bz11 inside {3'b?01, 3'b011});
// TODO: Add support for inside expressions with side effects.
// initial $display("F", sideEffect(3'bz11) inside {3'b?11});
// initial $display("G", 3'bz11 inside {sideEffect(3'b?11)});
generate generate
begin : patterns begin : patterns
...@@ -53,7 +62,7 @@ module top; ...@@ -53,7 +62,7 @@ module top;
function integer test3; function integer test3;
input integer inp; input integer inp;
case (inp) inside case (1 + sideEffect(inp)) inside
[16:23]: return 1; [16:23]: return 1;
[32:47]: return 2; [32:47]: return 2;
default: return 0; default: return 0;
......
module top; module top;
function integer sideEffect;
input integer inp;
begin
$display("sideEffect(%b)", inp);
sideEffect = inp;
end
endfunction
initial begin : foo initial begin : foo
reg [1:0] a; reg [1:0] a;
for (a = 0; a < 3; a++) begin for (a = 0; a < 3; a++) begin
...@@ -15,6 +23,14 @@ module top; ...@@ -15,6 +23,14 @@ module top;
initial $display("C", 1'bx); initial $display("C", 1'bx);
initial $display("D", 1'bx); initial $display("D", 1'bx);
initial $display("E", 1'bx); initial $display("E", 1'bx);
// TODO: Add support for inside expressions with side effects.
// initial begin : bar
// integer tmp;
// tmp = sideEffect(3'bz11);
// $display("F", 1'b1);
// tmp = sideEffect(3'b?11);
// $display("G", 1'b1);
// end
function test1; function test1;
input [2:0] inp; input [2:0] inp;
...@@ -54,6 +70,7 @@ module top; ...@@ -54,6 +70,7 @@ module top;
function [0:31] test3; function [0:31] test3;
input integer inp; input integer inp;
begin begin
inp = 1 + sideEffect(inp);
if (16 <= inp && inp <= 23) test3 = 1; if (16 <= inp && inp <= 23) test3 = 1;
else if (32 <= inp && inp <= 47) test3 = 2; else if (32 <= inp && inp <= 47) test3 = 2;
else if (inp == 0 || (60 <= inp && inp <= 61) || inp == 4) test3 = 3; else if (inp == 0 || (60 <= inp && inp <= 61) || inp == 4) test3 = 3;
......
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