Formal property verification 形式验证 第四章

目录

一、FPV简介

二、FPV实际应用

 三、基本的FPV环境

1.编写RTL

2.创建覆盖点

3、创建假设

4、创建断言

5、时钟和复位

6、运行验证

 四、FPV不同于仿真

1、可以运行哪些类型和尺寸的模型

2、如何达到目标行为

3、检查哪些值

4、怎样约束模型

5、如何处理内部节点上的约束

6、我们使用什么进行调试(debug)

7、典型的轨迹(traces)有多长

五、决定在哪里以及如何运行FPV

1、使用Design exercise FPV

 2、使用Bug hunting FPV       

3、使用full proof FPV

4、使用Application-specific FPV

一、FPV简介

上图中,左边三个是FPV的输入内容,右边是输出内容。

1.输入:

  • RTL模块
  •  断言和覆盖点
  • 假设,时钟、复位定义

2.输出:

  • 经证明的属性列表:经验证的断言和无法实现的覆盖点
  • 对于每个被推翻的断言或可到达的覆盖点,显示故障/可到达情况的波形
  • 未经证实或反驳的断言和覆盖

上图中:

  • All possible RTL values:RTL设计中可分配给节点(nodes)的所有可能值
  • Reset state:根据用户提供的设置信息,系统可能的启动状态
  • Reachable states:在重置状态下启动时,系统实际可能达到的所有可能状态
  • Assumptions:每个假设限制了设计的可能行为,排除了部分状态空间,橙色的椭圆形表示被假设排除的部分状态空间;有时,假设(冗余)排除了部分无法到达的空间(即橙色和亮绿色范围外)。
  • Assertions: 每个断言都对模型的行为进行了说明,有效地将设计空间的某些子集定义为该模型不合法。深蓝色框表示模型断言定义为非法的状态集
  • Cover Points:每个覆盖点定义了一类良好状态,我们希望确保这些状态在当前验证环境中是可访问的。星星标记由模型覆盖点定义的状态集。

        FPV工具基本上采用一个模型、一组属性和一组约束,并试图确定每个约束在该状态空间中的位置,这种基本技术可以用在典型的片上系统(SOC)设计和验证流程中,许多不同类型任务的基础:

  • Design exercise FPV
  • Bug hunting FPV
  • “Traditional” full proof FPV
  • Application-specific FPV

二、FPV实际应用

组合锁RTL的基本框图:

组合锁RTL的顶层描述:

 

 三、基本的FPV环境

1.编写RTL

        编写可在FPV中运行的RTL模块,现在所有的FPV工具都要求是可综合的RTL,通常排除以下SystemVerilog元素:

  • 代码中的显式时间延迟(#n)。但序列和属性中的SVA ##延迟构造是可以存在的
  • 面向对象的测试台(testbench)结构,如类和方法
  • 晶体管、弱分配和类似的非逻辑电路元件

        通常FPV是处理可综合RTL,bind可以将不可综合的RTL和可综合RTL分离,通过适当的计划,应该能够将可综合代码与任何不可综合代码分开,以便完全启用FPV 。

2.创建覆盖点

        在一些没有太多FPV经验的项目中,覆盖点被视为FPV的事后考虑,但本书作者认为这是一个严重的错误,在FPV工具中,碰上覆盖点有助于确认,在当前设置的验证环境中,系统可能会出现期望的典型行为。(一些应用实例,FPV用户在忽略覆盖点的情况下创建了有用的断言页面,表明这些断言都是经过验证的,并告诉他们的经理,他们完成了一个主要的验证项目,但后来发现由于一些小问题,例如使用了错误的重置极性,实际验证的设计逻辑百分比为个位数。)

        为模型创建一组合理的覆盖点,开始任何FPV工作。

        对于合适的覆盖点集,没有简单的公式,因为它非常依赖于精确设计,经常想要涵盖的常见情况包括:

  • 将规范(specification)文档中的每个波形图转换为SVA序列。
  • 每个输入和输出都可以假定一组值。
  • 每种类型的事务/操作都可以成功完成
  • 状态机的每个状态都是可能的。
  • 每个队列都可以达到空状态和几乎满状态
  • 设计必须处理或报告的每种预期错误类型的示例

        不一定都会有上述怎这么多覆盖点,但必须包含以下内容:

  • lock可能locked也可能unlocked:
c1: cover property (open == 0);

c2: cover property (open == 1);
  • 表盘上的每个输入都可以合法地接受每个数字,而不会在模型中造成某种矛盾:
generate for (i=0; i<3; i++) begin
for (j=0; j<9; j++) begin
// We use a one-hot encoding
c3: cover property (digit[i][j] == 1);
end
end

3、创建假设

        创建假设:关于模型输入的基本行为的陈述,这将使FPV工具能够关注问题空间的有效部分。

        在上述组合锁示例中,一个基于四位小数中每一位的独热编码模型的输入:

input bit [9:0] digits [3:0];

        基于此建模,我们希望确保在四位插槽中的每个插槽中,只有一位处于有效状态:

generate for (i=0; i<4; i++) begin
a1: assume property ($onehot(digits[i]));
end

        对于这个模型,可能会遇到更多需要的假设,但在调试过程中会找到答案。

4、创建断言

        理想情况下,能够使用FPV工具,来确保断言对模型上所有可能的仿真(模拟)都是真实的。最初在设计中提出FPV环境时,需要记住一个重要原则:首次提出模型时,查看覆盖点痕迹比试图证明断言更重要。

        事实上,有时意外地过度约束了模型,用过度激进的假设排除了有趣的痕迹,使得断言全部经证明,并未覆盖到有风险的角落实例。覆盖点会迫使工具生成波形,代表当前验证环境支持的潜在模拟,这些覆盖点让人确信,该工具在探索证据空间。

        理想情况下,我们希望根据输入编写断言,并检查输出,我们可以使用SVA序列为正确的组合属性编写端到端断言:

sequence correct_combo_entered;
(digits == COMBO_FIRST_PART) ##1
(digits == COMBO_SECOND_PART) ##1
(digits == COMBO_THIRD_PART);
endsequence
open_good: assert property (correct_combo_entered |=> open);

        这意味着我们还需要一个断言,如果任何组合不好,它不会打开锁。我们真正想证明的是,如果三个循环组合中的任何一个部分都是错误的,锁就不会打开。因此,与其创建一个单一属性,不如创建三个更简单的属性:

open_ok2: assert property (
open |-> $past(digits,3)==COMBO_FIRST_PART);
open_ok1: assert property (
open|-> $past(digits,2)==COMBO_SECOND_PART);
open_ok0: assert property (
open |-> $past(digits,1)==COMBO_THIRD_PART);

        我们将能够直接看到哪个逻辑条件失败,而不必与多个逻辑条件混合在一起进行分析。

        使每个断言尽可能简单,且使用多个小断言而不是一个(逻辑上等价的)大断言。

5、时钟和复位

        创建FPV环境还需要两个关键的设置信息:clock和reset。

6、运行验证

        运行FPV工具然后查看结果,我们希望的结果包含以下内容:

  • 对于每个经过的覆盖点,一个示例跟踪显示一种覆盖方式
  • 对于每一个失败的断言,都会有一个示例跟踪,显示违反断言的一种方式
  • 对于每个通过的断言或失败的覆盖,一个声明表明该工具已证明它通过或不可通过
  • 具有有界证明的断言或覆盖的列表,这些断言或覆盖没有得到充分证明,但对于长度为n的所有痕迹,对于某些值为n的痕迹,都是经过验证的。

        第一次使用FPV工具,看到断言失败,不应该马上去找debug fail assertions,第一步应该做健全性检查,确保覆盖痕迹看起来合理。这里的覆盖点可以帮助我们演示一些显示预期行为的示例波形:让我们使用它们来确定行为是否合理,或者在设置环境时是否遗漏了一些关键内容。

        在debug assertion failures 之前,观察主要覆盖点的波形,确保其符合RTL的预期行为。

         上图为第一次运行的结果图。

        覆盖点c1是为了演示锁未打开的情况:

        上述设计应该需要三个周期才能进入完整的组合,但该工具声称它可以在两个周期内打开锁,存在错误。

        上图是覆盖点2打开锁的波形图。

        看看图4.7,可以看到锁是如何在循环2打开的:忘记了覆盖输入(override input),通过将此覆盖设置为1,我们可以随时打开锁。有两种主要方法可以解决这个问题:

  • 方法1:在断言和覆盖中解释override,可以做以下替换:

        c2:cover property(open == 1);

替换为:

        c2:cover property((open == 1) && !$past(override));

  • 方法2:出于验证目的忽视override,在这种情况下,只需添加一个新的假设,而不是修改每个断言和覆盖以解释override:

        fix1: assume property (override == 0);

        根据我们的验证目标,上述任一解决方案都可能是合适的。

        如果override逻辑被认为是有趣的、新的,或者是由于其他原因导致的潜在错误源,应该使用解决方案1,并在其他属性中考虑它;如果不认为override逻辑有趣或有风险,或者不想为了当前的验证而专注于它,那么解决方案2更容易实现。

        现在使用方法2,加入假设并得到c2的波形图:

         新的结果如下表所示:

         失败的断言,可以要求工具为其中一个失败的断言提供一个失败跟踪或反例,下图显示了一个用于断言open_good的断言:

        在本例中,可以对照波形中的值检查代码,以验证“数字”输入是否与代码中的常量匹配,但它们似乎不是实际打开锁的值,事实上,最初在RTL中使用的可疑规则常量{3210,3210,3210}(当从独热二进制转换为它们所代表的小数时),实际上只是占位符,不能正确定义所需的值。这在实际处理过程中很常见。

        覆盖点c2覆盖了想要的条件,显示了一个特定的波形,我们可以看到每个循环的正确值,这将导致我们设计中的锁打开,如图4.10所示:

        从这个覆盖波形可以看出,读取打开锁所需的三个周期的组合值:{2733, 0003, 2733},并更正RTL中的常数。

        这是FV能力的一个很好的证明:不需要弄清(能够得到想要结果的)详细输入,指定了一个覆盖点,FPV工具能自己找到一种方法得到想要的结果。

        一旦将常数更改为正确的值并重新运行验证,将看到表4.3所示的结果:

         可以看到属性open_good Pass,表明常数中提到的组合确实打开了锁。

        使用FPV查看其它fail的情况:

         仔细观察这个断言的相关周期上的数字输入值,发现是组合{2735},与预期的{2733}只有最后一位不同。在研究了bad1和bad0的反例之后,可以看到一个类似的问题,帮助找到了一个剩余的RTL错误,该错误实际上允许组合的最后一位使用多个可选值。

         在解决这个问题并对常数进行相关更改后,最终得到了一个完全整洁的运行,如表4.4所示:

 四、FPV不同于仿真

         FPV和仿真都是与RTL设计交互和测试的方法。

不同:

  1. 处理不同类型SVA的验证语句:assertions,assumptions,cover points。

下表显示仿真和FPV不同之处:

语句类型仿真FPV
Assertion报告当前测试中使用的任何测试值是否违反了断言报告任何一组测试值是否可能违反断言
Assumption报告当前测试中使用的任何测试值是否违反了假设使用假设来限制可能测试值的空间
Cover points报告在当前测试中使用了多少个测试值运行了cover points报告是否有可能对任何一组测试值进行覆盖点测试

         仿真工具总是在特定的测试向量上运行,检查代码中每个断言和假设的当前值是否符合预期,并检查它们是否达到覆盖点。

        FPV工具分析受假设限制的可能的仿真空间,这意味着它正在执行一项复杂的任务,并且可以发现是否有任何可能的方法违反断言或达到覆盖点。

        下表显示了在早期FPV采用过程中的一些差异:

关键差异领域仿真FPV
可以运行哪些类型和尺寸的模型全芯片级,可综合代码和行为代码。单元级或集群级,或带有大量被移除逻辑和可综合代码的完整芯片
如何达到目标行为描述过程:生成输入值以创建所需的行为描述目的:指定目标属性或状态,工具查找是否可以访问
检查哪些值具体值:仿真器根据用户指定的输入检查设计所有可能值的体系:工具分析当前约束下的合法值空间。
怎样约束模型主动约束:通过限制仿真过程中传入的值来隐式约束模型被动约束:使用假设排除所有非法情况
如何处理内部节点上的约束强制值:内部信号的活性(live)约束只影响下游逻辑反向传播+正向传播:约束在其扇入和扇出逻辑中影响可能值的范围
我们使用什么进行调试(debug)单一跟踪:当仿真失败时,需要调试仿真的内容FPV空间示例:该工具提供了一系列可能故障的示例
典型的轨迹(traces)有多长数千个周期:通常需要代表整个机器启动,并在遇到复杂的错误之前做许多随机的事情。数十个周期:FPV通常生成一条到任何目标的最小路径,从而产生更小的traces,几乎没有额外的活动

1、可以运行哪些类型和尺寸的模型

      由于其近似线性的复杂性,FPV通常必须针对集群或单元级别,建议的目标是模型大小小于40000个状态元素。

        FPV分析模型上所有可能仿真的空间,而不仅仅是特定的值,有效地提供了与在设计上运行指数级仿真相同的结果。

        如果使用更大的模型,需要使用智能技术,只关注模型的相关部分,而不是将整个模型输入工具。

        这里需要记住的关键一点是,通过使用上述技术,能够在比最初预期的大得多的模型上可靠地运行FPV,在某些情况下,在全芯片模型上执行有针对性的FPV验证任务。

2、如何达到目标行为

仿真:

        在典型仿真环境中,需要设计一个测试台(testbench),将活动值驱动到模型中,所以需要提供一个程序来决定驱动哪些随机值,然后检查这些值是否符合我们的期望条件。

        在上面的组合锁例子中,如果想找到可能会错误打开锁的替代组合,需要设计测试台来驱动大量的随机值,通过猜测找到,导致在输出端错误地看到open == 1的随机值。

        在上述所例子中,如果每次尝试打开锁都需要三个周期,在每个周期中驱动10^{4}个可能的值,那么在我们偶然发现所需结果之前,我们平均需要经历\frac{1}{2}10^{4*3}或大约5000亿个仿真周期。

        此外,即使花了所有这些仿真周期来寻找替代组合,然后修复错误,仍然不知道是否存在其他替代组合,必须运行一万亿个周期才能实现全面覆盖。

FPV:

        一旦定义了这些属性,FPV工具就可以尝试找到一些违反给定断言的合法执行轨迹(traces)。不存在需要多次迭代的问题:一次FPV运行原则上覆盖了整个验证空间。如果没有遇到复杂性问题,该工具将返回一个证明不存在此类替代组合的证据,或者一个具体的反例,显示成功打开锁的某些替代组合。

        最重要的是,一旦修复了最初的错误,并且相信不再存在其他替代组合,接下来确保RTL修复后在相同的属性上再次运行FPV,如果工具报告属性现在通过,则无需进行仿真或进一步的FPV运行。

3、检查哪些值

仿真:

        每次仿真运行都会检查通过模型驱动的一组特定值,即使在一个快速的随机仿真环境,它仍然只是检查一组特定的、有限的值,如果查看未成功打开锁的仿真运行结果,则无法确定其他值是否会成功。

FPV:

        FPV检查所有可能的值,而不仅仅是特定的值。        

        如果FPV在模型上运行完成,并声称没有无效的组合打开锁,那么在当前的模型约束下,没有一组无效值可能达到打开状态。

        如果一个模型没有受到假设的适当约束,许多不可能的执行路径也可能会被有效地检查,从而在一个不切实际的例子中,当断言失败时,会导致误判。因此,FPV工作的很大一部分将包括确定所需的约束,以确保只检查实际值,并消除错误故障。

4、怎样约束模型

        在实际验证中,通常会在驱动到模型上的实际值中增加约束、限制,约束模型的典型原因有很多:

  • 一些值无法生成
  • 有些值可能永远不会被环境选择
  • 由于用户需要遵守的文件限制,某些值可能不被允许
  • 一些值可能代表了设计的一些方面,而这些方面不是当前验证的重点

        在上面的组合锁例子中,override输入是有问题的,这个信号绕过锁机制,并强制锁打开。对于我们试图检查组合正确性问题的验证环境,我们需要将override强制为0,如上所述:

fix1: assume property (override == 0);

仿真:

        在模拟中,通常我们设置的环境仅驱动合法值到我们的信号中,在这种情况下,需要设置模拟驱动程序,以便它们始终为override信号提供值0。如果使用随机仿真,可以使用半被动的方法,比如SystemVerilog constraint 算子,这在表面上与使用正式假设类似。但即使在这种情况下,模拟器仍在驱动一组特定值。

        如果模拟测试通过,在我们的约束下,对于一些可能值的子集,我们的设计是正确的。我们无意或试图涵盖该约束下所有可能的合法值。

FPV

        在FPV中,没有设置专门驱动活动值的环境:FPV覆盖整个验证空间,我们需要添加假设以排除非法值(提供约束以消除验证中对当前一组检查无效的部分)。

        如果FPV证明成功,该工具已在给定的约束下测试了所有可能的值,它不仅检查override为0时的采样,还覆盖了所有可能的情况。

5、如何处理内部节点上的约束

       例如, 假设我们对上述组合锁出现的更大系统有一些了解,一旦三个十进制数字周期被组合并解码为内部信号上的64位二进制值,所有组合将小于一些已知值 MAX_COMBO。有没有一种简单的方法可以在内部comb信号上表示这种约束,而不必对传递到数字输入中的数字创建一组更复杂的约束?

仿真:

        可以让仿真工具直接将值驱动到内部comb节点,从而在该节点上强制使用合法值,然而组合检查器中的后续逻辑将受到新值的影响,但digit(数字)输入和解码器中的值将完全无关。当我们观察波形时,必须认识到内部组合信号上游的任何值,或同时从其源逻辑生成的并行信号,实际上都是需要忽略的垃圾值。

FPV:

        在FPV的情况下,任何约束都有效地限制了可能的仿真范围。因此约束一个内部节点,不仅会影响下游逻辑,还会有效地反向传播,导致我们只能看到其驱动程序上与约束一致的值。

        可以对组合信号进行以下简单假设:

assume property (combo <= MAX_COMBO);

        根据这一假设,在FPV环境中,digit输入上看到的任何值都是一致的:当发送到解码器块时,导致combo的合法值符合假设。

        从同一源逻辑生成的其他内部信号也是如此。

        如果很难为FPV任务编写好的输入假设,可以根据解码/中间内部信号编写假设。但这会带来风险,即驱动这些信号的逻辑并没有完全包含在我们的验证中。

6、我们使用什么进行调试(debug)

仿真:

        从随机仿真中收到的失败波形本质上是模型失败的单一实例,它显示了一次特定运行的结果,而获得一次完全不同的运行可能需要许多随机周期。

        例如,假设我们查看上述例子中的一个覆盖点波,并确定它是非法的,因为输入没有得到适当的约束以提供有效的组合。修改测试环境以解决这个问题,然后启动一组新的随机仿真,希望发现另一个失败案例。

        我们不确定是否已经正确排除了非法组合,除非在测试过程中偶然碰到了另一个坏值,或者运行了完全覆盖所需的不现实的仿真周期数。

FPV:

        由FPV运行生成的波形看起来和仿真波形相似,因为它显示了模型中随时间变化的一组具体值。但有一个关键区别:FPV波形代表了验证引擎发现的一系列可能故障。如果用户发现了想要改变的东西,比如需要一个影响输入值的假设,则其可为这个效果添加一个约束,并要求引擎重新求解。该工具将返回一个波形,该波形仍符合新约束条件下要求的覆盖案例,或者尝试证明附加假设排除了所有此类案例。

7、典型的轨迹(traces)有多长

        调试波形的典型长度

仿真:

        一个典型的仿真波形会包含上千个周期,可能会有一些复杂的模型重置,然后是许多随机或不相关的活动循环,直到达到特定的测试条件或失败。失败的实际原因可能埋在这个长期仿真的中间,实际原因的循环难以推导。在调试期间,要检查数千个数据周期,并准确确定哪些周期与当前故障特别相关,通常是非常困难的。

FPV:

        FPV中典型的失败轨迹很短,  在很多案例中复位之后仅10-20个周期, 这是因为大多数FPV引擎搜索一个可能导致断言失败的最小示例,FPV波形可以准确地到达点,而不会在当前示例不需要的随机活动上浪费额外的周期。典型的FPV工具也显示更短的重置序列,它们通常会检测到在模型状态停止改变之前所需的最小重置量,而模拟则倾向于使用更宽松的边界来确定所需的重置长度。

五、决定在哪里以及如何运行FPV

运行FPV的动机:

        首先了解何时以及为什么使用以下每种方法。

  • Design exercise FPV:使用形式化技术去探索设计的基本行为,而无需创建仿真测试台。
  • Bug hunting FPV:以同样通过仿真验证的复杂块为目标,但创建特性能检查仿真可能遗漏的
    corner cases
  • “Traditional” full proof FPV:针对复杂或有风险的设计块,创建并验证属性以验证其是否符合规范。
  • Application-specific FPV:针对设计功能的某些特定方面,例如控制寄存器、顶级调试总线连接或新功能插入,并证明此方面设计正确。

1、使用Design exercise FPV

        如果有以下情况,你应该考虑做设计练习FPV:

  • 编写新的RTL,想看其在简单案例中的表现,或者验证其基本功能
  • 想在所需的辅助(如相邻单元或测试台)准备就绪之前,做一些简单验证
  • 有一个局部设计,想看看其如何与一些已知的关于未实现部分的假设相结合
  • 有一些未完全记录的遗留RTL代码,希望了解其典型行为
  • 探索FPV在新RTL设计中的适用性,作为寻找缺陷或全面验证FPV的初步步骤

        对于新的RTL,需要在testbench已就绪之前进行早期验证,想更好地理解局部已完成的设计,需要帮助理解遗留RTL模型,或者只是开始探索验证聚焦FPV用于设计的可能性,考虑使用Design exercise FPV。

 2、使用Bug hunting FPV       

        如果有以下情况,考虑使用寻找漏洞FPV:

  • 正在设计一个包含很多corner cases的设计,并且希望获得额外的验证信心
  • 已在设计上运行了常规的仿真,其中一部分在随机测试中反复出现新错误
  • 已经在模型上做过Design exercise FPV,因此通过添加额外的目标断言来增加FPV覆盖率的成本相对较低
  • 有一个成熟的/可重用的模型,基本上不需要进一步验证,但添加了一个新特性,希望自信地进行验证

        如果正在验证一个设计有很多corner cases,在随机测试中看到很多缺陷,已经成功完成Design exercise FPV,并想做进一步验证,或者刚刚添加了一个功能到一个成熟的模型,考虑使用Bug hunting FPV。

3、使用full proof FPV

        这个使用模式,生成机制证明设计是100%正确。我们将尝试编写定义完整规范的属性,然后证明所有这些属性都适用于我们的设计。

        full proof FPV是最费力的,因为它涉及到试图完全证明设计的功能性,但也有一个好处:如果正确地运行了完整的证明,并包含了检查假设是否合理的措施,则可以确信已经完全验证了我们的RTL,并且不需要花费任何精力运行仿真或其他验证方法。

        由于full proof FPV可能是一项巨大的工作,本书作者建议我们从设计练习FPV开始,然后将其扩展到bug搜索,最后是全面验证FPV。我们的设计探索和缺陷搜索将作为初始的健全性检查,检查是否选择了适合FPV的尺寸和样式,以及对于FPV工具来说具有合理复杂度的逻辑。

        如果有以下情况,考虑使用全面验证FPV:

  • 有一份详细的参考规范,该规范预计将得到实施
  • 有一个符合标准接口的设计,其中有预先验证的FPV附加包
  • 设计由一组表定义,这些表完全概述了预期的行为
  • RTL有一部分需要防弹验证(bulletproof verification),以降低设计风险

        如果有一个详细的参考规范或表格来完全定义我们所期望的行为,那么就有标准的接口来提供大量的预先包装的FPV附加品,或者强烈要求设计中的一部分,因已知的风险而具有防弹规范,考虑full proof FPV。

4、使用Application-specific FPV

        以下是一些常见的Application-specific FPV:

  • Reusable protocol verification:使用FPV验证设计的接口行为是否符合某些已知协议,例如公共总线规范
  • Unreachable coverage elimination(不可达的覆盖排除):使用FPV识别设计中的覆盖点,这些覆盖点可以证明是不可到达的,因此可以将它们排除在仿真环境中的覆盖度量之外
  • Post-silicon bug reproduction(流片后错误再生产):使用FPV重现在流片中看到的bug非常有效果,这种用法中用户试图产生一个小的、定义良好的行为集,而不是尝试通用FPV;FPV是一种强大的方法,可以找到一条RTL能达到观察到的意外行为的合法途径
  • Top-level connectivity verification:使用FPV去验证从SOC引脚环到内部单元的顶层连接,对于一组给定的控制寄存器或其他参数值来说是否正确,虽然这种电路在逻辑上很简单,但有太多可能的组合,无法有效地通过模拟进行检查
  • Control register verification:使用FPV来检查设计中已实现的控制寄存器是否正确遵循其访问规范,例如,有些可能是只读的,有些可能是只读的,或者有些可能只能在特定条件下访问

          为block设置通用FPV环境之前,请检查当前正在解决的问题是否存在特定于域的解决方案

  • 11
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值