UVM:2.3 为验证平台加入各个组件->2.3.7 加入field_automation机制

177 篇文章 139 订阅

1. 前面的my_print,my_copy,my_compare函数,虽然各自不同,但对于transaction来说,都是类似的。使用UVM中的field_automation机制,可以自动实现这3个函数,不需要我们写,my_transaction:

`ifndef MY_TRANSACTION__SV
`define MY_TRANSACTION__SV

class my_transaction extends uvm_sequence_item;

   rand bit[47:0] dmac;
   rand bit[47:0] smac;
   rand bit[15:0] ether_type;
   rand byte      pload[];
   rand bit[31:0] crc;

   constraint pload_cons{
      pload.size >= 46;
      pload.size <= 1500;
   }

   function bit[31:0] calc_crc();
      return 32'h0;
   endfunction

   function void post_randomize();
      crc = calc_crc;
   endfunction

   `uvm_object_utils_begin(my_transaction)
      `uvm_field_int(dmac, UVM_ALL_ON)
      `uvm_field_int(smac, UVM_ALL_ON)
      `uvm_field_int(ether_type, UVM_ALL_ON)
      `uvm_field_array_int(pload, UVM_ALL_ON)
      `uvm_field_int(crc, UVM_ALL_ON)
   `uvm_object_utils_end

   function new(string name = "my_transaction");
      super.new();
   endfunction

endclass
`endif

1)pload.size还是可以限制的。

2)使用uvm_object_utils_begin 和 uvm_object_utils_end 实现my_transaction 的factory注册。

3)uvm_field系列宏不同:uvm_field_int 对 int;uvm_field_array_int  对 byte。


2.my_model变为:

task my_model::main_phase(uvm_phase phase);
   my_transaction tr;
   my_transaction new_tr;
   super.main_phase(phase);
   while(1) begin
      port.get(tr);
      new_tr = new("new_tr");
      new_tr.copy(tr);//<===========
      `uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
      new_tr.print();//<===========
      ap.write(new_tr);
   end
endtask

之前是my_copy 和 my_print。


3.my_scoreboard变为:

while (1) begin
         act_port.get(get_actual);
         if(expect_queue.size() > 0) begin
            tmp_tran = expect_queue.pop_front();
            result = get_actual.compare(tmp_tran);//<============
            if(result) begin 
               `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
            end

之前是my_compare。


4.field_automation的另一个好处是简化了driver 和 monitor。my_driver 的 drv_one_pkt任务和my_monitor的collect_one_pkt 很长,而且都是些重复性的代码。使用field_automation后,drv_one_pkt 可以简化为:

task my_driver::drive_one_pkt(my_transaction tr);
   byte unsigned     data_q[];
   int  data_size;
   
   data_size = tr.pack_bytes(data_q) / 8; 
   `uvm_info("my_driver", "begin to drive one pkt", UVM_LOW);
   repeat(3) @(posedge vif.clk);
   for ( int i = 0; i < data_size; i++ ) begin
      @(posedge vif.clk);
      vif.valid <= 1'b1;
      vif.data <= data_q[i]; 
   end

   @(posedge vif.clk);
   vif.valid <= 1'b0;
   `uvm_info("my_driver", "end drive one pkt", UVM_LOW);
endtask

1)pack_bytes 将tr 中所有的字段变成byte流放入data_q中。字段按照uvm_field 系列宏的顺序排列。


5.my_monitor的collect_one_pkt :

task my_monitor::collect_one_pkt(my_transaction tr);
   byte unsigned data_q[$];
   byte unsigned data_array[];
   logic [7:0] data;
   logic valid = 0;
   int data_size;
   
   while(1) begin
      @(posedge vif.clk);
      if(vif.valid) break;
   end
   
   `uvm_info("my_monitor", "begin to collect one pkt", UVM_LOW);
   while(vif.valid) begin
      data_q.push_back(vif.data);
      @(posedge vif.clk);
   end
   data_size  = data_q.size();   
   data_array = new[data_size];
   for ( int i = 0; i < data_size; i++ ) begin
      data_array[i] = data_q[i]; 
   end
   tr.pload = new[data_size - 18]; //da sa, e_type, crc
   data_size = tr.unpack_bytes(data_array) / 8; 
   `uvm_info("my_monitor", "end collect one pkt", UVM_LOW);
endtask

1)使用unpack_bytes (UVM的内容)函数将data_q 中的byte流转换成tr 中的各个字段。

2)unpack_bytes的输入参数必须为一个动态数组,所以把收集到的,放在data_q 中的数据复制到一个动态数组中。

3)由于tr中pload是一个动态数据,在调用unpack_bytes前,应该指定其大小。

问题:1)data_q这个queue 不是动态数组吗? 2)data_array不能直接用push_back吗?这样就不需要data_q[$]。


6.使用field_automation机制后,打印的信息室下面格式的:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值