difuzz框架详解——从初学者角度理解处理器模糊测试(1)

0. 前言

这篇博客主要其实是写个自己看的,最核心的目标有这三个:

  1. 了解目前比较新的处理器模糊测试(Fuzz)的框架构成是怎么样的。
  2. 熟悉当前模糊测试使用的工具以及理解这个实践的案例。
  3. 阅读论文,并理解当前处理器模糊测试关注的标准(metric),思考之后自己的工作可以怎么做。

0.1笔者背景

有一定的verilog测试经验,基本了解cocotb, verilaltor等仿真器或者仿真组件。对于处理器内部构造实现不了解,对于处理器仿真没有经验。

1. 简介

DifuzzRTL 是一种用于 CPU 验证的差异化模糊测试方法。我们引入了一种新的覆盖度量标准,寄存器覆盖,能够全面捕捉 RTL 设计的状态,并正确引导输入生成。DifuzzRTL 自动实施寄存器覆盖,随机生成并变异 ISA 中定义的指令,然后与 ISA 模拟器进行对照检查以发现错误。论文在这个链接

2. 框架安装

框架依赖于这几个库,但是可能因为这几个组件更新得比较多,我在本机搭建安装比较新的版本之后跑不起来,所以强烈建议使用docker安装,dockerfile在这个链接,如果安装不上可以在评论区找笔者。

需要的库有:

  1. sbt 用于 FIRRTL
  2. verilator 用于 RTL 仿真(v4.106)
  3. cocotb 用于 RTL 仿真(1.5.2)
  4. riscv 用于 RISC-V 指令变异(2021.04.23)

2.1. 运行方法

第一步:

需要在docker内部,找到项目的根目录,然后执行source env.sh

第二步:执行运行指令

cd Fuzzer
make SIM_BUILD=<build_dir> VFILE=<target> TOPLEVEL=<topmodule> NUM_ITER=<num_iter> OUT=<outdir> DEBUG=<DEBUG> RECORD=<RECORD>

SIM_BUILD:用于cocotb构建RTL仿真二进制文件的目录
VFILE:在 DifuzzRTL/Benchmarks/Verilog/ 中的目标RTL设计
(例如,RocketTile_state, SmallBoomTile_v_1.2_state, SmallBoomTile_v1.3_state)
TOPLEVEL:顶层模块
(例如,RocketTile 或 BoomTile)
NUM_ITER:要运行的模糊测试迭代次数
OUT:输出目录
RECORD:设置为 1 以记录覆盖率日志
DEBUG:设置为 1 以打印调试信息

3. 理解基于覆盖率的fuzzing的工作流

在这里插入图片描述

  • Coverage instrumentation(覆盖率插桩):基于覆盖率的插桩,一般是在待测的设计中插入一些寄存器或者监测变量或者打印语句,来确认某个信号是否被覆盖。
  • Seed corpus(种子语料库):初始有效输入的集合,变异引擎使用它们来生成新的测试用例。
  • Mutation engine(变异引擎):一个组件,它从种子语料库中取出输入,并应用随机变化(变异)来创建变异输入。
  • Mutated input(变异输入):变异引擎的输出,它是原始输入的修改版,旨在通过探索新代码路径来发现错误。
  • Interesting?(是否有新的覆盖率?):一个决策点,模糊器确定变异输入是否导致了新的覆盖率,表明它已经探索了程序代码的新部分。

3.1. 我的疑问

  • Coverage instrumentation有哪几种,具体是怎么操作的?
  • 种子语料库是怎么获得的,mutation engine怎么对种子语料库进行mutate?

4. Coverage instrumentation(覆盖率插桩)

4.1. RFuzz的mux-coverage (ICCAD’18)

RFuzz是一个提出了基于多路复用器覆盖率指导的模糊测试技术的框架。这一技术的核心思想是多路复用器的选择信号会导致状态转换,因此基于多路复用器的选择信号来指导模糊测试可以探索更多的有限状态机(FSM)状态。具体来说,这项技术在运行时序电路的同时监控所有多路复用器的选择信号,并识别在运行结束时哪些信号被切换。如果有新的多路复用器被切换,则认为提供给电路的输入(即,每个周期的有效validF和validS信号序列)是有价值的,并将其添加到语料库中。这是因为新的切换表明输入已经探索了新的状态转换。如果没有新的多路复用器被切换,则提供的输入会被丢弃。

RFuzz的多路复用器覆盖率技术有两个关键的局限性。首先,由于多路复用器覆盖率指标对时钟不敏感,它无法精确捕捉FSM的状态转换。换句话说,它没有识别跨时钟的多路复用器切换事件之间的相互作用和依赖关系,因此在语义上不同的多路复用器切换事件被当作相同,未能正确识别状态转换。

举个例子,在下面这张图里,我们先有一个设计,这个设计里面有flash和SDRAM,下面这个是他的状态转移图,这里的R,P和B分别代表ready state, pending state和busy state,这几个状态可以互相转换。
在这里插入图片描述

下面这个是案例里的memory controller,这里最需要关注的是5个mux,我们去状态转移图那里看一下:
在这里插入图片描述
总的来说就是

在这里插入图片描述

总的来说就是

  • {Ready, Ready} -> {Busy, Pending} -> {Ready, Busy}
  • {Ready, Ready} -> {Ready, Pending} -> {Busy, Busy}
    的mux的cov map情况可能是一样的。

在这里插入图片描述
上面这个情况就是这个案例的一个详细例子。

DIFUZZRTL提出了一种针对RTL(寄存器传输级)的寄存器覆盖(register coverage)方法来改进硬件测试中的模糊测试过程。寄存器覆盖的主要特点包括:

  • 支持时钟敏感覆盖:
    • 寄存器覆盖能够精确捕捉有限状态机(FSM)的状态转换。
    • 有限状态机是数字逻辑中的关键组件,它根据输入信号和当前状态在不同的操作状态之间移动。
      由于对时钟周期敏感,寄存器覆盖可以追踪每个时钟周期中FSM状态的变化,这对于理解测试硬件的行为至关重要。
  • 基于控制寄存器的测量:
    • 与基于多路复用器(muxes)控制信号的测量方法不同,寄存器覆盖的测量是基于控制寄存器的。
      这使得寄存器覆盖方法更为高效和可扩展。
    • 在进一步的评估中(见§VI),与RFuzz的基于多路复用器覆盖相比,DIFUZZRTL的寄存器覆盖显示出了40倍的执行速度提升,以及6.4倍更快的探索脆弱状态的时间。更重要的是,DIFUZZRTL能够对包括乱序执行的Boom Core在内的所有三个实际的RTL进行模糊测试,而RFuzz由于可扩展性问题无法对Boom Core进行模糊测试。

4.2. 如何找到控制信号(Control Register)

  • 构建图表:首先构建一个图表示模块中所有元素(例如寄存器、线路和多路选择器)之间的连接。
  • 反向数据流分析:对每个多路选择器的控制信号进行递归的反向数据流分析。如果这种追踪到达一个寄存器,就认定此寄存器为控制寄存器。这是因为此寄存器的值会直接或间接(通过组合逻辑)用于控制多路选择器的行为。
  • 分析终止:如果追踪超出模块边界或者到达已追踪点(由于电路是循环的),则分析停止。
    在这里插入图片描述

4.3. 如何评价寄存器覆盖

DIFUZZRTL通过每个时钟周期测量寄存器覆盖率的技术,使得按时钟周期的测量成为可能。它通过在每个RTL模块中插入三个新的寄存器:regstate、covmap和covsum。DIFUZZRTL将所有控制寄存器的值通过哈希函数(使用一系列的XOR操作和左移操作)映射到regstate。之后,它尝试在covmap中的相应位置写入1,这个位置由regstate的值决定,标记对应的FSM状态(即控制寄存器值的哈希)已被探索。

如果写操作发生时covmap对应位置的值是0,则covsum会增加,表示在当前时钟周期探索了新的FSM状态。这些更新操作每个时钟周期都会执行,使得DIFUZZRTL的寄存器覆盖机制对时钟敏感。然后covsum会输出到父RTL模块,这样从所有子RTL模块累积covsum值,直至达到顶层RTL模块。顶层RTL模块中的covsum值作为DIFUZZRTL模糊测试过程中的最终覆盖值。

值得注意的是,covmap和covsum的值在模糊迭代过程中会被保持,以致于一旦覆盖的状态在后续迭代中不会被认为是新的。
在这里插入图片描述

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值