zoukankan      html  css  js  c++  java
  • *2-3-7-加入field_automation机制

    在2.3.3节中引入my_mointor时,在my_transaction中加入了my_print函数;

    在2.3.5节中引入reference model时,加入了my_copy函数;

    在2.3.6节引入scoreboard时,加入了my_compare函数。

    上述三个函数虽然各自不同,但是对于不同的transaction来说,都是类似的:它们都需要逐字段地对transaction进行某些操作。

    那么有没有某种简单的方法,可以通过定义某些规则自动实现这三个函数呢?答案是肯定的。这就是UVM中的field_automation机制,使用uvm_field系列宏实现:


    代码清单 2-52
    文件:src/ch2/section2.3/2.3.7/my_transaction.sv
      4 class my_transaction extends uvm_sequence_item;
      5
      6   rand bit[47:0] dmac;
      7   rand bit[47:0] smac;
      8   rand bit[15:0] ether_type;
      9   rand byte      pload[];
     10   rand bit[31:0] crc;
     …
     25   `uvm_object_utils_begin(my_transaction)
     26     `uvm_field_int(dmac, UVM_ALL_ON)
     27     `uvm_field_int(smac, UVM_ALL_ON)
     28     `uvm_field_int(ether_type, UVM_ALL_ON)
     29     `uvm_field_array_int(pload, UVM_ALL_ON)
     30     `uvm_field_int(crc, UVM_ALL_ON)
     31   `uvm_object_utils_end
     …
     37 endclass


    这里使用uvm_object_utils_begin和uvm_object_utils_end来实现my_transaction的factory注册,在这两个宏中间,使用uvm_field宏注册所有字段。uvm_field系列宏随着transaction成员变量的不同而不同,如上面的定义中出现了针对bit类型的uvm_field_int及针对byte类型动态数组的uvm_field_array_int。

    3.3.1节列出了所有的uvm_field系列宏。

    当使用上述宏注册之后,可以直接调用copy、compare、print等函数,而无需自己定义。这极大地简化了验证平台的搭建,提高了效率:


    代码清单 2-53
    文件:src/ch2/section2.3/2.3.7/my_model.sv
     26 task my_model::main_phase(uvm_phase phase);
     27   my_transaction tr;
     28   my_transaction new_tr;
     29   super.main_phase(phase);
     30   while(1) begin
     31     port.get(tr);
     32     new_tr = new("new_tr");
     33     new_tr.copy(tr);
     34     `uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
     35     new_tr.print();
     36     ap.write(new_tr);
     37   end
     38 endtask



    代码清单 2-54
    文件:src/ch2/section2.3/2.3.7/my_scoreboard.sv

     34      while (1) begin
     35        act_port.get(get_actual);
     36        if(expect_queue.size() > 0) begin
     37          tmp_tran = expect_queue.pop_front();
     38          result = get_actual.compare(tmp_tran);
     39          if(result) begin
     40            `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
     41          end


    引入field_automation机制的另外一大好处是简化了driver和monitor。在2.3.1节及2.3.3节中,my_driver的drv_one_pkt任务和my_monitor的collect_one_pkt任务代码很长,但是几乎都是一些重复性的代码。使用field_automation机制后,drv_one_pkt任务可以简化为:


    代码清单 2-55
    文件:src/ch2/section2.3/2.3.7/my_driver.sv
     38 task my_driver::drive_one_pkt(my_transaction tr);
     39   byte unsigned data_q[];
     40   int  data_size;
     41
     42   data_size = tr.pack_bytes(data_q) / 8;
     43   `uvm_info("my_driver", "begin to drive one pkt", UVM_LOW);
     44   repeat(3) @(posedge vif.clk);
     45   for ( int i = 0; i < data_size; i++ ) begin
     46      @(posedge vif.clk);
     47      vif.valid <= 1'b1;
     48      vif.data <= data_q[i];
     49   end
     50
     51   @(posedge vif.clk);
     52   vif.valid <= 1'b0;
     53   `uvm_info("my_driver", "end drive one pkt", UVM_LOW);
     54 endtask


    第42行调用pack_bytes将tr中所有的字段变成byte流放入data_q中,在2.3.1节中是手工地将所有字段放入data_q中的。

    pack_bytes极大地减少了代码量。在把所有的字段变成byte流放入data_q中时,字段按照uvm_field系列宏书写的顺序排列。在上述代码中是先放入dmac,再依次放入smac、ether_type、pload、crc。假如my_transaction定义时各个字段的顺序如下:


    代码清单 2-56
    `uvm_object_utils_begin(my_transaction)
       `uvm_field_int(smac, UVM_ALL_ON)
       `uvm_field_int(dmac, 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


    那么将会先放入smac,再依次放入dmac、ether_type、pload、crc。

    my_monitor的collect_one_pkt可以简化成:


    代码清单 2-57
    文件:src/ch2/section2.3/2.3.7/my_monitor.sv
     34 task my_monitor::collect_one_pkt(my_transaction tr);
     35   byte unsigned data_q[$];
     36   byte unsigned data_array[];
     37   logic [7:0] data;
     38   logic valid = 0;
     39   int data_size;
     …
     46   `uvm_info("my_monitor", "begin to collect one pkt", UVM_LOW);
     47   while(vif.valid) begin
     48      data_q.push_back(vif.data);
     49      @(posedge vif.clk);
     50   end
     51   data_size  = data_q.size();
     52   data_array = new[data_size];
     53   for ( int i = 0; i < data_size; i++ ) begin
     54      data_array[i] = data_q[i];
     55   end
     56   tr.pload = new[data_size - 18]; //da sa, e_type, crc
     57   data_size = tr.unpack_bytes(data_array) / 8;
     58   `uvm_info("my_monitor", "end collect one pkt", UVM_LOW);
     59 endtask


    这里使用unpack_bytes函数将data_q中的byte流转换成tr中的各个字段。unpack_bytes函数的输入参数必须是一个动态数组,所以需要先把收集到的、放在data_q中的数据复制到一个动态数组中。由于tr中的pload是一个动态数组,所以需要在调用unpack_bytes之前指定其大小,这样unpack_bytes函数才能正常工作。

  • 相关阅读:
    [Bootstrap]全局样式(四)
    [Bootstrap]全局样式(三)
    [Bootstrap]全局样式(二)
    [Bootstrap]全局样式(一)
    [Bootstrap]概述
    原生JS-----一个剪刀石头布游戏
    聊聊 ES6 中的箭头函数
    jQuery中的 AJAX
    AJAX封装
    AJAX 初识
  • 原文地址:https://www.cnblogs.com/YINBin/p/6915664.html
Copyright © 2011-2022 走看看