system verilog(降龙十八掌)
第一式:开启多个线程
SV——线程及线程间的通信(一) · 大专栏 (dazhuanlan.com)https://www.dazhuanlan.com/idadai/topics/1523517
initial begin语句1;#10;fork语句2;语句3;join_none语句4;语句5;
end// #0 语句1
// #10 语句2,语句3,语句4并发执行
// #10 语句4执行完之后才执行语句5。4执行完之后,即使2,3没执行完,也会接着执行5,因为fork块内语句与之后的语句是并行的,不会阻塞之后的语句
// 来源:https://www.dazhuanlan.com/idadai/topics/1523517
如果循环启动线程,需要用 automatic 关键字,来自动创建变量,这样为每个线程单独分配内存。
initial beginfor(int i=0;i<3;i++)forkautomatic int k=i;//注意k的声明$display(k); // 注意这里用的式kjoin_none
end
wait fork 来等待线程都执行完。
需求:在某一个循环里面,根据条件来决定是否开启fork join_none;但是可能需要把对应的条件打印出来。(注意automatic 的使用)
foreach (mab_is_1[i]) beginif(mab_is_1[i] == 1 ) beginint search_range_window=0;forkautomatic int interrupt_qid = i;do beginif ( ???) begin`uvm_info(get_type_name(), $sformatf("Congratulation: interrupt compare is success!(Qid=%0d)",interrupt_qid), UVM_LOW);break;end@(posedge v_xxx_intf.clk);search_range_window++;while(search_range_window <= 10) ;join_noneendend
线程间通信
测试平台中所有的线程需要传递数据,可能多个线程同时要访问同一个数据,测试平台的代码是使得同一时间只有一个线程能访问。
@e1是边沿敏感的阻塞语句;wait(e1.triggered()) 是电平敏感的。
event done[N];// N是发生器数目 int cnt; initial beginforeach (gen[i])begingen[i]=new(done[i]);gen[i].run();endforeach(gen[i]) forkautomatic int k=i;begin //begin块wait(done[k].triggered());cnt++; //触发一个,计数加一。endjoin_nonewait(cnt==N); //等待计数到N。说明所有的fork执行完毕,所有的事件都触发 end
第二式:callback 机制(三步骤)
回调的概念:(参考公众号:芯片学堂)
回调函数概念:在上面的类比中,“制作身份证”是一个首先被执行的主函数(main function),填写信息表中取送方式一栏就是向主函数注册回调函数(register a callback function),而“邮寄”和“本人来取”其实就是被注册的回调函数(callback function),主函数在结束之前会调用回调函数,这个调用的地方叫做回调函数的hook。回调函数的接口通常是预先定义好的,比如CC总不能给主函数注册一个“由民警配送到我家”的回调函数吧。
SV的callback步骤
1、在需要回调的地方预留入口;(类似pre_callback、post_callback)
2、定义回调的类及其内部的回调函数;(virtual class;virtual task;)
3、例化和添加回调类的实例;(回调类 xx=new(); 添加到1的地方)
// 第一步:添加回调函数和hook
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type;
class slave_driver;
resp_type resp;
// 这个就是回调函数,一般声明称virtual,方便override
// 在使用的时候是直接继承该类并重载定义回调函数
virtual task update_resp;
endtasktask send_response;std::randomize(resp) with {resp == OKAY;}; update_resp();// 这行代码就是回调函数的hook
endtaskendclass// 第二步:使用回调数
class err_inject extends slave_driver;
// 在子类中重新定义回调函数的实现 virtual task update resp;$display("Injecting SLVERR"); resp = SLVERR;endtask
endclass// 第三步:使用回调数
program error_test;slave env env;
err_inject err_driver;
initial begin// 例化环境组件 env =new();err driver =new();// 用err_driver覆盖slave_driverenv.slv_driver = err_driver();// 仿真开始 env.run();
end
endprogram
UVM的callback
参考白皮书P288的9.1.4小节
callback的开发者:
1、定义一个A类:class A extend uvm_callback;回调函数要添加virtual(以便使用者重载)
如:virtual task pre_tran(xxx123 m_driver, ref transaction tr)
2、声明yigeA_pool类:typedef uvm_callback #(xxx123,A) A_pool;
第一个参数:xxx123:这个A_pool将会被xxx123这个类使用;
第二个参数:A:这是一个A类型的pool;
3、在要预留callback函数|任务接口的类中调用uvm_register_cb宏:
class xxx123 extend uvm_driver #(transaction);// 在主函数中注册回调函数`uvm_register_cb(xxx123,A)
4、在调用callback函数或任务接口的函数或任务中,使用宏uvm_do_callback来调用回调函数;
task xxx123::main_phase(uvm_phase phase)
//.........
`uvm_do_callback(xxx123,A,pre_tran(parameters))
//........
endtask
使用者:需要实现具体的callback函数
1、从A中派生一个类ex_A,并重载回调函数pre_tran;
2、在测试用例这一层的connect_phase中(要求就是在上面步骤4中使用回调函数之前的phase即可):把ex_A类实例化并加入到A_pool中。(A_pool::add(xx.a,my_cb))参考白皮书P290 代码清单9-13
下面是:芯片学堂给出的一个实例
// 第一步:添加和引用回调函数,回调基类定义和hook分开
class driver_callback extends uvm_callback;uvm object utils(driver callback)function new(string name = "driver_callback");super.new(name);
endfunction
// 定义回调函数
virtual task pre drive;
endtask virtual task post_drive;
endtask endclass// 回调函数在使用之前,需要先被注册到回调hook的object当中
//注册的时候可以使用UVM提供的宏来完成,并且在object中加hook
class driver extends uvm_component;`uvm_component_utils(driver)// 这里就是对回调函数的注册,将回调基类和驱动类型关联起来`uvm_register_cb(driver, driver_callback)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunctiontask run_phase(uvm phase phase);
//这里就是对两个回调函数的hook,实际上是从回调函数资源池里面找函数执行
// 函数索引是驱动类型+回调类型+回调函数名
`uvm_do_callbacks(driver, driver_callback, pre_drive()); drive_pkt();
`uvm_do_callbacks(driver, driver_callback, post_drive());
endtasktask drive pkt();
`uvm_info("DRIVER", "Inside drive_pkt method", UVM_LOW);
endtask
endclass// 第二步:实现回调函数
// 在上面SystemVerilog的例子中,实现回调函数是要继承整个driver
// 在UVM这个例子中,回调函数的声明和hook是分开的,因此在实现回调函数的时候
// 只要继承callback类就可以了
class user callback extends driver callback:
`uvm_object utils(user callback)function new(string name = "user_callback")
super.new(name);
endfunctiontask pre_drive;
uvm_info("USER_CALLBACK", "Inside pre_drive method", UVM_LOW);
endtasktask post drive;
uvm_info( "USER_CALLBACK", "Inside post_drive method", UVM_LOW)
endtask endclass// 第三步:使用回调函数
// 在UVM这个例子中,因为回调函数跟hook是分开的,在使用的时候也需要单独例化
//在SystemVerilog实现的例子中,则是只要例化driver就可以,这是个区别
class user callback_test extends basic_test;
// 声明用户实现后的回调类user_callback callback_1;uvm_component_utils(user_callback_test)function new(string name = "user_callback_test", uvm_component parent);
super.new(name,parent);
endfunctionfunction void build_phase(uvm_phase phase);
super.build_phase(phase);// 回调类实例化
callback 1 = user callback::type id::create("callback 1", this);
// 给env的driver的回调函数资源池里添加回调对象
uvm callback #(driver, driver callback)::add(env.drv, callback_1);endfunctionendclass
第三式:给函数传递参数和函数返回
第1个点:函数返回,task是不能声明类型的,只有function允许声明类型,如下图所示。
第2个点就是:
- function或task里面参数的方向如果没有显示声明的话,就是input;
- 如果第一个参数指明方向是output,而后面的参数没有指明方向的话,也会是output,沿用前面的方向属性;
- const ref 这个特性也会被后面的参数沿用,如果后面的参数没有指明方向属性的话,正确方式如下图;
第3点:函数返回可以用return提前结束函数的执行;参数output类型可以直接用;(外面声明一下,传给函数处理,再引用这个参数时,是已经处理后的值了)
第四式:随机化
1、调用randomize可以只随机部分变量;
2、多个随机约束冲突后,工具不会进行随机化,此时给出的值一般都是0;
解决方案1:关闭部分约束或调整约束;(xx.constraint_mode(0):参考绿皮书P157,例子6.38)
3、在约束里面使用foreach
4、随机化二维数组
上面截图来自iEEE手册
system verilog(降龙十八掌)相关推荐
- crc生成多项式怎么算_利用system Verilog生成任意CRC多项式
IC君的第43篇原创文章 之前有一篇文章讲了CRC串行和并行电路的实现:CRC算法的硬件电路实现:串行电路和并行电路. 有做过类似设计的同学问:有没有办法轻松愉快地生成任意CRC多项式的电路?我们在设 ...
- System Verilog学习小结
System Verilog课程小结 第一周 问题1:设计人员和验证人员他们的协作关系体现在哪些地方? 1.设计人员和验证人员都需要围绕功能描述文档开展工作 2.设计只有经过充分量化验证,才有信心去流 ...
- System Verilog Assertion for debug
System Verilog Assertion是非常好的验证方法,通过SVA可以显式描述需要验证的电路逻辑,并且仿真工具可以在仿真的过程中自动输出波形出错信息,从而替代传统的看波形调试方法,提高前端 ...
- (149)System Verilog接口(interface)连线待测模块
(149)System Verilog接口(interface)连线待测模块 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog接口(in ...
- (150)System Verilog仿真结束机制
(150)System Verilog仿真结束机制 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog仿真结束机制 5)结语 1.2 FP ...
- (140)System Verilog替代交叉覆盖率
(140)System Verilog替代交叉覆盖率 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog替代交叉覆盖率 5)结语 1.2 ...
- (136)System Verilog覆盖组参数传递实例
(136)System Verilog覆盖组参数传递实例 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog覆盖组参数传递实例 5)结语 ...
- (138)System Verilog覆盖率目标设置
(138)System Verilog覆盖率目标设置 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog覆盖率目标设置 5)结语 1.2 ...
- (130)System Verilog忽略仓数与违反仓数用法
(130)System Verilog忽略仓数与违反仓数用法 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog忽略仓数与违反仓数用法 5 ...
- (129)System Verilog限制建仓方法
(129)System Verilog限制建仓方法 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog限制建仓方法 5)结语 1.2 FP ...
最新文章
- Connect模块解析 转载
- python为什么中文要encoding-python中encoding是什么意思
- Markdown中数学公式练习
- JavaDoc命令使用说明
- LeetCode之Hamming Distance
- 如何将Anaconda更新到想要的python版本(其实使用的是Anaconda中的切换不同环境的方法,不过步骤挺好)
- 【链表】剑指offer:反转链表
- 20200308——多项式回归预测工资
- 第四步_安装gcc交叉编译工具
- 什么是NoSQL及NoSQL四大分类
- 研究生数学建模竞赛准备
- php旅游管理系统,基于Laravel框架开发的旅游网站管理系统PHP源码
- 台式计算机蓝牙完成配对,电脑蓝牙已配对但连不上 带你快速解决一下
- 如何清除redis缓存
- 新的GSMA报告强调“智联万物”在全球的作用
- Windows原版系统下载地址
- PhotoSwipe.js 相册展示插件学习
- 远程桌面怎么记住登录计算机,大神处理windows10电脑远程桌面自动记录登录密码的具体操作办法...
- 洛谷 p2404 自然数拆分问题
- 一.软件使用与基础入门