Hi Dave,
In one of the thread i have asked a question and you had responded to ask in new thread since that thread is quite long.
I have a question in mind, how does this below piece of code suitable for clock-based and event based simulations.
for(int i = 0; i < 5; i++) begin
automatic int j;
j = i;
fork
thread(j);
join_none
end
I am particularly looking for to understand clock-based simulation on above explained code by you.
It helps to understand for implementing some checks for other requirements.
Your inputs are much appreciated.
Sreeni.
Reason to having this question is from this below code.
for(int i = 0; i < 5; i++) begin
automatic int j;
j = i;
fork
if(blk_en[j]) begin
l_hw_timer0_on = 1;
l_hw_timer4_on = 0;
if(l_hw_timer0_on) begin
l_hw_timer0 ++ ;
if(l_hw_timer0==10) begin
l_cntr0[j] = l_cntr0[j] + 1;
end
if(l_cntr0[j]==5) begin //some threshold value
l_hw_timer0 = 0;
l_hw_timer4_on = 1;
end
//display statement having [j]
end //timer0
//timer4 starts as show on above for some requirement
end
join_none
end
``` verilog
Here timer increment is on clock based.
Needs some information whether this spawns all the values of j.
I thought I understood what you meant by clock-based simulation until I saw your second post. I think of clock-based (sometimes also called cycle-based) simulation of SystemVerilog is an optimization of the scheduling algorithm by making assumptions about the coding style, or through simplifications/disregarding other features like #delays. Can you please explain what you mean using more descriptive words?
The point of the original example was demonstrating the fact that arguments the task ‘thread()’ won’t get passed until after for-loop has finished all its iterations. The reply in my previous post explains a way to get unique value arguments for each iteration.
It’s not clear to me what behavior you’re looking for in your last post. It would certainly help to show where the declarations of all variables in your code are located. (i.e. which are global, and which are local to the forked processes.
for(int i = 0; i < 5; i++) begin
automatic int j;
j = i;
fork
if(blk_en[j]) begin ----> this is global, snooped from interface
l_hw_timer0_on = 1; -->timers are local which are dependent on each other
l_hw_timer4_on = 0;
if(l_hw_timer0_on) begin
l_hw_timer0 ++ ; --> this timer give interval between the events triggered
if(l_hw_timer0==10) begin
l_cntr0[j] = l_cntr0[j] + 1; -->local counter
end
if(l_cntr0[j]==5) begin //some threshold value --> counter equals rtl value
l_hw_timer0 = 0;
l_hw_timer4_on = 1;
end
//display statement having [j]
end //timer0
//timer4 starts as show on above for some requirement
end
join_none
end
This kind piece of code is sitting in state machine under a state in forever block
Please let me know your inputs.
In reply to nivas:
Bit length code to show you actual implementation.
Purpose is to check the event intervals are meeting with defined values, this is one of the state.
please let me know does this takes for all for loop values.
fork
forever begin
@(posedge i_dut.sample_clk);
STATE1: begin
for(int l_c_num=0; l_c_num <=3; ++l_c_num) begin : for_loop
fork
automatic int l_n_num = l_c_num;
begin
if(m_b_blk0_en[l_n_num] ==1 && m_b_blk4_en[l_n_num]==1) begin
l_blk0_timer_on = 1;
l_blk4_timer_on = 0;
l_b_blk_en[l_n_num] = 1;
l_s_blk_name[l_n_num] = $sformatf("\"block%0d\"",l_n_num);
if(l_blk0_timer_on==1) begin
l_blk0_timer ++;
l_blk4_timer = 0;
if(l_blk0_timer == m_n_base_tr) begin //RTL value m_n_base_tr
//increment blk0_cntr on every base_timer clocks cycles
//blk0 and blk4 are local variable counters
l_n_blk0_cntr[l_n_num] = l_n_blk0_cntr[l_n_num] + 1;
//sum every count blk0_timer
l_event_interval[l_n_num] = l_event_interval[l_n_num] + l_blk0_timer;
//reset blk0_timer on every base_timer reach
l_blk0_timer = 0;
end
//condition to check cntr value equals thr value
if(l_n_num==0) begin
if(l_b_blk_en[l_n_num]==1) begin
//RTL values
if(m_b_blk0_thr[0] > m_b_blk0_thr[1] + m_b_blk0_thr[2] + m_b_blk0_thr[3]) begin
if(l_n_blk0_cntr[l_n_num]==m_b_blk0_thr[l_n_num]) begin
//blk0_cntr becomes 0 after blk0_cntr=blk0_thr
l_n_blk0_cntr[l_n_num] = 0;
//check RTL blk0_cntr is equals to local blk0_cntr
if(l_n_blk0_cntr[l_n_num]==m_b_blk0_cntr[l_n_num])
l_b_blk0_cntr_expired[l_n_num] = 1;
end
end
end
end
else if(l_n_num==1) begin
if(l_b_blk_en[l_n_num]==1) begin
if(m_b_blk0_thr[1] > m_b_blk0_thr[0] + m_b_blk0_thr[2] + m_b_blk0_thr[3]) begin
if(l_n_blk0_cntr[l_n_num]==m_b_blk0_thr[l_n_num]) begin
//blk0_cntr becomes 0 after blk0_cntr=blk0_thr
l_n_blk0_cntr[l_n_num] = 0;
//check RTL blk0_cntr is equals to local blk0_cntr
if(l_n_blk0_cntr[l_n_num]==m_b_blk0_cntr[l_n_num])
l_b_blk0_cntr_expired[l_n_num] = 1;
end
end
end
//check for events after blk0_cntr expired
if(l_b_blk0_cntr_expired[l_n_num]==1) begin
//condition to check eventtart event on rank blk0(master)
if(m_event_start) begin //RTL signal snoop
l_event_start[l_n_num] ++;
//set flag once eventtart event is issued
l_b_mpc_event_start_done[l_n_num] = 1;
//event_start min intervals check ////l_event_min_interval is a constant value
if(l_event_interval[l_n_num]>l_event_min_interval[l_n_num]) begin
///check PASS
end
else begin
///Check FAIL
end
//reset blk0_timer & enable blk4_timer_on
l_blk0_timer = 0;
l_blk4_timer_on = 1;
l_blk0_timer_on = 0;
end //event_start
end //blk0_cntr_expired
end //blk0_timer
end //blk_en
end
join_none
end : for_loop
wait fork;
``` verilog