我有一类接口。
我在顶部创建了2个此接口的实例:
//Interface declaration
pakmx_if_out vif_out[2](clk, rst);
//Registers the Interface in the configuration block
//so that other blocks can use it
uvm_resource_db#(virtual pakmx_if_out)::set(.scope("ifs"), .name("pakmx_if_out0"), .val(vif_out[0]));
uvm_resource_db#(virtual pakmx_if_out)::set(.scope("ifs"), .name("pakmx_if_out1"), .val(vif_out[1]));
在监视器中,我通过以下方式创建虚拟接口:
//interface
virtual pakmx_if_out vif_out;
另外,我在监视器中有一个访问上述接口信号的任务。 如何在代理程序类中创建监视器的2个实例,以便每个监视器将引用该接口的不同实例?
我创建了一个监视器实例,在构建阶段连接它并运行代理程序的阶段:
//build phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent_ap = new (.name("agent_ap"), .parent(this));
pm_seqr = pakmx_sequencer::type_id::create(.name("pm_seqr"), .parent(this));
pm_drvr = pakmx_driver::type_id::create(.name("pm_drvr"), .parent(this));
pm_mon = pakmx_monitor::type_id::create(.name("pm_mon"), .parent(this));
endfunction: build_phase
//connect phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pm_drvr.seq_item_port.connect(pm_seqr.seq_item_export);
pm_mon.mon_ap.connect(agent_ap);
endfunction: connect_phase
答案 0 :(得分:0)
uvm_config_db是一种更好的传递接口的方法,建议使用uvm_resource_db。 uvm_config_db采用实例名称和上下文,我们可以使用它确切地定位哪个块获取配置值。
//in Monitor
function void connect_phase ( uvm_phase phase ) ;
uvm_config_db#(virtual pakmx_if_out)::get(.cntxt (this),.inst_name(""), .field_name("pakmx_if_out"), .value(vif_out));
end function
在代理程序中创建了两个监视器实例。由于监视器名称不同,我们将使用这些名称来传递这些监视器的不同接口实例。
//build phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
//agent_ap = new (.name("agent_ap"), .parent(this));
pm_seqr = pakmx_sequencer::type_id::create(.name("pm_seqr"), .parent(this));
pm_drvr = pakmx_driver::type_id::create(.name("pm_drvr"), .parent(this));
pm_mon = pakmx_monitor::type_id::create(.name("pm_mon"), .parent(this));
pm_mon1 = pakmx_monitor::type_id::create(.name("pm_mon1"), .parent(this));
endfunction: build_phase
来自顶级TB。
// from top
uvm_config_db#(virtual pakmx_if_out)::set(.cntxt(null), .inst_name("*pm_mon"), .field_name("pakmx_if_out"), .value(vif_out[0]));
uvm_config_db#(virtual pakmx_if_out)::set(.cntxt(null), .inst_name("*pm_mon1"), .field_name("pakmx_if_out"), .value(vif_out[1]));
这里instance_name用于区分监视器的两个实例。使用“*”将前缀与监视器获取的名称相匹配。我们也可以指定完整/精确路径。在这种情况下,无需为config_db中的实例指定不同的field_name / name。
链接解释了uvm_config_db的各种细微差别 https://www.synopsys.com/Services/Documents/hierarchical-testbench-configuration-using-uvm.pdf
另一种解决方案 -
如果两个接口都可以具有不同的field_name。 代理可以获取这两个接口,并在连接阶段将其分配给监视器。
//connect phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
uvm_config_db#(virtual pakmx_if_out)::get(.cntxt (null),.inst_name(""), .field_name("pakmx_if_out0"), .value(vif_out[0]));
uvm_config_db#(virtual pakmx_if_out)::get(.cntxt(null), .inst_name(""),.field_name("pakmx_if_out1"), .value(vif_out[1]));
pm_mon.vif_out = vif_out[0];
pm_mon1.vif_out = vif_out[1];
pm_drvr.seq_item_port.connect(pm_seqr.seq_item_export);
pm_mon.mon_ap.connect(agent_ap);
end function:connect_phase
构建阶段实例化监视器的两个实例。
//build phase
function void build_phase(uvm_phase phase); super.build_phase(phase);
agent_ap = new (.name("agent_ap"), .parent(this));
pm_seqr = pakmx_sequencer::type_id::create(.name("pm_seqr"), .parent(this));
pm_drvr = pakmx_driver::type_id::create(.name("pm_drvr"), .parent(this));
pm_mon = pakmx_monitor::type_id::create(.name("pm_mon"), .parent(this));
pm_mon1 = pakmx_monitor::type_id::create(.name("pm_mon1"), .parent(this));
endfunction: build_phase
从顶级tb。这里不需要提供任何特定的实例或context.Still使用uvm_config_db。
uvm_config_db#(virtual pakmx_if_out)::set(.cntxt(null), .inst_name(""), .field_name("pakmx_if_out0"), .value(vif_out[0]));
uvm_config_db#(virtual pakmx_if_out)::set(.cntxt(null), .inst_name(""), .field_name("pakmx_if_out1"), .value(vif_out[1]));