Jump to content
muffadal

uvm_reg adapter (bus2reg) issue

Recommended Posts

Hello Folks, 

 

I am unable to get a response from the vsequencer to my register model sequence. I see that the register model sequence does generate the first transaction and when the response of this transaction comes back to the vsequencer the sequence hangs. I found on couple of forums that setting provides_responses bit to 1 in the adapter class should resolve this issue. However I am still not able to make this work.  

 

Here are the steps that I followed to Integrate uvm_reg model in my uvm environment.  

 

1. Generate the uvm_reg model using one iregGen/ralGen script

2. Instantiate the model in the uvm_env. 

3. Instantiate the adapter class in uvm_env 

4. Assign a sequencer and adapter class to the register model. 

 

I am running the basic built-in register model sequence uvm_reg_hw_reset_seq. 

 

 

*********************************************

AXI Adapter code

********************************************

 

class ps_regm_axi_adapter extends uvm_reg_adapter;
  `uvm_object_utils(ps_regm_axi_adapter)
 
  function new(string name = "ps_regm_axi_adapter"); 
    super.new(name);
    supports_byte_enable = 1; 
    provides_responses = 1;   
  endfunction : new
 
  /* Convert RGM packet type to APB packet type */
  virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
    dummy_seq_item transfer = dummy_seq_item::type_id::create("dummy_seq_item");
transfer.set_cmd_type(((rw.kind == UVM_READ) ? AXI_READ : AXI_WRITE));
transfer.set_4byte_payload(0,rw.data);
transfer.addr = rw.addr;
 
`uvm_info(get_name(), $psprintf("Printing response (reg2bus): %s to addr: %h with Payload: %h", rw.kind.name(), rw.addr, rw.data),UVM_LOW);
    return transfer;
  endfunction : reg2bus
 
  /* Convert APB packet type to RGM packet type */
  virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
bit [3:0] [7:0] ret_data;
    dummy_seq_item transfer;
    if (!$cast(transfer,bus_item)) begin
      `uvm_fatal("NOT_AXI_TYPE", "Provided bus_item is not of the correct type")
      return;
    end
assert(transfer.cmd_sprintf()) else $fatal;
rw.kind = (transfer.get_cmd_type() == AXI_WRITE)? UVM_WRITE : UVM_READ;
rw.addr = transfer.addr;
// rw.data = transfer.data[0];
transfer.get_4byte_payload(0,ret_data);
rw.data = ret_data;
`uvm_info(get_name(), $psprintf("Printing response (bus2reg): %s to addr: %h with Payload: %h", rw.kind.name(), rw.addr, rw.data),UVM_LOW);
  endfunction : bus2reg
 
endclass : 
 
*************************************
Sequence 
************************************
 
//adapter sequence to handle requests on the regm_vseq
class axi_adapter_seq extends uvm_sequence #(dummy_seq_item);
   `uvm_object_utils(axi_adapter_seq)
   `uvm_declare_p_sequencer(ps_regm_vsequencer)
    
function new (string name="axi_adapter_seq");
super.new(name);
endfunction
 
task body();
dummy_seq_item transfer;
uvm_object cloned;
 
forever begin
p_sequencer.get_next_item(req);
transfer = dummy_seq_item::type_id::create();
if(req.get_cmd_type() == AXI_WRITE)begin
transfer.set_sequencer(p_sequencer.wr_seqr);
start_item(transfer);
p_sequencer.wr_seqr.initialize_axi3_transaction(transfer);
transfer.set_xfer_wrcmd_order(XAM_WRCMD_ORDER_CMD_BEFORE_DATA);
transfer.set_driver_return_item();
transfer.data.rand_mode(0);
transfer.data = req.data;
 
assert(transfer.randomize() with {addr == req.addr[31:0];
id == 0;
size == AXI_SIZE_4BYTE;
burst == AXI_BURST_TYPE_INCR;
prot == 0;
region == 0;
qos ==0;
}) else $fatal;
finish_item(transfer);
end
 
else begin
transfer.set_sequencer(p_sequencer.rd_seqr);
start_item(transfer);
p_sequencer.rd_seqr.initialize_axi3_transaction(transfer);
transfer.set_driver_return_item();
assert(transfer.randomize() with {addr == req.addr[31:0];
id == 0;
len ==0;
size == AXI_SIZE_4BYTE;
burst == AXI_BURST_TYPE_INCR;
prot == 0;
region == 0;
qos ==0;
}) else $fatal;
finish_item(transfer);
end
get_response(rsp);
req.data=rsp.data;
rp.print();
p_sequencer.item_done(req);
end
endtask
 
endclass : axi_adapter_seq
 
 
Any suggestion or pointer in the right direction will really be helpful. 
 
Thanks,
Muffadal

Share this post


Link to post
Share on other sites

Hi Tudor, 

 

Thanks for your response. I am running the adapter sequence on a dummy virutal sequencer. Here is the code for the dummy virutal sequencer. 

 

********************************************

Virutal Sequencer

********************************************

 

class ps_regm_vsequencer extends uvm_sequencer #(dummy_seq_item);
 
      `uvm_component_utils(ps_regm_vsequencer)
      mst_rd_sequencer    rd_seqr;
      mst_wr_sequencer    wr_seqr;
 
      ps_axi_adapter_sequence adapter_seq;
      // axi_adapter                  reg2axi;
 
      function new (string name          = "pmu_regm_vsequencer",
          uvm_component parent =  null);
          super.new(name,parent);
      endfunction : new
 
      function void build_phase (uvm_phase phase);
          rd_seqr = mst_rd_sequencer::type_id::create("rd_seqr", this);
          wr_seqr = mst_wr_sequencer::type_id::create("wr_seqr", this);
          adapter_seq = ps_axi_adapter_sequence::type_id::create("adapter_seq", this);
          super.build();
      endfunction : build_phase
 
      virtual task run();
 
          adapter_seq.start(this);
          super.run();
      endtask
 
 endclass: ps_regm_vsequencer
 
I have gone through that section in the UVM user guide. However I am still stuck at this problem. I wish there was an easier way to debug this :(

Share this post


Link to post
Share on other sites

Hi All,

 

After debugging this issue for couple of weeks I figured out the solution to this problem. In my testbench I had a define called UVM_DISABLE_AUTO_ITEM_RECORDING enabled. This define forces the driver to end a sequence through req.end_tr();. If you don't have this line in your driver the do_read task in uvm_reg_map will keep waiting at the bus_req.end_event.wait_on().

 

I removed this define and it all works now :).  The annoying part is since this is a SoC level testbench I had to digg into many files before I figured out that one of the files has this define. 

 

Thanks,

Muffadal 

Share this post


Link to post
Share on other sites

I'd say that that define is kinda broken. This is in part because because begin/end_tr trigger these begin/end_events which are used for other stuff too. Whether transaction recording is or is not enabled shouldn't affect the behavior of other aspects.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×