// DESCRIPTION: Verilator: Verilog Test module // // This file ONLY is placed under the Creative Commons Public Domain, for // any use, without warranty, 2022 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 `ifdef TEST_VERBOSE `define WRITE_VERBOSE(args) $write args `else `define WRITE_VERBOSE(args) `endif module t; // ============================================= // EVENTS class EventClass; event e; task sleep; /* @e; */ endtask // Unsupported task wake; ->e; endtask endclass EventClass ec = new; int event_trig_count = 0; initial begin @ec.e; ec.sleep; end initial #25 ec.wake; initial #50 ->ec.e; always @ec.e begin event_trig_count++; `WRITE_VERBOSE(("Event in class triggered at time %0t!\n", $time)); end // ============================================= // DELAYS virtual class DelayClass; pure virtual task do_delay; pure virtual task do_sth_else; endclass `ifdef TEST_VERBOSE `define DELAY_CLASS(dt) \ class Delay``dt extends DelayClass; \ virtual task do_delay; \ $write("Starting a #%0d delay\n", dt); \ #dt \ $write("Ended a #%0d delay\n", dt); \ endtask \ virtual task do_sth_else; \ $write("Task with no delay (in Delay%0d)\n", dt); \ endtask \ endclass `else `define DELAY_CLASS(dt) \ class Delay``dt extends DelayClass; \ virtual task do_delay; \ #dt; \ endtask \ virtual task do_sth_else; \ endtask \ endclass `endif `DELAY_CLASS(10); `DELAY_CLASS(20); `DELAY_CLASS(40); class NoDelay extends DelayClass; virtual task do_delay; `WRITE_VERBOSE(("Task with no delay\n")); endtask virtual task do_sth_else; `WRITE_VERBOSE(("Task with no delay (in NoDelay)\n")); endtask endclass class AssignDelayClass; logic x; logic y; task do_assign; y = #10 x; `WRITE_VERBOSE(("Did assignment with delay\n")); endtask endclass initial begin DelayClass dc; Delay10 d10 = new; Delay20 d20 = new; Delay40 d40 = new; NoDelay dNo = new; AssignDelayClass dAsgn = new; `WRITE_VERBOSE(("I'm at time %0t\n", $time)); dc = d10; dc.do_delay; dc.do_sth_else; `WRITE_VERBOSE(("I'm at time %0t\n", $time)); if ($time != 10) $stop; dc = d20; dc.do_delay; dc.do_sth_else; `WRITE_VERBOSE(("I'm at time %0t\n", $time)); if ($time != 30) $stop; dc = d40; dc.do_delay; dc.do_sth_else; `WRITE_VERBOSE(("I'm at time %0t\n", $time)); if ($time != 70) $stop; dc = dNo; dc.do_delay; dc.do_sth_else; `WRITE_VERBOSE(("I'm at time %0t\n", $time)); dAsgn.x = 1; dAsgn.y = 0; fork #5 dAsgn.x = 0; join_none dAsgn.do_assign; if ($time != 80) $stop; if (event_trig_count != 2) $stop; if (dAsgn.y != 1) $stop; // Test if the object is deleted before do_assign finishes: fork dAsgn.do_assign; join_none #5 dAsgn = null; #15 $write("*-* All Finished *-*\n"); $finish; end // ============================================= // FORKS class ForkDelayClass; task do_delay; #40; endtask endclass class ForkClass; int done = 0; task do_fork(); ForkDelayClass d; fork begin #10 done++; `WRITE_VERBOSE(("Forked process %0d ending at time %0t\n", done, $time)); end begin #20 done++; `WRITE_VERBOSE(("Forked process %0d ending at time %0t\n", done, $time)); d = new; end begin #30 d.do_delay; done++; `WRITE_VERBOSE(("Forked process %0d ending at time %0t\n", done, $time)); end join done++; `WRITE_VERBOSE(("All forked processes ended at time %0t\n", $time)); endtask endclass initial begin ForkClass fc = new; fc.do_fork; if (fc.done != 4 || $time != 70) $stop; end initial #101 $stop; // timeout endmodule