I have a scenario where I created two scoreboard objects derived from uvm_scoreboard as below.
`include my_scoreboard.sv
class my_env extends uvm_env;
scbd_a scbd_a_o;
scbd_b scbd_b_o;
`uvm_component_utils(my_env)
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
scbd_a_o = scbd_a::type_id::create("scbd_a_o",this);
scbd_b_o = scbd_b::type_id::create("scbd_b_o",this);
endfunction: build_phase
endclass: my_env
The base and derived scoreboards are defined in my_scoreboard.sv.
class a extends uvm_object;
`uvm_object_utils(a)
function new(string name = "a");
super.new(name);
endfunction: new
endclass: a
class b extends uvm_object;
`uvm_object_utils(b)
function new(string name = "b");
super.new(name);
endfunction: new
endclass: b
class my_scbd #(type T = uvm_object, type COMP = uvm_comparer) extends uvm_scoreboard;
typedef T queue [$];
queue scbd;
COMP comparer;
function new(string name="my_scbd", uvm_component parent = null);
super.new(name, parent);
comparer = new();
endfunction
`uvm_component_utils(my_scbd)
function void match_in_scbd (T rhs);
T lhs = scbd.pop_front();
endfunction: match_in_scbd
endclass: my_scbd
class scbd_a#(type COMP = uvm_comparer) extends my_scbd #(a, COMP);
function new(string name="scbd_a", uvm_component parent = null);
super.new(name, parent);
endfunction
`uvm_component_utils(scbd_a)
endclass: scbd_a
class scbd_b#(type COMP = uvm_comparer) extends my_scbd #(b, COMP);
function new(string name="scbd_b", uvm_component parent = null);
super.new(name, parent);
endfunction
`uvm_component_utils(scbd_b)
endclass: scbd_b
However, the compiler keeps telling me there’s a uncompatible class object. Anyone knows why?
Error-[SV-ICA] Illegal class assignment
/my_path/my_scoreboard.sv, 103
“automatic $unit::a lhs = this.scbd.pop_front;”
Expression ‘this.scbd.pop_front’ 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 given code compiles fine. Are you sure that the object types are correct in the line 103?
T lhs = scbd.pop_front();
Also, use uvm_component_param_utils for registering parameterized classes with factory. This will correctly create registry classes and allow cleaner parameter overrides.
`uvm_component_param_utils(my_scbd #(T,COMP))
P.S.: Here you have not overridden any parameters with classes ‘a’ and ‘b’.
Thank you for helping! So I simplified my code before putting it on the forum, and compilation error was gone after that. Here’s the complete code:
class a extends uvm_object;
`uvm_object_utils(a)
function new(string name = "a");
super.new(name);
endfunction: new
endclass: a
class b extends uvm_object;
`uvm_object_utils(b)
function new(string name = "b");
super.new(name);
endfunction: new
endclass: b
class my_scbd #(type T = uvm_object, type COMP = uvm_comparer) extends uvm_scoreboard;
typedef T queue [$];
queue scbd[int unsigned];
COMP comparer;
function new(string name="my_scbd", uvm_component parent = null);
super.new(name, parent);
comparer = new();
endfunction
`uvm_component_utils(my_scbd)
virtual function int unsigned get_index(T item);
return 0;
endfunction: get_index
function void match_in_scbd (T rhs);
int unsigned index = get_index(rhs);
T lhs = scbd[index].pop_front();
endfunction: match_in_scbd
endclass: my_scbd
class scbd_a#(type COMP = uvm_comparer) extends my_scbd #(a, COMP);
int x, y;
function new(string name="scbd_a", uvm_component parent = null);
super.new(name, parent);
endfunction
`uvm_component_utils(scbd_a)
virtual function int unsigned get_index(T item);
return x*y;
endfunction: get_index
endclass: scbd_a
class scbd_b#(type COMP = uvm_comparer) extends my_scbd #(b, COMP);
int x, y;
function new(string name="scbd_b", uvm_component parent = null);
super.new(name, parent);
endfunction
`uvm_component_utils(scbd_b)
virtual function int unsigned get_index(T item);
return x*y;
endfunction: get_index
endclass: scbd_b
I also found that if I do a type casting as below, it compiles fine.
function void match_in_scbd (T rhs);
int unsigned index = get_index(rhs);
T lhs;
$cast(lhs, scbd[index].pop_front());
endfunction: match_in_scbd
Any idea why? I tried registering the factory using `uvm_component_param_utils() but still seeing the error.
I also found that if I do a type casting as below, it compiles fine.
Can you show from where the match_in_scbd is called and how? Looks like “scbd.pop_front()” is returning an object of parent class and T is of type extended class. So casting is solving the issue. Not sure how “scbd” is filled or “match_in_scbd” is invoked.
Error-[SV-ICA] Illegal class assignment
my_scoreboard.sv, 41
“automatic $unit::a lhs = this.scbd[index].pop_front;”
Expression ‘this.scbd[index].pop_front’ 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.
Instance stack trace:
my_scbd#($unit::b,uvm_pkg::uvm_comparer) my_scoreboard.sv, 63
scbd_b#(uvm_pkg::uvm_comparer) my_uvm_env.sv, 6
my_env /user/seh/my_uvm/my_test_library.sv, 9
my_test /user/seh/my_uvm/my_test_library.sv, 26
You are Working on the wrong place to resolve your issue.The construction command for the scoreboards is wrong.
The scoreboard is a parameterized class and to have to pass actual parameters during the construction.
I thought the derived scoreboards (scbd_a and scbd_b) are parameterized this way:
class scbd_a#(type COMP = uvm_comparer) extends my_scbd #(a, COMP);
How do you pass the parameters during construction? Are you talking about the constructor of scbd_a and scbd_b? Or should I pass in the paremeters during build_phase of the environment class?
class scbd_a#(type T = a, type COMP = uvm_comparer) extends my_scbd #(a, COMP);
int x, y;
function new(string name="scbd_a", uvm_component parent = null);
super.new(name, parent);
//parent = my_scbd #(T, COMP)::type_id::create("parent",this);
endfunction
`uvm_component_utils(scbd_a)
virtual function int unsigned get_index(T item);
return (x * y);
endfunction: get_index
endclass: scbd_a
However, the same error still pops up. But if I modify as follows error is gone:
class my_scbd #(type T = uvm_object, type COMP = uvm_comparer) extends uvm_scoreboard;
typedef T queue [$];
queue scbd[int unsigned];
...
function void match_in_scbd (T rhs);
int unsigned index = get_index(rhs);
//T lhs = scbd[index].pop_front();
T lhs = scbd[index][0];
endfunction: match_in_scbd
endclass: my_scbd
I am suspecting that the definition “queue scbd[int unsigned]” is wrong somehow or confuses the compiler. If I change it to a simple queue (i.e T scbd [$]) or associative array (i.e. T scbd [int unsiged]) everything works fine.