verilator/test_regress/t/t_assert_ctl_immediate.v

210 lines
5.4 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2024 Antmicro
// SPDX-License-Identifier: CC0-1.0
module t (
input clk
);
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);
end
always @(negedge clk) begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
module module_with_assert (
input clk
);
always @(posedge clk) assert (0);
endmodule
module module_with_assertctl (
input clk
);
function void assert_off;
begin
$assertoff;
end
endfunction
function void assert_on;
begin
$asserton;
end
endfunction
function void f_assert;
begin
assert (0);
end
endfunction
initial begin
assert_on();
assert (0);
assert_off();
assert_off();
assert (0);
assert_on();
assert_on();
assert (0);
f_assert();
f_assert();
assert_off();
f_assert();
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