Hi,
I would like to write a task that receives a signal by reference and waits for its posedge or negedge. If the signal is not set to the desired value within a specified timeout, an error message should be set.
I wrote something like this:
task automatic timeout(ref logic signal,input logic value,input time timeout_value);
if(signal !== value) begin
fork
begin
#timeout_value;
`uvm_error(....
end
begin
if (signal !== signal_value)
@(signal === signal_value);
end
join_any
disable fork;
endtask
This code does not compile because it violates Verilog LRM section 9.3.2(parallel blocks):it is illegal to refer to an argument passed by reference in fork - join_any block.
Do you have any suggestions? Maybe there is a solution for this in UVM? I could not find any.
Thanks
task automatic timeout(ref logic signal,input logic value,input time timeout_value);
bit timed_out;
fork begin
fork
begin
#timeout_value;
`uvm_error(....
timed_out = '1;
end
join_none
wait(signal === value || timed_out);
disable fork;
end join
endtask
Note the enclosing fork/join is needed to prevent the disable fork from killing other child threads that may have been spawned before calling this task.
Why add another bit “timed_out” instead of using join_any?
task automatic timeout(ref logic signal,input logic value,input time timeout_value);
fork begin
fork
begin
#timeout_value;
`uvm_error(....
end
begin
wait(signal === value);
end
join_any
disable fork;
end join
endtask
In reply to shaygueta:
Just fork the timeout delay.
task automatic timeout(ref logic signal,input logic value,input time timeout_value);
bit timed_out;
fork begin
fork
begin
#timeout_value;
`uvm_error(....
timed_out = '1;
end
join_none
wait(signal === value || timed_out);
disable fork;
end join
endtask
Note the enclosing fork/join is needed to prevent the disable fork from killing other child threads that may have been spawned before calling this task.
HI Dave :
1 can I use disable {name of fork} instead of the guard fork/join here ? i.e
wait(signal === value || timed_out);
disable < name of fork process>; // assume there is name of fork/join_none
2. Do you recommend always use a guard fork/join when there is disable fork ? for example
in run_phase(uvm_phase phase);
Using
disable name_of_fork has problems if there are multiple concurrent instances of the fork. Since you are allowed to use
disable name_of_fork from anywhere, it has no way of knowing which instance you mean and it kills all instances.
I do recommend using guard fork/join whenever there is disable fork as a good habit. But you can avoid it if you are sure no other processes would get disabled accidentally. All of the UVM phase tasks are forked as a separate process so there are no other child process that could get disabled accidentally.