UVM Driver sequencer handshaking

1,762 views 19 slides Aug 12, 2020
Slide 1
Slide 1 of 19
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19

About This Presentation

UVM Driver sequencer handshaking


Slide Content

DRIVER AND SEQUENCER

Sequencer G enerates stimulus data and passes it to a driver for execution. The sequencer controls the flow of request and response sequence items between sequences and the driver Uses uvm_sequencer base class, which is parameterized by the request and response item types. The uvm_sequencer base class contains all of the base functionality required to allow a sequence to communicate with a driver. class  sequencer  extends   uvm_sequencer #( seqss_item );      ` uvm_sequencer_utils (sequencer)    function   new  ( string  name,  uvm_component parent);      super . new (name, parent);    endfunction  :  new endclass  

Driver The driver’s role is to drive data items to the bus following the interface protocol. The UVM Class Library provides the uvm_driver base class, from which all driver classes should be extended. The driver has a TLM port through which it communicates with the sequencer. The driver implement the run phase define its operation. To create a driver: a) Derive from the uvm_driver base class. b) If desired, add UVM infrastructure macros for class properties to implement utilities for printing, copying, comparing, and so on. c) Obtain the next data item from the sequencer and execute it. d) Declare a virtual interface in the driver to connect the driver to the DUT.

Driver Example code

Connecting the Driver and Sequencer The driver and the sequencer are connected via TLM, with the driver’s seq_item_port connected to the sequencer’s seq_item_export . The sequencer produces data items to provide via the export. The driver consumes data items through its seq_item_port and, optionally, provides responses. function void mas_agt :: connect_phase ( uvm_phase phase);     if( m_cfg.is_active == UVM_ACTIVE) begin     m_dri.seq_item_port.connect ( m_seqr.seq_item_export ); end endfunction

Basic Sequencer and Driver Interaction Basic interaction between the driver and the sequencer is done using the tasks get_next_item () and item_done (). the driver uses get_next_item () to fetch the next randomized item to be sent. After sending it to the DUT, the driver signals the sequencer that the item was processed using item_done (). forever begin get_next_item ( req ); // Send item following the protocol. item_done (); end get_next_item () is blocking until an item is provided by the sequences running on that sequencer.

Try_next_item Try_next_item will return in the same simulation step if no data items are available for execution. we can use this task to have the driver execute some idle transactions, such as when the DUT has to be stimulated when there are no meaningful data to transmit.

Sending Processed Data back to the Sequencer In some sequences, a generated value depends on the response to previously generated data. So the driver needs to return the processed response back to the sequencer. Do this using the optional argument to item_done (), seq_item_port.item_done ( rsp ); or using the put_response () method, seq_item_port.put_response ( rsp ); or using the built-in analysis port in uvm_driver . rsp_port.write ( rsp ); Before providing the response, the response’s sequence and transaction id must be set to correspond to the request transaction using rsp.set_id_info ( req ). put_response () is a blocking method, so the sequence must do a corresponding get_response ( rsp ).

Using TLM-Based Drivers The seq_item_port , which is built into uvm_driver , is a bidirectional port. It also includes the standard TLM methods get() and peek() for requesting an item from the sequencer, and put() to provide a response. peek() is a blocking method, so the driver may block waiting for an item to be returned. peek( req ); // Pause sequencer operation while the driver operates on the transaction. The get() operation notifies the sequencer to proceed to the next transaction. It returns the same transaction as the peek(), so the transaction may be ignored. get( req );//Allow sequencer to proceed immediately upon driver receiving transaction. To provide a response using the blocking_slave_port , the driver would call: seq_item_port.put ( rsp ); The response may also be sent back using an analysis_port as well.

Declaring User-Defined Sequences Sequences are made up of several data items, which together form an interesting scenario or pattern of data. To create a user-defined sequence: a) Derive a sequence from the uvm_sequence base class and specify the request and response item type parameters. In the example below, only the request type is specified, simple_item . This will result in the response type also being of type simple_item . b) Use the ` uvm_object_utils macro to register the sequence type with the factory. c) If the sequence requires access to the derived type-specific functionality of its associated sequencer, add code or use the ‘ uvm_declare_p_sequencer macro to declare and set the desired sequencer pointer. d) Implement the sequence’s body task with the specific scenario you want the sequence to execute. In the body task, you can execute data items and other sequences

Sequence Example code

Basic Flow for Sequences and Sequence Items To send a sequence item, the body() of a sequence needs to create() the item (use the factory)., call start_item () on the item, optionally randomize the item, and call finish_item () on the item. To send a subsequence, the body() of the parent sequence needs to create the subsequence, optionally randomize it, and call start() for the subsequence. If the subsequence item has an associated response, the parent sequence can call get_response ().

Fig.Sequence Item Flow

Sequencer Arbitration Multiple sequences can interact concurrently with a driver connected to a single interface. The sequencer supports an arbitration mechanism to ensure that at any point of time only one sequence has access to the driver. The choice of which sequence can send a sequence_item is dependent on a user selectable sequencer arbitration algorithm. T here are five built-in sequencer arbitration mechanisms that are implemented in UVM.

SEQ_ARB_FIFO (Default if none specified). If this arbitration mode is specified, then the sequencer picks sequence items in a FIFO order from all sequences running on the sequencer. For Example: if seq0, seq1,seq2 and seq3 are running on a sequencer, it will pick an item from seq0 first, followed by seq1, followed by seq2 and then seq3 if available, and continue .

SEQ_ARB_WEIGHTED: If this arbitration mode is selected, sequence items from the highest priority sequence are always picked first until none available, then the sequence items from next priority sequence, and so on. If two sequences have equal priority, then the items from them are picked in a random order.

SEQ_ARB_RANDOM: If this arbitration mode is selected, sequence items from different sequences are picked in a random order by ignoring all priorities .

SEQ_ARB_STRICT_FIFO: This is similar to SEQ_ARB_WEIGHTED except that if two sequences have same priority, then the items from those sequences are picked in a FIFO order rather than in a random order.

SEQ_ARB_STRICT_RANDOM: This is similar to SEQ_ARB_RANDOM except that the priorities are NOT ignored. The items are picked randomly from sequences with highest priority first followed by next and in that order . SEQ_ARB_USER : This algorithm allows a user to define a custom algorithm for arbitration between sequences. This is done by extending the uvm_sequencer class and overriding the user_priority_arbitration () method .