Search code examples
eventsspecman

specman event is counted although it wasn't fired


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?


Solution

  • 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;
    };