如何在UVM驱动程序中获取被覆盖的事务项?

huangapple go评论53阅读模式
英文:

How do I get overridden transaction item in UVM driver?

问题

我正在尝试在UVM驱动程序中获取重写的事务项。我创建了一个UVM序列项类,其中包含多个继承的类。

class mem_seq_item extends uvm_sequence_item;
  // ...(您的代码)
endclass

class child_seq_item extends mem_seq_item;
  // ...(您的代码)
endclass

您创建了my_sequence类,并尝试在my_test类中执行它。

class my_sequence extends mem_sequence;
  // ...(您的代码)
endclass

class my_test extends mem_wr_rd_test;
  // ...(您的代码)
endclass

但问题是,您无法在UVM驱动程序中获取重写的事务项。错误信息显示A不是一个类项。

您可以在UVM驱动程序中获取重写的事务项,确保您在mem_driver中正确引用了子类的成员。请注意,如果要访问子类的成员,您需要将事务项强制转换为子类类型。在您的mem_driver中,可以这样做:

virtual task drive(input mem_seq_item trans);
  `DRIV_IF.wr_en <= 0;
  `DRIV_IF.rd_en <= 0;
  @(posedge vif.DRIVER.clk);

  if (trans'is_a(child_seq_item)) begin
    child_seq_item child_trans;
    child_trans = trans;
    `DRIV_IF.addr <= child_trans.A;
  end
  // 可以添加其他事务项的处理
endtask : drive

这将允许您在驱动程序中正确获取A项,前提是事务项是child_seq_item的实例。确保在处理其他类型的事务项时也进行适当的类型检查和转换。

英文:

I'm trying to get the overridden transaction item in UVM driver.
I made a UVM sequence item class which has multiple inherited classes.

class mem_seq_item extends uvm_sequence_item;
  //---------------------------------------
  //data and control fields
  //---------------------------------------
  rand bit [1:0] addr;
  rand bit       wr_en;
  rand bit       rd_en;
  rand bit [7:0] wdata;
       bit [7:0] rdata;
  
  //---------------------------------------
  //Utility and Field macros
  //---------------------------------------
  `uvm_object_utils_begin(mem_seq_item)
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_en,UVM_ALL_ON)
    `uvm_field_int(rd_en,UVM_ALL_ON)
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end
  
  //---------------------------------------
  //Constructor
  //---------------------------------------
  function new(string name = &quot;mem_seq_item&quot;);
    super.new(name);
  endfunction
  
  //---------------------------------------
  //constaint, to generate any one among write and read
  //---------------------------------------
  constraint wr_rd_c { wr_en != rd_en; }; 
  
endclass

class child_seq_item extends mem_seq_item;
  //---------------------------------------
  //data and control fields
  //---------------------------------------
   rand bit [7:0] A;
   rand bit [7:0] B;
   rand bit [7:0] C;
  
  //---------------------------------------
  //Utility and Field macros
  //---------------------------------------
  `uvm_object_utils_begin(child_seq_item)
    `uvm_field_int(A,UVM_ALL_ON)
    `uvm_field_int(B,UVM_ALL_ON)
    `uvm_field_int(C,UVM_ALL_ON)
  `uvm_object_utils_end
  
  //---------------------------------------
  //Constructor
  //---------------------------------------
  function new(string name = &quot;child_seq_item&quot;);
    super.new(name);
  endfunction
  
endclass

And I create the my_sequence

class my_sequence extends mem_sequence;
  
  child_seq_item  child_item;
  `uvm_object_utils(my_sequence)
   
  //--------------------------------------- 
  //Constructor
  //---------------------------------------
  function new(string name = &quot;my_sequence&quot;);
    super.new(name);
  endfunction
  
  virtual task body();
    child_item = child_seq_item::type_id::create(&quot;child_item&quot;);

    `uvm_do(child_item)
     child_item.print();
  endtask
endclass

and tried to execute the my_sequence class in my_testclass .

class my_test extends mem_wr_rd_test;

  `uvm_component_utils(my_test)
  
  //---------------------------------------
  // sequence instance 
  //--------------------------------------- 
  my_sequence my_seq;

  //---------------------------------------
  // constructor
  //---------------------------------------
  function new(string name = &quot;my_test&quot;,uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

  //---------------------------------------
  // build_phase
  //---------------------------------------
  virtual function void build_phase(uvm_phase phase);
    set_type_override_by_type(mem_seq_item::get_type(), child_seq_item::get_type());
    super.build_phase(phase);

    // Create the sequence
    my_seq = my_sequence::type_id::create(&quot;my_seq&quot;);
  endfunction : build_phase
  
  //---------------------------------------
  // run_phase - starting the test
  //---------------------------------------
  task run_phase(uvm_phase phase);
    
    phase.raise_objection(this);
      my_seq.start(env.mem_agnt.sequencer);
    phase.drop_objection(this);
    
    //set a drain-time for the environment if desired
    phase.phase_done.set_drain_time(this, 50);
  endtask : run_phase
  
endclass 

But Problem is I can't get overridden transaction item in UVM driver.

class mem_driver extends uvm_driver #(mem_seq_item);

  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new


  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    ...
  endfunction: build_phase

  //---------------------------------------  
  // run phase
  //---------------------------------------  
  virtual task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(req);
      drive(req);
      `DRIV_IF.addr &lt;= req.addr;
      `DRIV_IF.addr &lt;= req.B; //&lt;=== B is not a class item.
      seq_item_port.item_done();
    end
  endtask : run_phase
  

  virtual task drive(input mem_seq_item trans );
    `DRIV_IF.wr_en &lt;= 0;
    `DRIV_IF.rd_en &lt;= 0;
    @(posedge vif.DRIVER.clk);
    
    `DRIV_IF.addr &lt;= trans.A;

The error message I can't get the A item.

`DRIV_IF.addr &lt;= trans.A;
                       |
xmvlog: *E,NOTCLM (mem_driver.sv,52|27): A is not a class item.

How can I get the overridden transaction item in UVM driver?

答案1

得分: 3

由于驱动程序是使用mem_seq_item参数化的,并且没有关于覆盖事务的信息,您需要将类变量向下转换为一个了解覆盖的类型。

virtual task drive(input mem_seq_item trans);
   child_seq_item csi;
   `DRIV_IF.wr_en <= 0;
   `DRIV_IF.rd_en <= 0;
   @(posedge vif.DRIVER.clk);
    if ($cast(csi, trans))
    `DRIV_IF.addr <= csi.A;

如果trans不是child_seq_item,那么您需要决定在这种情况下会发生什么。

英文:

Since the driver is parameterized with a mem_seq_item and has no information about overridden transactions, you need to downcast the class variable to a type that would know about the override

virtual task drive(input mem_seq_item trans );
   child_seq_item csi;
   `DRIV_IF.wr_en &lt;= 0;
   `DRIV_IF.rd_en &lt;= 0;
   @(posedge vif.DRIVER.clk);
    if ($cast(csi,trans)
    `DRIV_IF.addr &lt;= csi.A;

If the trans is not a child_seq_item, then you will need to decide what happens in that case.

huangapple
  • 本文由 发表于 2023年5月10日 20:28:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76218428.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定