How to "start" the sequence/s?

Hi all,

I have 3 sequences listed as below…

virtual class mem_base_sequence extends uvm_sequence #(mem_pkt);
...

	virtual task pre_body();
		if (starting_phase!=null) begin
			`uvm_info(get_type_name(),
				$sformatf("%s pre_body() raising %s objection", get_sequence_path(),
				starting_phase.get_name()),UVM_MEDIUM );
			starting_phase.raise_objection(this);
		end
	endtask

	virtual task post_body();
		if (starting_phase!=null) begin
			`uvm_info(get_type_name(),
				$sformatf("%s post_body() dropping %s objection", 
					get_sequence_path(),
					starting_phase.get_name()), UVM_MEDIUM);
			starting_phase.drop_objection(this);
		end
	endtask

endclass : mem_base_sequence

// SEQUENCE: mem_abv_seq

class mem_abv_seq extends mem_base_sequence;
// ...

virtual task body();
	`uvm_info(get_type_name(),"Calling mem_abv_seq sequence",UVM_LOW)
	repeat (100) begin
		#10;
	`uvm_do_with(req, 
		{ req.addr >= 150; req.data < 150; } )
	end
	//get_response(rsp);
endtask

endclass : mem_abv_seq

// SEQUENCE2: mem_blw_seq

class mem_blw_seq extends mem_base_sequence;
 ...

virtual task body();
	`uvm_info(get_type_name(),"Calling mem_blw_seq sequence",UVM_LOW)
	repeat (100) begin
	#10;
	`uvm_do_with(req, 
		{ req.addr < 150; req.data >= 150; } )
	end
	
	//get_response(rsp);
endtask

endclass : mem_blw_seq

// SEQUENCE3: mem_zero_seq

class mem_zero_seq extends mem_base_sequence;
...
virtual task body();
	`uvm_info(get_type_name(),"Calling mem_zero_seq sequence",UVM_LOW)
	repeat (10) begin
	#100;
	`uvm_do_with(req, 
		{req.addr inside {0,255}; req.data inside {0,255}; } )
	end
	`uvm_info(get_type_name()," mem_zero_seq Done!!",UVM_LOW)
	//get_response(rsp);
endtask

endclass : mem_zero_seq

Here is my seq_lib

// SEQUENCE LIB: mem_seq_lib
class mem_seq_lib extends uvm_sequence_library #(mem_pkt);
function new(string name="mem_seq_lib");
	super.new(name);
	add_sequence (mem_abv_seq::get_type());
	add_sequence (mem_blw_seq::get_type());
	add_sequence (mem_zero_seq::get_type());
	init_sequence_library();
endfunction
`uvm_object_utils(mem_seq_lib)
endclass : mem_seq_lib

Here is my test class

// Test class
class  mem_test extends uvm_test;

	`uvm_component_utils(mem_test)

     // TB handle
     mem_tb memtb;
     
     mem_seq_lib seq_lib;
     
	// Constructor
	function new(string name = "mem_test", uvm_component parent);
		super.new(name, parent);
	endfunction: new

	// Build phase
	virtual function void build_phase(uvm_phase phase);
		//Create memtb
		memtb = mem_tb::type_id::create ("memtb",this);
		//Setting default Seq for the Seqr
		uvm_config_wrapper::set(this,"memtb.memenv.agents[0].seqr.run_phase","default_sequence",mem_zero_seq::type_id::get());
		super.build();
	endfunction :build_phase

    //End of elaboration phase
	function void end_of_elaboration_phase(uvm_phase phase);
		uvm_report_info(get_full_name(),"End of Elaboration",UVM_LOG);
		print();
	endfunction : end_of_elaboration_phase
	
	//Run Task
	task run_phase (uvm_phase phase);
		`uvm_info(get_type_name(),
				$sformatf("Test Raising Objection"),UVM_MEDIUM);
		uvm_test_done.raise_objection (this);
		
		//seq_lib.mem_blw_seq.starting_phase = phase;
		//seq_lib.mem_blw_seq.start(memtb.memenv.agents[0].seqr);
		#2000;
		global_stop_request();
		//To stop the run_phase
		`uvm_info(get_type_name(),
			$sformatf("Test Dropping Objection"), UVM_MEDIUM);
		uvm_test_done.drop_objection (this);
	endtask : run_phase

endclass

When I tried to start a sequence (other than default_sequence) from the test run_phase, I’m getting compliant…

Let say I have only one sequencer which is “seqr”

Can you anyone explain me, how to start the sequence?

Appropriate place to start.

John

There is no reason to create a sequence library. Just create the sequence you want to start, then start it.

There is no reason to raise/drop objections on every sequence if your test does it for you and the sequence blocks until it is done. It’s extra overhead.

There is no reason to be using legacy OVM global_stop_request() as it has been deprecated. Dropping the objection will end the run_phase.

In reply to dave_59:

Dave,

I aware that seq_lib is not mandatory for this test. I have another seq_lib_test, which is using seq_lib (randomly selecting sequences in different order).

Yes, I agree “global_stop_request()” added for no reason. I was explaining that to my peer, but forgot to comment it out here.

But I did not understand “no reason” for raise/drop objection. I have added raise/drop objection in pre/post body of each sequences, to hole the control from the sequences.

Here I have cases as below…
Case 1:

  1. raise objection from uvm_test run_phase
  2. raise objection from seq1
  3. raise objection from seq2
  4. drop objection from seq2
  5. drop objection from seq1
  6. drop objection from uvm_test run_phase

Case 2:

  1. raise objection from uvm_test run_phase
  2. raise objection from seq1
  3. drop objection from seq1
  4. some delay
  5. raise objection from seq2
  6. drop objection from seq2
  7. drop objection from uvm_test run_phase

Case 3:

  1. raise objection from uvm_test run_phase
  2. raise objection from seq1
  3. raise objection from seq2
  4. drop objection from seq1
  5. drop objection from uvm_test run_phase
  6. drop objection from seq2

Case 4:

  1. raise objection from uvm_test run_phase
  2. raise objection from seq1
  3. drop objection from seq1
  4. drop objection from uvm_test run_phase
  5. <seq2 did not started yet, but test done>

How to achieve above scenarios??

At present, I’m using random delay (#1000;) from the test.

sometimes, sequence/s did not start, till end of delay, and test ends.

John

In reply to John Verif:

John,
Since in all scenarios you list, the sequence(s) is/are started from the test, and the sequences are blocking, you simply raise the objection from the test at the beginning of run_phase, and drop it when the last sequence completes.

In your case 3, it’s not clear why you want to drop the objection from uvm_test.run_phase before the sequence completes. I’m assuming you’ve initiated the sequence from a fork/join_none. In that case, it would be appropriate to raise an objection from the test before starting the sequence, and dropping the objection when the sequence returns within the fork/join_none. But you still don’t need to raise/drop and objection from the sequence in any case.
-Tom

I do the objections and start my sequences from my test which extends my uvm test.
In my following code I run 2 sequences on the same sequencer from my top level test.


class class_test_ge extends class_bb_test;
   `uvm_component_utils(class_test_ge)
   // my sequences
   seq_usb_host_ctrl       c_seq_usb_host_ctrl;
   seq_usb_host_bulk_in_out c_seq_usb_host_bulk_in_out;

function void build_phase(uvm_phase phase);
   super.build_phase(phase);
   // create the sequences
   c_seq_usb_host_ctrl = new("c_seq_usb_host_ctrl");
   c_seq_usb_host_bulk_in_out = new("bulk_in_out");

   // get the ref to the sequencer
   if (!uvm_config_db#(uvm_sequencer_base)::get(null, "", "usb_host_sqr", usb_host_sqr))
         `uvm_fatal("NOVIF", {"Usb Host sequencer must be set for: ", get_full_name(), ".usb_host_sqr"});
endfunction

task main_phase(uvm_phase phase);
   phase.raise_objection(this);
   fork
      c_seq_usb_host_ctrl.start(usb_host_sqr);
      c_seq_usb_host_bulk_in_out.start(usb_host_sqr);
   join_any

   // run the test for 200 usec
   #200_000;
   phase.drop_objection(this);
endtask

endclass

The lower level agent adds the name of the sequencer to the uvm_config_db and then the top level test gets the ref to sequencer from the uvm_config_db and uses this as the ref for the sequence.start function.
I used to do the objection in the pre_body and post_body of the sequence because I saw this in one of the uvm examples. I do not believe this correct and only the top level test should raise and drop the objection. This allows the top level test to control the duration of the sim and not the sequence.

In reply to kkejser:

Thanks Guys, I got it!!

John