Commit b7a23276 by Zachary Snow

simple for loop elaboration applies in more cases

parent 5e17ef0d
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* Added conversion for `do` `while` loops * Added conversion for `do` `while` loops
* Added support for passing through DPI imports and exports * Added support for passing through DPI imports and exports
* Added support for passing through functions with output ports * Added support for passing through functions with output ports
* Extended applicability of simplified Yosys-compatible `for` loop elaboration
### Other Enhancements ### Other Enhancements
......
...@@ -121,12 +121,25 @@ convertStmts stmts = do ...@@ -121,12 +121,25 @@ convertStmts stmts = do
pattern SimpleLoopInits :: Identifier -> [(LHS, Expr)] pattern SimpleLoopInits :: Identifier -> [(LHS, Expr)]
pattern SimpleLoopInits var <- [(LHSIdent var, _)] pattern SimpleLoopInits var <- [(LHSIdent var, _)]
pattern SimpleLoopGuard :: Identifier -> Expr
pattern SimpleLoopGuard var <- BinOp _ (Ident var) _
pattern SimpleLoopIncrs :: Identifier -> [(LHS, AsgnOp, Expr)] pattern SimpleLoopIncrs :: Identifier -> [(LHS, AsgnOp, Expr)]
pattern SimpleLoopIncrs var <- [(LHSIdent var, _, _)] pattern SimpleLoopIncrs var <- [(LHSIdent var, _, _)]
-- check if an expression contains a reference to the given identifier
usesIdent :: Identifier -> Expr -> Writer Any ()
usesIdent x (Ident y)
| x == y = tell $ Any True
| otherwise = return ()
usesIdent x expr =
collectSinglyNestedExprsM (usesIdent x) expr
-- identifies loops which could likely be statically unrolled, and so may
-- benefit from avoiding complicating the loop guard with jump state, assuming
-- the guard and incrementation do not have side effects
simpleLoopVar :: [(LHS, Expr)] -> Expr -> [(LHS, AsgnOp, Expr)] -> Identifier
simpleLoopVar (SimpleLoopInits var1) comp (SimpleLoopIncrs var3)
| var1 == var3, getAny $ execWriter $ usesIdent var1 comp = var1
simpleLoopVar _ _ _ = ""
-- rewrites the given statement, and returns the type of any unfinished jump -- rewrites the given statement, and returns the type of any unfinished jump
convertStmt :: Stmt -> State Info Stmt convertStmt :: Stmt -> State Info Stmt
...@@ -140,20 +153,12 @@ convertStmt (Block Par x decls stmts) = do ...@@ -140,20 +153,12 @@ convertStmt (Block Par x decls stmts) = do
convertStmt (Block Seq "" convertStmt (Block Seq ""
decls@[CommentDecl{}, Variable Local _ var0 [] Nil] decls@[CommentDecl{}, Variable Local _ var0 [] Nil]
[ comment@CommentStmt{} [comment@CommentStmt{}, For inits comp incr stmt])
, For | var1@(_ : _) <- simpleLoopVar inits comp incr, var0 == var1 =
inits@(SimpleLoopInits var1) convertLoop (Just var1) loop comp incr stmt
comp@(SimpleLoopGuard var2)
incr@(SimpleLoopIncrs var3)
stmt
]) =
convertLoop localInfo loop comp incr stmt
>>= return . Block Seq "" decls . (comment :) . pure >>= return . Block Seq "" decls . (comment :) . pure
where where
loop c i s = For inits c i s loop c i s = For inits c i s
localInfo = if var0 /= var1 || var1 /= var2 || var2 /= var3
then Nothing
else Just ""
convertStmt (Block Seq x decls stmts) = convertStmt (Block Seq x decls stmts) =
step stmts >>= return . Block Seq x decls step stmts >>= return . Block Seq x decls
...@@ -192,16 +197,11 @@ convertStmt (Case unique kw expr cases) = do ...@@ -192,16 +197,11 @@ convertStmt (Case unique kw expr cases) = do
modify $ \s -> s { sHasJump = hasJump } modify $ \s -> s { sHasJump = hasJump }
return $ Case unique kw expr cases' return $ Case unique kw expr cases'
convertStmt (For convertStmt (For inits comp incr stmt)
inits@(SimpleLoopInits var1) | var@(_ : _) <- simpleLoopVar inits comp incr =
comp@(SimpleLoopGuard var2) convertLoop (Just var) loop comp incr stmt
incr@(SimpleLoopIncrs var3) stmt) =
convertLoop localInfo loop comp incr stmt
where where
loop c i s = For inits c i s loop c i s = For inits c i s
localInfo = if var1 /= var2 || var2 /= var3
then Nothing
else Just var1
convertStmt (For inits comp incr stmt) = convertStmt (For inits comp incr stmt) =
convertLoop Nothing loop comp incr stmt convertLoop Nothing loop comp incr stmt
where loop c i s = For inits c i s where loop c i s = For inits c i s
......
...@@ -44,6 +44,15 @@ module top; ...@@ -44,6 +44,15 @@ module top;
return k * 3; return k * 3;
k = k * 2 + 1; k = k * 2 + 1;
endfunction endfunction
function automatic integer l;
input integer inp;
l = 1;
for (integer idx = inp; 0 < idx; idx--) begin
if (l == 32)
break;
l = l * 2;
end
endfunction
integer i; integer i;
initial initial
for (i = 0; i < 10; i = i + 1) begin for (i = 0; i < 10; i = i + 1) begin
...@@ -52,5 +61,6 @@ module top; ...@@ -52,5 +61,6 @@ module top;
$display("h(%0d) = %0d", i, h(i)); $display("h(%0d) = %0d", i, h(i));
$display("j(%0d) = %0d", i, j(i)); $display("j(%0d) = %0d", i, j(i));
$display("k(%0d) = %0d", i, k(i)); $display("k(%0d) = %0d", i, k(i));
$display("l(%0d) = %0d", i, l(i));
end end
endmodule endmodule
...@@ -34,6 +34,13 @@ module top; ...@@ -34,6 +34,13 @@ module top;
else else
k = inp * 2 + 1; k = inp * 2 + 1;
endfunction endfunction
function automatic integer l;
input integer inp;
if (inp > 5)
l = 32;
else
l = 2 ** inp;
endfunction
integer i; integer i;
initial initial
for (i = 0; i < 10; i = i + 1) begin for (i = 0; i < 10; i = i + 1) begin
...@@ -42,5 +49,6 @@ module top; ...@@ -42,5 +49,6 @@ module top;
$display("h(%0d) = %0d", i, h(i)); $display("h(%0d) = %0d", i, h(i));
$display("j(%0d) = %0d", i, j(i)); $display("j(%0d) = %0d", i, j(i));
$display("k(%0d) = %0d", i, k(i)); $display("k(%0d) = %0d", i, k(i));
$display("l(%0d) = %0d", i, l(i));
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