You cannot use strings to create references to identifiers.
You can create list of class objects that refer to a hierarchical path, and put those objects in a list indexed by a string.
`define NOC_PATH l1_inst
package probe_pkg;
interface class abstract_probe;
pure virtual function logic get_Rst;
endclass
abstract_probe list[string];
endpackage
interface probe #(string name) (input logic p);
import probe_pkg::*;
class concrete_probe implements abstract_probe;;
function new(string name);
list[name]=this;
endfunction
virtual function logic get_Rst();
return p;
endfunction
endclass
concrete_probe h=new(name);
endinterface
module top;
level1 l1_inst();
initial begin
l1_inst.l2_inst.t4();
`define probe(path,name) bind path.name probe#(`"name`") prb(rst);
`probe(`NOC_PATH,l2_inst);
if (probe_pkg::list[0].rst)
$display ("rst is set");
end
endmodule
module level1;
level2 l2_inst();
endmodule
module level2;
int rst;
task t4();
rst = 1;
endtask
endmodule
Thanks, Dave for the suggestion. I created this example which depicts more closer behaviour of my TB.
But it is resulting in below error - Could you please help.
Error-[SE] Syntax error
Following verilog source has syntax error :
"testbench.sv", 40 (expanding macro): token is 'bind'
`probe(`NOC_PATH,array[0]); // manually passing 0 here, but in actual it
will be a random index
^
SystemVerilog keyword 'bind' is not expected to be used in this context.
#0, probe(path=l1_inst.l2_inst, name=array[0]) : "testbench.sv":38
full expansion of macro (probe), error at line 1
=>bind l1_inst.l2_inst.array[0] probe#("array[0]") prb(a);
1 error
The bind construct cannot be placed inside procedural code. Move the `probe macro references outside.
Also, my example declared list as an associative array–you cannot access list[0]. If you don’t care how you access elements in list, use a queue instead
Hi @dave_59 , Follow-up - I have observed that the declared queue.push() is storing module name as per design instantiation sequence and not as per `probe calling.
I have mentioned in the end of the code comment that why the same sequence of full_path and queue is important for me.
I could think of below 2 ways, but don’t know to do code :-
Is there a way to get elements in probe_pkg::queue as per `probe calling ?
foreach (probe_pkg::queue[i])
full_path [i] = {“dut.”, “noc.”, here , “.addr”}; // Is there a way to get module name stored in probe_name here? // this way full_path and queue element sequence will match
module dut;
noc noc();
endmodule
module noc;
rom rom3();
rom rom2();
rom rom1();
rom rom();
ram ram();
// probe_pkg::queue is getting filled as per this sequence
endmodule
module ram;
int rst = 1;
int addr = 2;
endmodule
module rom;
int rst = 1;
int addr = 4;
endmodule
`define NOC_PATH dut.noc
package probe_pkg;
interface class abstract_probe;
pure virtual function int get_Rst;
endclass
abstract_probe queue[$];
endpackage
interface probe #(string name) (input int p);
import probe_pkg::*;
class concrete_probe implements abstract_probe;
string probe_name;
function new(string name);
probe_name = name;
queue.push_back(this);
endfunction
virtual function int get_Rst();
return p;
endfunction
endclass
concrete_probe h = new(name);
endinterface
module tb;
dut dut();
int idx = 2;
int path_val;
`define probe(path, name) bind path.name probe#(`"name`") prb(rst);
`probe(`NOC_PATH, rom);
`probe(`NOC_PATH, rom1);
`probe(`NOC_PATH, rom3);
`probe(`NOC_PATH, ram);
`probe(`NOC_PATH, rom2);
string names[] = {"rom", "rom1", "rom3", "ram", "rom2"}; // same sequence as `probe calling
string full_path [];
initial begin
full_path = new [names.size()];
foreach (names[i])
full_path [i] = {"dut.", "noc.", names[i], ".addr"}; //creating path to node register
//foreach (probe_pkg::queue[i])
// full_path [i] = {"dut.", "noc.", ---- , ".addr"}; // Is there a way to get module name here ?
foreach (probe_pkg::queue[i]) $display ("probe_pkg::queue [%0d] = %0p", i, probe_pkg::queue[i]);
/*
if (probe_pkg::queue[idx].get_Rst())
assert(uvm_hdl_read(full_path[idx], path_val));
// inject error on the node register (addr)
// Here idx will be a random integer - that's why sequence of queue[idx] & full_path[idx] is important.
// Otherwise Reset will be checked for different module and Error will be injected on different module.
*/
end
endmodule
----------- Output --- Not as per `probe() -----
probe_pkg::queue [0] = '{probe_name:"rom3"}
probe_pkg::queue [1] = '{probe_name:"rom2"}
probe_pkg::queue [2] = '{probe_name:"rom1"}
probe_pkg::queue [3] = '{probe_name:"rom"}
probe_pkg::queue [4] = '{probe_name:"ram"}