I have a base class that creates a child of it’s own class such as the following:
class parent_class extends uvm_component;
`uvm_component_utils(parent_class)
...
function void create_child();
...
// Here it seems like parent_class is "hardcoded" but how would I replace this?
child = parent_class::type_id::create("m_child_class" + children.size, this, get_full_name());
...
endfunction : create_child
...
endclass : parent_clas
Calling this function from a parent_class object works, but I want to be able to extend this base class such as
class extended_class extends parent_class
...
endclass : extended_class
And call the function, create_child. This returns me an error because it will try to create the parent_class instead.
I want to be able to do something like this…
function void create_child();
...
child = THIS_OBJECT_TYPE_HERE::type_id::create("m_child_class" + children.size, this, get_full_name());
...
endfunction : create_child
is that possible? Or am I approaching this in a wrong way
In reply to jimmyhuang0904:
I understand what you want to do, but don’t understand what error you are getting.
Try calling
create_component() instead.
if ( !$cast(child, create_component(get_type_name(), $sformatf("m_child_class%0d",children.size() )
`uvm_fatal("ID","Failed because you didn't register this class with the factory")
In reply to dave_59:
Hi, thanks for the suggestion. I am unfortunately, still getting the same error :(
The error I am getting is
Error-[SV-ICA] Illegal class assignment
src/manager_test.sv, 26
"this.m_child_manager = this.m_parent_manager.create_child();"
Expression 'this.m_parent_manager.create_child()' on rhs is not a class
or a compatible class and hence cannot be assigned to a class handle on lhs.
Please make sure that the lhs and rhs expressions are compatible.
The line on 26 and line relevant to that is:
svt_manager m_parent_manager;
svt_manager m_child_manager;
function void build_phase(uvm_phase);
...
// svt_manager extends parent_class
m_parent_manager = svt_manager ::type_id::create("m_parent_manager", this, get_full_name());
m_child_manager = m_parent_manager.create_child(); // Line 26
endfunction : build_phase
this error happens when my m_parent_manager is of type extended_class (in my specific case, it would be the svt_manager) , but there is no error if my m_parent_manager is of type parent_class (if I replaced all svt_manager with parent_class).
*NOTE: The class create_child actually returns a handle to the child object and doesn’t return void, so I would be returning the variable, child.
I tried your suggestion and it seemed to be on the right track but maybe my error is elsewhere?
(Also ,thanks for the $sformatf, that was actually a small known bug I had when I was thinking Python)
In reply to jimmyhuang0904:
Oh. I think I have found my mistake… I was returning the parent_class object the whole time…
Here is the fuller picture of what I had before… I wrote too fast of a pseudocode :
// RETURNS PARENT_CLASS, NOT VOID
function parent_class create_child();
...
if ( !$cast(child, create_component(get_type_name(), $sformatf("m_child_class%0d",children.size() ) ) )
`uvm_fatal("ID","Failed because you didn't register this class with the factory")
...
endfunction : create_child
But how would I return the class of get_type_name()?
My function can only return a handle of parent_class, but in this case, I want it to return my extended_class (svt_manager instead of base_manager)?
In reply to jimmyhuang0904:
There are several ways (not elegant) that actually can achieve this… obviously with casting such as :
svt_manager m_parent_manager;
svt_manager m_child_manager;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_parent_manager = svt_manager ::type_id::create("m_parent_manager", this, get_full_name());
if ( !$cast(m_child_manager, m_parent_manager.create_child(500, 200)))
`uvm_fatal("BUILD_PHASE", "Cannot create child")
endfunction : build_phase
This is not elegant because it is not intuitive to the user. The user would have to know to do a cast every time it creates a child… I would preferably have this managed by the parent_class component itself so it makes it easy for the user… I will stick with this solution until I find a better way,
Thanks for all the help so far! Learned something or two from this. Still a beginner at UVM unfortunately and I always forget about downcasting, no overrides, etc. etc. etc…