在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函数才能正常工作。

*2-3-7-加入field_automation机制的更多相关文章

  1. 笔记:Binder通信机制

    TODO: 待修正 Binder简介 Binder是android系统中实现的一种高效的IPC机制,平常接触到的各种XxxManager,以及绑定Service时都在使用它进行跨进程操作. 它的实现基 ...

  2. JAVA回调机制(CallBack)详解

    序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...

  3. 谈谈DOMContentLoaded:Javascript中的domReady引入机制

    一.扯淡部分 回想当年,在摆脱写页面时js全靠从各种DEMO中copy出来然后东拼西凑的幽暗岁月之后,毅然决然地打算放弃这种处处“拿来主义”的不正之风,然后开启通往高大上的“前端攻城狮”的飞升之旅.想 ...

  4. 路由的Resolve机制(需要了解promise)

    angular的resovle机制,实际上是应用了promise,在进入特定的路由之前给我们一个做预处理的机会 1.在进入这个路由之前先懒加载对应的 .js $stateProvider .state ...

  5. Android权限管理之Permission权限机制及使用

    前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...

  6. Java学习之反射机制及应用场景

    前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...

  7. .NET Core采用的全新配置系统[10]: 配置的同步机制是如何实现的?

    配置的同步涉及到两个方面:第一,对原始的配置文件实施监控并在其发生变化之后从新加载配置:第二,配置重新加载之后及时通知应用程序进而使后者能够使用最新的配置.要了解配置同步机制的实现原理,先得从认识一个 ...

  8. Go结构体实现类似成员函数机制

    Go语言结构体成员能否是函数,从而实现类似类的成员函数的机制呢?答案是肯定的. package main import "fmt" type stru struct { testf ...

  9. 操作系统篇-分段机制与GDT|LDT

    || 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言     在<操作系统篇-浅谈实模式与保护模式>中提到了两种模式,我们说在操作系统中,其实大部分时间是待在保护模式中的. ...

随机推荐

  1. ASP.NET2.0 Newtonsoft.Json 操作类分享

    JSON 是现在比较流行的数据交互格式,NET3.0+有自带类处理JSON,2.0的话需要借助Newtonsoft.Json来完成,不然自己写的话,很麻烦. 网上搜索下载 Newtonsoft.Jso ...

  2. visualstudio部分快捷键

    [工具快捷键] Ctrl+Shift+N: 新建项目 Ctrl+Shift+O: 打开项目 Ctrl+Shift+S: 全部保存 Shift+Alt+C: 新建类 Ctrl+Shift+A: 新建项 ...

  3. nginx 托管.net core的service文件

    在 /etc/systemd/system/ 中新建一个服务文件site1.service vim /etc/systemd/system/site1.service [Unit] Descripti ...

  4. PostSharp 结合 log4net 自动记录日志

    环境: VS 2012 PostSharp-4.1.28  (下载地址)https://visualstudiogallery.msdn.microsoft.com/a058d5d3-e654-43f ...

  5. 【cocos2d-x 手游研发小技巧(4)与Android混编实现换“头像图片”】

    cocos2dx在android平台上的游戏开发中往往会遇到一些混编需求,如: 比方有的社区类游戏需要用到更换玩家的“头像”操作,其实就是调用android servers服务里面的本地图片,以及选取 ...

  6. java线程池(一)

    自JDK5之后,Java推出了一个并发包,java.util.concurrent,在Java开发中,我们接触到了好多池的技术,String类的对象池.Integer的共享池.连接数据库的连接池.St ...

  7. BZOJ1558 等差数列

    题目链接:戳我 实话实话,看了几篇题解真的没看懂,我觉得讲的都有问题.这里对于线段树维护的s写了一点我自己的理解. 看到等差数列,我们考虑对数列做差,这样如果是等差数列,那么值应该相等.(比较容易维护 ...

  8. C/C++,python,java,C#月经贴问题

    在刚开始的时候,一直纠结于语言之争,什么什么有前途,什么什么没前途.对于什么的支持不好啦,个人信仰问题啦.什么都有. 首先最主要的一个个人观点:“语言不是老婆,不是一夫一妻制”.你可以同时拥有许多的女 ...

  9. jmeter+ant+jenkins+mac报告优化(一):解决Min Time和Max Time显示NaN

    一.在上篇博客中生成的报告有两个问题: 1.date not defined 2.Min Time和Max Time显示成了NaN 二.Jmeter+Ant报告生成原理: 1.在Jmeter的extr ...

  10. Android中线程和线程池

    我们知道线程是CPU调度的最小单位.在Android中主线程是不能够做耗时操作的,子线程是不能够更新UI的.在Android中,除了Thread外,扮演线程的角色有很多,如AsyncTask,Inte ...