UVM验证平台加入field_automation机制

  (1)uvm_field宏实现field_automation机制

      UVM中需要逐字段地对transaction进行某些操作。这就是UVM中的 field_automation机制,使用uvm_field系列宏实现:

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;endfunctionfunction 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_endfunction new(string name = "my_transaction");super.new();endfunctionendclass

        这里使用uvm_object_utils_begin和uvm_object_utils_end来实现my_transaction的factory注册,在这两个宏中间,使用uvm_field宏 注册所有字段。uvm_field系列宏随着transaction成员变量的不同而不同。
        当使用上述宏注册之后,可以直接调用copy、compare、print等函数,而无需自己定义。这极大地简化了验证平台的搭建,提 高了效率:

  (2)  引入field_automation机制的另外一大好处是简化了driver和monitor

my_model.svclass my_model extends uvm_component;uvm_blocking_get_port #(my_transaction)  port;uvm_analysis_port #(my_transaction)  ap;extern function new(string name, uvm_component parent);extern function void build_phase(uvm_phase phase);extern virtual  task main_phase(uvm_phase phase);`uvm_component_utils(my_model)
endclass function my_model::new(string name, uvm_component parent);super.new(name, parent);
endfunction function void my_model::build_phase(uvm_phase phase);super.build_phase(phase);port = new("port", this);ap = new("ap", this);
endfunctiontask my_model::main_phase(uvm_phase phase);my_transaction tr;my_transaction new_tr;super.main_phase(phase);while(1) beginport.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_scoreboard.sv class my_scoreboard extends uvm_scoreboard;my_transaction  expect_queue[$];uvm_blocking_get_port #(my_transaction)  exp_port;uvm_blocking_get_port #(my_transaction)  act_port;`uvm_component_utils(my_scoreboard)extern function new(string name, uvm_component parent = null);extern virtual function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclass function my_scoreboard::new(string name, uvm_component parent = null);super.new(name, parent);
endfunction function void my_scoreboard::build_phase(uvm_phase phase);super.build_phase(phase);exp_port = new("exp_port", this);act_port = new("act_port", this);
endfunction task my_scoreboard::main_phase(uvm_phase phase);my_transaction  get_expect,  get_actual, tmp_tran;bit result;super.main_phase(phase);fork while (1) beginexp_port.get(get_expect);expect_queue.push_back(get_expect);endwhile (1) beginact_port.get(get_actual);if(expect_queue.size() > 0) begintmp_tran = expect_queue.pop_front();result = get_actual.compare(tmp_tran);//直接调用compare函数,不需要自己定义compare函数if(result) begin `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);endelse begin`uvm_error("my_scoreboard", "Compare FAILED");$display("the expect pkt is");tmp_tran.print();//直接调用print函数,不需要自己定义print函数$display("the actual pkt is");get_actual.print();//直接调用print函数,不需要自己定义print函数endendelse begin`uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");$display("the unexpected pkt is");get_actual.print();end endjoin
endtask

(3)使用field_automation机制后,可以 简化drv_one_pkt任务

class my_driver extends uvm_driver;virtual my_if vif;`uvm_component_utils(my_driver)function new(string name = "my_driver", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))`uvm_fatal("my_driver", "virtual interface must be set for vif!!!")endfunctionextern task main_phase(uvm_phase phase);extern task drive_one_pkt(my_transaction tr);
endclasstask my_driver::main_phase(uvm_phase phase);my_transaction tr;phase.raise_objection(this);vif.data <= 8'b0;vif.valid <= 1'b0;while(!vif.rst_n)@(posedge vif.clk);for(int i = 0; i < 2; i++) begin tr = new("tr");assert(tr.randomize() with {pload.size == 200;});drive_one_pkt(tr);endrepeat(5) @(posedge vif.clk);phase.drop_objection(this);
endtasktask my_driver::drive_one_pkt(my_transaction tr);byte unsigned     data_q[];int  data_size;data_size = tr.pack_bytes(data_q) / 8; //调用pack_bytes将tr中所有的字段变成byte流放入data_q中`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

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

`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可以简化成:

`ifndef MY_MONITOR__SV
`define MY_MONITOR__SV
class my_monitor extends uvm_monitor;virtual my_if vif;uvm_analysis_port #(my_transaction)  ap;`uvm_component_utils(my_monitor)function new(string name = "my_monitor", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))`uvm_fatal("my_monitor", "virtual interface must be set for vif!!!")ap = new("ap", this);endfunctionextern task main_phase(uvm_phase phase);extern task collect_one_pkt(my_transaction tr);
endclasstask my_monitor::main_phase(uvm_phase phase);my_transaction tr;while(1) begintr = new("tr");collect_one_pkt(tr);ap.write(tr);end
endtasktask 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) begindata_q.push_back(vif.data);@(posedge vif.clk);enddata_size  = data_q.size();   data_array = new[data_size];for ( int i = 0; i < data_size; i++ ) begindata_array[i] = data_q[i]; endtr.pload = new[data_size - 18]; //da sa, e_type, crcdata_size = tr.unpack_bytes(data_array) / 8; `uvm_info("my_monitor", "end collect one pkt", UVM_LOW);
endtask`endif

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/202232.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openGauss学习笔记-146 openGauss 数据库运维-备份与恢复-配置文件的备份与恢复

文章目录 openGauss学习笔记-146 openGauss 数据库运维-备份与恢复-配置文件的备份与恢复146.1 背景信息146.2 前置条件146.3 操作步骤146.4 示例 openGauss学习笔记-146 openGauss 数据库运维-备份与恢复-配置文件的备份与恢复 146.1 背景信息 在openGauss使用过程中&#x…

在编老师拒绝当班主任会怎样

作为一名在编老师&#xff0c;拒绝当班主任会怎样&#xff1f;这个问题其实有很多角度可以回答&#xff0c;因为不同的人可能会有不同的看法和经历。 从学校角度来说&#xff0c;拒绝当班主任可能会被视为缺乏责任感和担当精神。班主任是一个非常重要的职务&#xff0c;需要承担…

LLM微调(二)| 微调LLAMA-2和其他开源LLM的两种简单方法

本文将介绍两种开源工具来微调LLAMA-2。 一、使用autotrain-advanced微调LLAMA-2 AutoTrain是一种无代码工具&#xff0c;用于为自然语言处理&#xff08;NLP&#xff09;任务、计算机视觉&#xff08;CV&#xff09;任务、语音任务甚至表格任务训练最先进的模型。 1&#xf…

循环队列中的求队列长度公式怎么来的?【数学角度】

循环队列中的队列长度怎么来的? 引入 在一个循环队列中&#xff0c;队列的元素个数可以通过头指针&#xff08;Front&#xff0c;通常用F表示&#xff09;和尾指针&#xff08;Rear&#xff0c;通常用R表示&#xff09;来计算。假设队列的存储空间大小为n&#xff0c;队列中…

二:C语言-数据类型和变量

二&#xff1a;数据类型和变量 1.数据类型的介绍&#xff1a; ​ 内置数据类型&#xff08;C语言本身具有的&#xff09;&#xff1a;字符 - char&#xff1b;整型 - int&#xff1b;浮点型 - float&#xff1b;布尔类型 - _Bool ​ 自定义数据类型&#xff08;自己创建的类…

选择更好的Notes索引附件方式

大家好&#xff0c;才是真的好。 首先介绍最近产品更新消息。在上一周&#xff0c;HCL主要发布了以下几个产品更新&#xff1a;HCL Verse 3.2.0、HCL Volt MX Go 2.0.2、HCL Domino Rest API 1.0.8。 HCL Verse是今后Domino的产品当中主要使用的webmail功能&#xff0c;这一次…

kafka学习笔记--基础知识概述

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

【开题报告】基于SpringBoot的农场管理系统的设计与实现

1.选题背景 随着社会经济的发展和人们对食品安全和质量的要求不断提高&#xff0c;农业管理也面临着新的挑战和需求。传统的农场管理方式往往依靠手工记录和经验积累&#xff0c;存在信息不及时、管理效率低下等问题。而基于SpringBoot的农场管理系统的设计与实现&#xff0c;…

国标GB28181设备注册安防监控平台EasyCVR不上线是什么原因?

安防视频监控EasyCVR平台兼容性强&#xff0c;可支持的接入协议众多&#xff0c;包括国标GB28181、RTSP/Onvif、RTMP&#xff0c;以及厂家的私有协议与SDK&#xff0c;如&#xff1a;海康ehome、海康sdk、大华sdk、宇视sdk、华为sdk、萤石云sdk、乐橙sdk等。平台能将接入的视频…

[头歌Python实验]Python入门之基础语法

目录 第1关&#xff1a;行与缩进 第2关&#xff1a;标识符与保留字 第3关&#xff1a;注释 第4关&#xff1a;输入输出 如果对你有帮助的话&#xff0c;不妨点赞收藏关注评论走一波吧&#xff0c;爱你么么哒吗&#x1f618;&#x1f496;&#x1f496;&#x1f496; 第1关…

逆向爬虫进阶实战:突破反爬虫机制,实现数据抓取

文章目录 一、引言二、逆向爬虫进阶技巧三、逆向爬虫进阶实战代码片段四、总结与展望好书推荐内容简介作者简介前言节选 一、引言 随着网络技术的发展&#xff0c;网站为了保护自己的数据和资源&#xff0c;纷纷采用了各种反爬虫机制。然而&#xff0c;逆向爬虫技术的出现&…

【Python百宝箱】漫游Python数据可视化宇宙:pyspark、dash、streamlit、matplotlib、seaborn全景式导览

Python数据可视化大比拼&#xff1a;从大数据处理到交互式Web应用 前言 在当今数字时代&#xff0c;数据可视化是解释和传达信息的不可或缺的工具之一。本文将深入探讨Python中流行的数据可视化库&#xff0c;从大数据处理到交互式Web应用&#xff0c;为读者提供全面的了解和…

控乐屋品牌|智汇恒星全宅智能空间万物互联,千亿蓝海蓄势待发

随着5G、大数据、云计算、物联网等技术的发展&#xff0c;智能化正覆盖人们生活的方方面面&#xff0c;全屋智能的出现为“一键式”智能家居生活享受提供无限可能。近年来智能家居行业总体规模增长迅速&#xff0c;数据显示&#xff0c;2022年中国智能家居行业市场规模约为6200…

Redis滚动分页的使用

Feed流 关注推送也叫Feed流。通过无限下拉刷新获取新的信息。 Feed流产品常见有两种模式&#xff1a; Timeline: 不做内容筛选&#xff0c;简单的按照内容发布时间排序&#xff0c;常用于好友或关注。例如朋友圈 优点&#xff1a;信息全面&#xff0c;不会有缺失。并且实现也…

2023五岳杯量子计算挑战赛APMCM亚太地区

问题一要求在特定区域内部署两个边缘服务器&#xff0c;以便根据计算需求分布覆盖最大的计算需求。每个边缘服务器都有一个覆盖半径为1。目标是确定两个边缘服务器的位置&#xff0c;以覆盖最大的计算需求。假设边缘服务器的位置位于网格的中心&#xff0c;每个网格内的计算需求…

我们为什么那么关注 Java 中的 String Template ,Java 21 特性

本心、输入输出、结果 文章目录 我们为什么那么关注 Java 中的 String Template &#xff0c;Java 21 特性前言String TemplateString Template 有什么好处字符串连接 – 一个常见但无趣且容易出错的任务jetbrains IDEA 2023.2 版本及以上对于 String Template 的支持字符串模板…

试编写算法将带头结点的单链表就地逆置(就地是指辅助空间复杂度为 O(0))。

题目描述&#xff1a;试编写算法将带头结点的单链表就地逆置&#xff08;就地是指辅助空间复杂度为 O(0)。 分析&#xff1a; 将单链表就地逆置可以考虑使用头插法。 LinkList Reverse(LinkList L){LNode *p L->next;LNode *r;L->next NULL;while(p){r p->next;p…

redis中使用pipeline

在操作数据库时&#xff0c;为了加快程序的执行速度&#xff0c;在新增或更新数据时&#xff0c;可以通过批量提交的方式来减少应用和数据库间的传输次数&#xff1b;在redis中也有这样的技术实现批量处理&#xff0c;也就是管道——Pipeline。它也是通过批量提交数据的方式来实…

FPS和SFTP的速度哪个更快?区别在哪里?

在互联网时代&#xff0c;我们频繁需要传输大文件&#xff0c;如视频、音乐、图片和文档等。这些文件不仅占用大量空间&#xff0c;而且传输时间长。确保传输过程的安全性和稳定性&#xff0c;以防文件被窃取或损坏成为重要考虑因素。在选择传输方式时&#xff0c;FPS和SFTP是两…

力扣-435.无重叠空间

利用快排&#xff0c;对数组右边界进行排序。 用一个变量记录区间的分割点&#xff0c;然后用这个分割点去和下一个区间做比较&#xff0c;如果没有重叠&#xff0c;更新右边界&#xff0c;没有重叠的区间个数加一。 然后更新右边界&#xff0c;继续进行比较。 最后用总区间…