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把钥匙
	endfunction
	
	task get(int N= 1,string str);//请添加需要的参数,并且实现该方法
		s.get();//拿到钥匙
		holder = str;
		#1ns;
		//$display("%0t: %s get the key",$time,str);
	endtask
	task put(int N= 1,string str);//请添加需要的参数,并且实现该方法
		s.put();//放回钥匙
		#1ns;
		//$display("%0t: %s put the key",$time,str);
	endtask
	function void print_key_holders();//请事先该方法,使其能够打印出当前获得钥匙的ID
		$display("%0t: now %s hold the key",$time,holder);
	endfunction
		
endclass: smart_key
	
initial begin
	smart_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);
		end
		begin 
			skey.get(1,string2);
			skey.print_key_holders();
		    skey.put(1,string2);
		end
		begin 
			skey.get(1,string3);
		    skey.print_key_holders();
			skey.put(1,string3);
		end
	join
end
	
endmodule: 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

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据类型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举类型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口中的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装:类 209 5.1 概述 209 5.2 类的成员 233 5.3 类的继承 245 三种类型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率类型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 类型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的类 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425
### 回答1: 《SystemVerilog路科验证v2学习笔记》是一本非常全面深入的书籍,对于学习SystemVerilog语言及验证方法学习者是非常有帮助的。 本书详细介绍了SystemVerilog语言的基础知识和高级特性,包括数据类型、运算符、流控制语句、函数、任务、类、接口等内容,同时紧密结合实际应用场景,给出了大量的示例和案例,让读者能够深入理解语言的特性和应用。 在验证方法方面,本书介绍了常用的验证方法,包括自动化验证、端到端验证、仿真验证和硬件验证方法等。并且配合测试实践,详细介绍常用的验证步骤,例如验证计划、验证环境设计、测试用例生成、仿真调试等。 除此之外,本书还介绍了SystemVerilog中非常重要的Constrained Random Verification方法,包括约束对象、约束条件等内容的详细介绍。并且还介绍了常用的SystemVerilog验证库,例如UVM等内容。 本书内容丰富、实用性强,对于想要了解SystemVerilog语言和验证方法的读者来说,是一本非常不错的参考资料。但读者在阅读本书的时候,需要具备一定的硬件系统知识和编程基础,这样能够更好的理解及学习本书的知识内容。 ### 回答2: 路科验证v2学习笔记是一本全面介绍SystemVerilog验证语言的畅销书籍,共计600页。本书由作者路科阅读SystemVerilog语言规范,并将其实践经验结合编写而成。书中内容包含SystemVerilog语言的基础、高级语法、重要特性以及实际应用等方面,特别适合初学者和有一定基础的验证工程师阅读。 在基础部分,作者详细介绍了SystemVerilog语言的数据类型、操作符、数据结构及宏定义等内容,还介绍了模块的声明、端口、实例化及连接等基本使用方法。在高级语法部分,作者介绍了SystemVerilog中常用的语法,如过程、任务、函数、静态存储类、重载及继承等。另外,作者还介绍了异步时序控制器、顺序时序控制器、交互验证及UVM使用方法等内容。在实际应用方面,作者给出了一系列SystemVerilog验证实例,涉及到寄存器验证、串口验证、DMA验证、AXI验证等多个领域。 总之,如果您是SystemVerilog的初学者或想进一步学习这门语言,这本书可以作为一本好的学习笔记。 ### 回答3: SystemVerilog是一种硬件描述语言,主要用于硬件验证和设计。而路科验证v2学习笔记就是一本详尽的SystemVerilog学习资料,全书共600页,内容涵盖了从SystemVerilog基础语法到高级验证技术的全面介绍。 该书以工程实例为主线,结合实际项目经验,详细讲解了SystemVerilog语言的各个方面,包括数据类型、运算符、流程控制语句、函数、任务、类、接口、时序建模、仿真调试等。同时,本书还特别强调了SystemVerilog中重要的验证特性,如断言、覆盖率、约束随机等。 此外,路科验证v2学习笔记还提供了大量的实战练习,通过实践加深读者对SystemVerilog的理解和应用能力。同时,作者还介绍了常用的EDA工具、仿真平台和验证方法,帮助读者快速掌握实际应用技能。 总之,路科验证v2学习笔记是一本完整、系统、实用的SystemVerilog学习资料,适合各类硬件设计和验证工程师、从业人员、硬件爱好者及学生使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值