Support more types in wait (#4374)
This commit is contained in:
parent
3454641244
commit
1549ff9185
|
|
@ -469,23 +469,6 @@ private:
|
|||
int scalePowerOfTen = timeunit.powerOfTen() - m_netlistp->timeprecision().powerOfTen();
|
||||
return std::pow(10.0, scalePowerOfTen);
|
||||
}
|
||||
// Construct SenItems from VarRefs in an expression
|
||||
AstSenItem* varRefpsToSenItemsp(AstNode* const nodep) const {
|
||||
AstNode* senItemsp = nullptr;
|
||||
const VNUser4InUse user4InUse;
|
||||
nodep->foreach([&](AstNodeVarRef* refp) {
|
||||
if (refp->access().isWriteOnly()) return;
|
||||
AstVarScope* const vscp = refp->varScopep();
|
||||
if (vscp->user4SetOnce()) return;
|
||||
const bool isEvent = vscp->dtypep() && vscp->dtypep()->basicp()
|
||||
&& vscp->dtypep()->basicp()->isEvent();
|
||||
const auto edgeType = isEvent ? VEdgeType::ET_EVENT : VEdgeType::ET_CHANGED;
|
||||
senItemsp = AstNode::addNext(
|
||||
senItemsp, new AstSenItem{refp->fileline(), edgeType,
|
||||
new AstVarRef{refp->fileline(), vscp, VAccess::READ}});
|
||||
});
|
||||
return VN_AS(senItemsp, SenItem);
|
||||
}
|
||||
// Creates the global delay scheduler variable
|
||||
AstVarScope* getCreateDelayScheduler() {
|
||||
if (m_delaySchedp) return m_delaySchedp;
|
||||
|
|
@ -1023,11 +1006,14 @@ private:
|
|||
if (stmtsp) AstNode::addNext<AstNode, AstNode>(ifp, stmtsp);
|
||||
nodep->replaceWith(ifp);
|
||||
} else {
|
||||
AstSenItem* const senItemsp = varRefpsToSenItemsp(condp);
|
||||
UASSERT_OBJ(senItemsp, nodep, "No varrefs in wait statement condition");
|
||||
// Put the event control in a while loop with the wait expression as condition
|
||||
AstEventControl* const controlp
|
||||
= new AstEventControl{flp, new AstSenTree{flp, senItemsp}, nullptr};
|
||||
// We are using a global sentree, so we cannot use ET_TRUE, as that could lead to the
|
||||
// active region never converging. Because of this, we need to use ET_CHANGED in a
|
||||
// loop.
|
||||
AstEventControl* const controlp = new AstEventControl{
|
||||
flp,
|
||||
new AstSenTree{
|
||||
flp, new AstSenItem{flp, VEdgeType::ET_CHANGED, condp->cloneTree(false)}},
|
||||
nullptr};
|
||||
controlp->user2(true); // Commit immediately
|
||||
AstWhile* const loopp = new AstWhile{flp, new AstLogNot{flp, condp}, controlp};
|
||||
if (stmtsp) AstNode::addNext<AstNode, AstNode>(loopp, stmtsp);
|
||||
|
|
|
|||
|
|
@ -5690,7 +5690,8 @@ private:
|
|||
}
|
||||
if (nodep->fileline()->timingOn()) {
|
||||
if (v3Global.opt.timing().isSetTrue()) {
|
||||
userIterate(nodep->condp(), WidthVP{SELF, PRELIM}.p());
|
||||
iterateCheckBool(nodep, "Wait", nodep->condp(),
|
||||
BOTH); // it's like an if() condition.
|
||||
iterateNull(nodep->stmtsp());
|
||||
return;
|
||||
} else if (v3Global.opt.timing().isSetFalse()) {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
%Warning-WAITCONST: t/t_timing_wait1.v:48:12: Wait statement condition is constant
|
||||
48 | wait(1);
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:52:12: Wait statement condition is constant
|
||||
52 | wait(1);
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/WAITCONST?v=latest
|
||||
... Use "/* verilator lint_off WAITCONST */" and lint_on around source to disable this message.
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:50:14: Wait statement condition is constant
|
||||
50 | wait(0 < 1) $write("*-* All Finished *-*\n");
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:54:14: Wait statement condition is constant
|
||||
54 | wait(0 < 1) $write("*-* All Finished *-*\n");
|
||||
| ^
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:54:17: Wait statement condition is constant
|
||||
54 | initial wait(0) $stop;
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:58:17: Wait statement condition is constant
|
||||
58 | initial wait(0) $stop;
|
||||
| ^
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:55:19: Wait statement condition is constant
|
||||
55 | initial wait(1 == 0) $stop;
|
||||
%Warning-WAITCONST: t/t_timing_wait1.v:59:19: Wait statement condition is constant
|
||||
59 | initial wait(1 == 0) $stop;
|
||||
| ^~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
module t;
|
||||
process job[] = new [8];
|
||||
bit is_alloc = 0;
|
||||
|
||||
initial begin
|
||||
foreach (job[j]) fork
|
||||
|
|
@ -16,8 +15,7 @@ module t;
|
|||
end
|
||||
join_none
|
||||
foreach (job[j]) begin
|
||||
is_alloc = !!job[j];
|
||||
wait (is_alloc);
|
||||
wait (job[j]);
|
||||
end
|
||||
$write("all jobs started\n");
|
||||
foreach (job[j]) begin
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@ module t (/*AUTOARG*/
|
|||
);
|
||||
input clk;
|
||||
process p;
|
||||
bit s = 0;
|
||||
|
||||
initial begin
|
||||
wait (s);
|
||||
wait (p);
|
||||
p.kill();
|
||||
p.await();
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
|
@ -23,7 +22,6 @@ module t (/*AUTOARG*/
|
|||
always @(posedge clk) begin
|
||||
if (!p) begin
|
||||
p = process::self();
|
||||
s = 1;
|
||||
end else begin
|
||||
$stop;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ module t;
|
|||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int q[$];
|
||||
|
||||
initial begin
|
||||
`WRITE_VERBOSE("start with a==0, b==0, c==0\n");
|
||||
|
|
@ -26,7 +27,8 @@ module t;
|
|||
#1 c = 3; `WRITE_VERBOSE("assign 3 to c\n");
|
||||
#1 c = 4; `WRITE_VERBOSE("assign 4 to c\n"); // a+b<c
|
||||
#1 c = 4; `WRITE_VERBOSE("assign 5 to b\n"); // a<b && b>c
|
||||
b = 5;
|
||||
b = 5; `WRITE_VERBOSE("push_back b to q\n");
|
||||
q.push_back(b);
|
||||
end
|
||||
|
||||
initial begin
|
||||
|
|
@ -44,6 +46,8 @@ module t;
|
|||
wait(a + b < c) if (a + b >= c) $stop;
|
||||
`WRITE_VERBOSE("waiting for a<b && b>c\n");
|
||||
wait(a < b && b > c) if (a >= b || b <= c) $stop;
|
||||
`WRITE_VERBOSE("waiting for q.size() > 0\n");
|
||||
wait(q.size() > 0) if (q.size() <= 0) $stop;
|
||||
|
||||
wait(1);
|
||||
|
||||
|
|
@ -54,5 +58,5 @@ module t;
|
|||
initial wait(0) $stop;
|
||||
initial wait(1 == 0) $stop;
|
||||
|
||||
initial #11 $stop; // timeout
|
||||
initial #12 $stop; // timeout
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2023 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2023 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
|
||||
module t;
|
||||
typedef process pr;
|
||||
pr p[4];
|
||||
int n = 0;
|
||||
|
||||
initial begin
|
||||
wait (p[1]);
|
||||
p[1].await();
|
||||
p[0] = process::self();
|
||||
if (n == 3) n++;
|
||||
#2 $write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
wait (p[2]);
|
||||
p[2].await();
|
||||
p[1] = process::self();
|
||||
if (n == 2) n++;
|
||||
end
|
||||
|
||||
initial begin
|
||||
wait (p[3]);
|
||||
p[3].await();
|
||||
p[2] = process::self();
|
||||
if (n == 1) n++;
|
||||
end
|
||||
|
||||
initial begin
|
||||
p[3] = process::self();
|
||||
if (n == 0) n++;
|
||||
end
|
||||
|
||||
initial #1 if (n != 4) $stop;
|
||||
initial #3 $stop; // timeout
|
||||
endmodule
|
||||
Loading…
Reference in New Issue