Have a small design where an environment class has two different objects driver1 and drive2 instantiated in it.
I am trying to access a class variable in driver1 from driver2 using Hierarchical referencing in the task printRefPartial.
Here is a testbench:
// driver1 class
class driver1;
int someint;
function new();
$display("Constructing driver1");
someint = 1;
endfunction
endclass
// driver2 class
class driver2;
int someint;
function new();
$display("Constructing driver2");
someint = 2;
endfunction
// Tools don't like this name
task printRefPartial();
$display("Ref partial path value = %0d",driver1_inst.someint);
endtask
// Tools don't like this name
task printRefFull();
//$display("Ref full path value = %0d",myblock.env_inst.driver1_inst.someint);
endtask
endclass
// env class has instance of driver1 & driver2
class env;
driver1 driver1_inst;
driver2 driver2_inst;
function new ();
driver1_inst = new;
driver2_inst = new;
$display("-----Constructing env-----");
endfunction
endclass
Running the testbench produces:
** Error (suppressible): design.sv(23): (vopt-7063) Failed to find ‘driver1_inst’ in hierarchical name ‘$root.driver1_inst.someint’.
Region: testbench_sv_unit
It does not like my path?
Seems like it should work.
The simulator should not find driver1_inst.someint, but then should look up one level and the path should be found to its neighbor.
I think local scope is the term you all are looking for.
A module and all procedural constructs like tasks/functions/begin/end blocks all create local scope, some of which can be nested. An instance of module tb creates a local scope of which env_inst is a member. Since there is only one instance of tb, you can refer to tb.env_int or explicitly $root.tb.env_inst from anywhere (except inside a package which does not allow any hierarchical references)
task printRefFull();
$display("Ref full path value = %0d",$root.tb.env_inst.driver1_inst.someint);
endtask
If you have a statement inside a nested local scope (myblock), it can refer upwards to members in the outer scope directly. that is why the $display statements inside myblock work correctly.
The $display statement inside the task printRefPartial does not compile because there is no driver1_inst in the local scope of the task, nor is the a driver_inst inside the local scope of the class driver2. The local scope above the class is the compilation unit, and there is no driver1_inst there either. The fact that driver2 was constructed inside env does not make env an upwards scope to driver2. Objects get constructed dynamically during execution, and the search for identifiers needs to happen during compilation.
Based on this statement:
“Objects get constructed dynamically during execution, and the search for identifiers needs to happen during compilation”
Which makes sense, the dynamic object does not exist at compile time, how could it possibly be accessed???
Therefore, it seems like this task you tweaked for me should not work, because it refers to an object which is dynamic and does not exist at compile time. But it compiles, runs, and accesses the buried dynamic object (Questa/EDA Playground). There seems to be some way that the path to a future created object is allowed/reconciled/facilitated at compile time?
How does this work?
task printRefFull();
$display("Ref full path value = %0d",$root.tb.env_inst.driver1_inst.someint);
endtask