SystemVerilog学习笔记(九)

2024-03-27 01:10
文章标签 学习 笔记 systemverilog

本文主要是介绍SystemVerilog学习笔记(九),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文思维导图如下:

1. 线程控制

1.1 并行线程

Verilog中与顺序线程begin…end相对的是并行线程fork…join。

1.1.1创建线程

SV引入了两种新新的创建线程的方法,fork…join_nonefork…join_any

  • fork…join
    fork…join需要所有并行的线程都结束以后才会继续执行。
  • fork…join_any
    fork…join_any则会等到任何一个线程结束以后就继续执行。
  • fork…join_none
    fork…join_none则不会等待其子线程而继续执行。
实例

1.1.2子程序等待/停止

需要注意的是,fork…join_any和fork. . .join_none继续执行后,其一些未完成的子程序仍将在后台运行。如果要等待这些子程序全部完成,或者停止这些子程序,可以使用wait fork或者disable fork。
(1)wait fork

(2)disable fork

1.2 时序控制

SV可以通过延迟控制或者事件等待来对过程块完成时序控制。

1.2.1 延迟控制

延迟控制即通过#来完成。

#10 rega = regb;

1.2.2 事件控制

事件(event)控制即通过@来完成。

@r rega = regb ;
@(posedge clock) rega = regb;

1.2.3 事件等待

wait语句也可以与事件或者表达式结合来完成。

real AOR[] ;
initial wait(AOR.size() > 0) … ;

2. 进程间同步和通信

测试平台中的所有线程都需要同步并交换数据。
一个线程等待另外一个,例如验证环境需要等待所有激励结束、比较结束才可以结束仿真。比如监测器需要将监测到的数据发送至比较器,比较器又需要从不同的缓存获取数据进行比较。

2.1 事件

  • 声明
    可以通过event来声明一个命名event变量,并且去触发它。这个命名event可以用来控制进程的执行。
  • 触发
    可以通过->来触发事件。
    其它等待该事件的进程可以通过@操作符或者wait()来检查event触发状态来完成。
  • 等待
    wait__order可以使得进程保持等待,直到在参数列表中的事件event按照顺序从左到右依次完成。如果参数列表中的事件被触发但是没有按照要求的顺序,那么会使得等待操作失败。

wait_order ( a, b, c);

wait order( a, b, c ) else $display ( “Error: eventsout of order” );

bit success ;
wait order( a, b, c ) success = 1; else success = 0 ;

2.2 旗语

旗语从概念上讲,是一个容器。在创建旗语的时候,会为其分配固定的钥匙数量。使用旗语的进程必须先获得其钥匙,才可以继续执行。旗语的钥匙数量可以有多个,等待旗语钥匙的进程也可同时有多个。旗语通常用于互斥,对共享资源的访问控制,以及基本的同步

### 2.2.1用法 * 创建旗语,并为其分配钥匙的方式如下: >semaphore sm; >sm = new ();
  • 创建一个具有固定钥匙数量的旗语:

new (N = 0)

  • 从旗语那里获取一个或多个钥匙(阻塞型) :

get (N = 1)

  • 将一个或多个钥匙返回到旗语中:

put (N = 1)

  • 尝试获取一个或多个钥匙而不会阻塞(非阻塞型) :

try_get (N = 1)

2.2.2基本操作

senmaphore: :new()

new ())的原型如下:

function new (int keyCount = 0) ;

keyCount指定最初分配给旗语的钥匙数目。keyCount的默认值为0。当更多钥匙放入旗语时,钥匙数目可以超出初始时的keyCount数量,而不是删除。

semaphore: :put()

put ()方法用于将钥匙数量返回给旗语。
put ()的原型如下:

function void put (int keyCount = 1) ;

keycount指定返回到旗语的钥匙数量。默认值为1。调用semaphore.put ()函数时,指定数量的钥匙将返回到旗语。如果其它进程已经在等待旗语,则该进程应在有足够数量钥匙的情况下返回。

semaphore: :get()

get ()方法用于从旗语中获取指定数量的钥匙。get ()的原型如下:

task get (int keycount = 1) ;

keyCount指定从旗语获取所需的钥匙数,默认值为1。如果指定数量的钥匙可用,则该方法返回并继续执行。如果指定数量的钥匙不足,进程将阻塞,直到钥匙数目充足。旗语的等待队列是先进先出(FIFO),即先排队等待旗语的将优先得到钥匙。

semaphore : :try_get()

try get ()方法用于从信号量中获取指定数量的钥匙,但不会被阻塞。try_get ()的原型如下:

function int try_get (int keyCount = 1) ;

keyCount指定从旗语处获取所需的钥匙数目,默认值为1。如果指定数量的钥匙可用,则该方法返回正数并继续执行。如果指定数量的钥匙不足,则该方法返回0。

2.2.3实例

2.3 信箱

信箱mailbox可以使得进程之间的信息得以交换,数据可以由一个进程写入信箱,再由另外一个进程获得。

信箱在创建时可以限制其容量,或者不限制。 当信箱容量写满时,后续再写入的动作会被挂起,直到信箱的数据从中读取,使得信箱有空间以后才可以继续写入。 不限制容量的信箱则不会挂起写入信箱的动作。

2.3.1 内建方法

new()

new()用于创建信箱。可以在创建信箱的时候限定或者不限定其大小默认情况下,如果不传入参数,bound默认值为0,表示不限定信箱大小,如果传入的数值大于0,那么表示信箱的最大容量。bound应为正数,如果未负数的话,系统会提示警告和出现无法预期的行为。

function new (int bound = 0) ;

put()

put()会将信息按照FIFO的顺序写入到信箱中,如果信箱此时已满,则put()任务会挂起,直到信箱有新的空间可以容纳消息。

try_put()

try put()试着写入信箱但不会阻塞。try put()也会按照FIFO顺序写入信箱,不会发生阻塞。如果信箱已满,则写入失败,返回0;如果信箱未满,则写入成功,返回1。

get()/peek()

获取信息: get()同时会取出数据,peek()不会取出数据。get()会将信息从信箱中取出,如果信箱此时为空,则get()任务会挂起,直到信箱中有消息可以读取,任务才会返回。该方法会将读取到的消息从信箱中移除。

try_get()/try_peek()

试着从信箱取出数据但不会阻塞。try get()也会将信息从信箱中取出,只是该函数不会发生阻塞。如果信箱为空,则读取失败,返回0;如果信箱不为空,则读取成功,返回1。该方法也会将读取到的消息从信箱中移除。

num()

num()会返回信箱目前的消息数目。可以结合num()与get()或者put(),防止get()/put()方法在信箱为空或者为满的时候被阻塞。

2.3.2 实例

mailbox #(int) mb;//声明mailbox句柄,并且指明该mailbox中只能存放int类型的数据

2.4虚方法

给pringtB添加关键词virtual,P1扩大查找范围,扩大到子类对象里面。如果子类里面有同名的方法,若有,调用子类里面同名的方法(以子类的实现优先)。
子类不添加virtual无影响,父类添加即可。

3. 类型转换

3.1 静态转换

静态转换操作符不对转换值进行检查。
转换时指定目标类型,并在要转换的表达式前加上单引号即可。Verilog对整数和实数类型,或者不同位宽的向量之间进行隐式转换。

int i;
real r;
i = int ’ (10.0 - 0.1); //cast is optional
r= real’(42);// cast is optional

3.2 动态转换

我们总是可以将子类的句柄赋值给父类的句柄。但是在我们将父类的句柄赋值给子类的句柄时,编译将会报错。
$cast()系统函数可以将父类句柄转换为子类句柄,只要该父类句柄指向的是一个子类的对象。

function int $cast( singular dest_var, singularsource_exp ) ;

或者

task $cast( singular dest_var, singular source_exp );

4. 问答题

1. 用bit key =0来实现的类似旗语(semaphore)的功能,来保护对共享资源的访问,是否有不安全的地方?示例代码如下(包含自然语言表征)。如果有不安全的地方,请用文字表述,并且对以下代码进行修改,并且进行测试、编译和仿真打印消息。

bit key = 1;//创建钥匙
task get_key();
wait(key > 0);
key = 0;//获得钥匙
…//省略对于共享资源的处理
key = 1; /还回钥匙
endtask

答:当多个task并行执行时,只要key=1,满足wait(key>0)即可执行,无法实现资源同时只能被指定个数的进程访问的目的。

2. SV的原生旗语semaphore在例化以后,并不能从其获取哪一个对象(字符串stringID)获取了钥匙,那么请你将semaphore封装到一个类中,重新定义get()/put(方法,并且通过最后的一个打印函数来得知当前获取钥匙的string ID是谁?示例代码大致如下,请完成提示需要完成的地方,对你的代码进行编译和仿真,展示你的代码和仿真的打印消息。
答:sv代码如下

module tb;class smart_key;semaphore s;//创建旗语string holder;function new(N= 1);s = new(N);//分配1把钥匙endfunctiontask get(int N= 1,string str);//请添加需要的参数,并且实现该方法s.get();//拿到钥匙holder = str;#1ns;//$display("%0t: %s get the key",$time,str);endtasktask put(int N= 1,string str);//请添加需要的参数,并且实现该方法s.put();//放回钥匙#1ns;//$display("%0t: %s put the key",$time,str);endtaskfunction void print_key_holders();//请事先该方法,使其能够打印出当前获得钥匙的ID$display("%0t: now %s hold the key",$time,holder);endfunctionendclass: smart_keyinitial beginsmart_key skey = new();string string1 = "A";string string2 = "B";string string3 = "C";fork begin skey.get(1,string1);skey.print_key_holders();skey.put(1,string1);endbegin skey.get(1,string2);skey.print_key_holders();skey.put(1,string2);endbegin skey.get(1,string3);skey.print_key_holders();skey.put(1,string3);endjoin
endendmodule: tb

仿真结果:

1000: now A hold the key
2000: now B hold the key
3000: now C hold the key

3. 我们在使用信箱mailbox时,如何可以限定其容量为8,并且只能存放string类型呢?那么,是否类似的方法也可以限定一个存放字符串的队列其最大容量为8呢?
答:声明方法如下

mailbox #(int) mb;
mb = new(8);

队列空间是动态的,不能限定其最大容量。

写的不错,可以参考:SV学习笔记—线程之间的通信(事件event、信箱mailbox、旗语semaphore)_Verification_White的博客-CSDN博客_sv event

这篇关于SystemVerilog学习笔记(九)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/850464

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件