uvm_reg_bus_op中byte_en详解

在使用寄存器模型的adapter进行数据转换时,会直接对uvm_reg_bus_op进行操作,其包含变量有操作类型、地址、数据等,除byte_en的描述不太清晰外,其他几个都比较好懂。从字面意思来看,该变量似乎是对数据按字节操作进行使能,但实际并不一定,本文将从源码的角度来解读byte_en。

//
//定义在uvm_reg_item.svh//
/
typedef struct {

  // Variable: kind
  //
  // Kind of access: READ or WRITE.
  //
  uvm_access_e kind;


  // Variable: addr
  //
  // The bus address.
  //
  uvm_reg_addr_t addr;


  // Variable: data
  //
  // The data to write. If the bus width is smaller than the register or
  // memory width, ~data~ represents only the portion of ~value~ that is
  // being transferred this bus cycle.
  //
  uvm_reg_data_t data;

   
  // Variable: n_bits
  //
  // The number of bits of <uvm_reg_item::value> being transferred by
  // this transaction.

  int n_bits;

  /*
  constraint valid_n_bits {
     n_bits > 0;
     n_bits <= `UVM_REG_DATA_WIDTH;
  }
  */


  // Variable: byte_en
  //
  // Enables for the byte lanes on the bus. Meaningful only when the
  // bus supports byte enables and the operation originates from a field
  // write/read.
  //
  uvm_reg_byte_en_t byte_en;


  // Variable: status
  //
  // The result of the transaction: UVM_IS_OK, UVM_HAS_X, UVM_NOT_OK.
  // See <uvm_status_e>.
  //
  uvm_status_e status;

} uvm_reg_bus_op;

先看定义,可见该变量的位宽为总线位宽/8,每一位代表对应字节的使能。

///
//uvm_reg_defines.svh//
///

// Macro: `UVM_REG_DATA_WIDTH
//
// Maximum data width in bits
//
// Default value is 64. Used to define the <uvm_reg_data_t> type.
//
`ifndef UVM_REG_DATA_WIDTH
 `define UVM_REG_DATA_WIDTH 64
`endif


// Macro: `UVM_REG_BYTENABLE_WIDTH
//
// Maximum number of byte enable bits
//
// Default value is one per byte in <`UVM_REG_DATA_WIDTH>.
// Used to define the <uvm_reg_byte_en_t> type.
//
`ifndef UVM_REG_BYTENABLE_WIDTH 
  `define UVM_REG_BYTENABLE_WIDTH ((`UVM_REG_DATA_WIDTH-1)/8+1) 
`endif

/
//uvm_reg_model.svh//
/

// Type: uvm_reg_byte_en_t
//
// 2-state byte_enable value with <`UVM_REG_BYTENABLE_WIDTH> bits
//
typedef  bit unsigned [`UVM_REG_BYTENABLE_WIDTH-1:0]  uvm_reg_byte_en_t ;

该变量看起来似乎是在对寄存器读写的时候可以对寄存器的某些byte进行单独的读写,但我在源码中只发现了do_predict()函数对byte_en有直接使用,只对寄存器模型进行了预测,而不是对总线前门访问数据的byte进行使能。现对uvm_reg.svh和uvm_reg_field.svh中的使用进行分析。

///
//uvm_reg.svh//
///

function void uvm_reg::do_predict(uvm_reg_item      rw,
                                  uvm_predict_e     kind = UVM_PREDICT_DIRECT,
                                  uvm_reg_byte_en_t be = -1);

   uvm_reg_data_t reg_value = rw.value[0];
   m_fname = rw.fname;
   m_lineno = rw.lineno;

   rw.status = UVM_IS_OK;

   if (m_is_busy && kind == UVM_PREDICT_DIRECT) begin
      `uvm_warning("RegModel", {"Trying to predict value of register '",
                  get_full_name(),"' while it is being accessed"})
      rw.status = UVM_NOT_OK;
      return;
   end
   
   foreach (m_fields[i]) begin
      rw.value[0] = (reg_value >> m_fields[i].get_lsb_pos()) &
                                 ((1 << m_fields[i].get_n_bits())-1);
      m_fields[i].do_predict(rw, kind, be>>(m_fields[i].get_lsb_pos()/8));
   end

   rw.value[0] = reg_value;

endfunction: do_predict

/
//uvm_reg_field.svh//
/
function void uvm_reg_field::do_predict(uvm_reg_item      rw,
                                        uvm_predict_e     kind = UVM_PREDICT_DIRECT,
                                        uvm_reg_byte_en_t be = -1);
   
   uvm_reg_data_t field_val = rw.value[0] & ((1 << m_size)-1);

   if (rw.status != UVM_NOT_OK)
     rw.status = UVM_IS_OK;

   // Assume that the entire field is enabled
   if (!be[0])
     return;

    ...
    ...

endfunction: do_predict

在uvm_reg.svh的do_predict可以看到,有一个对be(byte_en)的移位操作,这里get_lsb_pos获取的是field在reg中的首位置,整个移位操作就是看field在哪个byte。比如field是[3:1],那么就相当于是be>>(1/8)=be;如果是[9:8]那么就相当于be>>(8/8)=be>>1,右移一位,移动后的be被传到了uvm_reg_field.svh的do_predict里面,该do_predict被field调用。

在uvm_reg_field.svh中,前几行有对be的判断,看be[0]是否为0,如果是0就return,不进行操作,就相当于不使能这个field。be的默认值是-1,因为是unsigned类型,所以是全1,默认不屏蔽。

单这么说有点抽象,举个例子,假如有一个寄存器位宽32,里面4个field,每个field占1个byte,be的值是4'b1101,对于第一个field,它收到的be是be>>(0/8)=be>>0=4'b1101,它的be[0]是1,那么就代表它不会被屏蔽,能够进行后续操作;而对于第二个field,他收到的be是be>>(8/8)=be>>1=4'b110,它的be[0]就是0,被屏蔽,没有操作;第三个第四个be[0]都是1,能够被操作。所以在这种情况下,就相当于对第二个byte没使能。

但对于一个reg的field,很多情况下不一定是一个完整的byte,假如field1是[1:0],field2是[5:2],field3是[9:6],be依然是4'b1101的情况下,field123的be都是4'b1101,因为field3的be为be>>(6/8)=be>>0=4'b1101,此时field3就不会被屏蔽,即第二个byte的前两位(field3[9:8])没有屏蔽,此时按byte使能实际就不是byte了,这里也是命名的歧义所在,也是使用限制。

其他地方暂时还没有找到对byte_en的使用,如果解析有错误欢迎打脸讨论。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值