Jump to content
ljepson74

simple override example - with error

Recommended Posts

I am trying to recreate/understand a testbench problem I currently have by creating a small example.  In creating that small example, I am running into a problem.

 

Below, in the "try1" and "try2" lines, I am attempting to override apple with orange.  Can anyone tell me what I am doing incorrectly?

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

class orange extends uvm_component;
   `uvm_component_utils(orange)

   function new(string name, uvm_component parent);
      super.new(name,parent);
   endfunction : new

   task run_phase (uvm_phase phase);
      `uvm_info("UVC","run_phase: Executing.   Orange <<<<<<<<<<<<<",UVM_LOW)
   endtask : run_phase
endclass : orange

class apple extends uvm_component;
   `uvm_component_utils(apple)

   function new(string name, uvm_component parent);
      super.new(name,parent);
   endfunction : new

   task run_phase (uvm_phase phase);
      `uvm_info("UVC","run_phase: Executing.   Apple run_phase<<<<<<<<<<",UVM_LOW)
    endtask : run_phase
endclass : apple

class my_testbench extends uvm_component;
   apple my_uvc;

   `uvm_component_utils(my_testbench)

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction : new
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);

      //try1	apple::type_id::set_type_override(orange::get_type());
      my_uvc=apple::type_id::create("my_uvc",this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      `uvm_info("TESTBENCH","run_phase: Executing.  Testbench run_phase<<<<<<<<<<<",UVM_LOW)      
   endtask : run_phase
endclass : my_testbench
endpackage : my_pkg


module top;
   import uvm_pkg::*;
`include "uvm_macros.svh"
   import my_pkg::*;

   my_testbench testbench;

   initial
     begin
//try2	apple::type_id::set_type_override(orange::get_type());
	$display("******Start of Sim w/ the kids*******************");
	testbench = my_testbench::type_id::create("testbench",null);
	run_test();
     end
endmodule : top

Running with Cadence irun 13.1, I get the following error when I try "try1".

 

UVM_FATAL @ 0: reporter [FCTTYP] Factory did not return a component of type 'apple'. A component of type 'orange' was returned instead. Name=my_uvc Parent=my_testbench contxt=testbench
 
 
irun -sv top.sv -uvm

Share this post


Link to post
Share on other sites

the $cast() in the create function fails because orange is not an apple.

if you change orange to derive from apple then $cast will succeed.

i.e 

typedef class apple;
class orange extends apple;

Share this post


Link to post
Share on other sites
Thanks a lot for the feedback, uwes and adiel.

Below is my code that works and the relevant output.  Commenting out the override line reverts back to apple, as expected.



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

class apple extends uvm_component;
`uvm_component_utils(apple)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction : new
task run_phase (uvm_phase phase);
`uvm_info("UVC","run_phase: Executing. Apple run_phase<<<",UVM_LOW)
endtask : run_phase
endclass : apple
class orange extends apple;
`uvm_component_utils(orange)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction : new
task run_phase (uvm_phase phase);
`uvm_info("UVC","run_phase: Executing. Orange run_phase<<<<",UVM_LOW)
endtask : run_phase
endclass : orange

class my_testbench extends uvm_component;
apple my_uvc;
`uvm_component_utils(my_testbench)

function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apple::type_id::set_type_override(orange::get_type()); //Replace apple with orange
my_uvc=apple::type_id::create("my_uvc",this);
endfunction : build_phase

task run_phase (uvm_phase phase);
//my_uvc=apple::type_id::create("my_uvc",this); //**1 cannot create a component in run phase
`uvm_info("TESTBENCH","run_phase: Executing. Testbench run_phase<<<<",UVM_LOW)
endtask : run_phase
endclass : my_testbench
endpackage : my_pkg


module top;
import uvm_pkg::*;
`include "uvm_macros.svh"
import my_pkg::*;

my_testbench testbench;

initial
begin
$display("******Start of Sim w/ the kids*******************");
testbench = my_testbench::type_id::create("testbench",null);
run_test();
end
endmodule : top




******Start of Sim w/ the kids*******************
UVM_INFO @ 0: reporter [RNTST] Running test ...
UVM_INFO top.sv(39) @ 0: testbench [TESTBENCH] run_phase: Executing. Testbench run_phase<<<<
UVM_INFO top.sv(20) @ 0: testbench.my_uvc [UVC] run_phase: Executing. Orange run_phase<<<<



 

Sharing with other newbies something I 'learned':

See commented out line "**1", which gave the below error and taught me that I cannot create components after build.  It makes sense, but I had never thought about it before.

UVM_FATAL @ 0: my_uvc [iLLCRT] It is illegal to create a component ('my_uvc' under 'testbench') after the build phase has ended.

Share this post


Link to post
Share on other sites
  Allowable creation times:    transaction objects  versus  testbench components

 

Can someone comment on why I/we cannot create a component after the build_phase, or even during the run_phase. (See UVM_FATAL note above.)

I think I understand the philosophy behind or difference between 

  • 'statically instantiated hierarchy'
  • 'dynamically instantiated hierarchy'
  • 'transaction objects'
 as Doulos breaks it down in their literature.

 

But, I haven't dug enough into the UVM base-class to understand what prevents component creation during this time.

Share this post


Link to post
Share on other sites

Hi, Linc -

 

I'll take a stab at this one.

 

Without knowing the Doulos terminology, I think they are referring to "static hierarchy" (top-module, DUT and interface), "dynamic hierarchy" (UVM testbench components - class based), and "transaction objects" (class based data - sequences and sequence_item transactions).

 

UVM has a predictable set of phases. All UVM testbench components are first built (build_phase) similar to module instantiation during compilation, once all components have been constructed in the build phase using factory calls, then we can connect them (connect_phase) which is little more than passing class handles to each other (since classes cannot have module-like input/output/inout ports) equivalent to wiring instantiated modules together during the elaboration phase, then we can run a simulation.

 

This is pretty much the same as building a Verilog testbench using modules. You are not allowed to start instantiation (compile) then start wiring modules together (elaborate) then go back and instantiate more modules after elaboration, and then start simulating for 10ns and then instantiate more modules, wait 10ns and then wire the new modules together.

 

UVM components are referred to as being semi-static, because they are built after you execute the run_test() command at time 0 and they remain in place and unchanged until the run phase is done, which is the final time-slot of the simulation. Since testbench components are classes, they are dynamic, but for all practical purposes, they are as static as the rest of the testbench but they are created at time-0 as soon as you call the run_test() command in the top module.

 

Hope this helps.

 

Regards - Cliff Cummings

Verilog & SystemVerilog Guru

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×