Issue with triggering event using uvm_event

Hi,

I have two uvm components producer and consumer, which are connected in test_lib.sv. I have declared an event in consumer and I wait for that trigger. The display after event wait is not printed. I think the trigger not happening properly, Am I MISSING ANYTHING?

I am giving an executable code here:

filename: filelist.svh


`include "uvm_pkg.sv"
import uvm_pkg::*;
`include "axi_tx.sv"
`include "producer.sv"
`include "consumer.sv"
`include "top.sv"

filename: axi.tx.sv


class axi_tx extends uvm_sequence_item;

	bit [31:0] awaddr;
	bit [2:0] awburst;
	bit [2:0] awsize;
	bit [3:0] awlen;
	bit [31:0] wdata[$];
	bit test_bit;

	`uvm_object_utils_begin (axi_tx) // add the following fields to existing methods (pack,print,compare,etc..)

		`uvm_field_int(awaddr, UVM_ALL_ON);
		`uvm_field_int(awburst, UVM_ALL_ON);
		`uvm_field_int(awsize, UVM_ALL_ON);
		`uvm_field_int(awlen, UVM_ALL_ON);
		`uvm_field_queue_int(wdata, UVM_ALL_ON);
		
	`uvm_object_utils_end

	function new (string name ="");  
		super.new(name); 	
	endfunction
endclass

filename: top.sv


module top;
	
	`include "test_lib.sv"
       initial begin
	 run_test();
       end 
endmodule

filename: test_lib.sv


class base_test extends uvm_test;
	
	producer prod_h;
	consumer cons_h;
	uvm_table_printer printer_h;

	`uvm_component_utils(base_test)

	function new (string name="", uvm_component parent=null);

		super.new(name,parent);		
		printer_h=new();
	endfunction
	
	function void build_phase(uvm_phase phase);
		
		super.build_phase(phase);
		prod_h = producer::type_id::create("prod_h",this);
		cons_h = consumer::type_id::create("cons_h",this);

	endfunction	

	function void connect_phase(uvm_phase phase);
		
		super.connect_phase(phase);
		// connection  between prod and cons
		prod_h.put_port.connect(cons_h.put_imp); //  

	endfunction

	function void end_of_elaboration_phase (uvm_phase phase);
				
		`uvm_info(get_type_name(), $psprintf("Printing the test topology : \n%s", this.sprint(printer_h)), UVM_LOW); // (ID,msg,verbosity) 
				// sprint returns as string 
	endfunction		
	

endclass

filename: producer.sv


class producer extends uvm_component;
	`uvm_component_utils(producer)
	uvm_blocking_put_port#(axi_tx) put_port; // put_port of producer
        axi_tx tx;
        function new (string name="", uvm_component parent=null);
		super.new(name,parent);		
	endfunction
	
	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		put_port = new("put_port", this);
       endfunction

       function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
       endfunction

       task run_phase(uvm_phase phase);
                 repeat(3) begin 
			tx = axi_tx::type_id::create("tx");
			assert(tx.randomize());
			tx.test_bit = 1;
			put_port.put(tx); // defined put in consumer
		end 	       
	endtask		
endclass

filename:consumer.sv


class consumer extends uvm_component;

	`uvm_component_utils(consumer)
         uvm_blocking_put_imp#(axi_tx, consumer) put_imp;
         uvm_event event_h;

	function new (string name="", uvm_component parent=null);	
		super.new(name,parent);		
	endfunction	

	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		put_imp = new("put_imp", this); // use it for consumer without subcomponents
		event_h = new("event_handle");
		//event_h.reset();
	endfunction

        function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
        endfunction
        
        task dummy_print();
           $display("display before event wait");
           event_h.wait_trigger(); // waiting for the event
	   $display("event triggered due to bit set to 1"); // issue here, am I not getting this print ?
	endtask
      
        task put(axi_tx tx1); 
		$display("consumer received contents");
                $display("test_bit = %0d",tx1.test_bit);
		//tx1.print();
		if (tx1.test_bit == 1) begin 
			$display("test_bit condition satisfied");
                        fork
                        begin 
                          $display("event trigger at time %0t", $time);
                          #10; // intentionally delaying to make dummy_print task to be called first
			  event_h.trigger();
			  //event_h.is_on();
                        end
                        begin 
			  $display("calling dummy_print task in put imp");
                	  dummy_print(); 
                        end 
                        join
		end 
	endtask 

endclass

Thanks your help is appreciated.

In reply to rakesh2learn:

Hi

  1. Close the fork construct with “join”.
  2. Remove the delay.

Now run.

@Sunils ok “join” was missing in consumer component when I pasted here. It was a typo. However why i should remove the delay? Moreover removing delay also doesn’t fix the issue.

In reply to rakesh2learn:

Here is the output in QuestaSim after using fixes:

# ------------------------------------------------
# Name          Type                   Size  Value
# ------------------------------------------------
# uvm_test_top  base_test              -     @457 
#   cons_h      consumer               -     @473 
#     put_imp   uvm_blocking_put_imp   -     @481 
#   prod_h      producer               -     @465 
#     put_port  uvm_blocking_put_port  -     @491 
# ------------------------------------------------
# 
# consumer received contents
# test_bit = 1
# test_bit condition satisfied
# event trigger at time 0
# calling dummy_print task in put imp
# display before event wait
# event triggered due to bit set to 1
# consumer received contents
# test_bit = 1
# test_bit condition satisfied
# event trigger at time 0
# calling dummy_print task in put imp
# display before event wait
# event triggered due to bit set to 1
# consumer received contents
# test_bit = 1
# test_bit condition satisfied
# event trigger at time 0
# calling dummy_print task in put imp
# display before event wait
# event triggered due to bit set to 1
# 
# --- UVM Report Summary ---
# 
# ** Report counts by severity
# UVM_INFO :    4

Why you are putting the delay?

that is very strange. I didn’t get that display.
This is my output.

------------------------------------------------
# Name          Type                   Size  Value
# ------------------------------------------------
# uvm_test_top  base_test              -     @490 
#   cons_h      consumer               -     @506 
#     put_imp   uvm_blocking_put_imp   -     @514 
#   prod_h      producer               -     @498 
#     put_port  uvm_blocking_put_port  -     @524 
# ------------------------------------------------
# 
# consumer received contents
# test_bit = 1
# test_bit condition satisfied
# event triggered at time 0
# calling dummy_print task in put imp
# display before dummy_print
# 
# --- UVM Report Summary ---
# 
# ** Report counts by severity
# UVM_INFO :    3

In reply to rakesh2learn:

To debug your problem you can make the following modification in the consumer code:

replace the fork/join with a fork/join_any. Then you see the second process in this concurrent process is called first. I believe it is not a good idea to use the wait_trigger and trigger in the same process.