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 ...@@ -15,6 +15,7 @@ import qualified Convert.Assertion
import qualified Convert.Bits import qualified Convert.Bits
import qualified Convert.EmptyArgs import qualified Convert.EmptyArgs
import qualified Convert.Enum import qualified Convert.Enum
import qualified Convert.ForDecl
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.Interface import qualified Convert.Interface
import qualified Convert.IntTypes import qualified Convert.IntTypes
...@@ -43,6 +44,7 @@ phases excludes = ...@@ -43,6 +44,7 @@ phases excludes =
, Convert.Assertion.convert , Convert.Assertion.convert
, Convert.Bits.convert , Convert.Bits.convert
, selectExclude (Job.Logic , Convert.Logic.convert) , selectExclude (Job.Logic , Convert.Logic.convert)
, Convert.ForDecl.convert
, Convert.FuncRet.convert , Convert.FuncRet.convert
, Convert.EmptyArgs.convert , Convert.EmptyArgs.convert
, Convert.Enum.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 } ...@@ -691,6 +691,7 @@ StmtNonAsgn :: { Stmt }
| "begin" opt(Tag) DeclsAndStmts "end" opt(Tag) { Block (combineTags $2 $5) (fst $3) (snd $3) } | "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 "else" Stmt { If $1 $4 $6 $8 }
| Unique "if" "(" Expr ")" Stmt %prec NoElse { If $1 $4 $6 Null } | 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 } | "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 } | Unique CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $2 $4 $6 $7 }
| Identifier "(" CallArgs ")" ";" { Subroutine (Nothing) $1 $3 } | Identifier "(" CallArgs ")" ";" { Subroutine (Nothing) $1 $3 }
......
...@@ -59,6 +59,7 @@ executable sv2v ...@@ -59,6 +59,7 @@ executable sv2v
Convert.Bits Convert.Bits
Convert.EmptyArgs Convert.EmptyArgs
Convert.Enum Convert.Enum
Convert.ForDecl
Convert.FuncRet Convert.FuncRet
Convert.Interface Convert.Interface
Convert.IntTypes 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