My BFM should fire an event rd_trig_o. As seen below rd_trig_o is an event port that is triggered after drive_packet was done:
unit collector_bfm_u like uvm_bfm {
!p_smp : collector_smp_u;
!p_drv : collector_driver_u;
!pkt : collector_packet_s;
p : collector_data;
port_num : uint (bits:2);
event clk_e is rise (p_smp.clk_in$) @sim;
rd_addr_o : out buffer_port of addr_t is instance;
rd_trig_o : out event_port is instance;
keep rd_addr_o.buffer_size() == 4;
!rd_address_fifo : deque of (addr_t);
run() is {
rd_address_fifo = new;
start run_main_tcms();
};
run_main_tcms() @clk_e is {
--wait true (p_smp.rst_in$ == 0); // wait till reset is negated
wait delay(10);
message(LOW,"out of reset!!!");
all of {
{request_and_drive_packet()};
{send_rd_address()};
}
};
request_and_drive_packet() @clk_e is {
while (TRUE) {
pkt = p_drv.get_next_item();
drive_packet( pkt );
emit p_drv.item_done;
};
};
drive_packet(req: collector_packet_s) @clk_e is {
var signal_name : string;
p_smp.i_we_b[port_num]$ = req.we_b;
p_smp.i_addr_b[port_num]$ = req.addr_b;
rd_address_fifo.push(req.addr_b);
emit rd_trig_o$;
};
My monitor should sample after event was fired. sample_data() TCM waits for an event rd_trig_i in order to sample data:
unit collector_monitor_u like uvm_monitor {
!p_smp : collector_smp_u;
event clk_e is fall (p_smp.clk_in$) @sim;
port_num : uint (bits:2);
rd_data_o : out buffer_port of data_t is instance;
rd_trig_i : in event_port is instance;
keep rd_data_o.buffer_size() == 4;
run() is {
start run_main_tcms();
};
run_main_tcms() @clk_e is {
sample_data();
};
sample_data() @rd_trig_i$ is {
var rd_data: bit;
var data_value: data_t;
while (TRUE) do {
wait cycle;
rd_data = p_smp.i_we_b[port_num]$;
if (rd_data == 0) {
data_value = p_smp.o_q_b[port_num]$;
rd_data_o.put(data_value);
outf("read data = %d \n", data_value);
}
}
};
};
The monitor and bfm event ports are bind at the agent:
keep bind(bfm.rd_trig_o, mon.rd_trig_i);
But in the simulation the monitor sample without waiting for the event to be fired. Why the monitor doesn't wait to bfm event?
In a small example (kept only the stuff related to the event port), i can see that the monitor does get triggered correctly. are you sure it was triggered before the bfm emitted?
<'
struct collector_packet_s {};
unit collector_bfm_u {
!pkt : collector_packet_s;
event clk_e is @sys.any;
rd_trig_o : out event_port is instance;
run() is also {
start request_and_drive_packet();
};
request_and_drive_packet() @clk_e is {
raise_objection(TEST_DONE);
for i from 0 to 3 {
wait [5] * cycle;
gen pkt;
drive_packet( pkt );
};
drop_objection(TEST_DONE);
};
drive_packet(req: collector_packet_s) @clk_e is {
message(LOW, "drive_packet now emits");
emit rd_trig_o$;
};
};
unit collector_monitor_u {
event clk_e is @sys.any;
rd_trig_i : in event_port is instance;
run() is {
start sample_data();
};
sample_data() @rd_trig_i$ is {
message(LOW, "sample_data starts, ",
"because the port was triggered");
while (TRUE) do {
wait cycle;
message(LOW, "sample_data waited cycle, ",
" port triggered again");
};
};
};
unit env_u {
bfm : collector_bfm_u is instance;
mon: collector_monitor_u is instance;
keep bind(bfm.rd_trig_o, mon.rd_trig_i);
};
extend sys {
env : env_u is instance;
};