zoukankan      html  css  js  c++  java
  • *2.3.3-加入monitor

    验证平台必须监测DUT的行为,只有知道DUT的输入输出信号变化之后,才能根据这些信号变化来判定DUT的行为是否正确。

    验证平台中实现监测DUT行为的组件是monitor。driver负责把transaction级别的数据转变成DUT的端口级别,并驱动给DUT,monitor的行为与其相对,用于收集DUT的端口数据,并将其转换成transaction交给后续的组件如reference model、scoreboard等处理。

    一个monitor的定义如下:


    代码清单 2-29
    文件:src/ch2/section2.3/2.3.3/my_monitor.sv
      3 class my_monitor extends uvm_monitor;
      4
      5    virtual my_if vif;
      6
      7    `uvm_component_utils(my_monitor)
      8    function new(string name = "my_monitor", uvm_component parent = null);
      9       super.new(name, parent);
     10    endfunction
     11
     12    virtual function void build_phase(uvm_phase phase);
     13       super.build_phase(phase);
     14       if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
     15          `uvm_fatal("my_monitor", "virtual interface must be set for vif!!!")
     16    endfunction
     17
     18    extern task main_phase(uvm_phase phase);
     19    extern task collect_one_pkt(my_transaction tr);
     20 endclass
     21
     22 task my_monitor::main_phase(uvm_phase phase);
     23    my_transaction tr;
     24    while(1) begin
     25       tr = new("tr");
     26       collect_one_pkt(tr);
     27    end
     28 endtask
     29
     30 task my_monitor::collect_one_pkt(my_transaction tr);
     31    bit[7:0] data_q[$];
     32    int psize;
     33    while(1) begin
     34      @(posedge vif.clk);
     35      if(vif.valid) break;
     36    end
     37
     38    `uvm_info("my_monitor", "begin to collect one pkt", UVM_LOW);
     39    while(vif.valid) begin
     40       data_q.push_back(vif.data);
     41       @(posedge vif.clk);
     42    end
     43    //pop dmac
     44    for(int i = 0; i < 6; i++) begin
     45       tr.dmac = {tr.dmac[39:0], data_q.pop_front()};
     46    end
     47    //pop smac
     …
     51    //pop ether_type
     …
     58    //pop payload
     …
     62    //pop crc
     63    for(int i = 0; i < 4; i++) begin
     64       tr.crc = {tr.crc[23:0], data_q.pop_front()};
     65    end
     66    `uvm_info("my_monitor", "end collect one pkt, print it:", UVM_LOW);
     67    tr.my_print();
     68 endtask


    有几点需要注意的是:

    第一,所有的monitor类应该派生自uvm_monitor;

    第二,与driver类似,在my_monitor中也需要有一个virtual my_if;

    第三,uvm_monitor在整个仿真中是一直存在的,所以它是一个component,要使用uvm_component_utils宏注册;

    第四,由于monitor需要时刻收集数据,永不停歇,所以在main_phase中使用while(1)循环来实现这一目的。

    在查阅collect_one_pkt的代码时,可以与my_driver的drv_one_pkt对比来看,两者代码非常相似。当收集完一个transaction后,通过my_print函数将其打印出来。my_print在my_transaction中定义如下:


    代码清单 2-30
    文件:src/ch2/section2.3/2.3.3/my_transaction.sv
     31    function void my_print();
     32      $display("dmac = %0h", dmac);
     33      $display("smac = %0h", smac);
     34      $display("ether_type = %0h", ether_type);
     35      for(int i = 0; i < pload.size; i++) begin
     36        $display("pload[%0d] = %0h", i, pload[i]);
     37      end
     38      $display("crc = %0h", crc);
     39    endfunction


    当完成monitor的定义后,可以在env中对其进行实例化:


    代码清单 2-31
    文件:src/ch2/section2.3/2.3.3/my_env.sv
      4 class my_env extends uvm_env;
      5
      6   my_driver drv;
      7   my_monitor i_mon;
      8
      9   my_monitor o_mon;
     …
     15   virtual function void build_phase(uvm_phase phase);
     16     super.build_phase(phase);
     17     drv = my_driver::type_id::create("drv", this);
     18     i_mon = my_monitor::type_id::create("i_mon", this);
     19     o_mon = my_monitor::type_id::create("o_mon", this);
     20   endfunction
     …
     23 endclass


    需要引起注意的是这里实例化了两个monitor,一个用于监测DUT的输入口,一个用于监测DUT的输出口。

    DUT的输出口设置一个monitor没有任何疑问,但是在DUT的输入口设置一个monitor有必要吗?

    由于transaction是由driver产生并输出到DUT的端口上,所以driver可以直接将其交给后面的reference model。

    在2.1节所示的框图中,也是使用这样的策略。所以是否使用monitor,这个答案仁者见仁,智者见智。这里还是推荐使用monitor,原因是:

    第一,在一个大型的项目中,driver根据某一协议发送数据,而monitor根据这种协议收集数据,如果driver和monitor由不同人员实现,那么可以大大减少其中任何一方对协议理解的错误;

    第二,在后文将会看到,在实现代码重用时,使用monitor是非常有必要的。

    现在,整棵UVM树的结构如图2-4所示。

    在env中实例化monitor后,要在top_tb中使用config_db将input_if和output_if传递给两个monitor:


    代码清单 2-32
    文件:src/ch2/section2.3/2.3.3/top_tb.sv
     47 initial begin
     48    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.drv", "vif", input_if);
     49    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.i_mon", "vif", input_if);
     50    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.o_mon", "vif", output_if);
     51 end

  • 相关阅读:
    findall查找 ^$*+?{ }{m,n}[].[.] w s d  D W
    find查找、split分隔、replace替换
    round四舍五入
    pow求一个数的n次幂
    iter创建一个可以被迭代的对象
    notepad++ gmt中文乱码问题
    matlab eps 字体用AI打开乱码的解决
    [转载]Matlab中使用xlswrite函数时出现服务器出现异常的解决方法
    How to determine which grid cells a line segment passes through?
    matlab给定点生成多边形,多边形掩膜处理
  • 原文地址:https://www.cnblogs.com/YINBin/p/6839005.html
Copyright © 2011-2022 走看看