uvm_config_db ist eine bessere Möglichkeit, die Schnittstellen zu passieren und es ist die Verwendung über die uvm_resource_db empfohlen. uvm_config_db verwendet den Namen und den Kontext von Instanzen, mit denen wir genau bestimmen können, welcher Block den Konfigurationswert erhält.
//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
Im Agenten werden zwei Instanzen des Monitors erstellt. Da die Monitornamen unterschiedlich sind, verwenden wir diese Namen, um diesen Monitoren verschiedene Instanzen der Schnittstelle zu übergeben.
//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
Von Top-Level-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]));
Hier wird der instance_name verwendet, um zwischen den beiden Instanzen des Monitors zu unterscheiden. Verwenden Sie "*", um das Präfix den Namen der Monitore zuzuordnen. Wir könnten auch den vollständigen/genauen Pfad angeben. In diesem Fall müssen Sie den Instanzen in der config_db keinen anderen field_name/name geben.
Link verschiedene Nuancen von uvm_config_db erklärt https://www.synopsys.com/Services/Documents/hierarchical-testbench-configuration-using-uvm.pdf
Eine andere Lösung -
wenn die beiden Schnittstellen unterschiedliche field_name haben. Der Agent kann beide Schnittstellen abrufen und während der Verbindungsphase dem Monitor zuweisen.
//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 instanziiert zwei Instanzen des Monitors.
//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
Von der obersten Ebene tb. Hier muss keine bestimmte Instanz oder kein bestimmter Kontext angegeben werden. Verwenden Sie jedoch immer noch "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]));