第一式:开启多个线程
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个点就是:

  1. function或task里面参数的方向如果没有显示声明的话,就是input;
  2. 如果第一个参数指明方向是output,而后面的参数没有指明方向的话,也会是output,沿用前面的方向属性;
  3. const ref 这个特性也会被后面的参数沿用,如果后面的参数没有指明方向属性的话,正确方式如下图;

第3点:函数返回可以用return提前结束函数的执行;参数output类型可以直接用;(外面声明一下,传给函数处理,再引用这个参数时,是已经处理后的值了)


第四式:随机化

1、调用randomize可以只随机部分变量;

2、多个随机约束冲突后,工具不会进行随机化,此时给出的值一般都是0;

解决方案1:关闭部分约束或调整约束;(xx.constraint_mode(0):参考绿皮书P157,例子6.38)

3、在约束里面使用foreach

4、随机化二维数组

 上面截图来自iEEE手册

system verilog(降龙十八掌)相关推荐

  1. crc生成多项式怎么算_利用system Verilog生成任意CRC多项式

    IC君的第43篇原创文章 之前有一篇文章讲了CRC串行和并行电路的实现:CRC算法的硬件电路实现:串行电路和并行电路. 有做过类似设计的同学问:有没有办法轻松愉快地生成任意CRC多项式的电路?我们在设 ...

  2. System Verilog学习小结

    System Verilog课程小结 第一周 问题1:设计人员和验证人员他们的协作关系体现在哪些地方? 1.设计人员和验证人员都需要围绕功能描述文档开展工作 2.设计只有经过充分量化验证,才有信心去流 ...

  3. System Verilog Assertion for debug

    System Verilog Assertion是非常好的验证方法,通过SVA可以显式描述需要验证的电路逻辑,并且仿真工具可以在仿真的过程中自动输出波形出错信息,从而替代传统的看波形调试方法,提高前端 ...

  4. (149)System Verilog接口(interface)连线待测模块

    (149)System Verilog接口(interface)连线待测模块 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog接口(in ...

  5. (150)System Verilog仿真结束机制

    (150)System Verilog仿真结束机制 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog仿真结束机制 5)结语 1.2 FP ...

  6. (140)System Verilog替代交叉覆盖率

    (140)System Verilog替代交叉覆盖率 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog替代交叉覆盖率 5)结语 1.2 ...

  7. (136)System Verilog覆盖组参数传递实例

    (136)System Verilog覆盖组参数传递实例 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog覆盖组参数传递实例 5)结语 ...

  8. (138)System Verilog覆盖率目标设置

    (138)System Verilog覆盖率目标设置 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog覆盖率目标设置 5)结语 1.2 ...

  9. (130)System Verilog忽略仓数与违反仓数用法

    (130)System Verilog忽略仓数与违反仓数用法 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog忽略仓数与违反仓数用法 5 ...

  10. (129)System Verilog限制建仓方法

    (129)System Verilog限制建仓方法 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog限制建仓方法 5)结语 1.2 FP ...

最新文章

  1. Connect模块解析 转载
  2. python为什么中文要encoding-python中encoding是什么意思
  3. Markdown中数学公式练习
  4. JavaDoc命令使用说明
  5. LeetCode之Hamming Distance
  6. 如何将Anaconda更新到想要的python版本(其实使用的是Anaconda中的切换不同环境的方法,不过步骤挺好)
  7. 【链表】剑指offer:反转链表
  8. 20200308——多项式回归预测工资
  9. 第四步_安装gcc交叉编译工具
  10. 什么是NoSQL及NoSQL四大分类
  11. 研究生数学建模竞赛准备
  12. php旅游管理系统,基于Laravel框架开发的旅游网站管理系统PHP源码
  13. 台式计算机蓝牙完成配对,电脑蓝牙已配对但连不上 带你快速解决一下
  14. 如何清除redis缓存
  15. 新的GSMA报告强调“智联万物”在全球的作用
  16. Windows原版系统下载地址
  17. PhotoSwipe.js 相册展示插件学习
  18. 远程桌面怎么记住登录计算机,大神处理windows10电脑远程桌面自动记录登录密码的具体操作办法...
  19. 洛谷 p2404 自然数拆分问题
  20. 一.软件使用与基础入门

热门文章

  1. 修改注册表设置管理员权限
  2. css 头像右下角圆圈,CSS3 头像动效 - 悬停时透明圆形盖子旋转遮盖
  3. 超神学院基因计算机,《超神学院》超级基因的起源
  4. 完整學習機器學習實錄 1 —— 安裝 Ubuntu 18.04
  5. 【元宇宙欧米说】Big Time——探索Gamefi的未来及其经济模型
  6. 【校内训练2019-04-03】星际穿越
  7. 790leetcode多米诺和托米诺平铺
  8. 理想中的Web3信誉体系:如何在Web2基础上升级?
  9. 从百度信誉评级看未来网络优化的方向
  10. 【概率论与数理统计】猴博士 笔记 p33-35 超几何分布、正态分布、二项分布