mirror of https://github.com/zachjs/sv2v.git
execute always_comb/latch at time zero
This commit is contained in:
parent
756dbbb84f
commit
f9917d94da
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
### Other Enhancements
|
||||
|
||||
* `always_comb` and `always_latch` now reliably execute at time zero
|
||||
* Added error checking for unresolved typenames
|
||||
* Added constant folding for `||` and `&&`
|
||||
* `input reg` module ports are now converted to `input wire`
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
-
|
||||
- `always_comb` and `always_latch` become `always @*`, or produce an explicit
|
||||
- sensitivity list if they need to pick up sensitivities from the functions
|
||||
- they call. `always_ff` simply becomes `always`.
|
||||
-
|
||||
- TODO: `always_comb` blocks do not run at time zero
|
||||
- they call. These blocks are triggered at time zero by adding a no-op
|
||||
- statement reading from `_sv2v_0`, which is injected and updated in an
|
||||
- `initial` block. `always_ff` simply becomes `always`.
|
||||
-}
|
||||
|
||||
module Convert.AlwaysKW (convert) where
|
||||
|
|
@ -24,9 +24,15 @@ convert :: [AST] -> [AST]
|
|||
convert = map $ traverseDescriptions traverseDescription
|
||||
|
||||
traverseDescription :: Description -> Description
|
||||
traverseDescription description@Part{} =
|
||||
evalState (evalScoperT $ scopePart op description) mempty
|
||||
where op = traverseModuleItem >=> scoper
|
||||
traverseDescription (Part att ext kw lif name pts items) =
|
||||
Part att ext kw lif name pts $
|
||||
if getAny anys && not (elem triggerDecl items')
|
||||
then triggerDecl : items' ++ [triggerFire]
|
||||
else items'
|
||||
where
|
||||
op = traverseModuleItem >=> scoper
|
||||
(items', (anys, _)) = flip runState mempty $ evalScoperT $
|
||||
insertElem triggerIdent Var >> scopeModuleItems op name items
|
||||
traverseDescription description = description
|
||||
|
||||
type SC = ScoperT Kind (State (Any, [Expr]))
|
||||
|
|
@ -182,12 +188,13 @@ push x = lift $ modify' (x <>)
|
|||
-- custom traversal which converts SystemVerilog `always` keywords and tracks
|
||||
-- information about task and functions
|
||||
traverseModuleItem :: ModuleItem -> SC ModuleItem
|
||||
traverseModuleItem (AlwaysC AlwaysLatch stmt) = do
|
||||
e <- fmap toEvent $ findNonLocals $ Initial stmt
|
||||
return $ AlwaysC Always $ Timing (Event e) stmt
|
||||
traverseModuleItem (AlwaysC AlwaysLatch stmt) =
|
||||
traverseModuleItem $ AlwaysC AlwaysComb stmt
|
||||
traverseModuleItem (AlwaysC AlwaysComb stmt) = do
|
||||
e <- fmap toEvent $ findNonLocals $ Initial stmt
|
||||
return $ AlwaysC Always $ Timing (Event e) stmt
|
||||
push (Any True, [])
|
||||
e <- fmap toEvent $ findNonLocals $ Initial stmt'
|
||||
return $ AlwaysC Always $ Timing (Event e) stmt'
|
||||
where stmt' = addTriggerStmt stmt
|
||||
traverseModuleItem (AlwaysC AlwaysFF stmt) =
|
||||
return $ AlwaysC Always stmt
|
||||
traverseModuleItem item@(MIPackageItem (Function _ _ x decls _)) = do
|
||||
|
|
@ -220,8 +227,28 @@ port _ = ("", Local)
|
|||
findNonLocals :: ModuleItem -> SC (Bool, [Expr])
|
||||
findNonLocals item = do
|
||||
scopes <- get
|
||||
prev <- lift get
|
||||
lift $ put mempty
|
||||
_ <- scoper item
|
||||
(anys, exprs) <- lift get
|
||||
lift $ put prev
|
||||
let nonLocals = mapMaybe (longestStaticPrefix scopes) exprs
|
||||
return (getAny anys, nonLocals)
|
||||
|
||||
triggerIdent :: Identifier
|
||||
triggerIdent = "_sv2v_0"
|
||||
|
||||
triggerDecl :: ModuleItem
|
||||
triggerDecl = MIPackageItem $ Decl $ Variable Local t triggerIdent [] Nil
|
||||
where t = IntegerVector TReg Unspecified []
|
||||
|
||||
triggerFire :: ModuleItem
|
||||
triggerFire = Initial $ Asgn AsgnOpEq Nothing (LHSIdent triggerIdent) (RawNum 0)
|
||||
|
||||
triggerStmt :: Stmt
|
||||
triggerStmt = If NoCheck (Ident triggerIdent) Null Null
|
||||
|
||||
addTriggerStmt :: Stmt -> Stmt
|
||||
addTriggerStmt (Block Seq name decls stmts) =
|
||||
Block Seq name decls $ triggerStmt : stmts
|
||||
addTriggerStmt stmt = Block Seq "" [] [triggerStmt, stmt]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
module top;
|
||||
logic x;
|
||||
always_comb
|
||||
x = 0;
|
||||
|
||||
`include "always_comb.vh"
|
||||
`TEST(_comb, 1)
|
||||
`TEST(_comb, 2)
|
||||
`TEST(@*, 3)
|
||||
`TEST(@*, 4)
|
||||
|
||||
initial x1 = 0;
|
||||
initial x3 = 0;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
module top;
|
||||
reg x;
|
||||
initial
|
||||
x = 0;
|
||||
|
||||
`include "always_comb.vh"
|
||||
`TEST(@(x1), 1)
|
||||
`TEST(@(x1), 2)
|
||||
`TEST(@*, 3)
|
||||
`TEST(@*, 4)
|
||||
|
||||
initial x1 = 0;
|
||||
initial x3 = 0;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
reg never;
|
||||
`define TEST(sense, num) \
|
||||
reg x``num, y``num, z``num; \
|
||||
function automatic t``num; \
|
||||
input inp; \
|
||||
t``num = x``num; \
|
||||
endfunction \
|
||||
always``sense begin \
|
||||
y``num = 0; \
|
||||
z``num = t``num(0); \
|
||||
if (never) ; \
|
||||
end
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
`define ALWAYS(trigger) always @(trigger)
|
||||
`define ALWAYS(trigger) always @(trigger, start)
|
||||
`include "always_prefix.vh"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module mod(
|
|||
);
|
||||
localparam Y = 2;
|
||||
localparam X = 10000;
|
||||
reg start;
|
||||
|
||||
`define TEST(expr, trigger, extra) \
|
||||
if (1) begin \
|
||||
|
|
@ -40,4 +41,6 @@ parameter FOUR = 4;
|
|||
`TEST(data[THREE], data[3], )
|
||||
`TEST(data[ignored], data, )
|
||||
`TEST(data[THREE], data[0] or data[3], & data[0])
|
||||
|
||||
initial start = 0;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ module mod(
|
|||
o = i;
|
||||
endtask
|
||||
|
||||
logic start;
|
||||
|
||||
always_comb
|
||||
t(out1);
|
||||
always_comb
|
||||
|
|
@ -82,4 +84,6 @@ module mod(
|
|||
endfunction
|
||||
always_comb
|
||||
asgn(.i(i(ZERO)), .o(outC));
|
||||
|
||||
initial start = 0;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -39,17 +39,19 @@ module mod(
|
|||
o = i;
|
||||
endtask
|
||||
|
||||
reg start;
|
||||
|
||||
always @*
|
||||
t(out1);
|
||||
always @(inp2)
|
||||
out2 = f(ZERO);
|
||||
always @(inp1, inp2)
|
||||
always @(start, inp1, inp2)
|
||||
out3 = f(ZERO) & inp1;
|
||||
always @(inp1, inp2)
|
||||
always @(start, inp1, inp2)
|
||||
out4 = g(ZERO);
|
||||
always @*
|
||||
out5 = flip(inp1);
|
||||
always @(inp1, inp2) begin : blk
|
||||
always @(start, inp1, inp2) begin : blk
|
||||
reg x;
|
||||
x = g(ZERO);
|
||||
out6 = x;
|
||||
|
|
@ -58,11 +60,11 @@ module mod(
|
|||
u(out7);
|
||||
parameter ONE = 1;
|
||||
if (ONE)
|
||||
always @(inp1, inp2) begin
|
||||
always @(start, inp1, inp2) begin
|
||||
asgn(out8, flip(inp1));
|
||||
out9 = f(ZERO);
|
||||
end
|
||||
always @(inp1, inp2)
|
||||
always @(start, inp1, inp2)
|
||||
if (inp1)
|
||||
outA = f(ZERO);
|
||||
|
||||
|
|
@ -80,4 +82,6 @@ module mod(
|
|||
endfunction
|
||||
always @(s[1])
|
||||
asgn(outC, i(ZERO));
|
||||
|
||||
initial start = 0;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ module Example(inp, out);
|
|||
input wire inp;
|
||||
output reg out;
|
||||
generate
|
||||
if (ENABLED)
|
||||
always @* out = inp;
|
||||
if (ENABLED) begin
|
||||
reg start;
|
||||
always @(inp, start) out = inp;
|
||||
initial start = 0;
|
||||
end
|
||||
else
|
||||
initial out = DEFAULT;
|
||||
endgenerate
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ if __name__ == "__main__":
|
|||
# Find and drop dumped parameters.
|
||||
if line.startswith("$var "):
|
||||
parts = line.split()
|
||||
should_drop = parts[1] == "parameter"
|
||||
should_drop = parts[1] == "parameter" or parts[4] == "_sv2v_0"
|
||||
if not should_drop and not pending:
|
||||
print(line, end="")
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ simulate() {
|
|||
$sim_prog -no-date > $sim_log
|
||||
assertTrue "simulating $1 failed" $?
|
||||
# remove parameters from the VCD if present
|
||||
if grep "var parameter" $sim_vcd_tmp > /dev/null; then
|
||||
if grep -E "var parameter| _sv2v_0 " $sim_vcd_tmp > /dev/null; then
|
||||
$SCRIPT_DIR/clean_vcd.py < $sim_vcd_tmp > $sim_vcd
|
||||
elif [ $sim_vcd != "/dev/null" ]; then
|
||||
mv -f $sim_vcd_tmp $sim_vcd
|
||||
|
|
|
|||
Loading…
Reference in New Issue