Support more types in wait (#4374)

This commit is contained in:
Aleksander Kiryk 2023-07-24 14:14:01 +02:00 committed by GitHub
parent 3454641244
commit 1549ff9185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 39 deletions

View File

@ -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);

View File

@ -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()) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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