If you’ve visited my previous posts, you got to know by now – What is a Sequence in UVM and What is the role of a Sequence & How a Sequence works in UVM Testbench?
As a quick recap, Sequence is a dynamic key component of the UVM Testbench which is used to generate stimulus in an UVM environment. A Sequence is executed on a target Sequencer to generate usually the series of the sequence items & transact these sequence items with the UVM Driver to perform the simulation data transfer.
Before jumping to the Virtual Sequences, lets first understand the Sequence Hierarchy in UVM. It will help us to see the bigger picture of stimulus generation arrangement & process in UVM. For this, lets see the Diagram 1 below which shows the Sequence Hierarchy.
Diagram 1: Sequence Hierarchy
In this Diagram 1, we can see that there are 3 different levels of Sequences:
- Top-level Sequence aka Virtual Sequence
- Mid-level Sequences i.e. Sub-Sequences
- Bottom-level Sequences i.e. Primitive Sequences
Top-level Sequence & Mid-level Sequences practically does not send any Transaction item to the UVM Driver. Their main role is to trigger the relevant Sub-Sequences or Primitive Sequences.
A Top-level Sequence is also called Virtual Sequence. It co-ordinates between the different Sub-Sequences. For example, lets consider the DUT is having 2 different interface ports, in this situation there would be 2 Agents serving each interface port inside the UVM Testbench. Virtual Sequence will co-ordinate & synchronize the Transactions for the 2 Agents to generate the simulation uses cases using the corresponding Sub-Sequences. Virtual Sequence decides which Agent’s Sequence will start first and the order of Sub-Sequences execution. We can say, Virtual Sequence acts like a Controller of the simulation data being generated for the DUT.
Mid-level Sequences i.e. Sub-Sequences, usually, do not create transaction items. As per the sequence hierarchy scheme, Sub-Sequences provides modularity to the Sequence management. Sub-Sequences calls the Primitive Sequences in the defined order and control flow to create the required scenarios. Sub-Sequences can also do things like DUT configuration, Loading a Memory etc.
Low-level Sequences i.e. Primitive Sequences are the Sequences where the Transaction items are generated and sent to the UVM Driver and response from the Driver is received back. Function specific Sequences can be created to perform a specific function e.g. Read, Write, Read Modify & Write etc.
So by now, we’re clear that Virtual Sequence is a Top-level Sequence which controls the whole show of generating stimulus data/simulation data with the help of available Sub-Sequences and Primitive Sequences. Next, lets see the implementation & initialization approaches of the Virtual Sequence.
Virtual Sequence Implementation:
In UVM, Virtual Sequence can be implemented using 2 approaches.
- In the 1st approach, Virtual Sequence will contain itself the handles of the Agent’s Sequencers on which the Sub-Sequences are to be executed.
- In the 2nd approach, Virtual Sequence will run on a Virtual Sequencer which is of type uvm_sequencer. In this approach, Virtual Sequencer will contain the target Agent Sequencer’s handle.
In this post i.e. “How Virtual Sequence Works? – Part 1”, we’ll discuss the 1st approach.
“How Virtual Sequence Works? – Part 2” will cover 2nd approach in detail.
Virtual Sequence Implementation (1st approach):
Fundamental thing to understand in 1st approach is that the Agent’s target Sequencer handle are contained by the Virtual Sequence itself.
Apart from this, there are following points to focus upon in terms of Virtual Sequence implementation:
- Virtual Sequence declaration which includes target Sequencers handles
- The way a Virtual Sequence starts the Sub-Seqs on target Sequencers
- The way a Virtual Sequence is started from a Test class
Diagram 2 below shows an example of 1st approach.
Diagram 2: Virtual Sequence Implementation (1st approach)
As shown in the diagram above, Virtual Sequence contains two Sequencer handles i.e. SQR_AHB & SQR_AXI. There are 2 Agents i.e. AHB Agent & AXI Agent which physically contains 2 Sequencers. These 2 Sequencers are assigned to the Sequencer handles inside Virtual Sequence in a Test. As per the shown diagram above, Virtual Sequence also creates two Sequences which are to be run on the Sequencers of the respective Agents.
Lets now dive deep into the points being mentioned above to understand the Virtual Sequence implementation using 1st approach.
Virtual Sequence Class:
To develop the Virtual Sequence, its a good idea to create a “Base Virtual Sequence” which may contain the handles of all the required target Sequencers. Later this Base Virtual Sequence can be extended to create the Virtual Sequence with the code to start the Sub-Sequences on the target Sequencers. Lets analyze all this by using the UVM code below:
///// Base Virtual Sequence Class class base_vseq extends uvm_sequence #(uvm_sequence_item); `uvm_object_utils(base_vseq) /// Target Agent Sequencers uvm_sequencer #(ahb_txn) SQR_AHB; uvm_sequencer #(axi_txn) SQR_AXI; /// Constructor function new (string name = "base_vseq"); super.new(name); endfunction: new endclass: vseq_base ///// Virtual Sequence Class class my_vseq extends base_vseq; `uvm_object_utils(my_vseq) /// Constructor function new (string name = "my_vseq"); super.new(name); endfunction: new /// Sequence Body Task task body(); ahb_seqeunce ahb_seq; axi_sequence axi_seq; ahb_seq = ahb_sequence::type_id::create("ahb_seq"); axi_seq = axi_sequence::type_id::create("axi_seq"); fork abh_seq.start(SQR_AHB); axi_seq.start(SQR_AXI); join endclass: my_vseq
In the UVM code above, we got two classes i.e. & my_vseq class. base_vseq is the base virtual sequence class and my_vseq is the intended Virtual Sequence. Base virtual sequence contains the handle of the two taret Sequencers i.e. SQR_AHB & SQR_AXI.
Virtual Sequence class is extended from the Base Virtual Sequence class. It creates the two Sub-Sequences i.e. ahb_seq & axi_seq using the Factory mechanism. Later inside the body() task the Sub-Sequences are started on the target Agent’s Sequencer by the Virtual Sequence.
Starting the Virtual Sequence:
Next we need to see how the Sequencer handle assignment happens inside the Test and how the Virtual Sequence is started from the Test?
Lets further see the required UVM code for it:
///// Base Test Class class base_test extends uvm_test; `uvm_component_utils(base_test); /// Environment Class Instantiation top_env Env; /// Constructor function new (string name = "base_test", uvm_component parent = null); super.new(name, parent); endfunction: new /// Build Phase function void build_phase (uvm_phase phase); Env = top_env::type_id::create("Env"); endfunction: build_phase /// Method to Connect Sequencer Handles in VSEQ function void init_vseq (base_vseq vseq); vseq.SQR_AHB = test.env.ahb_agent.SQR_AHB; vseq.SQR_AXI = test.env.axi_agent.SQR_AXI; endfunction: init_vseq endclass: base_test
In the test base class i.e. base_test, shown UVM code above, a method i.e. init_vseq() is created which is used to assign the sequencer handles to the handles in classes derived from the virtual sequence base class.
///// Main Test class test extends base_test; `uvm_component_utils(test) /// Constructor function new (string name = "test", uvm_component parent = null); super.new(name, parent); endfunction: new /// Run Phase task run_phase (uvm_phase phase); /// Create the Virtual Sequence my_vseq vseq = my_vseq::type_id::create("vseq"); phase.raise_objection(this); /// Virtual Sequence Initialization init_vseq(vseq); /// Start the Virtual Sequence vseq.start(null); phase.drop_objection(this); endtask: run_phase endclass: test
Inside the main test which is derived from the base test, Virtual Sequence is created using Factory. Later, the initialization method i.e. init_vseq() is being called to connect the Sequencers handle. Finally Virtual Sequence is started using “Null” since this Virtual Sequence is NOT started on any particular Sequencer.
With this, I would like to pen down for the Part 1 of “How Virtual Sequence Works?”. In Part 2, we’ll discuss about 2nd approach of the Virtual Sequence Implementation.
I hope this post will provide you the value I wanted to share with all of you. Please keep sharing your valuable comments, suggestions & inputs. I love to hear from you. Thank you for your time being spent with me via my blog. Keep visiting!
Till next time, take care..bye!