How to execute sequence from test?

Hi

I’m trying to understand about sequence mechanism from uvm_test and I found that there are 2way of implementing test with sequence.

**1. using uvm_config_wrapper::set(this, “yapp.tx_agent.sequencer.run_phase”,
“default_sequence”,
yapp_5_packets::type_id::get());

  1. using sequencer and sequence in uvm_test

**

====================================================================================

So I’ve implemented simple example of uvm_config_wrapper as the below
https://www.edaplayground.com/x/Tmer

But Problem is that I can’t getting run the sequence from uvm_test.

Here is my test code,

class apb_basic_test extends uvm_test;
  int packets;
  
  `uvm_component_utils_begin(apb_basic_test)
  `uvm_field_int(packets,UVM_ALL_ON)
  `uvm_component_utils_end
 
  apb_master_environment apb_environment;
 
  
  function new(string name, uvm_component parent);
    super.new(name,parent);
    `uvm_info(get_type_name(),"the objection test object has been built",UVM_LOW);
  endfunction
  
    function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    apb_environment = apb_master_environment::type_id::create("apb_environment", this);
    
    
         uvm_config_wrapper::set(this, "apb_environment.apb_agent.sequencer.run_phase",
                            	 "default_sequence",
                            sylee_apb_sequence::type_id::get());
  
      
  endfunction 
  
  
  virtual function void connect_phase(uvm_phase phase);
   `uvm_info(get_type_name(),"the connect phase of the basic_test completed", UVM_LOW)
  endfunction
  
  virtual function void start_of_simulation_phase(uvm_phase phase);
    uvm_top.print_topology();
  endfunction
  
 
endclass

class seq_from_test extends apb_basic_test;
  `uvm_component_utils(seq_from_test)
  
  apb_sequencer s_apb_sequencer;
  apb_sequence  s_apb_sequence;
  
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    s_apb_sequence = apb_sequence::type_id::create("s_apb_sequence", this);
    super.build_phase(phase);
  endfunction
  
  task run_phase(uvm_phase phase);
    s_apb_sequence.start(s_apb_sequencer);
  endtask
  
  function void connect_phase(uvm_phase phase);
    s_apb_sequencer = apb_environment.apb_agent.sequencer;
  endfunction
endclass
  
    

I surely connected with sequence and sequencer in uvm_test class as the below. But I can’t understand why sequence does not work as well?

class seq_from_test extends apb_basic_test;
  `uvm_component_utils(seq_from_test)
  
  apb_sequencer s_apb_sequencer;
  apb_sequence  s_apb_sequence;

Would you please help me how to run the sequence from https://www.edaplayground.com/x/Tmer ?

In reply to UVM_LOVE:

Running a sequence with the “default_sequence” method is a poor practice and not recommended. It is better to start all of the required sequences at the test level.

Also, you have no objections. Your run_phase will immediately end, and you won’t see the “default_sequence” run.

In reply to cgales:

Thanks cgales,
Got It, I won’t running a sequence with default_sequence method. but at this time this is for understanding each method. so please understand me.

so I make 2 run_tests

  1. for uvm_config_wrapper test
  2. for sequence from uvm_test test

I understand sequence from test need raise/drop objection as your answer,
but I can’t understand still I need raise/drop objection in uvm_config_wrapper?

Could you guide me with some code for understand? My run_phase still immediately end.

In reply to UVM_LOVE:

In the test you are running (seq_from_test), you are starting ‘apb_sequence’. In ‘apb_sequence’, you are sending ‘packets’ number of packets. Since ‘packets’ is never set to any specific value, it defaults to 0, hence the sequence not doing anything and the test immediately exiting.

In reply to cgales:

In reply to UVM_LOVE:
In the test you are running (seq_from_test), you are starting ‘apb_sequence’. In ‘apb_sequence’, you are sending ‘packets’ number of packets. Since ‘packets’ is never set to any specific value, it defaults to 0, hence the sequence not doing anything and the test immediately exiting.

  1. Thank you Sir, I found it. And, I set uvm_config_db#(int)::set(null,“*”,number_of_packets",i); in testbench.sv

and I get a ‘packets’ by if(!uvm_config_db#(int)::get(this,“”,number_of_packets",packets))
'uvm_info(get_type_name(), “the getting of packets variable failed”,UVM_LOW)

and I checked packets value 20 from apb_basic_test class.

but stil my sequence can’t get a packets variable from parent class.
I though that if parent get a packets value from uvm_config_db , this packets properties will be inherited to child class. so I could use packets variable in uvm_config_wrapper_from_test and seq_from_test class. but when I check it packets variable value is still 0 which means the packets variable couldn’t pass to child class.

Do I need to get a packets value at every each sequence?
(Not sure but I already add
if(!uvm_config_db#(int)::get(this,“”,number_of_packets",packets))
'uvm_info(get_type_name(), “the getting of packets variable failed”,UVM_LOW)
to every sequence then it seems work. but is this right way?

  1. if I choose “uvm_config_wrapper_from_test”, sylee_apb_sequence can’t get a next stage .
    It’s stuck on create apb_sequence_item.
    so could you guide me how to resolve this?

In reply to UVM_LOVE:

You need to assign the value that you get for packets in your sequence.


class seq_from_test extends apb_basic_test;
  `uvm_component_utils(seq_from_test)
  
  apb_sequence  s_apb_sequence;
  
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  task run_phase(uvm_phase phase);
    phase.raise_objection(this, "s_apb_sequence");
    s_apb_sequence = apb_sequence::type_id::create("s_apb_sequence", this);
    if(!uvm_config_db#(int)::get(this,"","number_of_packets",s_apb_sequence.packets))
      `uvm_info(get_type_name(),"the getting of packets variable failed",UVM_LOW)
    s_apb_sequence.start(apb_environment.apb_agent.sequencer);
    phase.drop_objection(this, "s_apb_sequence");
  endtask
  
endclass

In reply to cgales:

Thank you Sir,

I got you what you are trying to say for the sequence.
and I resolve it.

If you Ok, I’d like to ask one more thing about stuck on uvm_config_wrapper_from_test class issue.
I learn uvm_config_wrapper starting method doesn’t recommended from you Sir. but is that reason for my stuck on problem when I choose class uvm_config_wrapper_from_test in testbench.sv?

In reply to UVM_LOVE:

In your “uvm_config_wrapper_from_test” class, you have no objections in the run_phase(). Without any objections, the test will immediately finish at time 0.

In reply to cgales:

In reply to UVM_LOVE:
In your “uvm_config_wrapper_from_test” class, you have no objections in the run_phase(). Without any objections, the test will immediately finish at time 0.

Sir, I added the below at run_phase

phase.raise_objection(this);
phase.drop_objection(this);

Sir I’ve got a question.
Should I have to make it the same as seq_from_test class? because There is no any reference sequence or sequencer. I think something need to it. but I can’t find any reference of example. Although I can make a similar logic as class seq_from_test But there is no reason for using uvm_config_wrapper as the below doesn’t it?

    uvm_config_wrapper::set(this, "apb_environment.apb_agent.sequencer.run_phase",
                          	 "default_sequence",
                          sylee_apb_sequence::type_id::get());

Could you guide me once again?

https://www.edaplayground.com/x/i5zX

class uvm_config_wrapper_from_test extends apb_basic_test;
  `uvm_component_utils(uvm_config_wrapper_from_test)
   
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    `uvm_info(get_type_name(),"uvm_config_wrapper_from_test_build_phase ",UVM_LOW)      
    uvm_config_wrapper::set(this, "apb_environment.apb_agent.sequencer.run_phase",
                          	 "default_sequence",
                          sylee_apb_sequence::type_id::get());
    
    super.build_phase(phase);
  endfunction
  
  task run_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info(get_type_name(),"uvm_config_wrapper_from_test_run_phase ",UVM_LOW)    
   phase.drop_objection(this);
  endtask

In reply to UVM_LOVE:

This is why you should never use the “default_sequence”. There is nothing that consumes time at the test level where you raise/lower the objection. The “default_sequence” was intended to run background sequences that run throughout the entire test. You can’t use this method for a test-specific sequence.

In reply to UVM_LOVE:

In general, you want all of the testbench stimulus generation and response (i.e. sequences) to be configured/started during the run_phase() of your test. This is desired to allow the user to control the exact relationship between these sequences.

The problem is taht you do not set a value for ‘packet’ in your sequence. It is initialized to 0 and is not doing anything.
Additionally you should simplify your body task in the sequence. Please use start_item/finisch_item!
The setting of the default sequence is wrong. It has to be:

uvm_config_wrapper::set(this, “apb_environment.apb_agent.sequencer.run_phase”, “default_sequence”, sylee_apb_sequence::get_type());

And your driver does not have aclock signal. It is not progressing in time and getting values back from the DUT.
See a working example here:

Using the default_sequence makes your simple application so complicated!

There are several reasons using a default_sequence doesn’t follow this:

  • Setting a default_sequence is done outside of the run_phase(). Additionally, changing the default_sequence requires changes outside of the run_phase().
  • There is no mechanism to control when the default_sequence starts, other than at the beginning of a specific phase.
  • You can’t run more than one sequence
  • You can’t easily run additional sequences on the same sequencer
  • Debugging a default_sequence can be difficult since the user may not be aware that the default_sequence exists.
  • The default_sequence can’t be randomized() or otherwise configured

It’s simple enough to create()/randomize()/start() a single sequence at the beginning of the run_phase() instead of setting a default_sequence.