This is a short article about when we should set the provides_responses
bit of the register adapter.
Original Jelly Bean Driver
This is the orignal jelly_bean_driver
used in Register Abstraction. The driver gets requests using get_next_item
(line 23), then updates the request itself to store the response from the DUT (line 33). Finally, it calls item_done
(line 35). Since the driver does not return separate responses, we set the provides_responses
of jelly_bean_reg_adapter
to be zero.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class jelly_bean_driver extends uvm_driver#( jelly_bean_transaction ); `uvm_component_utils( jelly_bean_driver ) virtual jelly_bean_if jb_if; function new( string name, uvm_component parent ); super.new( name, parent ); endfunction: new function void build_phase( uvm_phase phase ); super.build_phase( phase ); endfunction: build_phase task main_phase( uvm_phase phase ); jelly_bean_transaction jb_tx; forever begin @jb_if.master_cb; jb_if.master_cb.command < = jelly_bean_types::NO_OP; jb_if.master_cb.color <= jelly_bean_types::NO_COLOR; jb_if.master_cb.flavor <= jelly_bean_types::NO_FLAVOR; seq_item_port.get_next_item( jb_tx ); // get the request @jb_if.master_cb; jb_if.master_cb.command <= jb_tx.command; if ( jb_tx.command == jelly_bean_types::WRITE ) begin jb_if.master_cb.flavor <= jb_tx.flavor; jb_if.master_cb.color <= jb_tx.color; jb_if.master_cb.sugar_free <= jb_tx.sugar_free; jb_if.master_cb.sour <= jb_tx.sour; end else if ( jb_tx.command == jelly_bean_types::READ ) begin @jb_if.master_cb; jb_tx.taste = jelly_bean_types::taste_e'( jb_if.master_cb.taste ); // update the request itself end seq_item_port.item_done(); end endtask: main_phase endclass: jelly_bean_driver |
Driver That Returns Separate Responses
If the provides_responses
is one, I would rewrite the driver as follows. (Usually this would be the other way around; if the driver provides separate responses, then we set the provides_responses
to be one.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | class jelly_bean_driver extends uvm_driver#( jelly_bean_transaction ); `uvm_component_utils( jelly_bean_driver ) virtual jelly_bean_if jb_if; function new( string name, uvm_component parent ); super.new( name, parent ); endfunction: new function void build_phase( uvm_phase phase ); super.build_phase( phase ); endfunction: build_phase task main_phase( uvm_phase phase ); jelly_bean_transaction jb_tx; jelly_bean_transaction jb_rsp; forever begin @jb_if.master_cb; jb_if.master_cb.command < = jelly_bean_types::NO_OP; jb_if.master_cb.color <= jelly_bean_types::NO_COLOR; jb_if.master_cb.flavor <= jelly_bean_types::NO_FLAVOR; seq_item_port.get( jb_tx ); // get the request $cast( jb_rsp, jb_tx.clone() ); // create a response jb_rsp.set_id_info( jb_tx ); // copy the sequence_id and the transaction_id @jb_if.master_cb; jb_if.master_cb.command <= jb_tx.command; if ( jb_tx.command == jelly_bean_types::WRITE ) begin jb_if.master_cb.flavor <= jb_tx.flavor; jb_if.master_cb.color <= jb_tx.color; jb_if.master_cb.sugar_free <= jb_tx.sugar_free; jb_if.master_cb.sour <= jb_tx.sour; end else if ( jb_tx.command == jelly_bean_types::READ ) begin @jb_if.master_cb; jb_rsp.taste = jelly_bean_types::taste_e'( jb_if.master_cb.taste ); // update the response end seq_item_port.put( jb_rsp ); // return the response end endtask: main_phase endclass: jelly_bean_driver |
The driver gets the request using get
(line 24), then clones the request to create a separate response (lines 25 and 26). The set_id_info
function copies some IDs from the request to the response so that the sequencer can route the response back to the originating sequence. Finally, the driver updates the response (line 37) and returns it to the sequencer (line 39). Hope this helps.
To provide the responses back to sequence, shouldn’t we use item_done ?
Please let me know what is the better approach.
You could do that, but since
item_done
blocksfinish_item
, you might want to use theget/put
pair if the driver needs to support pipelined transfers, for example.