Jump to content

Instance override RAL adapter transaction objects?


Recommended Posts

Hello,

 

We have a test bench environment where we have 2 objects of the same SPI env class.

 

The SPI env sets the sequencer for the RAL model as follows:

reg_model.default_map.set_sequencer(spi_master_agt.mem_sqr, reg2spi_adapter);

The transaction type handled by the spi_master_agt.mem_sqr is spi_mem_tr.

 

Now I need to extend the spi_mem_tr to spi_mem_tr_1 and spi_mem_tr_2, and then override spi_mem_tr with those separately for the 2 objects of the SPI env class.

// Below does not work
set_inst_override_by_type
  ( .relative_inst_path("env.spi_m[0].*"), // Here spi_m[0] is the first instance of the SPI env
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi_mem_tr_1::get_type()));
set_inst_override_by_type
  ( .relative_inst_path("env.spi_m[1].*"), // Here spi_m[1] is the second instance of the SPI env
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi_mem_tr_2::get_type()));

// This does not work too!
set_inst_override_by_type
  ( .relative_inst_path("env.*"),
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi_mem_tr_1::get_type()));

// Even this does not work!
// So looks like "inst" override by type does not work for tr objects in RAL
// connecting agents?
set_inst_override_by_type
  ( .relative_inst_path("*"),
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi_mem_tr_1::get_type()));


// Other the other hand, below works, BUT that overrides the tr in both SPI env objects
// That is not what I want; I need to override using different types for the
// two SPI env objects
spi_mem_tr::type_id::set_type_override(spi_mem_tr_1::get_type());

Questions:

 

  • Is it possible to do instance specific overrides over transaction class inside the SPI agent connecting to my RAL model?
  • If so, what is the correct way to set the relative_inst_path?
  • If not, are there any hacks to achieve the same?
  • The fact that the global type override does work gives me some hope.
Link to comment
Share on other sites

When using RAL like this, items aren't created by your agents, but by the adapters interfacing with those agents. If you set up the contexts properly when creating items inside your adapters, it's going to be possible to do instance-based overrides:

class spi_adapter extends uvm_reg_adapter;
  function uvm_sequence_item reg2bus(...);

    // notice the 'get_full_name()' here
    spi_item bus_item = spi_item::type_id::create("bus_item", null, get_full_name());

    // ...
  endfunction
endclass

The extra argument to create(...) sets the context for items create under the adapter as being "<adapter_name>.*". In your environment code, you can set instance overrides like this:

class some_tb_env;
  spi_adapter adapter0;
  spi_adapter adapter1;

  function void end_of_elaboration_phase(...);
    spi_mem_tr::type_id::set_inst_override(spi_mem_tr_0::get_type(), null, "adapter0.*");
    spi_mem_tr::type_id::set_inst_override(spi_mem_tr_1::get_type(), null, "adapter1.*");
  endfunction
endclass

Your adapters need to have different names otherwise you won't be able to differentiate between items create by one and ones created by the other.

 

Note: Don't confuse the context passed into create(...) with instance paths of uvm_components. The two are closely related, but aren't the same thing.

Link to comment
Share on other sites

Hi Tudor,

 

Thanks for the reply.

 

I have tried something similar. But that doesn't work. Here's is some code to show what I tried.

 

In the adapter class where I create the transaction objects:

mem_tr = spi_mem_tr::type_id::create(.name("mem_tr"), .contxt(get_full_name()));

In the base test where I do the overrides:

spi_mem_tr::type_id::set_inst_override(.override_type(spi_mem_ext_tr::get_type())
                                     , .inst_path("env.spi_m[0].reg2spi_adapter.*")
                                     , .parent(null));
spi_mem_tr::type_id::set_inst_override(.override_type(spi2_mem_ext_tr::get_type())
                                     , .inst_path("env.spi_m[1].reg2spi_adapter.*")
                                     , .parent(null));

Note that I have fixed the order of the arguments to set_inst_override; the parent argument is the last argument. To avoid confusion, I am using named argument association.

 

The difference here is that we have a VIP that wraps the SPI adapter, and I have 2 instances spi_m[0] and spi_m[1] of the same VIP class. the mem_tr objects are created inside the reg2spi_adapter.

 

Even then, the overrides do not work at all.

Link to comment
Share on other sites

Thank you. 

 

It now makes sense why that full path of "env..." did not work.

 

So I thought that the below would fix that. But it is not..

 

Below code is in the "SPI env" component whose objects are "spi_m[0]" and "spi_m[1]".

reg2spi_adapter = spi_master_reg_adapter::type_id::create(.name("reg2spi_adapter"), .contxt(get_full_name()));
`uvm_info("DEBUG_FULL_NAME", $sformatf("Full name of this spi_env obj is %s", this.get_full_name()), UVM_MEDIUM)
`uvm_info("DEBUG_FULL_NAME", $sformatf("Full name of the new reg2spi_adapter obj is %s", reg2spi_adapter.get_full_name()), UVM_MEDIUM)

Inside the "new" function of the "spi_master_reg_adapter" class, I have:

`uvm_info("DEBUG_FULL_NAME", $sformatf("Full name of this adapter obj is %s", this.get_full_name()), UVM_MEDIUM)

But still, this is what gets printed (formatting changed from default using a custom report server):

UVM_INFO @      0ns  Full name of this adapter obj is reg2spi_adapter            :DEBUG_FULL_NAME
UVM_INFO @      0ns  Full name of this spi_env obj is uvm_test_top.env.spi_m[0]  :DEBUG_FULL_NAME
UVM_INFO @      0ns  Full name of the new reg2spi_adapter obj is reg2spi_adapter :DEBUG_FULL_NAME

UVM_INFO @      0ns  Full name of this adapter obj is reg2spi_adapter            :DEBUG_FULL_NAME
UVM_INFO @      0ns  Full name of this spi_env obj is uvm_test_top.env.spi_m[1]  :DEBUG_FULL_NAME
UVM_INFO @      0ns  Full name of the new reg2spi_adapter obj is reg2spi_adapter :DEBUG_FULL_NAME

I am curious why the below does not work; I am specifying the env's "get_full_name()" as the context:

reg2spi_adapter = spi_master_reg_adapter::type_id::create(.name("reg2spi_adapter"), .contxt(get_full_name()));
Link to comment
Share on other sites

Hi Tudor,

 

Thanks for your immense help. I was finally able to get the overrides work with these changes:

 

(1) Append the full name to the transaction objects generated in the adapter:

mem_tr = spi_mem_tr::type_id::create({get_full_name(), ".mem_tr"});

(2) Append the full name even to the adapter object generated in the SPI env:

reg2spi_adapter = spi_master_reg_adapter::type_id::create({get_full_name(), ".reg2spi_adapter"});

 

(3) Finally set the instance overrides as usual in the base test:
 
set_inst_override_by_type
  ( .relative_inst_path("env.spi_m[0].*"),
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi_mem_ext_tr::get_type()));

set_inst_override_by_type
  ( .relative_inst_path("env.spi_m[1].*"),
    .original_type(spi_mem_tr::get_type()),
    .override_type(spi2_mem_ext_tr::get_type()));

Once again, I really appreciate the help you provided. Thanks!

 

Link to comment
Share on other sites

Here's a minor update with respect to point (1) in my above summary.

 

I had to do:

mem_tr = spi_mem_tr::type_id::create(.name("mem_tr"), .contxt(get_full_name()));

instead of 

mem_tr = spi_mem_tr::type_id::create({get_full_name(), ".mem_tr"});

With the latter, I get an SDI/Verilog warning saying:

Message!     [SDI/Verilog]                                                     
    In sdiT::transactionTypeT ctor, the transaction name had illegal characters.
Those characters have been replaced.  Here's the new name:
'uvm_test_top_env_spi_m[0]_reg2spi_adapter_mem_tr'

...

Message!     [SDI/Verilog]                                                     
    In sdiT::transactionTypeT ctor, the transaction name had illegal characters.
Those characters have been replaced.  Here's the new name:
'uvm_test_top_env_spi_m[1]_reg2spi_adapter_mem_tr'

But the overrides still worked.

 

Now with that fixed (by not using get_full_name() or "." in the "name" argument, mem_tr.get_full_name() now prints just "mem_tr". But the overrides still work!! This is very confusing.

Link to comment
Share on other sites

  • 2 months later...

hi

 

the difference is that with version one you create an object named "mem_tr" in the context of get_full_name() while with the second one you create an object named (long name with alot of dots) {get_full_name(), ".mem_tr"} in the uvm_root: context. Here it depends for which instances you set the factory override.

 

for various reasons it is not a good habit to have object names involving dots or other non a-Z0-9_ characters. just think of print out of a.b.c.e.f and you allow "." in names then it could be "a" . "a.c.d.e.f" or "a.b" . "c.e.f" or any weird combination.  with that you should avoid any get_full_name() in the name argument of the ctor.

 

for the particular SDI warning the name should have no "." since this is considered a hierarchical delimiter (which for you isnt true). 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...