Reputation: 468
In all the SystemVerilog test benches I could find on the internet the generator class always generates a fixed amount of samples and sends them to the mailbox. Driver reads the mailbox and generates an appropriate sequence by manipulating interface signals
One such generator, taken from [1] (chapter 1.3, paragraph 4) and reduced to essentials, is for example this:
class generator;
rand transaction trans;
mailbox gen2driv;
int repeat_count;
function new(mailbox gen2driv);
this.gen2driv = gen2driv;
endfunction
task main();
repeat(repeat_count) begin
trans = new();
if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
gen2driv.put(trans);
end
endtask
endclass
This one generates repeat_count
samples and sends them to the mailbox.
There are however situations, where user wants to generate infinite stream of data, because the testbench simulation is not terminated by a lack of input data, but rather by validation of a condition which happens somewhere in the future, at unknown time.
Extending the above example to replace repeat(repeat_count) begin
by forever begin
won't work. The simulator freezes in the loop as it tries to put infinite amount of samples to the mailbox. As the execution of main
task is a blocking action, driver's signal generator never get executed, and the entire simulation stalls.
So my question is: How to define correctly a generator class, which can send infinite stream of data?
I'm looking for a behaviour similar to pythonic yield
and generator function. This however requires some communication between driver and generator. So such generator model is probably not very suitable for SV?
[1] https://verificationguide.com/systemverilog-examples/systemverilog-testbench-example-01
Upvotes: 0
Views: 1025
Reputation: 19112
Somewhere in your main task you can add a wait statement such as wait(gen2driv.num()<pause_threshold);
. This will block the generator from adding more transaction until the driver has a chance to consume it.
task main();
forever begin
wait(gen2driv.num()<pause_threshold);
trans = new();
if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
gen2driv.put(trans);
end
endtask
Upvotes: 0
Reputation: 42748
What you are asking for is exactly how the UVM sequence/driver mechanism works. The generator does not do any randomization until the driver is ready and asks for an item to drive.
But you can get close to what the UVM does simply by constructing your mailbox with a bound of 1. Then the put(trans)
in the main loop blocks until after the driver has performed a get()
. Then there will always be one transaction in the mailbox waiting for the next drive cycle.
Upvotes: 2