主动事务处理器编写BFM

本文档详细介绍了如何在VMM(Virtual Memory Manager)框架下编写主动事务处理器APB_Master,该处理器用于APB(Advanced Peripheral Bus)总线。主要内容包括事务描述符、主动事务处理器的构造、读写任务的实现、回调方法的使用以及调试信息的添加。文章通过步骤指导,展示了如何扩展vmm_xactor基类,实现事务处理器的阻塞、非阻塞和乱序处理,并通过回调机制增强其可重用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章介绍命令层主动事务处理器的编写方法。命令层事务处理器就是一个一端是事务级接口,一端连接物理信号,也称为BFM。如图所示:

 

第一步:

第二步:

第三步:事务描述符(同命令层监视器)

第四步:主动事务处理器

现在开始写主动性事务处理器,它是由vmm_xactor基类扩展来的类。

实现读和写周期的任务在类中实现。它们定义为virtual,这样就可以在事务处理器的扩展类中修改它们的行为。它们定义为protected,以防止他们在类外被调用和出现同时访问总线的问题。

`ifndef APB_MASTER__SV 
`define APB_MASTER__SV 
`include “apb_if.sv” 
`include “apb_rw.sv” 
... 
class apb_master extends vmm_xactor; 
   ... 
   virtual protected task read(input  bit   [31:0] addr, 
                               output logic [31:0] data); 
      ... 
   endtask: read 
   virtual protected task write(input bit [31:0] addr, 
                                input bit [31:0] data); 
      ... 
   endtask: write 
   ... 
endclass: apb_master 


本事务处理器需要一个事务级接口来接收事务和一个物理级接口。前者用vmm_channel实例,后者用虚拟端口virtual modport。它们都通过构造函数传递给事务处理器,都保存在公共类属性中。

`ifndef APB_MASTER__SV 
`define APB_MASTER__SV 
`include “apb_if.sv” 
`include “apb_rw.sv” 
... 
class apb_master extends vmm_xactor; 
   apb_rw_channel        in_chan; 
   virtual apb_if.master sigs; 
   function new(string                name, 
                int unsigned          stream_id, 
                virtual apb_if.master sigs, 
                apb_rw_channel        in_chan = null); 
      super.new(“APB Master”, name, stream_id); 
      this.sigs = sigs; 
      if (in_chan == null) 
         in_chan = new(“APB Master Input Channel”, name); 
      this.in_chan = in_chan; 
      ... 
   endfunction: new 
   ... 
   virtual protected task read(input  bit   [31:0] addr, 
                               output logic [31:0] data); 
      ... 
   endtask: read 
   virtual protected task write(input bit [31:0] addr, 
                                input bit [31:0] data); 
      ... 
   endtask: write 
   ... 
endclass: apb_master 
`endif 


当事务处理器复位时,输入通道必须排空,关键的输出信号必须被驱动为空闲状态。这些都在vmm_xactor::reset_xactor方法的扩展类中实现。可在事务处理器的构造函数中初始化输出信号。

`ifndef APB_MASTER__SV 
`define APB_MASTER__SV 
`include “apb_if.sv” 
`include “apb_rw.sv” 
... 
class apb_master extends vmm_xactor; 
   apb_rw_channel        in_chan; 
   virtual apb_if.master sigs; 
   function new(string                name, 
                int unsigned          stream_id, 
                virtual apb_if.master sigs, 
                apb_rw_channel        in_chan = null); 
      super.new(“APB Master”, name, stream_id); 
      this.sigs = sigs; 
      if (in_chan == null) 
         in_chan = new(“APB Master Input Channel”, name); 
      this.in_chan = in chan; 
      this.sigs.mck.psel    <= ’0; 
      this.sigs.mck.penable <= ’0; 
   endfunction: new 
  virtual function void reset_xactor(reset_e rst_typ = SOFT_RST); 
      super.reset(rst_typ); 
      this.in_chan.flush(); //排空输入通道 
      this.sigs.mck.psel <= ’0; 
      this.sigs.mck.penable <= ’0; 
   endfunction: reset_xactor 


最灵活的事务处理器执行机制使用支持阻塞,非阻塞,乱序的有效时隙。因为协议支持事务之间的暂停,所以要应该用vmm_xactor;;wart_if_stopped_or_empty方法来停止事务处理器。

virtual protected task main(); 
     super.main(); 
     @ (this.sigs.mck); 
     forever begin 
        apb_rw tr; 
        this.wait_if_stopped_or_empty(this.in_chan); 
        this.in_chan.activate(tr); 
        ... 
        this.in_chan.start(); 
        case (tr.kind) 
        apb_rw::READ : this.read(tr.addr, tr.data); 
        apb_rw::WRITE: this.write(tr.addr, tr.data); 
        endcase 
        this.in_chan.complete(); 
        ... 


第六步:扩展点

前面的事务处理器具有基本的功能。但是可重用性低。回调方法允许用户在不修改事务处理器本身就能扩展事务处理器的行为。应该编写在事务处理前后的回调方法。"pre-transaction"回调方法允许注入错误和延迟;"post-transaction"回调方法允许插入延迟,或将事务的值记录在功能覆盖模型中,或与期望响应做对照。

要在回调基类的扩展类(callback facade)中把回调方法定义为virtual tasks 或这virtual void functions。在"pre-transaction"回调方法中创建一个允许丢弃事务的机制无疑是一个好的想法。

`ifndef APB_MASTER__SV 
`define APB_MASTER__SV 
`include “apb_if.sv” 
`include “apb_rw.sv” 
typedef class apb_master; 
class apb_master_cbs extends vmm_xactor_callbacks; 
   virtual task pre_cycle(apb_master xactor, 
                          apb_rw     cycle, 
                          ref bit    drop); 
   endtask: pre_cycle 
   virtual task post_cycle(apb_master xactor, 
                           apb_rw     cycle); 
   endtask: post_cycle 
endclass: apb_master_cbs 
class apb_master extends vmm_xactor; 
   apb_rw_channel        in_chan; 
   virtual apb_if.master sigs; 
   function new(string                name, 
                int unsigned          stream_id, 
                virtual apb_if.master sigs, 
                apb_rw_channel        in_chan = null); 


应该在恰当的点应用回调方法,用`vmm_callback()宏来实现。

virtual protected task main(); 
     super.main(); 
     @ (this.sigs.mck); 
     forever begin 
        apb_rw tr; 
       bit drop; 

        this.wait_if_stopped_or_empty(this.in_chan); 
        this.in_chan.activate(tr); 

      drop = 0; 
         `vmm_callback(apb_master_cbs, pre_cycle(this, tr, drop)); 
         if (drop) begin 
            this.in_chan.remove(); 
            continue; 
         end 

         this.in_chan.start(); 
         case (tr.kind) 
         apb_rw::READ : this.read(tr.addr, tr.data); 
         apb_rw::WRITE: this.write(tr.addr, tr.data); 
         endcase 
         this.in_chan.complete(); 
         `vmm_callback(apb_master_cbs, post_cycle(this, tr)); 
         this.in_chan.remove(); 
      end 
   endtask: main 
   virtual protected task read(input  bit   [31:0] addr, 
                               output logic [31:0] data); 
      ... 
   endtask: read 
   virtual protected task write(input bit [31:0] addr, 
                                input bit [31:0] data); 
      ... 
   endtask: write 
endclass: apb_master 
`endif 


第七步:调试信息

为了能完全的重用,应该不用查看源代码就能理解事务处理器在做什么和调试它的操作。调试信息应该加到合适的点来表明事务处理器将做什么,正在做什么,已经做了什么操作。这些调试信息要通过`vmm_trace,`vmm_debug,`vmm_verbose发出。

virtual protected task main(); 
     super.main(); 
     @ (this.sigs.mck); 
     forever begin 
        apb_rw tr; 
        bit drop; 

        this.wait_if_stopped_or_empty(this.in_chan); 
        this.in_chan.activate(tr); 

      drop = 0; 
      `vmm_callback(apb_master_cbs, pre_cycle(this, tr, drop)); 
      if (drop) begin 
        `vmm_debug(log, {“Dropping transaction.../n”, 
                          tr.psdisplay(“   “)}); 
         this.in_chan.remove(); 
         continue; 
      end 
      `vmm_trace(log, {“Starting transaction.../n”, 
                       tr.psdisplay(“   “)}); 
      this.in_chan.start(); 
      case (tr.kind) 
      apb_rw::READ : this.read(tr.addr, tr.data); 
      apb_rw::WRITE: this.write(tr.addr, tr.data); 
      endcase 
      this.in_chan.complete(); 
      `vmm_trace(log, {“Completed transaction.../n”, 
                       tr.psdisplay(“   “)}); 
      `vmm_callback(apb_master_cbs, post_cycle(this, tr)); 
      this.in_chan.remove(); 
   end 
endtask: main 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值