Commit 77b9d2f0 by Zachary Snow

support and conversion for foreach

parent 7f701cd1
......@@ -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)
......
{- 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
......
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
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" $?
}
......
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