先从SystemVerilog的语法说起
我们先来看一个简单的例子:
bird是一个基类
class bird;
bit [3:0] src =0;
bit [3:0] drc = 1;
virtual task exec_task();
$display("in bird");
endtask
endclass
parr是一个bird的扩展类
class parr extends bird;
bit [3:0] test =2;
virtual task exec_task();
$display("in parr");
endtask
endclass
top层调用
program ex6_14_tb;
bird A;
parr B;
parr C;
initial
begin
A = new();
B = new();
C = new();
A = B;
//$cast(C,A);
A.exec_task();
$display("A.src = %d,A.drc = %d",A.src,A.drc);
$display("A.test = %d",A.test);
end
endprogram
原因分析:
- A是bird的基类句柄,A=B,A基类的句柄指向B扩展类。
- A.exec_task因为有virtual修饰,所以是调用A句柄指向的B的对象,也就是B的exec_task的定义。
- A虽然是指向的B的对象,但是A句柄的类型是bird,并没有test的变量。
综上:所以会报错!
解决方案:A句柄指向的是B扩展类,C是扩展类的句柄,如果指向B扩展类对象是可以的。用cast做类型转换,$cast(C,A),这样的话就可以通过C的句柄访问扩展类的中独有的变量。参考$cast的用法:https://www.cnblogs.com/xuqing125/p/14759124.html
修改top层代码:
program ex6_14_tb;
bird A;
parr B;
parr C;
initial
begin
A = new();
B = new();
C = new();
A = B;
$cast(C,A);
A.exec_task();
$display("A.src = %d,A.drc = %d",A.src,A.drc);
$display("C.test = %d",C.test);
end
endprogram
m_sequencer与p_sequencer
uvm_sequencer_base m_sequencer;是uvm_sequence中的protected变量。
- my_sequencer是从uvm_sequencer中扩展来的,并拥有独特的dmac/smac的变量。
- m_sequencer是uvm_sequencer_base类型的句柄,实际指向的对象是my_sequencer。
- 所以如果想通过基类的句柄m_sequencer来访问扩展类在中独有的damc/smac的变量是不合法的,解决方案就是按照上面的来。
- p_sequencer和m_sequencer实际上都是指向my_sequencer的对象!
宏定义:`uvm_declare_p_sequencer(my_sequencer)
- 宏定义其实就是将上面的操作打了一个报,封装了一下。
- m_set_p_seqeuncer():是set_item_context(parent_seq, sqr);的callback函数,(如果没有定义的话,默认为空)也就是说这个uvm_declare_p_sequencer宏只能在uvm_sequence的扩展类中定义。
如果你没有访问my_sequencer中相对于uvm_sequencer_base中独有的变量话,你是没有必要声明uvm_declare_p_sequencer这个宏定义的。