设计模式在芯片验证中的应用——备忘录

1. 前言

软件设计模式定义了一组类和它们之间的关系,它们相互作用用以解决软件开发过程中面临的常见问题。由于验证工程师所做工作的重要部分包括使用面向对象语言(如SystemVerilog)进行编码,因此许多遇到的挑战都适合应用特定的设计模式来解决。将它们应用到代码中,有助于代码的可重用性和可维护性,从而提高了整体代码质量。本文介绍备忘录(亦称: 快照、Snapshot、Memento)在验证环境中的使用,来对设计逻辑中实现的特性进行建模。

2. 备忘录

备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。在软件开发环境中,它在应用程序中提供了撤销机制,促进了数据的隐藏,并且不违背封装原则。在验证环境中,它可以用来对需要“恢复的场景”进行建模。举个例子,如下图所示,比如Arm CPU运行在状态pstate1下,这时候突然来了个中断导致它切换到状态pstate2,中断可能嵌套,继续切换到状态pstate3、pstate4、pstate5等等,中断处理结束后,需要返回到之前的运行状态。因此在中断切换状态时需要保存当前的CPU状态信息,这样才能在中断处理完成后,根据历史保存的CPU状态信息切换回来。备忘录模式提供了很好的建模方式。

备忘录模式提供了三个主要组件:

Memento:表示要保存和恢复的内容的容器类,在上图示例中Memento类包含pstate的状态和相应的get/set方法。

Originator:使用Memento类来保存当前的状态。它类似于这里CPU的角色。

Caretaker:请求Originator保存状态,且它直到所有保存的状态,并且可以请求恢复到历史的某个状态。

下图使用UML类图提供了上述三者之间的图形化关系,如何看懂UML类图大家可以自行搜索下资料。

3. 参考代码

CPU处理中断进入和返回状态的参考代码如下:

typedef struct packed {bit [3:0] nzcv;bit [1:0] currentel;bit       tco;
} pstate_t;class memento extends uvm_object;`uvm_object_utils (memento)local pstate_t pstate;function new (string name = "memento");super.new(name);endfunction : newfunction void set_pstate(pstate_t _pstate);this.pstate = _pstate;endfunction : set_pstatefunction pstate_t get_pstate();return pstate;endfunction : get_pstateendclass : mementoclass originator extends uvm_object;`uvm_object_utils (originator)local pstate_t pstate;function new (string name = "originator");super.new(name);endfunction : newfunction void change();pstate = $random();endfunction : changefunction memento create_snapshot();memento m_memento = memento::type_id::create("m_memento");m_memento.set_pstate(pstate);`uvm_info("[snapshot pstate:]", $psprintf("nzcv:'b%b, currentel:'b%b, tco:'b%b", pstate.nzcv, pstate.currentel, pstate.tco), UVM_LOW)return m_memento;endfunctionfunction void restore (memento _snapshot);pstate = _snapshot.get_pstate();`uvm_info("[restore pstate:]", $psprintf("nzcv:'b%b, currentel:'b%b, tco:'b%b", pstate.nzcv, pstate.currentel, pstate.tco), UVM_LOW)endfunction : restoreendclass : originatorclass caretaker extends uvm_object;`uvm_object_utils (caretaker)local memento    memento_q[$];local originator m_orig;function new (string name = "caretaker");super.new(name);endfunction : newfunction void set_originator(originator _m_orig);m_orig = _m_orig;endfunction : set_originatorfunction void dosomething();memento_q.push_back(m_orig.create_snapshot);m_orig.change();endfunction : dosomethingfunction void undo(int unsigned _index);if (_index > memento_q.size() || memento_q.size() == 0 ) $fatal;m_orig.restore(memento_q[_index]);endfunction : undoendclass : caretaker

模拟测试代码如下:

class monitor;function void test();caretaker  m_caretaker  = caretaker::type_id::create("m_caretaker");originator m_originator = originator::type_id::create("m_originator");m_caretaker.set_originator(m_originator);m_caretaker.dosomething(); // snapshot0m_caretaker.dosomething(); // snapshot1m_caretaker.dosomething(); // snapshot2m_caretaker.dosomething(); // snapshot3m_caretaker.undo(1);m_caretaker.dosomething(); // snapshot4m_caretaker.undo(3);endfunction : testendclass : monitor

输出仿真结果如下:

[[snapshot pstate:]] nzcv:'b0000, currentel:'b00, tco:'b0
[[snapshot pstate:]] nzcv:'b0100, currentel:'b10, tco:'b0
[[snapshot pstate:]] nzcv:'b0000, currentel:'b00, tco:'b1
[[snapshot pstate:]] nzcv:'b0001, currentel:'b00, tco:'b1
[[restore pstate:]] nzcv:'b0100, currentel:'b10, tco:'b0
[[snapshot pstate:]] nzcv:'b0100, currentel:'b10, tco:'b0
[[restore pstate:]] nzcv:'b0001, currentel:'b00, tco:'b1

在提供的示例中,保存和恢复动作是由中断进入和中断退出事件触发的。在UVM中,事件由监视器(monitor)发出的,该监视器观察中断接口并使用Memento设计模式。该例子支持保存和恢复多个CPU状态。遇到中断时,caretaker的do_something()函数在开始时就把当前的pstate存储到memento里,然后进行其它的中断处理动作,相当于备份了历史状态。如果中断结束了,caretaker的undo()函数可以指定返回到哪个历史状态。

下次给大家分享下设计模式中责任链模式(Chain of Responsibility)在芯片验证中的应用。

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

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

相关文章

SCCM部署时遇到的问题:无法连接到SQL Server

根据提示信息逐一排除以下问题: 1、确保SQL服务器名称是否正确。 2、确保TCP1433和4022端口有没有被防火墙屏蔽。 3、站点服务器帐号加入SQLServer的sysadmin角色成员里 、确保SQL实例没有使用动态端口,可参考: Configure SQL Server to…

贪心 Leetcode 763 划分字母区间

划分字母区间 Leetcode 763 学习记录自代码随想录 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。 返…

题目 1572: 蓝桥杯-进制转换

题目描述: 程序提示用户输入三个字符,每个字符取值范围是0-9,A-F。然后程序会把这三个字符转化为相应的十六进制整数,并分别以十六进制,十进制,八进制输出。 代码: package lanqiao;import java.util.*;public clas…

重新启动vue-shop-maseter主支任务

以下是命令行,cmd任务管理程序进程中… 这部分是部分源码,用H5编辑器写的 等待慢慢启动重启中。。。。 然而没有反应,不知道为什么? 花里胡哨的,更加没看懂了。 我这暴脾气,气得我直接一顿乱敲 要怎…

C语言基础练习——Day01

目录 选择题 编程题 打印从1到最大的n位数 计算日期到天数转换 选择题 1、执行下面程序,正确的输出是 int x5,y7; void swap(int x, int y) {int z;zx;xy;yz; } int main() { int x3,y8; swap(int x, int y);printf("%d,%d\n",x, y);return …

vue3怎么设置路由 Vue Route

1. 安装Vue Router npm install vue-router 2. 创建Home.vue组件 在 src/views 目录下创建一个名为 Home.vue 的文件&#xff1a; <!-- <template> 标签是Vue组件的模板部分&#xff0c;其中包含了组件的HTML结构。 --> <template><div><h1>…

2024年最新阿里云服务器地域选择方法,以及可用区说明

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

iostat命令详解

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 iostat是一个使用频率较高的命令&#xff0c;主要用来统计和输出CPU和磁盘IO信息。它的安装很简单&#xff1a; # yum -y insta…

【PyQt】16-剪切板的使用

文章目录 前言一、代码疑惑快捷键 二、现象2.1 复制粘贴文本复制粘贴 2.2 复制粘贴图片复制粘贴 2.3 复制粘贴网页 总结 前言 1、剪切板的使用 2、pycharm的编译快捷键 3、类的属性和普通变量的关系 4、pyqt应该养成的编程习惯-体现在代码里了&#xff0c;自己看看。 一、代码…

PyTorch搭建LeNet测试集实现

搭建神经网络请看PyTorch搭建LeNet神经网络-CSDN博客 实现训练集请看PyTorch搭建LeNet训练集详细实现-CSDN博客 测试集比较简单&#xff0c;直接上代码。 代码实现 # 导包 不必多说 import torch import torchvision.transforms as transforms from PIL import Image from …

Spring三种依赖注入的方式

一.Spring三种依赖注入的方式 Setter注入 注解方式 Controller public class TestController {private TestService testService;Autowiredpublic void setTestService(TestService testService) {this.testService testService;} }XML方式 <bean id"testController&q…

ContentType类型总结

ContentType类型总结 Content-Type是一个HTTP头部字段&#xff0c;用于指示资源的媒体类型&#xff08;MIME类型&#xff09;&#xff0c;以及可选的字符集和编码方式。它告诉浏览器或其他客户端如何解释接收到的数据。以下是一些常见的Content-Type类型及其用途&#xff1a; t…

并发支持库(1)-线程

线程允许多个程序任务在统一时间执行&#xff0c;不同的线程可以共享内存空间&#xff0c;每个线程也有自己的栈空间。 线程类 thread 类thread表示单个执行线程。线程在thread构造对象时开始执行。每个thread对象表示唯一的一个线程&#xff0c;thread不支持复制构造和复制…

Python函数嵌套与参数你学会了吗

如何在函数中调用其他函数&#xff0c;以及如何定义和使用函数参数。函数嵌套可以调用其他函数&#xff0c;参数列表用于封装函数中的未知数据&#xff0c;参数在函数调用时被替换。形参和实参数量需一致&#xff0c;但名字可以相同。 1.函数嵌套 一个函数中可以调用别的函数 …

Spring JdbcTemplate JpaRepository 数据库配置多个数据源连接、查询

所谓多数据源&#xff0c;就是一个项目中采用了不同数据库实例中的多个库&#xff0c;或者同一个数据库实例中多个不同的库。比如实现数据库读写分离、分库分表、备份等操作。   JdbcTemplate多数据源的配置是比较简单的&#xff0c;因为一个JdbcTemplate对应一个DataSource&…

分布式搜索引擎-elasticsearch基础

分布式搜索引擎-elasticsearch基础 1、什么是elasticsearch&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容。 elasticsearch结合kibana、Logstash、Beats&#xff0c;也就是elastic stack&#xff08;ELK&a…

个人博客系列-后端项目-用户验证(5)

介绍 创建系统管理app&#xff0c;用于管理系统的用户&#xff0c;角色&#xff0c;权限&#xff0c;登录等功能&#xff0c;项目中将使用django-rest_framework进行用户认证和权限解析。这里将完成用户认证 用户验证 rest_framework.authentication模块中的认证类&#xff…

【C++】priority_queue和仿函数

priority_queue翻译过来就是优先队列&#xff0c;其实就是我们数据结构中的堆。堆这个东西之前也说过&#xff0c;它分为大根堆和小根堆&#xff0c;它的底层是一个类似数组的连续的空间&#xff0c;逻辑结构是一个完全二叉树&#xff0c;这个完全二叉树如果是小根堆的话父亲小…

Vue-03

Vue指令 v-bind 作用&#xff1a;动态设置html的标签属性&#xff08;src url title…&#xff09; 语法&#xff1a;v-bind:属性名"表达式" 举例代码如下&#xff1a; 实现效果如下&#xff1a; 案例&#xff1a;图片切换 实现代码如下&#xff1a; 实现的效果…

Redis面试问题纯享版

基础内容 1、简单介绍以下你了解的Redis 2、对比一下Redis和Memcache的异同&#xff1f; 3、为什么MySQL选用Redis作为缓存&#xff1f; 4、详细聊聊你对Redis各种数据类型的了解&#xff1f; 5、Redis中五种基本数据类型的底层数据结构是什么样的&#xff1f; Redis线程模型…