SystemVerilog Interface Class的妙用

前言

Interface Class是在SystemVerilog 2012版本中引入的,但目前在验证中几乎很少采用,大多数验证工程师要么不知道它,要么没有看到使用它的任何好处,这使得Interface Class成为一个未被充分使用和不被重视的特性。本文将举两个Interface Class的使用例子,在这些例子中,Interface Class提高了验证环境的灵活性和质量,同时进一步提高了其可维护性和可调试性。

示例1:观察者设计模式

Interface Class用于观察者设计模式(Observer Design pattern)。观察者模式允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。例如验证环境中monitor需要采集interface上的信息,将其组合成某种transaction数据结构,并将其发送给感兴趣的各方组件,例如scoreboard和checker。在这里,monitor也称作publisher,scoreboard和checker称作subscriber或listener。如下图所示。

图1 观察者设计模式

UVM方法学通过TLM analysis port开发了观察者模式,提供了在publisher和subscriber之间创建连接的方法,实现一对多的连接。这种方式在现在验证环境中大量使用了,但也有许多限制:

  • 限制一:这种方式的组件连接是静态的,它们通常在connect_phase就确定了,并且只有uvm_component可以参与连接。
  • 限制二:这种通信方式仅限于一种类型的单个事务传输。
  • 限制三:subscriber需要多个analysis port时需要求助于UVM宏,或者创建子层次结构来监听transaction。

使用Interface Class实现的观察者模式完美解决了所有这三个问题。下图提供与UVM analysis port非常相似功能的实例。

interface class resolve_listener;pure virtual function void new_resolve(txn_resolve resolve);
endclass : resolve_listenerclass monitor extends uvm_component;local resolve_listener m_resolve_listeners[$];function void add_listener(resolve_listener listener);m_resolve_listener.push_back(listener);endfunctionvirtual task run_phase(uvm_phase phase);forever begintxn_resolve resolve = get_next_resolve();foreach(m_resolve_listeners[i])m_resolve_listeners[i].new_resolve(resolve);endendtaskendclass : monitorclass resolve_checker extends uvm_component implements resolve_listener;virtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);m_config.monitor.add_listener(this);endfunctionvirtual function void new_resolve(txn_resolve resolve);if (resolve.is_abort())`uvm_fatal(get_name(), "Aborts are not expected")endfunctionendclass : resolve_checker

图2 使用Interface Class实现通信

首先这个实例使用了动态连接,subscribers可以在仿真过程中的任何时间点向publisher注册自己(并不限制于connect_phase阶段),并开始订阅transactions。另外,这个实例也允许UVM sequence等非uvm_component直接订阅monitor、BFM和checker等的transactions。下面为reactive sequence直接利用monitor监控到的接口行为产生其它动作的例子,这样的写法使得reactive sequence更容易编写。维护和理解,而不需要借助于sequencer和sequence之间错综复杂的通信通道。

task run_sequence();m_done = 0;m_config.monitor_l1l2.add_listener(this);wait(m_done);m_config.monitor_l1l2.remove_listener(this);
endtaskvirtual function void new_l1l2_request(txn_l1l2 req);// Wait until a request to upgrade line from shared to exclusive is seen and// send a snoop request to steal the line awayif (!m_done && l1l2.req_type() == READ_UNIQUE_HIT_SHARED) beginsend_snoop(SNOOP_INVALIDATE, l1l2.req_address());m_done = 1;end
endfunction

图3 使用观察者模式直接订阅monitor的事件

第二个是subscriber和publisher之间的接口并不局限于单个transaction传输。接口函数new_resolve(…)可以传递任何可能对subscriber有用的附加信息,如下面new_resolve新的函数参数。

pure virtual function void new_resolve(txn_uop uop, txn_resolve resolve);

图4 new_resolve新定义

最后,subscriber可以订阅多个publisher的消息,因为Interface Class允许多继承,下图的例子是order检查器一方面订阅正在进行的微操作(micro operation),另一方面订阅了ACE协议口发出的请求,并检查它们是否是以正确的顺序进行。这样生成的代码比使用UVM analysis port更干净和直接得多,那个函数做什么很清楚。

class ordering_checker extends checker implements uop_listener, ace_listener;local txn_uop m_ordered_uops[$];// Register ourselves with micro-op and ACE agentsvirtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);m_config.uop_agent.add_listener(this);m_config.ace_agent.add_listener(this);endfunction// On commits, record micro-ops that need to be orderedvirtual function void new_commit(txn_uop uop, txn_commit commit);if (commit.is_clean() && uop.is_ordered())m_ordered_uops.push_back(uop);endfunction// On ACE requests, compare address and sizevirtual function void new_ace_req(ace_req ace_request);txn_uop uop;if (!ace_request.needs_to_be_ordered())return;uop = m_ordered_uops.pop_front();check(ace_request.addr().equals(uop.addr()) && (ace_request.size() == uop.size()),{"ACE request seen doesn¿t match the oldest micro-op: ", uop.covert2string()});endfunctionendclass : ordering_checker

图5 checker订阅两个不同的monitor的事件

在某些情况下,用于复杂checker的subscriber的Interface Class定义了许多函数,但并非所有函数都在每个subscriber中用到。一种解决方案是将Interface Class分解为更小的类,但这需要向订阅所有events的subscriber添加额外代码。可以使用一个优雅的解决方案,也就是引入中间层类,中间层类为Interface Class的所有函数提供了空的实现,允许子类只覆盖它需要的函数,如下图所示。

class uop_listener_mixin(type T = uvm_component) extends T implements uop_listener;virtual function void new_resolve(txn_uop uop, txn_resolve resolve);endfunctionvirtual function void new_commit(txn_uop uop, txn_commit commit);endfunctionvirtual function void new_issue(txn_uop uop);endfunctionvirtual function void uop_flush(txn_uop uop, flush_cause_e cause);endfunctionendclass : uop_listener_mixinclass uop_checker extends uop_listener_mixin#(checker);virtual function void new_issue(txn_uop uop);check_uop(uop);endfunctionendclass : uop_checker

图6 在Interface Class中使用中间层

这种方式的一大优点是,仍然允许中间层继承多个Interface Class,进而订阅多个接口的transactions。order检查器的声明可以写成如下图所示。

class strongly_ordered_checker extends uop_listener_mixin#(l1l2_listener_mixin #(checker));

图7 中间层的嵌套使用

示例2:多继承

在SystemVerilog中缺乏真正的多继承,我们可以使用Interface Class来绕过这个限制,我们以Arm指令类为例。下图左边为带地址的指令,比如load和store指令,右边为不带地址的操作,比如data barrier指令中的DMB和DSB等。但如果引入了Load-Acquire(LDAR)和Store-Release(STLR)指令呢(LDAR和STLR指令的行为就像是二合一指令,它们即是load/store,也是barrier)?那么它们在下图中该处于什么位置呢?

图8 CPU指令集的典型类层次划分

如果支持类多继承的话,LDAR可以从load和data barrier类继承。但缺乏类多继承的情况下,大多数类层次结构只允许LDAR继承自load,并且要么将所有特定于barrier的函数放在共同基本类中,要么在任何地方编写特殊代码来处理此问题,这样会导致代码更难以维护。

然而,有了Interface Class一切就好办了,它允许我们做一些类似于多继承的实现。我们可以定义一个Barrier Interface Class,它声明描述Barrier行为的函数,然后让Dat啊Barrier、LDAR和STLR类实现它。现在,判断一个指令是否是Barrier只需要做一次$cast检查就好了。

interface class barrier;// Return 1 if this barrier affects the given uop in a given directionpure virtual function bit affects_uop(txn_uop uop, dir_e direction);// Perform age comparison between a barrier and a uoppure virtual function bit is_barrier_older(txn_uop uop);//...
endclass : barrierclass barrier_checker;function void check_out_of_order_resolve(txn_uop first, txn_uop second);barrier bar;if ($cast(bar, second) && bar.affects_uop(first, YOUNGER))`uvm_fatal(get_name(), "Uop bypassed a barrier it isn¿t allowed to.")endfunction
endclass :barrier_checker

图9 Barrier Interface Class的使用示例

这种方式可以用于指令类层次结构中的其它指令,比如exclusive指令、atomic指令等等。

总结

本文两个Interface Class用例都会使得验证环境开发更加容易,观察者模式使得transaction传递更加清晰和灵活,这对激励质量有特别积极的影响,sequence可以直接根据monitor中的事件自适应调整激励。多继承模式简化了类的层次结构,使每个类的职责有更清晰的划分。

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

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

相关文章

【越界写null字节】ACTF2023 easy-netlink

前言 最近在矩阵杯遇到了一道 generic netlink 相关的内核题,然后就简单学习了一下 generic netlink 相关概念,然后又找了一到与 generic netlink 相关的题目。简单来说 generic netlink 相关的题目仅仅是将用户态与内核态的交互方式从传统的 ioctl 变成…

【线性代数】SVDPCA

用最直观的方式告诉你:什么是主成分分析PCA_哔哩哔哩_bilibili 奇异值分解singular value decomposition,SVD principal component analysis,PCA 降维操作 pca就是降维后使得信息损失最小 投影在坐标轴上的点越分散,信息保留越多 pca的实现…

Qt5学习笔记(一):Qt Widgets Application项目初探

笔者长期使用MFC开发Windows GUI软件。随着软件向Linux平台迁移的趋势越发明朗,GUI程序的跨平台需求也越来越多。因此笔者计划重新抓一下Qt来实现跨平台GUI程序的实现。 0x01. 看看Qt Widgets Application项目结构 打开Qt5,点击“ New”按钮新建项目。…

Linux shell编程基础

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问 Linux 内核的服务。 Shell 脚本&#x…

网页中生成ZIP文件,Zip 压缩、解压技术在 HTML5 浏览器中的应用

JSZip 是一款可以创建、读取、修改 .zip 文件的 javaScript 工具。在 web 应用中,免不了需要从 web 服务器中获取资源,如果可以将所有的资源都合并到一个 .zip 文件中,这时候只需要做一次请求,这样既减少了服务器的压力&#xff0…

【复现】含能量路由器的交直流混合配电网潮流计算

目录 1 主要内容 2 理论及模型 3 程序结果 4 下载链接 1 主要内容 程序复现《含能量路由器的交直流混合配电网潮流计算》,主要是对算例4.1进行建模分析,理论和方法按照文献所述。能量路由器(ER)作为新兴的电力元器件&#xff…

【机器学习】机器学习引领AI:重塑人类社会的新纪元

📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀机器学习引领AI 📒1. 引言📕2. 人工智能(AI)🌈人工智能的发展🌞应用领…

2024 年最新 Python 基于百度智能云实现短语音识别详细教程

百度智能云语音识别 采用国际领先的流式端到端语音语言一体化建模算法,将语音快速准确识别为文字,支持手机应用语音交互、语音内容分析、机器人对话等场景。百度短语音识别可以将 60 秒以下的音频识别为文字。适用于语音对话、语音控制、语音输入等场景…

轻松连接远程服务器SecureCRT for Mac/Windows

SecureCRT是一款功能强大的终端仿真器和文件传输工具,专为网络管理员、开发人员和系统工程师设计。它支持SSH、Telnet、RDP和串口等多种协议,提供安全、高效的远程访问和管理体验。SecureCRT具有多窗口/多标签管理、自定义终端仿真、颜色方案优化等高级功…

【c语言】qsort函数及泛型冒泡排序的模拟实现

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:C语言 目录 一、qsort函数 1.回调函数 2.qsort函数 3.void* 指针 二、泛型冒泡排序的模拟实现 1.比较函数的编写 2.交换函数的编写 3.冒泡排序的编写 4…

【TB作品】MSP430F5529 单片机,数字时钟设计与实现,整点时通过蜂鸣器播放音乐进行报时

基于单片机的数字时钟设计与实现 作品名称 基于MSP430单片机的OLED显示数字时钟 作品功能 本作品实现了一个具有时间显示和整点报时功能的数字时钟。通过OLED屏幕显示当前时间,用户可以通过按键设置时间,并在整点时通过蜂鸣器播放音乐进行报时。 作…

WPF Treeview控件开虚拟化后定位节点

不开虚拟化&#xff0c;可以用下面的方法直接定位 <Window x:Class"WpfApplication2.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"Title"Main…

LabVIEW实现汽车逆变器功能测试系统

​介绍了如何利用LabVIEW开发汽车逆变器&#xff08;包括功率板和控制板&#xff09;的自动测试设备&#xff08;ATE&#xff09;&#xff0c;实现对额定800V电压、300A电流的逆变器进行功能测试。系统通过CAN2.0通讯协议&#xff0c;实现电机控制、温度传感器监测、电压校验和…

linux经典例题编程

编写Shell脚本&#xff0c;计算1~100的和 首先vi 1.sh,创建一个名为1.sh的脚本&#xff0c;然后赋予这个脚本权限&#xff0c;使用命令chmod 755 1.sh&#xff0c;然后就可以在脚本中写程序&#xff0c;然后运行。 shell脚本内容 运行结果&#xff1a; 编写Shell脚本&#xf…

IT闲谈-Kylin入门教程

目录 一、引言二、Kylin简介三、环境准备四、安装与配置五、数据导入与建模六、查询与分析七、总结 一、引言 Apache Kylin是一个开源的分布式分析引擎&#xff0c;旨在提供Hadoop/Spark之上的SQL接口及多维分析&#xff08;OLAP&#xff09;能力以支持超大规模数据。Kylin通过…

单链表复习 (C语言版)

目录 一.顺序表与链表的区别 二.链表概念 三.单链表 1.单链表的开始与初始化 2.单链表的打印 3.单链表的尾插 重难点&#xff1a;单链表实现时的指针详解 4.单链表的头插 5.单链表的尾删 6.单链表的头删 小结&#xff1a; 7.单链表的查找 8.在指定位置前插入数据 …

王学岗鸿蒙开发(北向)——————(四、五、六)ArkUi声明式组件

普通组件 1,注意&#xff0c;如上图&#xff0c;build只能有一个根节点 2,Entry表示程序的入口 Component表示自定义的组件 Preview表示可以预览 3&#xff0c;图片存放的地方 4&#xff0c; Image组件最好只给宽度&#xff0c;给了高度又给宽度容易失真。 build() {Row() {/…

24考研408大变化,25考研高分上岸规划+应对策略

巧了&#xff0c;我有现成的经验&#xff1a; 数学和专业课的成绩都不高不低&#xff0c;刚好够用&#xff0c;其实408想上岸&#xff0c;不仅仅要学好408&#xff0c;还要学好考研数学&#xff0c;这是我的肺腑之言&#xff0c;我复试的时候&#xff0c;我知道的那些没有进复试…

【SQLAlChemy】常见的数据类型有哪些,Column可选的参数有哪些呢?

常见数据类型与Column参数 常见类型 Integer&#xff1a;整数类型&#xff0c;对应数据库的 int 类型。Float&#xff1a;浮点数类型&#xff0c;对应数据库的 float 类型。它占用 32 位空间。Double&#xff1a;双精度浮点数类型&#xff0c;对应数据库的 double 类型&#…

鸿蒙开发接口安全:【@system.cipher (加密算法)】

加密算法 说明&#xff1a; 本模块首批接口从API version 3开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import cipher from system.ciphercipher.rsa rsa(Object): void RSA 算法加解密。 系统能力&#xff1a; SystemCapabil…