Commit 77b9d2f0 by Zachary Snow

support and conversion for foreach

parent 7f701cd1
...@@ -17,6 +17,7 @@ import qualified Convert.DimensionQuery ...@@ -17,6 +17,7 @@ import qualified Convert.DimensionQuery
import qualified Convert.EmptyArgs import qualified Convert.EmptyArgs
import qualified Convert.Enum import qualified Convert.Enum
import qualified Convert.ForDecl import qualified Convert.ForDecl
import qualified Convert.Foreach
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.Interface import qualified Convert.Interface
import qualified Convert.IntTypes import qualified Convert.IntTypes
...@@ -69,6 +70,7 @@ phases excludes = ...@@ -69,6 +70,7 @@ phases excludes =
, Convert.Enum.convert , Convert.Enum.convert
, Convert.NestPI.convert , Convert.NestPI.convert
, Convert.Return.convert , Convert.Return.convert
, Convert.Foreach.convert
, selectExclude (Job.Interface, Convert.Interface.convert) , selectExclude (Job.Interface, Convert.Interface.convert)
, selectExclude (Job.Always , Convert.AlwaysKW.convert) , selectExclude (Job.Always , Convert.AlwaysKW.convert)
, selectExclude (Job.Succinct , Convert.RemoveComments.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 ...@@ -235,6 +235,7 @@ traverseSinglyNestedStmtsM fullMapper = cs
cs (RepeatL e stmt) = fullMapper stmt >>= return . RepeatL e cs (RepeatL e stmt) = fullMapper stmt >>= return . RepeatL e
cs (DoWhile e stmt) = fullMapper stmt >>= return . DoWhile e cs (DoWhile e stmt) = fullMapper stmt >>= return . DoWhile e
cs (Forever stmt) = fullMapper stmt >>= return . Forever 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 cs (If u e s1 s2) = do
s1' <- fullMapper s1 s1' <- fullMapper s1
s2' <- fullMapper s2 s2' <- fullMapper s2
...@@ -682,6 +683,7 @@ traverseStmtExprsM exprMapper = flatStmtMapper ...@@ -682,6 +683,7 @@ traverseStmtExprsM exprMapper = flatStmtMapper
flatStmtMapper (DoWhile e stmt) = flatStmtMapper (DoWhile e stmt) =
exprMapper e >>= \e' -> return $ DoWhile e' stmt exprMapper e >>= \e' -> return $ DoWhile e' stmt
flatStmtMapper (Forever stmt) = return $ Forever stmt flatStmtMapper (Forever stmt) = return $ Forever stmt
flatStmtMapper (Foreach x vars stmt) = return $ Foreach x vars stmt
flatStmtMapper (If u cc s1 s2) = flatStmtMapper (If u cc s1 s2) =
exprMapper cc >>= \cc' -> return $ If u cc' s1 s2 exprMapper cc >>= \cc' -> return $ If u cc' s1 s2
flatStmtMapper (Timing event stmt) = return $ Timing event stmt flatStmtMapper (Timing event stmt) = return $ Timing event stmt
......
...@@ -162,6 +162,8 @@ readNumber n = ...@@ -162,6 +162,8 @@ readNumber n =
-- basic expression simplfication utility to help us generate nicer code in the -- basic expression simplfication utility to help us generate nicer code in the
-- common case of ranges like `[FOO-1:0]` -- common case of ranges like `[FOO-1:0]`
simplify :: Expr -> Expr simplify :: Expr -> Expr
simplify (UniOp LogNot (Number "1")) = Number "0"
simplify (UniOp LogNot (Number "0")) = Number "1"
simplify (Repeat (Number "0") _) = Concat [] simplify (Repeat (Number "0") _) = Concat []
simplify (Concat [expr]) = expr simplify (Concat [expr]) = expr
simplify (Concat exprs) = simplify (Concat exprs) =
...@@ -170,23 +172,17 @@ simplify (orig @ (Call Nothing "$clog2" (Args [Just (Number n)] []))) = ...@@ -170,23 +172,17 @@ simplify (orig @ (Call Nothing "$clog2" (Args [Just (Number n)] []))) =
case readNumber n of case readNumber n of
Nothing -> orig Nothing -> orig
Just x -> Number $ show $ clog2 x Just x -> Number $ show $ clog2 x
simplify (Mux (Number "0") e _) = e simplify (Mux cc e1 e2) =
simplify (Mux (BinOp Ge c1 c2) e1 e2) = case cc' of
case (c1', c2') of Number "1" -> e1'
(Number a, Number b) -> Number "0" -> e2'
case (readNumber a, readNumber b) of _ -> Mux cc' e1' e2'
(Just x, Just y) ->
if x >= y
then e1
else e2
_ -> nochange
_ -> nochange
where where
c1' = simplify c1 cc' = simplify cc
c2' = simplify c2
e1' = simplify e1 e1' = simplify e1
e2' = simplify e2 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 Sub (Number n1) (BinOp Sub (Number n2) e)) =
simplify $ BinOp Add (BinOp Sub (Number n1) (Number n2)) e simplify $ BinOp Add (BinOp Sub (Number n1) (Number n2)) e
simplify (BinOp Sub (Number n1) (BinOp Sub e (Number n2))) = simplify (BinOp Sub (Number n1) (BinOp Sub e (Number n2))) =
...@@ -211,21 +207,30 @@ simplify (BinOp op e1 e2) = ...@@ -211,21 +207,30 @@ simplify (BinOp op e1 e2) =
(Add, BinOp Sub e (Number "1"), Number "1") -> e (Add, BinOp Sub e (Number "1"), Number "1") -> e
(Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1") (Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1")
(_ , Number a, Number b) -> (_ , 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) (Add, Just x, Just y) -> Number $ show (x + y)
(Sub, 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) (Mul, Just x, Just y) -> Number $ show (x * y)
(Div, Just _, Just 0) -> Number "x" (Div, Just _, Just 0) -> Number "x"
(Div, Just x, Just y) -> Number $ show (x `quot` y) (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' _ -> BinOp op e1' e2'
(Add, BinOp Add e (Number a), Number b) -> (Add, BinOp Add e (Number a), Number b) ->
case (readNumber a, readNumber b) of case (readNumber a, readNumber b) of
(Just x, Just y) -> BinOp Add e $ Number $ show (x + y) (Just x, Just y) -> BinOp Add e $ Number $ show (x + y)
_ -> BinOp op e1' e2' _ -> BinOp op e1' e2'
(Sub, e, Number "-1") -> BinOp Add e (Number "1")
_ -> BinOp op e1' e2' _ -> BinOp op e1' e2'
where where
e1' = simplify e1 e1' = simplify e1
e2' = simplify e2 e2' = simplify e2
bool True = Number "1"
bool False = Number "0"
simplify other = other simplify other = other
rangeSize :: Range -> Expr rangeSize :: Range -> Expr
...@@ -258,7 +263,10 @@ sizedExpr x s (Number n) = ...@@ -258,7 +263,10 @@ sizedExpr x s (Number n) =
++ " doesn't have size " ++ show size ++ " doesn't have size " ++ show size
else Number res else Number res
where 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 unticked = case n of
'\'' : rest -> rest '\'' : rest -> rest
rest -> rest rest -> rest
......
...@@ -43,6 +43,7 @@ data Stmt ...@@ -43,6 +43,7 @@ data Stmt
| RepeatL Expr Stmt | RepeatL Expr Stmt
| DoWhile Expr Stmt | DoWhile Expr Stmt
| Forever Stmt | Forever Stmt
| Foreach Identifier [Maybe Identifier] Stmt
| If (Maybe UniquePriority) Expr Stmt Stmt | If (Maybe UniquePriority) Expr Stmt Stmt
| Timing Timing Stmt | Timing Timing Stmt
| Return Expr | Return Expr
...@@ -86,6 +87,7 @@ instance Show Stmt where ...@@ -86,6 +87,7 @@ instance Show Stmt where
show (RepeatL e s) = printf "repeat (%s) %s" (show e) (show s) 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 (DoWhile e s) = printf "do %s while (%s);" (show s) (show e)
show (Forever s ) = printf "forever %s" (show s) 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 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 (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) show (Return e ) = printf "return %s;" (show e)
......
...@@ -95,7 +95,10 @@ nullRange :: Type -> ([Range] -> Type) ...@@ -95,7 +95,10 @@ nullRange :: Type -> ([Range] -> Type)
nullRange t [] = t nullRange t [] = t
nullRange t [(Number "0", Number "0")] = t nullRange t [(Number "0", Number "0")] = t
nullRange (IntegerAtom TInteger sg) rs = 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")]) IntegerVector TBit sg (rs ++ [(Number "31", Number "0")])
nullRange t rs = nullRange t rs =
error $ "non-vector type " ++ show t ++ error $ "non-vector type " ++ show t ++
......
...@@ -884,6 +884,7 @@ StmtNonAsgn :: { Stmt } ...@@ -884,6 +884,7 @@ StmtNonAsgn :: { Stmt }
| "repeat" "(" Expr ")" Stmt { RepeatL $3 $5 } | "repeat" "(" Expr ")" Stmt { RepeatL $3 $5 }
| "do" Stmt "while" "(" Expr ")" ";" { DoWhile $5 $2 } | "do" Stmt "while" "(" Expr ")" ";" { DoWhile $5 $2 }
| "forever" Stmt { Forever $2 } | "forever" Stmt { Forever $2 }
| "foreach" "(" Identifier IdxVars ")" Stmt { Foreach $3 $4 $6 }
| "->" Identifier ";" { Trigger $2 } | "->" Identifier ";" { Trigger $2 }
| AttributeInstance Stmt { StmtAttr $1 $2 } | AttributeInstance Stmt { StmtAttr $1 $2 }
| ProceduralAssertionStatement { Assertion $1 } | ProceduralAssertionStatement { Assertion $1 }
...@@ -905,6 +906,12 @@ ForStepAssignment :: { (LHS, AsgnOp, Expr) } ...@@ -905,6 +906,12 @@ ForStepAssignment :: { (LHS, AsgnOp, Expr) }
| IncOrDecOperator LHS { ($2, AsgnOp $1, Number "1") } | IncOrDecOperator LHS { ($2, AsgnOp $1, Number "1") }
| LHS IncOrDecOperator { ($1, AsgnOp $2, 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]) } DeclsAndStmts :: { ([Decl], [Stmt]) }
: DeclOrStmt DeclsAndStmts { combineDeclsAndStmts $1 $2 } : DeclOrStmt DeclsAndStmts { combineDeclsAndStmts $1 $2 }
| StmtNonAsgn Stmts { ([], $1 : $2) } | StmtNonAsgn Stmts { ([], $1 : $2) }
......
...@@ -62,6 +62,7 @@ executable sv2v ...@@ -62,6 +62,7 @@ executable sv2v
Convert.EmptyArgs Convert.EmptyArgs
Convert.Enum Convert.Enum
Convert.ForDecl Convert.ForDecl
Convert.Foreach
Convert.FuncRet Convert.FuncRet
Convert.Interface Convert.Interface
Convert.IntTypes 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() { ...@@ -113,8 +113,8 @@ simulateAndCompare() {
# simulate and compare the two files # simulate and compare the two files
simulate "$ref_vcd" "$ref_log" top "$ve" "$tb" simulate "$ref_vcd" "$ref_log" top "$ve" "$tb"
simulate "$gen_vcd" "$gen_log" top "$cv" "$tb" simulate "$gen_vcd" "$gen_log" top "$cv" "$tb"
diff "$ref_vcd" "$gen_vcd" > /dev/null output=`diff "$ref_vcd" "$gen_vcd"`
assertTrue "VCDs are different" $? assertTrue "VCDs are different:\n$output" $?
output=`diff "$ref_log" "$gen_log"` output=`diff "$ref_log" "$gen_log"`
assertTrue "Simulation outputs differ:\n$output" $? 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