【前端验证】fork-join_none线程立即执行的一次代码优化记录

news2024/11/15 23:22:44

我们的目标是┏ (゜ω゜)=☞芯片前端全栈工程师~喵!

前言

【system verilog】fork-join_none与循环语句共同使用的行为探究

很早之前写过关于fork-join_none的探究文章,最近被人指出了一些错误:

我仔细理解了下他的意思,觉得确实使用#0来立刻进行进行阻塞,进而达到立即执行fork-join_none内语句的方式是比较合理的(当然了,其他阻塞行为一样会让fork-join_none内的语句执行,但不能达到立刻执行的效果)。经过这个勘误和指点后,我突然觉得又通彻了一些。

恰巧最近自己也在写一些验证的代码, 遇到了类似的问题,同时还帮别人debug了非常相似的问题(以下为被夸实录):

场景复盘

所以具体来说是个什么场景呢?最终完成部分代码片段如下:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            fork begin
                automatic bit[255:0]send_rdata = rdata;
                `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == send_rdata; r_trc.last == 1'b1;})
                end join_none
                #0;
        end
        else begin
            ...
        end
    end
end

 简单而言,就是一个简化的axi_slave(不过不需要总线地址对齐),当收到ar请求时要按照size返回对应笔rdata到总线上。因此代码组织最开始也比较简单,就是看arsize然后在ram中寻址返回数据并且给数据加一个随机延迟,因此最开始完成的代码是这样的:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == rdata; r_trc.last == 1'b1;})

        end
        else begin
            ...
        end
    end
end

 然后就发现了第一个问题,`uvm_do的返回时间是在driver中的seq_item_port.item_done()之后的,那么也就是说回到a_port.get(a_trc)时候是前一个ar的rdata已经发完的时间,而不是真正的从总线上获取到ar请求的时间,在这段时间里ram中的数据可能已经被改写了,因此`uvm_do必须要提并行线程来执行,所以代码就改成了这样:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            fork
                `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == rdata; r_trc.last == 1'b1;})
            join_none
        end
        else begin
            ...
        end
    end
end

然后继续仿真,就发现了第二个问题,r_trc并没有在`uvm_do_on_with的时刻就开始在driver内执行,而是呈现了比较奇怪的行为(当然这个问题并不一定是不加#0引起的),因此结合前言中的内容,我机智的加入了#0来及时执行提起的线程:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            fork
                `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == rdata; r_trc.last == 1'b1;})
            join_none
            #0;
        end
        else begin
            ...
        end
    end
end

而后继续跑仿真,自然而然的遇到了第三个问题,图示如下:

我的rdata只有一份,但是线程有多个,那么会导致每个线程中使用的rdata并不是预期的值 ,因此还要进一步的优化代码:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            fork begin
                automatic bit[255:0]send_rdata = rdata;
                `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == send_rdata; r_trc.last == 1'b1;})
                end join_none
                #0;
        end
        else begin
            ...
        end
    end
end

经过三次的优化之后,仿真行为终于符合了我的预期!

最后一下,经过和别人的讨论,其实不加#0也是可以的,这个时候需要把automatic赋值放在fork-join_none外面:

while(1)begin
    bit[255:0]rdata;
    p_sequencer.a_port.get(a_trc);
    ...
    for(int i=0; i<a_trc.size; i=i+1)begin
        rdata[(i%32)*8 +:8] = p_sequencer.ram[addr][7:0];
        if(i == arsize-1)begin
            r_transaction  r_trc = new();
            automatic bit[255:0]send_rdata = rdata;
            fork
                `uvm_do_on_with(r_trc, p_sequencer.r_sqr, {r_trc.data == send_rdata; r_trc.last == 1'b1;})
            join_none
        end
        else begin
            ...
        end
    end
end

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

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

相关文章

电容笔和触控笔有什么区别?平价好用的电容笔排行榜

从导电材料、作用机理、用途等方面来看&#xff0c;电容笔与一般的触摸笔有很大区别。电容笔的笔头设计为中等大小&#xff0c;笔头材料通常更耐磨损。随着技术的发展&#xff0c;人们的生活水平越来越高&#xff0c;人们都想要一支更好用的电容笔&#xff0c;不管是图纸绘画&a…

Java真的不难(五十一)SpringBoot使用EasyExcel实现导出

EasyExcel&#xff1a; 大家好久不见&#xff01; 一、什么是EasyExcel&#xff1f; EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址: https://github.com/alibaba/easyexcel 官方文档地址&#xf…

MAC安装redis的简单方法

使用mac的包管理工具brew一行命令搞定安装。若未安装brew&#xff0c;命令行先输入以下命令安装brew。 /bin/bash -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" brew install redis6.2 brew services restart redis6.2 一、安装…

三台服务器使用docker搭建redis一主二从三哨兵,概念-搭建-整合springboot【保姆级】

一、前言 redis在我们企业级开发中是很常见的&#xff0c;但是单个redis不能保证我们的稳定使用&#xff0c;所以我们要建立一个集群。 redis有两种高可用的方案&#xff1a; High availability with Redis Sentinel&#xff08;哨兵&#xff09;Scaling with Redis Cluster&…

FT 在图像处理中的应用

接上文&#xff1a;离散傅里叶变换(DFT) 四、二维傅里叶变换 在此之前&#xff0c;文章都是对 FT 的理论部分的科普推导&#xff0c;距离我们的实际应用还有一定距离 虽然之前提到函数时域时&#xff0c;都是默认我们以时间 t 作为自变量&#xff0c;但事实上自变量也可以是其…

小册上新 | 掌握 SpringBoot 场景整合,成为开发多面手!

只会 SpringBoot 还远远不够 SpringBoot 的强大不言而喻&#xff0c;其底层 SpringFramework 强大的 IOC 容器和 AOP 机制&#xff0c;加之 SpringBoot 的自动装配&#xff0c;使得 SpringBoot 成为当今 JavaEE 开发中最受欢迎&#xff0c;以及使用范围极其广泛的基本技术。 …

[附源码]计算机毕业设计JAVA领导干部听课评课管理系统

[附源码]计算机毕业设计JAVA领导干部听课评课管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM…

设计模式之美——DRY原则 和 迪米特法则

DRY原则 Don’t Repeat Yourself。中文直译为&#xff1a;不要重复自己。即&#xff0c;不要写重复的代码。 我们主要讲三种典型的代码重复情况&#xff1a;实现逻辑重复、功能语义重复和代码执行重复。 实现逻辑重复 public class UserAuthenticator {public void authenti…

Web(二)html5基础-表格高级样式的设置

第1关_表格高级样式设置相关概念 第2关_设置表格的外边框样式 编程要求 根据提示&#xff0c;在右侧编辑器补充代码&#xff0c;在右侧编辑器中的Begin - End区域内补充代码&#xff0c;具体要求是&#xff1a; 1.添加table标签及属性&#xff0c;使得表格的宽度为100&#x…

CAS号:81075-03-8,H2N-AYA-OH

血管紧张素-1转换酶抑制剂(IC₅₀14.2 μM)Ala-Tyr已作为酪氨酸源应用于大鼠静脉营养。二肽AY是肝衰竭患者肠外营养的有效Tyr来源。 Inhibitor of angiotensin-1 converting enzyme (ACE), IC₅₀ 14.2 μM. Ala-Tyr has been used as a tyrosine source in intravenous nutrit…

设置ZIP文件打开密码的两种方法

使用WinRAR缩包ZIP文件时&#xff0c;有两种方式来设置打开密码&#xff0c;我们可以根据不同需要选择不同的方法。 方法一&#xff1a; 在压缩文件的时候同时设置打开密码&#xff0c;只设置当下压缩的ZIP文件。 首先&#xff0c;鼠标选择需要压缩的文件&#xff0c;然后点…

推荐一个基于Springboot + Vue 开发的前后端分离博客

基于Springboot Vue 开发的前后端分离博客 博客介绍 本博客是参考 [风丶宇] 大佬的博客更新而成&#xff0c;感谢大佬提供的页面&#xff0c;然后定制新增部分功能&#xff0c;是个非常值得新手入门学习的Java规范化编程案例&#xff01; 在线地址 项目链接&#xff1a; h…

【附源码】计算机毕业设计JAVA忆居民宿管理

【附源码】计算机毕业设计JAVA忆居民宿管理 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JAVA mybati…

Yolov4 训练数据常见的问题

1.Failed to load module"canberra-gtk-module" 解决办法&#xff1a;安装对应的module sudo apt-get install libcanberra-gtk-module 2.Killed 注意&#xff1a;造成killed问题的可能性比较多&#xff0c;这里我只记录我是如何解决的 。 解决&#xff1a; 首先是…

膜拜,华为内部都在强推的783页大数据处理系统:Hadoop源代码pdf

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

数据结构和常用排序算法复杂度

1.顺序表 插入操作时间复杂度 最好O(1)&#xff0c;最坏O(n)&#xff0c;平均O(n) 移动结点的平均次数n/2 删除操作时间复杂度 最好O(1)&#xff0c;最坏O(n)&#xff0c;平均O(n) 移动结点的平均次数(n-1)/2 按值查找时间复杂度 最好O(1)&#xff0c;最坏O(n)&#xff0c;平…

数据库DQL数据查询语言

文章目录DQL数据查询语言语法:基础查询语法:WHERE子句使用AND"与"和OR"或"来连接多个条件进行查询IN(列表):等于列表其中之一(在列表中)NOT IN(列表):不在列表中&#xff0c;不能等于列表中的所有项BETWEEN...AND...:在一个范围之内DISTINCT去重操作。在结…

01.一个页面为啥有四个进程

打开了1个页面&#xff0c;Chrome启动了4个进程 并行处理 计算机中的并行处理就是同一时刻处理多个任务&#xff0c;比如我们要计算下面这三个表达式的值&#xff0c;并显示出结果。 A 12 B 20/5 C 7*8在编写代码的时候&#xff0c;我们可以把这个过程拆分为四个任务&…

sqli-labs/Less-57

这一关还是有14次尝试机会的 而且还是以id作为注入点的 首先输入如下语句 id1 and 12 查看回显 属于字符型 接着判断一下属于单引号还是双引号 输入1 查看回显 正确回显 在尝试一下双引号 输入1" 回显如下 肯定存在双引号包裹 但是是否有括号呢 不得而知 接着佐证一…

大一学生HTML期末作业 【html体育羽毛球6页面带注册】学生网页设计作业源码

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 校园篮球网页设计 | 足球体育运动 | 体育游泳运动 | 兵乓球 | 网球 | 等网站的设计与制作 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&…