At the start of simulation, my bfm initializes its local memory image with random packets. It also broadcasts via an analysis port, the same initialization packets, so that subscribers may set their internal memories to the same initial values.
The code looks something like: (i’ve just typed it out … might not be syntax error free)
function void configure();
init_pkt = new();
broadcast_pkt = new();
for (int i = 0; i < num_init_packets; i++)
begin
init_pkt.randomize();
update_local_image(init_pkt);
broadcast_pkt.a = init_pkt.a;
broadcast_pkt.b = init_pkt.b;
broadcast_pkt.c = init_pkt.c;
my_analysis_port.write(broadcast_pkt);
end
endfunction: configure
At another place, an analysis_fifo’s analysis_export is connected to this my_analysis_port. At yet another place, a slave bfm subscribes to this analysis_fifo’s blocking_get_export (subscribing to a nonblocking_get_export doesnt help either). Thus, a master bfm, an analysis port and a slave bfm are hooked up.
The problem I have is that the slave bfm only sees the last packet written when it calls the get task!
However, if I put the code above within a task and put a #0 at the end of the for loop, like below, it works:
//function void configure();
virtual task run();
init_pkt = new();
broadcast_pkt = new();
for (int i = 0; i < num_init_packets; i++)
begin
init_pkt.randomize();
update_local_image(init_pkt);
broadcast_pkt.a = init_pkt.a;
broadcast_pkt.b = init_pkt.b;
broadcast_pkt.c = init_pkt.c;
my_analysis_port.write(broadcast_pkt); #0;
end
endtask: run;
//endfunction: configure
I thought the ideal place to do what I want to do is the configure() function since it happens before anything starts. But I had to put an ugly #0 in a task to get it working. Can anyone please suggest any cleaner alternatives?
I need to use an analysis port since there could be multiple subscribers.
I think your problem is that you are overwriting the same packet (broadcast_pkt) many times before the subscriber code gets a chance to read it. write() does not block, so when you write, you are just copying the handle into the analysis fifo, then you are looping around and overwriting the memory that that handle is pointing to. So, at the end of your loop, you have a bunch of handles in the fifo pointing to the same object in memory.
By adding a #0, you are giving the other code a chance to execute before you overwrite the bloadcast_pkt object.
I would suggest you write your loop to do this:
for (int i = 0; i < num_init_packets; i++)
begin
init_pkt.randomize();
update_local_image(init_pkt);
**broadcast_pkt = init_pkt.clone();**
my_analysis_port.write(broadcast_pkt);
end
the clone() method takes care of all the copying of fields, but it also creates a new, fresh packet object. Now, each time through the loop, the handle that gets written into the fifo will be pointing to a different object.
Hi Kurt,
I have similar problem with the analysis port.
The below is the monitor task calling the write function to push the data from Monitor to Scoreboard.
The prints after the port write functions are going fine but still the Scoreboard get function(which is connected to the monitor port) is not really getting started not even once. What can be the problem here?
task monitor_task();
Packet txn,temp_txn;
forever begin
@(posedge clk)
if(rx_mon_req.size())begin
txn = rx_mon_req.pop_front();
$cast(temp_txn,txn.clone());
Drv2SbRx_port.write(temp_txn);
#0;
repeat (4) @(posedge clk);
\`ovm_info(get_type_name(),$psprintf("Sending data to scoreboard:%h ",temp_txn.data), OVM_MEDIUM)
end //if
end //forever
endtask
Am i missing something ? I am using VCS for running this. I have checked that port is connected properly and also if i remove the forever and make sure execute the whole task for a single time, then it is started working fine. So, now i dont understand how the forever loop is causing the problem even after using the clone function and delays. Or any other ways to debug this.
Hi Polas,
The code is looking fine.
Try checking connections once again, by calling the debug_connected_to and debug_provided_to methods on scoreboard export once again.
Thanks Vishnu.
I will try with these dubug options.
If i use the port_name.debug_connected_to() function in the end_of_elaboration phase, it shows that one import is connected to this. But during the run time, the ovm_port_base::size() function is returning ‘0’ which is not correct and i came to know about this after debugging the VCS step by step execution.
Does it look like simulator issue? As multiple instances of this class is being used, simulator is it getting confused or something like that…