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

时间: 2024-08-27 03:36:46

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

与uvm_componentt相关的factory宏

1.uvm_component_utils:它用于把一个直接或间接派生自uvm_component的类注册到factory中. 2.uvm_component_param_utils:它用于把一个直接或间接派生自uvm_component的参数化的类注册到factory中. 3.uvm_component_utils_begin uvm_component_utils_end:类似uvm_object_utils_begin ……uvm_object_utils_end,它用于同时需要使用fac

与uvm_object相关的factory宏

与uvm_object相关的factory宏: 1.uvm_object_utils:它用于把一个直接或间接派生自uvm_object的类注册到factory中: 2.uvm_object_parma_utils:它用于把一个直接或间接派生自uvm_object的参数化的类注册到factory中.所谓参数化的类,是指类似于以下的类: class A#(int  WIDTH=32) extends uvm_object;如果允许,尽可能使用参数化的类,它可以提高代码的可移植性. 3.uvm_obj

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Android小例子:使用反射机制来读取图片制作一个图片浏览器

效果图: 工程文件夹: 该例子可供于新手参考练习,如果有哪里不对的地方,望指正>-< <黑幕下的人> java代码(MainActivity.java): package com.example.imageswitchtest; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.v

TCP拥塞控制机制

我们知道TCP是拥有拥塞控制机制的,而UDP是没有的,为什么需要拥塞控制机制呢,就是防止丢包过多导致传输效率低下.网络中传输的包太多,路由器的缓存又不够,每一个发送端都以自己想要的发送速率发送包,自然会导致网络拥塞.所以我TCP就包括了拥塞控制机制. 有几种拥塞控制方法? 2种 1.端到端拥塞控制.网络层没有显示的告知传输层此时网络出现拥塞了,传输层通过报文段的丢失(超时或3次冗余确认得知)认为网络出现拥塞了,TCP会缩减其拥塞窗口,减小发送速率. 2.网络辅助的拥塞控制.网络层显示的告知发送端

Java性能优化之JVM GC(垃圾回收机制)

Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行.当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成.GC优化很多时候就是减少stop-the-world 的发生. JVM GC回收哪个区域内的垃圾? 需要注意的是,JV

Java必知必会:异常机制详解

一.Java异常概述 在Java中,所有的事件都能由类描述,Java中的异常就是由java.lang包下的异常类描述的. 1.Throwable(可抛出):异常类的最终父类,它有两个子类,Error与Exception. Throwable中常用方法有: getCause():返回抛出异常的原因.如果 cause 不存在或未知,则返回 null. getMeage():返回异常的消息信息. printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值.

JAVA synchronized关键字锁机制(中)

synchronized 锁机制简单的用法,高效的执行效率使成为解决线程安全的首选. 下面总结其特性以及使用技巧,加深对其理解. 特性: 1. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.       2. 当一个线程同时访问object的一个synchronized(this)同步代码块时,其它线程仍然可以访问非修饰的方法或代码块.       3. 当多个线程同时访问object的synchronized(this)同步代码

FreakZ学习笔记:路由发现机制

路由发现机制 路由发现机制只有在发送通信包的过程中会被调用,而接收过程因为发送时候已经进行了通信链路的扫描和连接,所以不会再进行路由发现机制. 路由的所有处理机制都是在NWK层进行的,当然,路由发现机制也一样.当协议栈进行数据发送时,会依次按照APP->APS->NWK->MAC->PHY->Radio的层次关系来进行,APS层执行完成之后,会跳转到NWK层的nwk_data_req函数,该函数为NWK数据请求服务,接收APS层的数据并且加上NWK层的包头,然后将数据打包.n