4

I have a parameterized seq_item as below

class seq_item#(int A = 64) extends uvm_sequence_item;
  `uvm_object_param_utils(seq_item#(A))
  rand logic [A-1:0] v;
  constraint v_c {
    v inside {[0:1000]};
  }
endclass : seq_item

class extended_seq_item#(int A = 64) extends seq_item#(A);
  `uvm_object_param_utils(extended_seq_item#(A))
  constraint extended_v_c {
    v inside {[10:50]};
  }
endclass : extended_seq_item

class reg_adapter#(int A = 100) extends uvm_reg_adapter;
  `uvm_object_param_utils(reg_adapter#(A))
  typedef seq_item#(A) seq_item_t;
  function new(string name = "reg_adapter")
    seq_item_t req;
    req = seq_item_t::type_id::create("req");
  endfunction
endclass : reg_adapter

class test extends uvm_test;
  `uvm_component_utils(test)
  reg_adapter#(10) adapter;
  function void build_phase(uvm_phase phase);
    seq_item#(10)::type_id::set_type_override(extended_seq_item#(10)::get_type());
    super.build_phase(phase);
    adapter = reg_adapter::type_id::create("adapter");
  endfunction : build_phase
endclass : test

In my UVM TB, I need to factory override all seq_item instances with extended_seq_item. Different instances will have different parameter values of A. How do I factory override this?

The problem is seq_item is from common collateral which has generic constraint for rand variable v which holds good for all IPs. For my IP, I need to add an additional constraint for v as given in extended_seq_item. My IP nuses reg_adapter which is expected to take extended_seq_item with additional constraints added

Thanks & Regards, Kiran

user1978273
  • 484
  • 10
  • 24
  • If possible, you should look into whether or not you can make `A` a member/variable of the class instead of a parameter. Parameters should be used sparingly. If not, @dave_59 's answer is the way to go. – Arun D'souza Feb 14 '20 at 20:21
  • 1
    I updated the description. I need A as the bit width for the variable v and hence it can not be a variable from another class and it has to be a parameter – user1978273 Feb 17 '20 at 22:02

1 Answers1

3

Unfortunately, parameterized classes with different parameter values (specializations is the LRM's terminology) are treated as separate class types, so you'll need to provide an override for each parameter value.

seq_item#(10)::type_id::set_type_override(extended_seq_item#(10)::get_type());
seq_item#(20)::type_id::set_type_override(extended_seq_item#(20)::get_type());
seq_item#(30)::type_id::set_type_override(extended_seq_item#(30)::get_type());

If you can get this code into a place where A is already parametrized, like in a the build_phase of a parameterized env or agent, then it might not be as painful as the above.


Now that I see more code, the problem is the class scope in this line, which should have been caught as an error

adapter = reg_adapter::type_id::create("adapter");

should be written as

adapter = reg_adapter#(10)::type_id::create("adapter");
dave_59
  • 39,096
  • 3
  • 24
  • 63
  • Unfortunately this wont work yet because we have to register seq_item as follows `uvm_object_param_utils(seq_item#(A)). If we expand the macro, it will call m_uvm_object_registry_param(T) define where there is a typedef of uvm_object_registry#(T). That means the other parameter Tname of uvm_object_registry remains "". If the type_name is unknown, we cant do type_override. Can you please help with this? – user1978273 Feb 17 '20 at 16:21
  • Your statement is not correct if you use the syntax I showed. You may want to read http://go.mentor.com/mcem. It applies to the UVM as well. – dave_59 Feb 17 '20 at 16:35
  • I tried what you suggested but I dont see the class getting overridden. I stepped into the code to see why and I saw this condition which was not getting met function uvm_object_wrapper uvm_default_factory::find_override_by_type(uvm_object_wrapper requested_type, string full_inst_path); – user1978273 Feb 17 '20 at 16:38
  • You should edit your original question to show a more complete example. – dave_59 Feb 17 '20 at 16:41
  • Updated the description. Can you please respond? – user1978273 Feb 17 '20 at 17:04
  • Since you have hardcoded the `A` parameter, you need to hardcode each override. `seq_item#(100)::type_id::set_type_override(extended_seq_item#(100)::get_type());` in your testbench should have overridden the `create()` inside your `reg_adapter` If that did not work, there might be other issues. – dave_59 Feb 17 '20 at 17:28
  • In the link http://go.mentor.com/mcem, you have mentioned using typedef for type_id separately in the class. Can you please give the snippet of that class? I tried doing that but I got compilation error saying type_id is declared twice. – user1978273 Feb 17 '20 at 17:32
  • OK I think I see the problem. This is the difference between UVM and OVM. The ovm_object_param_utils macro does not include typedef for type_id and hence the class can override it but uvm_object_param_utils macro also has typedef for type_id and hence the class can not override this – user1978273 Feb 17 '20 at 17:38
  • Can you please suggest another solution? – user1978273 Feb 17 '20 at 22:01
  • You still have not shown enough code to reproduce your issue. I think the link I gave you may be irrelevant after reading your additional comments, but it was meant to show what to do instead of using the macros, bot do both. – dave_59 Feb 18 '20 at 00:50
  • See updated answer. The problem was in code that you had not shown before. – dave_59 Feb 18 '20 at 18:58
  • I am sorry. That was in fact a typo. My code already has that parameter in place. I still got the problem inspite – user1978273 Feb 18 '20 at 23:18
  • go.mentor.com/mcem link is now at [Parameterized Classes, Static Members and the Factory Macros](https://blogs.sw.siemens.com/verificationhorizons/2011/02/13/parameterized-classes-static-members-and-the-factory-macros/) – dave_59 Jul 27 '23 at 16:33