Passing two different data type to scoreboard

Hi,
I want to pass different data type during calling of write method in scoreboard. I am using different data type(Take different seq item class in each module) in different module and wants to use single scoreboard for different modules. Is it possible to use parameterized class? if yes than how?

Hi Chintan8,
Not sure if I understand your question completely. If your question is how to write a scoreboard that can be instantiated in multiple places and connect each of these instances to different component (i.e., monitor); also, the transactions sent by each monitor to its own scoreboard is unique, then, yes, you can do it. You can write a parameterized scoreboard and instantiate its specialized version for each monitor. Here is the code for such a scoreboard:

class param_scoreboard #(type T= ovm_sequence_item) extends ovm_scoreboard;
   `ovm_analysis_imp_decl(_add)
   `ovm_analysis_imp_decl(_check)

   ovm_analysis_imp_add #( T, param_scoreboard#(T) ) sb_add_in = new("sb_add_in", this);
   ovm_analysis_imp_check #( T, param_scoreboard#(T) ) sb_check_in = new("sb_check_in1", this);
   
   T sb_queue[$];
   
   function new(string name="", ovm_component parent=null);
      super.new(name, parent);
   endfunction      
   `ovm_component_param_utils( param_scoreboard#(T) )

   extern virtual function void write_add(T p);
   extern virtual function void write_check(T p);   
endclass // param_scoreboard

function void param_scoreboard::write_add(T p);
   T sb_packet;
   $cast( sb_packet,  p.clone());
   ovm_report_info("Scoreboard", "PH> Add following packet to SB queue:");
   sb_queue.push_back(sb_packet);
   sb_packet.print();
endfunction
    
function void param_scoreboard::write_check(T p);
   if( sb_queue.size() == 0 ) begin
      ovm_report_warning("Scoreboard", "PH> Warning!!! Received unexpected packet; Scoreboard is empty!");
      ovm_report_warning("Scoreboard", "PH> Received packet is:");
      p.print();
      return;
   end
           
   if( p.compare(sb_queue[0]) ) begin
      void'(sb_queue.pop_front());
      ovm_report_info("Scoreboard", "PH> Received 'matched' packet:");
      p.print();
   end
   else begin
      ovm_report_warning("Scoreboard", "PH> Warning!!! Received unexpected packet:");
      ovm_report_warning("Scoreboard", "PH> Received packet is:");
      p.print();
      ovm_report_warning("Scoreboard", "PH> Expected packet is:");
      sb_queue[0].print();
   end
endfunction

Somewhere in your testbench, you will instantiate the specialized versions of the scoreboard and connect these scoreboard instances to their monitors:

...
   param_scoreboard #(packet1) sc1;
   param_scoreboard #(packet2) sc2;
   ...

   function void build();
      super.build();
      ...
      sc1 =  param_scoreboard #(packet1)::type_id::create("sc1", this);
      sc2 =  param_scoreboard #(packet2)::type_id::create("sc2", this);
      ...
   endfunction
   ...
   //connect TLM ports of specialized versions 
   //of the scoreboard to the monitors
       ...

To enable polymorphic behavior for write(), or any function or task for that matter, you need to have all the different things that you want to pass in be derived from the same base class, which in turn is derived from ovm_object. Make sure that get_type_name() is implemented in each of the derived classes. The argument to write (i.e. the T parameter in ovm_subscriber) is the base class. Then you use a case statement to cast the object accordingly

class base extends ovm_object;
endclass
class type_one extends base;
  function string get_type_name();
    return "type_one";
  endfunction
endclass
class type_two extends base;
  function string get_type_name();
    return "type_two";
  endfunction
endclass
 
class subscriber extends ovm_subscriber#(base);
  type_one t1;
  type_two t2;
  function write(base t);
    case (t.get_type_name())
     "type_one" : $cast(t1, t);
     "type_two" : $cast(t2, t);
    endcase
   ...
  endfunction
endclass

I’ve left out some details in the code for brevity, but this represents the essential idea.

– Mark

Hi phuynh,
According to your reply code is working fine. Thanks .But i have one minor problem.

(1) When i am using variable from scoreboard of that sequence item like “p.data” it
gives me error like “Hierarchical name component lookup failed at ‘data’” . I
have also check with the casting. It gives same error.

(2) Is it require to do casting?

The reason why you got the “Hierarchical name component lookup failed at ‘data’” was due to the scoreboard did not know about the specific properties of your transactions.

The scoreboard code that I posted was a parameterized one with the default type= ovm_sequence_item. Due to polymorphism, the clone() and the compare() methods, used by the scoreboard write_add() and write_check(), work correctly for any classes that are derived from the ovm_sequence_item, directly or indirectly; however, the properties specific to any of the children classes are not known to the scoreboard.

The easiest way to fix this is to change the default type of the scoreboard (i.e, line 1: …#(type T= ovm_sequence_item) from ovm_sequence_item to the base class of all the transactions that you plan to use with this scoreboard.

Hi Phuynh,
– Is there any other way to use local variable of different sequence item?
– Because while compling one module by same scoreboard other sequence item
of other module is unknown to that scoreboard. So as u reply last time it is good
to make scoreboard parameterized with #(type T= ovm_sequence_item).