How the forever loop breaks in the following code snippet? My assumption is the execution should remain inside forever loop indefinitely as there is no break condition. But the execution exits the loop to my surprise.
task evsock_alarm_center::run_phase(uvm_phase phase);
phase.raise_objection(this);
fork
forever begin
int_fifo.get(gpio_item);
parse_interrupt(gpio_item,interrupt_vector); //interrupt_vector_parsing
irq_out=interrupt_vector[0]|| interrupt_vector[1]; //merge the irq_out
if(irq_out) begin
if(interrupt_vector[2]) begin
`uvm_info("!INTERRUPT TRIGGERED!", "Interrupt Source is EM Classifier", UVM_LOW)
end
if(interrupt_vector[3]) begin
`uvm_info("!INTERRUPT TRIGGERED!", "Interrupt Source is EM Queue Manager", UVM_LOW)
end
if(interrupt_vector[4]) begin
`uvm_info("!INTERRUPT TRIGGERED!", "Interrupt Source is EM Scheduler", UVM_LOW)
end
if(interrupt_vector[5]) begin
`uvm_info("!INTERRUPT TRIGGERED!", "Interrupt Source is BM", UVM_LOW)
end
end
join_none
phase.drop_objection(this);
endtask
In reply to rbasnet:
It does never break and the objection will never drop, i.e. your simulation is running forever.
could you explain why the objection will never drop? I think in run phase, he uses the fork/join_none then the phase.drop_objection will be executed in main thread right?
I believe, the objection will raise and drop immediatly after fork. The fork will be terminated when all other phases parallel running with run phase are finished.
You are spawning the forever loop in a fork/join_none process, so the that runs in the background while you immediately drop the objection. Why are you raising/dropping an objection?
A following-up question. Let us assume Rbasent’s code is correct. When the fork/join_none kick off ? According the LRM, fork/join_none is started at the first blocking statement in main thread after join_none.
As the LRMs says, the parent thread has to block or terminate before the fork/join_none process starts executing the forked process. Since each component’s run_phase is started as a separate thread, this fork/join_none gets scheduled upon returning from the task vsock_alarm_center::run_phase. But there may be other component run_phases ahead in the queue to execute before getting to the fork thread.
In reply to rbasnet:
You are spawning the forever loop in a fork/join_none process, so the that runs in the background while you immediately drop the objection. Why are you raising/dropping an objection?
The objection raising/dropping is redundant. That was my bad. Now I got rid of the objection but still the execution comes out of the forever loop. I tried with the fork_join and fork_join_any to see if that makes any difference but no. I also completely got rid of the fork and tried with the forever loop only and i could see that the execution still exits the forever loop. What is going on here? Seems like I am missing something here.
In reply to dave_59:
The objection raising/dropping is redundant. That was my bad. Now I got rid of the objection but still the execution comes out of the forever loop. I tried with the fork_join and fork_join_any to see if that makes any difference but no. I also completely got rid of the fork and tried with the forever loop only and i could see that the execution still exits the forever loop. What is going on here? Seems like I am missing something here.
From the simulation it seems that the loop executes as many times as I have items in the fifo. If there are no items in the fifo, regardless of the call to get method, the loop exits. My understanding is the execution should stuck in the call to get method as it is a blocking call even if there are no items in the fifo. What is that I am missing here?
The your loop is located in run_phase, when the run_phase complete, simulation will terminate your fork/join_none and the loop as well. I think, the loop exists because your run_phase is completed (when all other phases such as reset, configure, main, shutdown, etc… parallel running with run_phase are finished). Please check again.
In reply to VE:
As the LRMs says, the parent thread has to block or terminate before the fork/join_none process. Since each component’s run_phase is started as a separate thread, this fork/join_none gets scheduled upon returning from the task vsock_alarm_center::run_phase. But there may be other component run_phases ahead in the queue to execute before getting to the fork thread.
Thanks Dave. Would you elaborate " As the LRMs says, the parent thread has to block or terminate before the fork/join_none process."? On IEEE1800-2012, P175. it says :
join_none :: The parent process continues to execute concurrently with all the processes spawned by the fork. The spawned processes do not start executing until the parent thread executes a blocking statement or terminates.
Just want to make sure i understand it correctly.
Thanks
Are you trying to say that regardless of the implementation in the run phase, the run phase should terminate at some point of time during the simulation and the execution proceeds to extract phase? Please consider the code below. What makes the forever loop break? My understanding is, the execution should get stuck forever inside the loop as get method is blocking. It should not return unless the item is available in the fifo and hence the execution should get stuck forever. If i remove the int_fifo.get(), then the execution remains inside the forever loop indefinitely. Any pointers will be appreciated!!!
uvm_tlm_analysis_fifo #(gpio_sequence_item) int_fifo;
...
task evsock_alarm_center::run_phase(uvm_phase phase);
forever begin
int_fifo.get(gpio_item);
end
endtask
The run_phase will be terminated by following reasons:
The post_shutdown_phase is finished (all objection are dropped)
Timeout 9200s.
In your example, the forever loop in run_phase will be terminated if all objections (from pre_reset to post_shutdown phase) are dropped. Let’s see the following example:
class phase_test extends uvm_test;
`uvm_component_utils(phase_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
task main_phase(uvm_phase phase);
phase.raise_objection(this);
#5;
phase.drop_objection(this);
endtask
task run_phase(uvm_phase phase);
forever begin
#1;
`uvm_info("PHASE_TEST", "Printed forever loop", UVM_NONE)
end
endtask
endclass
Can you guess, how many line “Printed forever loop” will be displayed in forever loop of run_phase? It will never stuck forever because in main_phase, the objection is dropped after 5ns delay.
In reply to cuonghl:
Now I see that the simulation time advances when executing the instructions inside the forever loop and ultimately the run phase proceeds to the extract phase. Had there been no instructions to execute inside the forever loop (I tried this to check), the simulation time never advances and the forever loop is never exited. Thanks for the replies…:)
Hi Cuonghle, could you please explain why a task with zero timing in forever loop of run_phase will be stuck forever? I get that a forever loop goes forever but what different does a task with zero timing make? Also, isn’t that technically a function?