Мой uvm_driver (производитель) обменивается данными с uvm_component (потребителем) через порт put. Общий элемент представляет собой класс xfer_data uvm_transaction с двумя элементами данных и методом getdata. Драйвер вызывает getdata, затем немедленно выполняет вызов .put, но через операторы $display я вижу, что задача потребительского ввода вызывается сразу после getdata, но до .put, и я получаю разыменование ужасного нулевого указателя.
Когда я вижу примеры из uvm_users_guide, они выглядят такими простыми и элегантными. Я попытался изменить своего потребителя на uvm_subscriber с тем же результатом. Как обычно, код компилируется без ошибок и работает, если я удаляю код порта. Любая помощь будет оценена!
--Росс
Я добавил код: CONSUMER, PRODUCER, class OBJECT of PORT, операторы подключения AGENT.
////////////////// CONSUMER /////////////////////
//class test_rcvr extends uvm_component; //RLHS
class test_rcvr extends uvm_subscriber #(xfer_data);
`uvm_component_utils(test_rcvr)
local int xfer_count; //RLHS
local logic [31:0] last_data;
local logic [3:0] last_datamask;
bit in_progress [$]; //RLHS indicate transaction in progress
uvm_blocking_put_imp #(xfer_data, test_rcvr) driver_dataport;
function new(string name = "test_rcvr", uvm_component parent = null);
super.new(name, parent);
xfer_count=0;
driver_dataport = new("driver_dataport",this);
endfunction
virtual task put(xfer_data test_data);
forever begin
// driver_dataport.get(test_data);
last_data = test_data.data1;
last_datamask = test_data.datamask;
xfer_count++;
end
endtask: put
endclass: test_rcvr
//////////////////////// PRODUCER //////////////////////////
class apb_driver extends uvm_driver #(apb_seq_item);
`uvm_component_utils(apb_driver)
apb_seq_item req;
virtual interface if_apb IF_APB;
uvm_blocking_put_port #(xfer_data) driver_dataport; //RLHS define port name
//1 uvm_analysis_port #(xfer_data) driver_dataport;//RLHS
function new(string name = "apb_driver", uvm_component parent = null);
super.new(name, parent);
driver_dataport = new("driver_dataport", this); //RLHS
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual if_apb)::get(null ,"uvm_test_top","field_apb_if", IF_APB)) begin
`uvm_fatal("NOVIF", {"You fool! Virtual interface must be set for field name: field_apb_if "});
end
// driver_dataport = new("driver_dataport", this); //RLHS
endfunction: build_phase
task run_phase(uvm_phase phase);
logic [31:0] data1;
logic [3:0] datamask;
xfer_data x_data; // create object of data to xfer //RLHS
// x_data = xfer_data::type_id::create("x_data"); // RLHS
forever begin // logic rstnapb, psel, pwrt, pen, perr clk_apb
IF_APB.psel <= 1'b0; // logic [31:0] pwdata;
IF_APB.pen <= 1'b0; // wire [31:0] prdata;
IF_APB.paddr <= 7'b0; // logic [6:0] paddr;
IF_APB.pwdata <= 32'b0;
IF_APB.pwrt <= 1'b0;
seq_item_port.get_next_item(req); // blocks until xfer occurs
x_data.get_test_data(3, 1, data1, datamask); // RLHS get data
$display("7.1. apb_pkg driver post call getdata = %5d", data1);
driver_dataport.put(x_data); // RLHS send DDR data
//1 driver_dataport.write(x_data); // RLHS
snip....
endclass:apb_driver
//////////////////////// object sent on PORT ///////////////
class xfer_data extends uvm_transaction;//RLHS
rand int data1;
rand bit [3:0] datamask;
bit wrtreadb;
task get_test_data(input int i, input bit [3:0] what,
output logic [31:0] data1, output logic [3:0] datamask);
// legend:
// i: item number in block
// what: which type of data being xfered
//
case (what)
default: begin
data1 = $random; datamask = $random;
end
1: begin
case (i[2:0])
0:begin data1 = 32'h0123_4567; datamask = 4'h0; end
1:begin data1 = 32'h89ab_cdef; datamask = 4'h1; end
snip....
///////////////////// AGENT ///////////////////////////
class apb_agent extends uvm_agent;
`uvm_component_utils(apb_agent)
uvm_analysis_port #(apb_seq_item) apbport; // this connects sequence
//1 uvm_analysis_port #(xfer_data) driver_dataport; //RLHS
apb_sequencer m_apb_sequencer;
apb_driver m_apb_driver;
apb_monitor m_apb_monitor;
apb_coverage_monitor m_fcov_monitor;
test_rcvr m_test_rcvr;//RLHS
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_apb_sequencer = apb_sequencer::type_id::create("m_apb_sequencer", this);
m_apb_driver = apb_driver::type_id::create("m_apb_driver", this);
m_apb_monitor = apb_monitor::type_id::create("m_apb_monitor", this);
m_fcov_monitor = apb_coverage_monitor::type_id::create("m_fcov_monitor", this);
m_test_rcvr = test_rcvr::type_id::create("m_test_rcvr", this);
apbport = new("apbport", this);
//1 driver_dataport = new("driver_dataport", this); //RLHS
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
m_apb_driver.seq_item_port.connect(m_apb_sequencer.seq_item_export);
//?? m_apb_monitor.apbport.connect(apbport);
m_apb_monitor.apbport.connect(m_fcov_monitor.analysis_export);
apbport = m_apb_monitor.apbport;
//1 driver_dataport = m_apb_driver.driver_dataport; // RLHS
//1 m_apb_driver.xfer_data.connect(driver_dataport);// RLHS
//1 m_apb_driver.xfer_data.connect(m_test_rcvr.analysis_export);// RLHS
m_apb_driver.driver_dataport.connect(m_test_rcvr.driver_dataport);
// m_test_rcvr.driver_dataport.connect(m_apb_driver.driver_dataport);
endfunction: connect_phase
endclass: apb_agent