Support assertion control system tasks in classes and interfaces (#7761)

This commit is contained in:
Yilou Wang 2026-06-15 13:33:55 +02:00 committed by GitHub
parent a07a980b73
commit 969a775ae5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 218 additions and 209 deletions

View File

@ -1001,12 +1001,6 @@ class AssertVisitor final : public VNVisitor {
visitAssertionIterate(nodep, nodep->failsp());
}
void visit(AstAssertCtl* nodep) override {
if (VN_IS(m_modp, Class) || VN_IS(m_modp, Iface)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: assertcontrols in classes or interfaces");
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
iterateChildren(nodep);
if (!resolveAssertType(nodep)) {

View File

@ -1,6 +1,15 @@
[0] %Error: t_assert_ctl_immediate.v:51: Assertion failed in top.t.module_with_assertctl: 'assert' failed.
-Info: t/t_assert_ctl_immediate.v:51: Verilog $stop, ignored due to +verilator+error+limit
[0] %Error: t_assert_ctl_immediate.v:57: Assertion failed in top.t.module_with_assertctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:45: Assertion failed in top.t.module_with_assertctl.f_assert: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:45: Assertion failed in top.t.module_with_assertctl.f_assert: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:52: Assertion failed in top.t.module_with_assertctl: 'assert' failed.
-Info: t/t_assert_ctl_immediate.v:52: Verilog $stop, ignored due to +verilator+error+limit
[0] %Error: t_assert_ctl_immediate.v:58: Assertion failed in top.t.module_with_assertctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:46: Assertion failed in top.t.module_with_assertctl.f_assert: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:46: Assertion failed in top.t.module_with_assertctl.f_assert: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:159: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:132: Assertion failed in top.t.module_with_method_ctl.Ctl.check_positive: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:169: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:93: Assertion failed in top.t.module_with_method_ctl.iface.check_positive: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:180: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:186: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:195: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:199: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
[0] %Error: t_assert_ctl_immediate.v:203: Assertion failed in top.t.module_with_method_ctl: 'assert' failed.
*-* All Finished *-*

View File

@ -10,6 +10,7 @@ module t (
module_with_assert module_with_assert (clk);
module_with_assertctl module_with_assertctl (clk);
module_with_method_ctl module_with_method_ctl ();
always @(posedge clk) begin
assert (0);
@ -63,3 +64,146 @@ module module_with_assertctl (
f_assert();
end
endmodule
// Assertion control invoked from class methods and interface functions, in a
// single sub-module with a single initial block so the golden output order is
// stable across --fno-inline (otherwise parallel sub-module initials are
// interleaved differently by the inliner).
//
// Covers:
// - class task $assertoff / $asserton
// - class static method $assertcontrol(Off=4 / On=3), IEEE 1800-2023 Table 20-5
// - $assertkill from a class method
// - assert that lives inside a class method (obeys context-global gating)
// - interface function $assertoff / $asserton
// - assert inside an interface function
// - virtual interface dispatch to an assertion-control function
// - interface class (AstClass with isInterfaceClass) via a concrete impl
// - multiple instances of each thing: OFF via one instance, ON via another
// (assertion control is global per-context, IEEE 1800-2023 20.11)
interface AssertCtlIf;
function void suppress();
$assertoff;
endfunction
function void enable();
$asserton;
endfunction
function void check_positive(int v);
assert (v > 0);
endfunction
endinterface
// verilog_format: off (verible-verilog-format mangles `pure virtual function`)
interface class IAssertCtl;
pure virtual function void suppress();
pure virtual function void enable();
endclass
// verilog_format: on
class IAssertCtlImpl implements IAssertCtl;
virtual function void suppress();
$assertoff;
endfunction
virtual function void enable();
$asserton;
endfunction
endclass
module module_with_method_ctl;
class Ctl;
virtual AssertCtlIf vif;
static function void off_all();
$assertcontrol(4);
endfunction
static function void on_all();
$asserton;
endfunction
function void kill_all();
$assertkill;
endfunction
function void inst_off();
$assertoff;
endfunction
function void inst_on();
$asserton;
endfunction
function void check_positive(int v);
assert (v > 0);
endfunction
function void vif_suppress();
vif.suppress();
endfunction
function void vif_enable();
vif.enable();
endfunction
endclass
Ctl c;
Ctl c2;
AssertCtlIf iface ();
AssertCtlIf iface2 ();
IAssertCtlImpl impl;
IAssertCtlImpl impl2;
initial begin
c = new;
c2 = new;
impl = new;
impl2 = new;
// --- class method coverage ---
Ctl::off_all();
assert (0); // gated via class static -> no fire
Ctl::on_all();
assert (0); // fires
Ctl::off_all();
c.check_positive(-1); // assert inside class method, gated -> no fire
Ctl::on_all();
c.check_positive(-2); // assert inside class method, fires
// --- interface function coverage ---
iface.suppress();
assert (0); // gated via iface fn -> no fire
iface.enable();
assert (0); // fires
iface.suppress();
iface.check_positive(-1); // assert inside iface fn, gated -> no fire
iface.enable();
iface.check_positive(-2); // assert inside iface fn, fires
// --- virtual interface dispatch coverage ---
c.vif = iface;
c.vif_suppress();
assert (0); // gated via virtual interface dispatch -> no fire
c.vif_enable();
assert (0); // fires
// --- interface class via concrete impl ---
impl.suppress();
assert (0); // gated via interface-class impl -> no fire
impl.enable();
assert (0); // fires
// --- multiple instances: OFF via one instance, ON via another ---
// Assertion control is global per-context (IEEE 1800-2023 20.11, no scope
// list), so OFF issued via one instance gates every assertion and ON issued
// via a different instance re-enables them.
c.inst_off(); // class: OFF via c
assert (0); // gated -> no fire
c2.inst_on(); // class: ON via c2
assert (0); // fires
iface.suppress(); // interface: OFF via iface
assert (0); // gated -> no fire
iface2.enable(); // interface: ON via iface2
assert (0); // fires
impl.suppress(); // interface class: OFF via impl
assert (0); // gated -> no fire
impl2.enable(); // interface class: ON via impl2
assert (0); // fires
// --- $assertkill (last: terminal per IEEE 1800-2023 Table 20-5) ---
c.kill_all();
assert (0); // killed -> no fire
end
endmodule

View File

@ -1,123 +1,103 @@
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:25:5: Unsupported: non-constant assert assertion-type expression
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:26:5: Unsupported: non-constant assert assertion-type expression
: ... note: In instance 't.unsupported_ctl_type'
25 | $assertcontrol(Lock, a);
26 | $assertcontrol(Lock, a);
| ^~~~~~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:27:5: Unsupported: $assertcontrol control_type '2'
27 | $assertcontrol(Unlock);
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:28:5: Unsupported: $assertcontrol control_type '2'
28 | $assertcontrol(Unlock);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:29:5: Unsupported: $assertcontrol control_type '6'
29 | $assertcontrol(PassOn);
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:30:5: Unsupported: $assertcontrol control_type '6'
30 | $assertcontrol(PassOn);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:30:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
30 | $assertpasson;
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:31:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
31 | $assertpasson(a);
31 | $assertpasson;
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:32:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
32 | $assertpasson(a, t);
32 | $assertpasson(a);
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:34:5: Unsupported: $assertcontrol control_type '7'
34 | $assertcontrol(PassOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:35:5: Unsupported: assert control assertion_type
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:33:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
35 | $assertpassoff;
33 | $assertpasson(a, t);
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:35:5: Unsupported: $assertcontrol control_type '7'
35 | $assertcontrol(PassOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:36:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
36 | $assertpassoff(a);
36 | $assertpassoff;
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:37:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
37 | $assertpassoff(a, t);
37 | $assertpassoff(a);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:39:5: Unsupported: $assertcontrol control_type '8'
39 | $assertcontrol(FailOn);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:40:5: Unsupported: assert control assertion_type
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:38:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
40 | $assertfailon;
| ^~~~~~~~~~~~~
38 | $assertpassoff(a, t);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:40:5: Unsupported: $assertcontrol control_type '8'
40 | $assertcontrol(FailOn);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:41:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
41 | $assertfailon(a);
41 | $assertfailon;
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:42:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
42 | $assertfailon(a, t);
42 | $assertfailon(a);
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:44:5: Unsupported: $assertcontrol control_type '9'
44 | $assertcontrol(FailOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:45:5: Unsupported: assert control assertion_type
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:43:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
45 | $assertfailoff;
43 | $assertfailon(a, t);
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:45:5: Unsupported: $assertcontrol control_type '9'
45 | $assertcontrol(FailOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:46:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
46 | $assertfailoff(a);
46 | $assertfailoff;
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:47:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
47 | $assertfailoff(a, t);
47 | $assertfailoff(a);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:49:5: Unsupported: $assertcontrol control_type '10'
49 | $assertcontrol(NonvacuousOn);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:50:5: Unsupported: assert control assertion_type
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:48:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
50 | $assertnonvacuouson;
| ^~~~~~~~~~~~~~~~~~~
48 | $assertfailoff(a, t);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:50:5: Unsupported: $assertcontrol control_type '10'
50 | $assertcontrol(NonvacuousOn);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:51:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
51 | $assertnonvacuouson(a);
51 | $assertnonvacuouson;
| ^~~~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:52:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
52 | $assertnonvacuouson(a, t);
52 | $assertnonvacuouson(a);
| ^~~~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:54:5: Unsupported: $assertcontrol control_type '11'
54 | $assertcontrol(VacuousOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:55:5: Unsupported: assert control assertion_type
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:53:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
55 | $assertvacuousoff;
| ^~~~~~~~~~~~~~~~~
53 | $assertnonvacuouson(a, t);
| ^~~~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:55:5: Unsupported: $assertcontrol control_type '11'
55 | $assertcontrol(VacuousOff);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:56:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
56 | $assertvacuousoff(a);
56 | $assertvacuousoff;
| ^~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:57:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
57 | $assertvacuousoff(a, t);
57 | $assertvacuousoff(a);
| ^~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:64:5: Unsupported: non-const assert control type expression
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:58:5: Unsupported: assert control assertion_type
: ... note: In instance 't.unsupported_ctl_type'
58 | $assertvacuousoff(a, t);
| ^~~~~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:65:5: Unsupported: non-const assert control type expression
: ... note: In instance 't.unsupported_ctl_type_expr'
64 | $assertcontrol(ctl_type);
65 | $assertcontrol(ctl_type);
| ^~~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:93:7: Unsupported: assertcontrols in classes or interfaces
: ... note: In instance 't.assert_class'
93 | $asserton;
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:99:7: Unsupported: assertcontrols in classes or interfaces
: ... note: In instance 't.assert_class'
99 | $assertoff;
| ^~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:172:5: Unsupported: assertcontrols in classes or interfaces
: ... note: In instance 't.assert_iface'
172 | $assertoff;
| ^~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:138:5: Unsupported: assertcontrols in classes or interfaces
: ... note: In instance 't.assert_iface_class'
138 | $assertoff;
| ^~~~~~~~~~
%Error-UNSUPPORTED: t/t_assert_ctl_unsup.v:145:5: Unsupported: assertcontrols in classes or interfaces
: ... note: In instance 't.assert_iface_class'
145 | $asserton;
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -4,15 +4,16 @@
// SPDX-FileCopyrightText: 2024 Antmicro
// SPDX-License-Identifier: CC0-1.0
module t(input logic clk);
unsupported_ctl_type unsupported_ctl_type(clk ? 1 : 2);
unsupported_ctl_type_expr unsupported_ctl_type_expr();
assert_class assert_class();
assert_iface assert_iface();
assert_iface_class assert_iface_class();
module t (
input logic clk
);
unsupported_ctl_type unsupported_ctl_type (clk ? 1 : 2);
unsupported_ctl_type_expr unsupported_ctl_type_expr ();
endmodule
module unsupported_ctl_type(input int a);
module unsupported_ctl_type (
input int a
);
initial begin
let Lock = 1;
let Unlock = 2;
@ -64,122 +65,3 @@ module unsupported_ctl_type_expr;
$assertcontrol(ctl_type);
end
endmodule
module assert_class;
virtual class AssertCtl;
pure virtual function void virtual_assert_ctl();
endclass
class AssertCls;
static function void static_function();
assert(0);
endfunction
static task static_task();
assert(0);
endtask
function void assert_function();
assert(0);
endfunction
task assert_task();
assert(0);
endtask
virtual function void virtual_assert();
assert(0);
endfunction
endclass
class AssertOn extends AssertCtl;
virtual function void virtual_assert_ctl();
$asserton;
endfunction
endclass
class AssertOff extends AssertCtl;
virtual function void virtual_assert_ctl();
$assertoff;
endfunction
endclass
AssertCls assertCls;
AssertOn assertOn;
AssertOff assertOff;
initial begin
$assertoff;
AssertCls::static_function();
AssertCls::static_task();
$asserton;
AssertCls::static_function();
AssertCls::static_task();
assertCls = new;
assertOn = new;
assertOff = new;
assertOff.virtual_assert_ctl();
assertCls.assert_function();
assertCls.assert_task();
assertCls.virtual_assert();
assertOn.virtual_assert_ctl();
assertCls.assert_function();
assertCls.assert_task();
assertCls.virtual_assert();
assertOff.virtual_assert_ctl();
assertCls.assert_function();
end
endmodule
interface Iface;
function void assert_func();
assert(0);
endfunction
function void assertoff_func();
$assertoff;
endfunction
initial begin
assertoff_func();
assert(0);
assert_func();
$asserton;
assert(0);
assert_func();
end
endinterface
module assert_iface;
Iface iface();
virtual Iface vIface = iface;
initial begin
vIface.assert_func();
vIface.assertoff_func();
vIface.assert_func();
iface.assert_func();
iface.assertoff_func();
iface.assert_func();
end
endmodule
interface class IfaceClass;
pure virtual function void assertoff_func();
pure virtual function void assert_func();
endclass
class IfaceClassImpl implements IfaceClass;
virtual function void assertoff_func();
$assertoff;
endfunction
virtual function void assert_func();
assert(0);
endfunction
endclass
module assert_iface_class;
IfaceClassImpl ifaceClassImpl = new;
initial begin
ifaceClassImpl.assertoff_func();
ifaceClassImpl.assert_func();
end
endmodule