Commit 243f7736 by Zachary Snow

convert for loop declarations and assignments to signle assignment (closes #15)

parent 1472ea0c
......@@ -15,6 +15,7 @@ import qualified Convert.Assertion
import qualified Convert.Bits
import qualified Convert.EmptyArgs
import qualified Convert.Enum
import qualified Convert.ForDecl
import qualified Convert.FuncRet
import qualified Convert.Interface
import qualified Convert.IntTypes
......@@ -43,6 +44,7 @@ phases excludes =
, Convert.Assertion.convert
, Convert.Bits.convert
, selectExclude (Job.Logic , Convert.Logic.convert)
, Convert.ForDecl.convert
, Convert.FuncRet.convert
, Convert.EmptyArgs.convert
, Convert.Enum.convert
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Verilog-2005 requires that for loops have have exactly one assignment in the
- initialization section. For generate for loops, we move any genvar
- declarations to a wrapping generate block. For procedural for loops, we pull
- the declarations out to a wrapping block, and convert all but one assignment
- to a preceding statement. If a for loop has no assignments or declarations, a
- dummy declaration is generated.
-}
module Convert.ForDecl (convert) where
import Data.Either (isLeft, isRight, lefts, rights)
import Convert.Traverse
import Language.SystemVerilog.AST
convert :: [AST] -> [AST]
convert =
map $ traverseDescriptions $ traverseModuleItems $
( traverseStmts convertStmt
. traverseGenItems convertGenItem
)
convertGenItem :: GenItem -> GenItem
convertGenItem (GenFor (True, x, e) a b c d) =
GenBlock Nothing
[ GenModuleItem $ Genvar x
, GenFor (False, x, e) a b c d
]
convertGenItem other = other
convertStmt :: Stmt -> Stmt
convertStmt (For [] cc asgns stmt) =
convertStmt $ For inits cc asgns stmt
where inits = [Left $ dummyDecl (Just $ Number "0")]
convertStmt (orig @ (For [Right _] _ _ _)) = orig
convertStmt (orig @ (For (inits @ (Left _: _)) cc asgns stmt)) =
if not $ all isLeft inits
then error $ "for loop has mix of decls and asgns: " ++ show orig
else Block
Nothing
decls
(initAsgns ++ [For [Right (lhs, expr)] cc asgns stmt])
where
splitDecls = map splitDecl $ lefts inits
decls = map fst splitDecls
initAsgns = map asgnStmt $ init $ map snd splitDecls
(lhs, expr) = snd $ last splitDecls
convertStmt (orig @ (For inits cc asgns stmt)) =
if not $ all isRight inits
then error $ "for loop has mix of decls and asgns: " ++ show orig
else Block
Nothing
[]
(initAsgns ++ [For [Right (lhs, expr)] cc asgns stmt])
where
origPairs = rights inits
(lhs, expr) = last origPairs
initAsgns = map asgnStmt $ init origPairs
convertStmt other = other
splitDecl :: Decl -> (Decl, (LHS, Expr))
splitDecl (Variable d t ident a (Just e)) =
(Variable d t ident a Nothing, (LHSIdent ident, e))
splitDecl other =
error $ "invalid for loop decl: " ++ show other
asgnStmt :: (LHS, Expr) -> Stmt
asgnStmt = uncurry $ AsgnBlk AsgnOpEq
dummyDecl :: Maybe Expr -> Decl
dummyDecl = Variable Local (IntegerAtom TInteger Unspecified) "_sv2v_dummy" []
......@@ -691,6 +691,7 @@ StmtNonAsgn :: { Stmt }
| "begin" opt(Tag) DeclsAndStmts "end" opt(Tag) { Block (combineTags $2 $5) (fst $3) (snd $3) }
| Unique "if" "(" Expr ")" Stmt "else" Stmt { If $1 $4 $6 $8 }
| Unique "if" "(" Expr ")" Stmt %prec NoElse { If $1 $4 $6 Null }
| "for" "(" ";" opt(Expr) ";" ForStep ")" Stmt { For [] $4 $6 $8 }
| "for" "(" DeclTokens(";") opt(Expr) ";" ForStep ")" Stmt { For (parseDTsAsDeclsAndAsgns $3) $4 $6 $8 }
| Unique CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $2 $4 $6 $7 }
| Identifier "(" CallArgs ")" ";" { Subroutine (Nothing) $1 $3 }
......
......@@ -59,6 +59,7 @@ executable sv2v
Convert.Bits
Convert.EmptyArgs
Convert.Enum
Convert.ForDecl
Convert.FuncRet
Convert.Interface
Convert.IntTypes
......
module top;
wire [0:31] a;
for (genvar n = 0; n < 32; n++) begin : gen_filter
assign a[n] = n & 1;
end
initial
for (integer i = 0; i < 32; i++)
$display("1: ", a[i]);
integer i = 0;
initial
for (; i < 32; i++)
$display("2: ", ~a[i]);
initial begin
for (integer i = 0, j = 42; i < 32; i++)
$display("3: ", ~a[i] + 5, " j=", j);
end
initial begin
integer i, j;
for (i = 0, j = 97; i < 32; i++)
$display("4: ", ~a[i] + 10, " j=", j);
end
integer j = 0, k;
initial begin
for (; j < 4; j++) begin
k = 0;
for (; k < 8; k++)
$display("5: ", ~a[j * 8 + k] + 11);
end
end
endmodule
module top;
wire [0:31] a;
generate
genvar n;
for (n = 0; n < 32; n = n + 1) begin : gen_filter
assign a[n] = n & 1;
end
endgenerate
integer i;
initial begin : foo_1
for (i = 0; i < 32; i = i + 1)
$display("1: ", a[i]);
end
initial begin : foo_2
integer i;
for (i = 0; i < 32; i = i + 1)
$display("2: ", ~a[i]);
end
initial begin : foo_3
integer i;
integer j;
j = 42;
for (i = 0; i < 32; i = i + 1)
$display("3: ", ~a[i] + 5, " j=", j);
end
initial begin : foo_4
integer i, j;
j = 97;
for (i = 0; i < 32; i = i + 1)
$display("4: ", ~a[i] + 10, " j=", j);
end
integer j, k;
initial begin
for (j = 0; j < 4; j++)
for (k = 0; k < 8; k++)
$display("5: ", ~a[j * 8 + k] + 11);
end
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