【芯片前端】auto_testbench的大版本升级——加入简单预期与自动比对

news2024/11/24 18:26:47

前言

前文提要:

【芯片前端】一键生成简易版本定向RTL验证环境的脚本——auto_verification_rtl脚本_尼德兰的喵的博客-CSDN博客

【芯片前端】可能是定向验证的巅峰之作——auto_testbench_autotestbench_尼德兰的喵的博客-CSDN博客

工具路径:

auto_testbench: 用于自动生成verilog rtl的定向用例仿真平台的脚本

在上次完成自诩为“定向验证的巅峰之作”之后,我觉得这个工具应该是写到头了,不过最近的实践中我发现,对于auto_testbench的主要应用场景——CBB与UT的验证而言,如果能不依赖于方法学进行一些简单预期和比对,还是可以大幅收敛debug时间的。

本次升级针对握手接口(因为好久没写其他类型接口了),脚本的功能概述为:

  1. 对于握手接口单输出的模块,会进行符合协议的输入随机,会自动生成采样与比对task,而根据输入生成预期的task需要手动填充;
  2. 对于不满足单输出的其他握手接口模块,会进行符合协议的输入随机,此时如果想要进行比对需要对环境进行比较大的改动;
  3. 对于其他接口模块,会生成整套验证环境,对接口进行初始化和随机驱动;
  4. 如果不进行仿真只想编译模块,在tb.f中注释掉testbench.sv路径然后在sim路径执行make cmp;

其他优化包括:

  1. 优化了生成的tb.f文件;
  2. 修正了模块中有注释是可能误读的问题;
  3. 美化和对齐了一下生成文件;

效果亲测

作为一个负责人的工具发布者,发布前我先亲自验证了一下这个工具的正确性,于是翻出来了去年写的一个cbb bypass_fifo进行了下验证,然后发现这个cbb有BUG!不过放心,我相信这个cbb是没有在工程中使用的。

bypass_fifo的功能是这样,对于输入的data,如果power为1则正常输出,如果为0则丢弃。这个cbb听起来很奇怪不过其实他是另外一个cbb的一部分(一对多的场景,每个数据可能有不同的通道需要)。那么看下出错的log:

对着log找到波形的错误处:

然后分析下问题不是出现在'h57eadcc1这个数身上,而是出现在前一个数'hb985d7ad,RTL出口没有就把valid和数变了!奇怪的是对于类似的场景,其他的数据在出口时序就很正确:

那么这个问题如果通过波形是否能发现呢?不是太容易:

因此,这个工具的新功能我初步认为是有效的。

使用说明

就以bypass_fifo的验证环境生成为例,看一下如何使用。

第一步还是切换到bypass_fifo的路径,执行:

auto_testbench -f bypass_fifo.v
#如果没有设置全局路径,请完整输入auto_testbench的脚本路径

打印信息为:

##====================================================================##
Gen over! please cd ./bypass_fifo_verification/sim
You need modify ./bypass_fifo_verification/top/testbench.sv
    like cp ./bypass_fifo_verification_bak/top/testbench.sv ./bypass_fifo_verification/top/
You need modify ./bypass_fifo_verification/cfg/tb.f
    like cp ./bypass_fifo_verification_bak/cfg/tb.f ./bypass_fifo_verification/cfg/
##====================================================================##

这里说明一下,我的本意是如果已经有bypass_fifo_verification目录了,就把bypass_fifo_verification重命名为bypass_fifo_verification_bak,不过吧脚本写的好像是有点问题导致这个功能时灵时不灵。

第二步,切换到bypass_fifo_verification/cfg路径,打开tb.f文件,并按照需求修改:

+libext+.v
-y /home/ICer/gitee_path/auto_testbench/src/

../ver/bypass_fifo_pkg.sv
/home/ICer/gitee_path/auto_testbench/src/bypass_fifo.v
../top/testbench.sv

第三步,切换到bypass_fifo_verification/ver路径,检查bypass_fifo_pkg.sv是否符合预期:

package bypass_fifo_pkg;

    parameter ERROR_DEBUG_CNT = 5;
    parameter DEPTH = 8;
    parameter WIDTH = 128;

    int error_cnt = 0;
    bit check_en  = 0;

    typedef struct{
        bit [WIDTH -1:0] data_in;
        bit  data_in_power;
    } data_in_valid_struct;
    data_in_valid_struct data_in_valid_bus_q[$];

    typedef struct{
        bit [WIDTH -1:0] data_out;
    } data_out_valid_struct;
    data_out_valid_struct rm_q[$];
    data_out_valid_struct data_out_valid_bus_q[$];

endpackage

重点说bypass_fifo_pkg文件,在这个文档中脚本根据每个valid信号的名字“推测”其它信号是否为该valid“管辖”的信号,并将结果按valid分组为struct结构。然后顺便把每个数据结构的队列进行声明,如果是输出的valid,那么同时声明reference model的预期队列。因此如果有多路valid输出握手的话,这里的rm声明会重复,需要手动修改。

ERROR_DEBUG_CNT表示发生错误的次数,check_en表示是否进行自动比对默认为0,需要进行比对时手动将这个值改为1。

第四步,切换到bypass_fifo_verification/top路径,打开testbench.sv文件,还是如此的赏心悦目:

其他部分之前都讲过,只需说明下新增的auto_verification部分即可。展开这部分可以看到如下代码:

task in_queue_gain();
  while(1)begin
    @(negedge clk);
    if(data_in_valid && data_in_ready)begin
      data_in_valid_struct data_in_valid_dat;
      data_in_valid_dat.data_in = data_in;
      data_in_valid_dat.data_in_power = data_in_power;
      data_in_valid_bus_q.push_back(data_in_valid_dat);
    end//if-end 
  end//while-end 
endtask: in_queue_gain

对输入进行采样,如果有多路输入,会在这个task里均进行采样;

task out_queue_gain();
  while(1)begin
    @(negedge clk);
    if(data_out_valid && data_out_ready)begin
      data_out_valid_struct data_out_valid_dat;
      data_out_valid_dat.data_out = data_out;
      data_out_valid_bus_q.push_back(data_out_valid_dat);
    end//if-end 
  end//while-end 
endtask: out_queue_gain

对输出进行采样,如果有多路输出,会在这个task里均进行采样;

task rm_queue_gain();
  data_in_valid_struct data_in_valid_dat;
  data_out_valid_struct data_out_valid_dat;
  //while(1)begin
    //wait(data_in_valid_bus_q.size > 0);
    //data_in_valid_dat = data_in_valid_bus_q.pop_front();
    //rm_q.push_back(data_out_valid_dat);
  //end
endtask: rm_queue_gain

rm_queue_gain是一个空壳task,用于产生预期,里面预置了数据类型和队列操作方法;

task queue_check();
  while(1)begin
    data_out_valid_struct rm_data;
    data_out_valid_struct dual_data;
    wait(data_out_valid_bus_q.size() > 0);
    dual_data = data_out_valid_bus_q.pop_front();
    if(rm_q.size() == 0) begin
      $display("dual_data = %0p, rm_queue.size = 0", dual_data);
      error_cnt += 1;
    end
    else begin
      rm_data = rm_q.pop_front();
      if(dual_data != rm_data)begin
        error_cnt += 1;
        $display("dual_data(%0p) != rm_data(%0p) at %t", dual_data, rm_data, $realtime);
      end
      else begin
        //$display("dual_data(%0p) == rm_data(%0p) at %t", dual_data, rm_data, $realtime);
      end
    end
    if(error_cnt >= ERROR_DEBUG_CNT) begin
      $display("Check Error!!!");
      $finish;
    end
  end
endtask: queue_check

对rm_q[$]和RTL输出接口queue[$]进行自动比对,同样需要注意,如果有多路进行输出,这里只会比对其中一路;

代码的最后是固定的initial函数:

initial begin
  fork
    in_queue_gain();
    out_queue_gain();
    rm_queue_gain();
    if(check_en == 1) queue_check();
  join_none
end

然后是关键点,根据bypass_fifo的功能对rm_queue_gain task进行改写,完成简单的功能预期:

task rm_queue_gain();
  data_in_valid_struct data_in_valid_dat;
  data_out_valid_struct data_out_valid_dat;
  while(1)begin
    wait(data_in_valid_bus_q.size > 0);
    data_in_valid_dat = data_in_valid_bus_q.pop_front();
    if(data_in_valid_dat.data_in_power == 1)begin
        data_out_valid_dat.data_out = data_in_valid_dat.data_in;
        rm_q.push_back(data_out_valid_dat);
    end
  end
endtask: rm_queue_gain

至此CBB的简单验证环境就完成了。

切换到auto_verification/sim目录,执行:

make run wave=on

之后根据仿真结果和波形进行debug。

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

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

相关文章

「量化」快乐:UC Berkeley 利用 AI 追踪多巴胺释放量及释放脑区

内容一览:多巴胺是神经系统中重要的神经递质,与运动、记忆和奖赏系统息息相关,它是快乐的信使,当我们看到令人愉悦的东西时,体内就会分泌多巴胺,诱导我们向它追寻。然而,多巴胺的准确定量分析目…

利用logstash/filebeat/插件,将graylog日志传输到kafka中

1.graylog配置输出 在System-outputs,选择GELF Output,填写如下内容,其它选项默认 在要输出的Stream中,选择Manage Outputs 选择GELF Output,右边选择刚才创建好的test。 2.安装logstash,作为中间临时…

idea报错:java: 程序包org.springframework.web.bind.annotation不存在

这个错误通常都是maven仓库的问题,试了网上很多方法,都没有解决,如果大家有遇到这个问题,且试了很多方法之后都没有解决,不妨可以试试我这个方法 先编译一下已经写好的代码,这时候会出现以上报错&#xff…

网络安全 | 揭秘网络安全攻防实战:探索互联网发展史,守护数字世界的安全堡垒

大家好,我是沐尘而生。 互联网发展史:数字世界的壮阔画卷 从早期的ARPANET到今天的万物互联,互联网经历了漫长的发展过程。然而,随着技术的进步,网络安全问题也随之而来。我们不仅要探索互联网的壮阔历程,…

普通索引和唯一索引,应该怎么选择(已经那个changebuffer - 和你这个线程连接池)

普通索引和唯一索引是什么 普通索引和唯一索引都是数据库中常用的索引类型,它们的主要区别在于索引列的值是否允许重复 普通索引允许索引列的值重复,也就是说,如果多个记录在索引列中具有相同的值,那么这些记录仍然可以通过普通…

条件操作符(三目操作符)

比如之前我们想写一个条件判断表达式是这样写的: 用操作符就可以这样写: 应用,比如求两个数的最大值

SQL | 分组数据

10-分组数据 两个新的select子句:group by子句和having子句。 10.1-数据分组 上面我们学到了,使用SQL中的聚集函数可以汇总数据,这样,我们就能够对行进行计数,计算和,计算平均数。 目前为止&#xff0c…

第一个ArkTS项目实践-鸿蒙ArkTS

第一个ArkTS项目实践-ArkTS 第一个ArkTS项目实践-ArkTS自定义组件的组成配置属性与布局配置属性布局 改变组件状态循环渲染列表数据代码ToDoItem组件ToDoList页面 效果参考资料 第一个ArkTS项目实践-ArkTS 本篇文章是官网上视频对ArkTS开发实践的第一个视频,主要是引…

Docker中部署redis

1.部署redis要求 2.部署教程 连接容器中的redis redis部署完毕

项目:基于UDP的TFTP文件传输

1)tftp协议概述 简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输特点: 是应用层协议 基于UDP协议实现 数据传输模式 octet:二进制模式(常用) mail:已经不再…

22、touchGFX学习Model-View-Presenter设计模式

touchGFX采用MVP架构,如下所示: 本文界面如下所示: 本文将实现两个操作: 1、触摸屏点击开关按键实现打印开关显示信息,模拟开关灯效果 2、板载案按键控制触摸屏LED灯的显示和隐藏 一、触摸屏点击开关按键实现打印开…

Mirror网络库 | 实战

此篇为下文,上篇:Mirror网络库 | 说明 一、官方实例说明 场景名说明AdditiveLevels场景为“关卡”,附加形式加载AdditiveScenes加载卸载附加场景Basic基础的连接/断开,消息发送Benchmark服务器1000“怪物”生成性能测试Benchmark…

Jenkins-CICD-python/Java包升级与回退

Jenkins- CICD流水线 python/Java代码升级与回退 1、执行思路 1.1、代码升级 jenkins上点击 upgrade和 代码版本号 --${tag} jenkins 推送 代码 和 执行脚本 到目标服务器/opt目录下 执行命令 sh run.sh 代码名称 版本号 upgrade 版本号 来自jenkins的 构建参数中的 标签…

自然语言处理: 第八章chatGPT的搭建

理论基础 Transformer 大模型家族可以分成三类, 至于三者的区别可以参考上一章: Encoder-only,Decoder-only, 只需要Pre_trainEncoder-decoder , 可以在一些任务上无需进行fine_tune 必须要在下游任务进行微调比如Bert , Bart 。 T5 这种无需要微调就能完成一些任…

使用Edge和chrom扩展工具(GoFullPage)实现整页面截图或生成PDF文件

插件GoFullPage下载:点击免费下载 如果在浏览网页时,有需要整个页面截图或导出PDF文件的需求,这里分享一个Edge浏览器的扩展插件:GoFullPage。 这个工具可以一键实现页面从上到下滚动并截取。 一、打开“管理扩展”(…

分类过程中的一种短程相互作用

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点,AB训练集各由6张二值化的图片组成,让A,B中各有3个点,且不重合,统计迭代次数并排序。 其中有10组数据 差值结构 迭代次数 构造平均列A 构造平均列AB…

JavaFx基础学习【四】:UI控件的通用属性

一、介绍 Node,就是节点,在整体结构中,就是黄色那一块,红色也算 个人理解,在实际中,Node可以说是我们的UI页面上的每一个节点了,比如按钮、标签之类的控件,而这些控件,大…

解决电脑声音正常但就是某些游戏没声音问题

电脑声音正常,玩普遍游戏也正常,就有游戏不出声音 详细介绍经过,不喜欢的请直接跳 第三部分。 一、先说下起因现象。 1 大富翁11 没声音。 前段时间无聊怀旧就买了个大富翁11玩玩,近二十年前的老台式机正常无问题。后来想在性能…

网络安全 Day31-运维安全项目-容器架构下

容器架构下 6. Dockerfile6.1 Docker自动化DIY镜像之Dockerfile1) 环境准备2) 书写Dockerfile内容3) 运行Dockerfile生成镜像4) 运行容器5) 小结 6.2 案例14:Dockerfile-RUN指令1) 书写Dockerfile2) 构建镜像3) 启动容器4) 测试结果 6.3 Dockerfile指令 …

CMake教程6:调用lib、dll

之前我们学到了如何编写一个可执行程序和Library,在继续学习之前,需要解释下target,在cmake中我们可以给executable和library设置一个target名字,这样可以方便我们在后续对target进行更加详细的属性设置。 本节我们将学习如何在项…