Problem in creating derived uvm_scbd object

Hi,

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.

In reply to wch:

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’.

Hi sharvil111,

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.

In reply to wch:

Could you please show the error message and the code line it is pointing to.
BTW, you are doing easy things complicated.

In reply to wch:

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.

In reply to chr_sue:

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

In reply to sharvil111:

I havn’t called match_in_scbd(); anywhere. The only thing I did was createing the scbd objects in my environment class:


`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

Why is scbd containing objects of the parent class?

In reply to wch:

What is your vendor compiler? I think your compiler gets confuse something. I ran your example with VCS, it worked without any error.

In reply to cuonghl:

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.

In reply to cuonghl:

I am using VCS 2017.03-SP2-1. What version are you using?

In reply to chr_sue:

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?

In reply to wch:

See here how it should look like:

import uvm_pkg::*;
`include "uvm_macros.svh"

`include "my_scoreboard.sv"

typedef class COMP;

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 #(COMP)::type_id::create("scbd_a_o",this);
	    scbd_b_o = scbd_b #(COMP)::type_id::create("scbd_b_o",this);
	endfunction: build_phase
endclass: my_env

class COMP extends uvm_comparer;
  `uvm_component_utils(COMP)

  function new (string name, uvm_component parent );
  endfunction

endclass : COMP

In reply to chr_sue:

I passed in the parameters into scbd_a and scbd_b as suggested:


   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      scbd_a_o = scbd_a #(a,uvm_comparer)::type_id::create("scbd_a_o",this);
      scbd_b_o = scbd_b #(b,uvm_comparer)::type_id::create("scbd_b_o",this);
   endfunction: build_phase

where scbd_a is defined as:


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.

In reply to wch:

You are specifying T as an uvm_object, i.e. a Class type. Afterwards you are trying to re-define T as Queue type. This is your problem.