UVM - 8 (override - 1)

在uvm 中可以利用factory机制的重载作用改变某些component的特性, 而不用去修改testbench。比如说:写了2个driver的class,但是uvm环境中只需要用到一个,如果这两个driver都是用factory注册,那么就可以用override的方式替换当前uvm环境中的driver。

Note:一、两个组件都注册,注册component时候使用uvm_component_utils,
创建component对象的时候使用::type_id::creat(), 而不是使用new()

案例

架构

Components:
- Agents 
	- my_agent
		1. my_agent_v2 (child)
- Drivers
	base_driver 
	 	1. eth_driver (child)
		2. spi_driver (child)
- Sequencer - my_seqeuncer
- Sequences
	- base_sequence
		1. seq1 (child)
		2. seq2 (child)
		3. seq3 (child)
- Data
	- eth_packet
		- eth_v2_packet (child)

Sequencer within m_agnt2 operate on seq3, while the other two operate on seq1 by default

Coding

1.packet

  • 定义一个data packet的base class,然后派生出一个子类
  • packet继承自uvm_sequence_item,继承自uvm_sequence_item的类是事务类,可以使用packet或者transaction进行命名
//------------------ eth_packet-----------------------------------
class eth_packet extends uvm_sequence_item;
   `uvm_object_utils (eth_packet) // 在工程中注册
 
  ...

   function new (string name = "eth_packet");
      super.new (name);
      `uvm_info (get_type_name(), "Packet created", UVM_MEDIUM)
   endfunction
endclass   

//------------------ eth_v2_packet-----------------------------------
class eth_v2_packet extends eth_packet; 
   `uvm_object_utils (eth_v2_packet) // 在工厂中注册
 
   ...
 
   function new (string name = "eth_v2_packet");
      super.new (name);
   endfunction
endclass

2. driver

  • 创建一个driver的base class ,然后派生出两个子类:eth_driver和spi_driver
//------------------ base_driver-----------------------------------
 
// driver需要传入事务类型
class base_driver #(type T=eth_packet) extends uvm_driver;
   `uvm_component_utils (base_driver #(T))
 
   T pkt;
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // 创建packet对象
      pkt = T::type_id::create ("pkt0");
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      super.run_phase (phase);
      `uvm_info (get_type_name(), $sformatf("Driver running ...with packet of type : %s", pkt.get_type_name()), UVM_MEDIUM)
   endtask
 
endclass
 
//----------------- eth_driver-----------------------------------
 
class eth_driver #(type T=eth_packet) extends base_driver #(T);
   `uvm_component_utils (eth_driver #(T))
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
endclass
 
//----------------- spi_driver-----------------------------------
 
class spi_driver #(type T=eth_packet) extends base_driver #(T); 
   `uvm_component_utils (spi_driver #(T))
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
endclass

3.sequence

  • 定义几个seqence
//----------------- base_sequence-----------------------------------
class base_sequence extends uvm_sequence;
  `uvm_object_utils (base_sequence)
endclass
 
//----------------- seq1 -------------------------------------------
class seq1 extends base_eth_sequence;
   `uvm_object_utils (seq1)
  ...
endclass
 
//----------------- seq2 -------------------------------------------
class seq2 extends base_eth_sequence;
   `uvm_object_utils (seq2)
   ...
endclass
 
//----------------- seq3 -------------------------------------------
class seq3 extends base_eth_sequence;
   `uvm_object_utils (seq3)
  ...
endclass

4.agent

//----------------- my_agent -------------------------------------------
class my_agent extends uvm_agent;
   `uvm_component_utils (my_agent)
 
   base_driver    m_drv0;
   my_sequencer   m_seqr0;
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void **build_phase** (uvm_phase phase);
      super.build_phase (phase);
      m_drv0 = base_driver::type_id::create ("m_drv0", this); // 创建driver对象
      m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this); // 创建sequencer对象
   endfunction
 
   virtual function void **connect_phase** (uvm_phase phase);
      super.connect_phase (phase);
      m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);//sequencer的seq_itme_export接口和driver.seq_item.port接口连接
   endfunction
endclass
 
//----------------- my_agent_v2 -------------------------------------------
class my_agent_v2 extends uvm_agent;
   `uvm_component_utils (my_agent_v2)
 
   eth_driver     m_drv0;
   my_sequencer   m_seqr0;
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_drv0 = eth_driver::type_id::create ("m_drv0", this);
      m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this);
   endfunction
 
   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase (phase);
      m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
   endfunction
endclass

5.env

  • my_agent中包含base_driver,my_agent_v2中包含eth_driver,
  • 在环境当中创建多个agent,每个agent中包含的组件不同
class my_env extends uvm_env ;
   `uvm_component_utils (my_env)
 
   my_agent       m_agnt0; 
   my_agent       m_agnt1; 
   my_agent_v2    m_agnt2;
 
   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction : new
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_agnt0 = my_agent::type_id::create ("m_agnt0", this);
      m_agnt1 = my_agent::type_id::create ("m_agnt1", this);
      m_agnt2 = my_agent_v2::type_id::create ("m_agnt2", this);
   endfunction : build_phase
endclass : my_env

6. test

class feature_test extends base_test;
      `uvm_component_utils (feature_test)
 
      function new (string name, uvm_component parent = null);
         super.new (name, parent);
      endfunction 
 
      virtual function void build_phase (uvm_phase phase);
         super.build_phase (phase); 
 
`ifdef PKT_OVERRIDE
         // Substitute all eth_packets with eth_v2_packet
  
         // 查找override表,也相当于在override表中更新信息
         // 用eth_v2_packet替代eth_packet类
         **set_type_override_by_type (eth_packet::get_type(), eth_v2_packet::get_type());**
`endif
 
 
 
// These are the three different styles to override something
 
`ifdef DRV_STYLE1
         // Substitute all instances of base_driver with driver2 
         set_type_override_by_type (base_driver::get_type(), spi_driver::get_type());
`elsif DRV_STYLE2
         // Substitute only eth_driver in agnt2 with spi_driver - by calling the component to be replaced method
         eth_driver::type_id::set_inst_override (spi_driver::get_type(), "m_top_env.m_agnt2.m_drv0", this);
`elsif DRV_STYLE3
         // Substitute base_driver only in agnt0 - by calling the factory method
         factory.set_inst_override_by_type (base_driver::get_type(), eth_driver::get_type(), {get_full_name(), ".m_top_env.m_agnt0.*"});
`endif
 
 
 
// Trying to override a sequence
 
`ifdef SEQ_TYPE
         // Substitute seq1 with seq2
         set_type_override_by_type (seq1::get_type(), seq3::get_type());
`elsif SEQ_INST
         // Substitute seq1 with seq2 only for agnt1
         set_inst_override_by_type ("m_top_env.m_agnt1.m_seqr0.*", seq1::get_type(), seq2::get_type());
`else
`endif
         factory.print();
      endfunction
      // Enter test code for feature here
   endclass
posted @ 2024-03-15 08:28  Icer_Newer  阅读(77)  评论(0编辑  收藏  举报