mirror of https://github.com/zachjs/sv2v.git
support and conversion for foreach
This commit is contained in:
parent
7f701cd112
commit
77b9d2f085
|
|
@ -17,6 +17,7 @@ import qualified Convert.DimensionQuery
|
|||
import qualified Convert.EmptyArgs
|
||||
import qualified Convert.Enum
|
||||
import qualified Convert.ForDecl
|
||||
import qualified Convert.Foreach
|
||||
import qualified Convert.FuncRet
|
||||
import qualified Convert.Interface
|
||||
import qualified Convert.IntTypes
|
||||
|
|
@ -69,6 +70,7 @@ phases excludes =
|
|||
, Convert.Enum.convert
|
||||
, Convert.NestPI.convert
|
||||
, Convert.Return.convert
|
||||
, Convert.Foreach.convert
|
||||
, selectExclude (Job.Interface, Convert.Interface.convert)
|
||||
, selectExclude (Job.Always , Convert.AlwaysKW.convert)
|
||||
, selectExclude (Job.Succinct , Convert.RemoveComments.convert)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion for `foreach` loops.
|
||||
-
|
||||
- We simply convert these loops to a series of loops, with the bounds and
|
||||
- direction provided by the array dimension query system functions. Omitted
|
||||
- indices are skipped.
|
||||
-}
|
||||
|
||||
module Convert.Foreach (convert) where
|
||||
|
||||
import Convert.Traverse
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
convert :: [AST] -> [AST]
|
||||
convert =
|
||||
map $ traverseDescriptions $ traverseModuleItems $
|
||||
traverseStmts convertStmt
|
||||
|
||||
convertStmt :: Stmt -> Stmt
|
||||
convertStmt (Foreach x idxs stmt) =
|
||||
(foldl (.) id $ map toLoop $ zip [1..] idxs) stmt
|
||||
where
|
||||
toLoop :: (Int, Maybe Identifier) -> (Stmt -> Stmt)
|
||||
toLoop (_, Nothing) = id
|
||||
toLoop (d, Just i) =
|
||||
For [Left idxDecl] (Just cmp) [incr]
|
||||
where
|
||||
queryFn f = DimFn f (Right $ Ident x) (Number $ show d)
|
||||
idxDecl = Variable Local (IntegerAtom TInteger Unspecified) i []
|
||||
$ Just $ queryFn FnLeft
|
||||
cmp =
|
||||
Mux (BinOp Eq (queryFn FnIncrement) (Number "1"))
|
||||
(BinOp Ge (Ident i) (queryFn FnRight))
|
||||
(BinOp Le (Ident i) (queryFn FnRight))
|
||||
incr = (LHSIdent i, AsgnOp Sub, queryFn FnIncrement)
|
||||
convertStmt other = other
|
||||
|
|
@ -235,6 +235,7 @@ traverseSinglyNestedStmtsM fullMapper = cs
|
|||
cs (RepeatL e stmt) = fullMapper stmt >>= return . RepeatL e
|
||||
cs (DoWhile e stmt) = fullMapper stmt >>= return . DoWhile e
|
||||
cs (Forever stmt) = fullMapper stmt >>= return . Forever
|
||||
cs (Foreach x vars stmt) = fullMapper stmt >>= return . Foreach x vars
|
||||
cs (If u e s1 s2) = do
|
||||
s1' <- fullMapper s1
|
||||
s2' <- fullMapper s2
|
||||
|
|
@ -682,6 +683,7 @@ traverseStmtExprsM exprMapper = flatStmtMapper
|
|||
flatStmtMapper (DoWhile e stmt) =
|
||||
exprMapper e >>= \e' -> return $ DoWhile e' stmt
|
||||
flatStmtMapper (Forever stmt) = return $ Forever stmt
|
||||
flatStmtMapper (Foreach x vars stmt) = return $ Foreach x vars stmt
|
||||
flatStmtMapper (If u cc s1 s2) =
|
||||
exprMapper cc >>= \cc' -> return $ If u cc' s1 s2
|
||||
flatStmtMapper (Timing event stmt) = return $ Timing event stmt
|
||||
|
|
|
|||
|
|
@ -162,6 +162,8 @@ readNumber n =
|
|||
-- basic expression simplfication utility to help us generate nicer code in the
|
||||
-- common case of ranges like `[FOO-1:0]`
|
||||
simplify :: Expr -> Expr
|
||||
simplify (UniOp LogNot (Number "1")) = Number "0"
|
||||
simplify (UniOp LogNot (Number "0")) = Number "1"
|
||||
simplify (Repeat (Number "0") _) = Concat []
|
||||
simplify (Concat [expr]) = expr
|
||||
simplify (Concat exprs) =
|
||||
|
|
@ -170,23 +172,17 @@ simplify (orig @ (Call Nothing "$clog2" (Args [Just (Number n)] []))) =
|
|||
case readNumber n of
|
||||
Nothing -> orig
|
||||
Just x -> Number $ show $ clog2 x
|
||||
simplify (Mux (Number "0") e _) = e
|
||||
simplify (Mux (BinOp Ge c1 c2) e1 e2) =
|
||||
case (c1', c2') of
|
||||
(Number a, Number b) ->
|
||||
case (readNumber a, readNumber b) of
|
||||
(Just x, Just y) ->
|
||||
if x >= y
|
||||
then e1
|
||||
else e2
|
||||
_ -> nochange
|
||||
_ -> nochange
|
||||
simplify (Mux cc e1 e2) =
|
||||
case cc' of
|
||||
Number "1" -> e1'
|
||||
Number "0" -> e2'
|
||||
_ -> Mux cc' e1' e2'
|
||||
where
|
||||
c1' = simplify c1
|
||||
c2' = simplify c2
|
||||
cc' = simplify cc
|
||||
e1' = simplify e1
|
||||
e2' = simplify e2
|
||||
nochange = Mux (BinOp Ge c1' c2') e1' e2'
|
||||
simplify (Range e NonIndexed r) = Range e NonIndexed r
|
||||
simplify (Range e _ (i, Number "0")) = Bit e i
|
||||
simplify (BinOp Sub (Number n1) (BinOp Sub (Number n2) e)) =
|
||||
simplify $ BinOp Add (BinOp Sub (Number n1) (Number n2)) e
|
||||
simplify (BinOp Sub (Number n1) (BinOp Sub e (Number n2))) =
|
||||
|
|
@ -211,21 +207,30 @@ simplify (BinOp op e1 e2) =
|
|||
(Add, BinOp Sub e (Number "1"), Number "1") -> e
|
||||
(Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1")
|
||||
(_ , Number a, Number b) ->
|
||||
case (op, readNumber a, readNumber b) of
|
||||
case (op, readNumber a :: Maybe Int, readNumber b :: Maybe Int) of
|
||||
(Add, Just x, Just y) -> Number $ show (x + y)
|
||||
(Sub, Just x, Just y) -> Number $ show (x - y)
|
||||
(Mul, Just x, Just y) -> Number $ show (x * y)
|
||||
(Div, Just _, Just 0) -> Number "x"
|
||||
(Div, Just x, Just y) -> Number $ show (x `quot` y)
|
||||
(Eq , Just x, Just y) -> bool $ x == y
|
||||
(Ne , Just x, Just y) -> bool $ x /= y
|
||||
(Gt , Just x, Just y) -> bool $ x > y
|
||||
(Ge , Just x, Just y) -> bool $ x >= y
|
||||
(Lt , Just x, Just y) -> bool $ x < y
|
||||
(Le , Just x, Just y) -> bool $ x <= y
|
||||
_ -> BinOp op e1' e2'
|
||||
(Add, BinOp Add e (Number a), Number b) ->
|
||||
case (readNumber a, readNumber b) of
|
||||
(Just x, Just y) -> BinOp Add e $ Number $ show (x + y)
|
||||
_ -> BinOp op e1' e2'
|
||||
(Sub, e, Number "-1") -> BinOp Add e (Number "1")
|
||||
_ -> BinOp op e1' e2'
|
||||
where
|
||||
e1' = simplify e1
|
||||
e2' = simplify e2
|
||||
bool True = Number "1"
|
||||
bool False = Number "0"
|
||||
simplify other = other
|
||||
|
||||
rangeSize :: Range -> Expr
|
||||
|
|
@ -258,7 +263,10 @@ sizedExpr x s (Number n) =
|
|||
++ " doesn't have size " ++ show size
|
||||
else Number res
|
||||
where
|
||||
Number size = simplify s
|
||||
size =
|
||||
case simplify s of
|
||||
Number v -> v
|
||||
other -> error $ "could not simplify sizedExpr: " ++ show other
|
||||
unticked = case n of
|
||||
'\'' : rest -> rest
|
||||
rest -> rest
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ data Stmt
|
|||
| RepeatL Expr Stmt
|
||||
| DoWhile Expr Stmt
|
||||
| Forever Stmt
|
||||
| Foreach Identifier [Maybe Identifier] Stmt
|
||||
| If (Maybe UniquePriority) Expr Stmt Stmt
|
||||
| Timing Timing Stmt
|
||||
| Return Expr
|
||||
|
|
@ -86,6 +87,7 @@ instance Show Stmt where
|
|||
show (RepeatL e s) = printf "repeat (%s) %s" (show e) (show s)
|
||||
show (DoWhile e s) = printf "do %s while (%s);" (show s) (show e)
|
||||
show (Forever s ) = printf "forever %s" (show s)
|
||||
show (Foreach x i s) = printf "foreach (%s [ %s ]) %s" x (commas $ map (maybe "" id) i) (show s)
|
||||
show (If u a b Null) = printf "%sif (%s) %s" (maybe "" showPad u) (show a) (show b)
|
||||
show (If u a b c ) = printf "%sif (%s) %s\nelse %s" (maybe "" showPad u) (show a) (show b) (show c)
|
||||
show (Return e ) = printf "return %s;" (show e)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,10 @@ nullRange :: Type -> ([Range] -> Type)
|
|||
nullRange t [] = t
|
||||
nullRange t [(Number "0", Number "0")] = t
|
||||
nullRange (IntegerAtom TInteger sg) rs =
|
||||
-- integer arrays are allowed in SystemVerilog but not in Verilor
|
||||
-- integer arrays are allowed in SystemVerilog but not in Verilog
|
||||
IntegerVector TBit sg (rs ++ [(Number "31", Number "0")])
|
||||
nullRange (IntegerAtom TInt sg) rs =
|
||||
-- int arrays are allowed in SystemVerilog but not in Verilog
|
||||
IntegerVector TBit sg (rs ++ [(Number "31", Number "0")])
|
||||
nullRange t rs =
|
||||
error $ "non-vector type " ++ show t ++
|
||||
|
|
|
|||
|
|
@ -884,6 +884,7 @@ StmtNonAsgn :: { Stmt }
|
|||
| "repeat" "(" Expr ")" Stmt { RepeatL $3 $5 }
|
||||
| "do" Stmt "while" "(" Expr ")" ";" { DoWhile $5 $2 }
|
||||
| "forever" Stmt { Forever $2 }
|
||||
| "foreach" "(" Identifier IdxVars ")" Stmt { Foreach $3 $4 $6 }
|
||||
| "->" Identifier ";" { Trigger $2 }
|
||||
| AttributeInstance Stmt { StmtAttr $1 $2 }
|
||||
| ProceduralAssertionStatement { Assertion $1 }
|
||||
|
|
@ -905,6 +906,12 @@ ForStepAssignment :: { (LHS, AsgnOp, Expr) }
|
|||
| IncOrDecOperator LHS { ($2, AsgnOp $1, Number "1") }
|
||||
| LHS IncOrDecOperator { ($1, AsgnOp $2, Number "1") }
|
||||
|
||||
IdxVars :: { [Maybe Identifier] }
|
||||
: "[" IdxVarsInside "]" { $2 }
|
||||
IdxVarsInside :: { [Maybe Identifier] }
|
||||
: opt(Identifier) { [$1] }
|
||||
| opt(Identifier) "," IdxVarsInside { $1 : $3 }
|
||||
|
||||
DeclsAndStmts :: { ([Decl], [Stmt]) }
|
||||
: DeclOrStmt DeclsAndStmts { combineDeclsAndStmts $1 $2 }
|
||||
| StmtNonAsgn Stmts { ([], $1 : $2) }
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ executable sv2v
|
|||
Convert.EmptyArgs
|
||||
Convert.Enum
|
||||
Convert.ForDecl
|
||||
Convert.Foreach
|
||||
Convert.FuncRet
|
||||
Convert.Interface
|
||||
Convert.IntTypes
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
module top;
|
||||
logic [1:0] foo [4] = {2'b10,2'b01,2'b11,2'b00};
|
||||
initial
|
||||
foreach (foo [ x ])
|
||||
$display(x, foo[x]);
|
||||
|
||||
// from the SystemVerilog-2017 specification
|
||||
int A [2][3][4];
|
||||
bit [3:0][2:1] B [5:1][4];
|
||||
initial begin
|
||||
A = 0;
|
||||
B = 0;
|
||||
foreach( A [ i, j, k ] )
|
||||
$display(i, j, k);
|
||||
foreach( B [ q, r, , s ] )
|
||||
$display(q, r, s);
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
module top;
|
||||
wire [7:0] foo = {2'b10,2'b01,2'b11,2'b00};
|
||||
initial begin : f
|
||||
integer x;
|
||||
for (x = 0; x <= 3; x = x + 1)
|
||||
$display(x, foo[6 - 2*x+:2]);
|
||||
end
|
||||
|
||||
reg [32*2*3*4 - 1:0] A;
|
||||
reg [5*4*4*2 + 32: 1 + 32] B;
|
||||
initial begin
|
||||
A = 0;
|
||||
B = 0;
|
||||
begin : g
|
||||
integer i, j, k;
|
||||
for (i = 0; i <= 1; i = i + 1)
|
||||
for (j = 0; j <= 2; j = j + 1)
|
||||
for (k = 0; k <= 3; k = k + 1)
|
||||
$display(i, j, k);
|
||||
end
|
||||
begin : h
|
||||
integer q, r, s;
|
||||
for (q = 5; q >= 1; q = q - 1)
|
||||
for (r = 0; r <= 3; r = r + 1)
|
||||
for (s = 2; s >= 1; s = s - 1)
|
||||
$display(q, r, s);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -113,8 +113,8 @@ simulateAndCompare() {
|
|||
# simulate and compare the two files
|
||||
simulate "$ref_vcd" "$ref_log" top "$ve" "$tb"
|
||||
simulate "$gen_vcd" "$gen_log" top "$cv" "$tb"
|
||||
diff "$ref_vcd" "$gen_vcd" > /dev/null
|
||||
assertTrue "VCDs are different" $?
|
||||
output=`diff "$ref_vcd" "$gen_vcd"`
|
||||
assertTrue "VCDs are different:\n$output" $?
|
||||
output=`diff "$ref_log" "$gen_log"`
|
||||
assertTrue "Simulation outputs differ:\n$output" $?
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue