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

This commit is contained in:
Zachary Snow 2019-08-30 00:11:57 -04:00
parent 1472ea0cfe
commit 243f773657
6 changed files with 163 additions and 0 deletions

View File

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

77
src/Convert/ForDecl.hs Normal file
View File

@ -0,0 +1,77 @@
{- 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" []

View File

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

View File

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

37
test/basic/for_decl.sv Normal file
View File

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

45
test/basic/for_decl.v Normal file
View File

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