Что может привести к вызову задачи uvm Consumer «put» до того, как производитель выполнит myport.put

Мой 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

person RossS    schedule 23.06.2016    source источник


Ответы (2)


Извините, это не ответ ... у меня нет разрешения комментировать, поэтому ......

Одна из возможностей заключается в том, что есть некоторая проблема с заказом. IMP put может выполнять предыдущий вызов put и, следовательно, нулевой указатель. Но вам нужно предоставить некоторый код [вызовы функций и подключение] и выходные/отображаемые сообщения. это поможет.

person Rahul Menon    schedule 24.06.2016
comment
// x_data = xfer_data::type_id::create(x_data); - в run_phase apb_driver - я предполагаю, что он не был закомментирован, когда вы использовали его в предыдущих запусках. Отсутствие экземпляра x_data может привести к нулевому указателю - person Rahul Menon; 24.06.2016
comment
возможно, может помочь сделать x_data глобальной переменной в классе. - person Rahul Menon; 24.06.2016
comment
вы можете добавить uvm_object_utils в свой xfer_data - person Rahul Menon; 24.06.2016
comment
вы помещаете реализацию в test_rcvr, имеет вечный цикл. Его нужно вернуть, иначе поток у водителя будет заблокирован, и даже ваш сим - person Rahul Menon; 24.06.2016
comment
Привет, спасибо за подсказку о создании x_data, я добавил его обратно; но для этого нужен был второй аргумент, и мне также нужно было зарегистрировать класс xfer_data на фабрике. Теперь я немного ближе, так как симуляция просто зависает. - person RossS; 24.06.2016
comment
Спасибо, Рахул, я вижу ваш комментарий о вечном цикле. - person RossS; 24.06.2016

Рахул сказал:

раскомментировать xfer_data создать

добавить это, чтобы создать список аргументов

зарегистрировать класс xfer_data на фабрике

удалить вечный цикл в реализации поставленной задачи

Спасибо, Рахул.

person RossS    schedule 24.06.2016