当前位置: 首页 > news >正文

第18篇 :深入剖析systemverilog中 randomize 失败案例启示录(二)

今天我们继续修改之前的例子,你会有意想不到的收获。程序源代码,和上一节文章一样。

症状3:

这里,我们没有显式调用类的randomize() 函数,而是定义了一个类函数。在函数中 ,重新约束了类内的随机变量。请看如下代码:

`timescale 1ns/1ps 
`include "uvm_macros.svh"
import uvm_pkg::*;class my_obj1 extends uvm_test;`uvm_component_utils(my_obj1)rand int  src=4;rand int dst;constraint dst_c {dst inside {[7:9]};}rand bit [3:0]  crc = 4'b0111;constraint crc_c {crc inside {5,6,7,8};}function new(string name = "my_obj1" , uvm_component parent = null );super.new(name, parent);endfunction // newextern virtual function print ();extern virtual function pure_print ();virtual task run_phase(uvm_phase phase);super.run_phase(phase);endtask endclass //function my_obj1::print();randomize (src)   with {(src) inside {[5:5]};} ;  // 新增代码,意图重新约束src变量`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunctionfunction my_obj1::pure_print();`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunction
//module tb();import uvm_pkg::*;
`include "uvm_macros.svh"initial beginrun_test("my_obj1");endendmodule // tb

运行仿真代码,得到如下仿真结果: dst 结果为0, 也即是声明初始化的初始化值; 而且仿真抛出异常Error-

奇怪? 为什么没有进行预期[7:9]的随机取值呢?而且,我们明明是在调用randomize(src) 进行随机src 变量,为什么报错的是 dst 变量呢?

 源代码修改:

修改前:

    randomize (src)   with {(src) inside {[5:5]};} ;

修改后方案A: 

    std::randomize (src)   with {(src) inside {[5:5]};} ;

修改后的仿真结果:符合预期。 

 修改后方案B: 增加this.randomize() 的类函数显式调用,并保持程序源代码其它一致。

仿真结果: PASS。 通过增加 this.randomize() 的调用,其它代码均没有改变。我们得到预期的仿真结果。这里为什么?因为:首先如前面文章讲述,经过显式randomize() 调用之后,dst 的取值为8;后执行     randomize (src)   with {(src) inside {[5:5]};} ;   时候,会重新对 randomize() 的所有对象进行随机求解,此时 dst = 8, 在 【7:9】范围之内,所有不会报错。最后,经过此次随机,只会更改 src 的数值。

分析3: 

(1)其实,这里我们犯了一个错误,在systemverilog 标准语法说中,从头至尾没有提到: randomize (src)   with {(src) inside {[5:5]};} ; 该随机化方式。也即是:通过调用类的内置函数 randomize(xxx) with {},可以去单独随机类中的某一个变量。

(2)所以,我们很自然想到一种解决办法,那就是调用 systemverilog 的内置 std::randomize() with 的方式,去随机特定某一个变量。这样做,仿真预期,没有发生错误。

(3)再分析:为什么我们调用的是 randmozie(src), 而报错的是 dst 求解失败呢?

         答: 这里虽然是对src变量特定去随机,但是求解器,内部还是会对类的所有随机变量进行求解评估的。如果某些变量求解失败,会抛出异常错误的。

         这个问题是关于SystemVerilog中的约束随机化。在你的代码中,你尝试对src进行随机化,但是报错是关于dst的约束求解失败。

         出现这个错误的原因可能是在my_obj1类的实例化或随机化过程中,dst的约束dst_cdst的初始值或其他约束产生了冲突。SystemVerilog的约束求解器试图满足所有约束,但当它不能满足所有约束时,就会报错。

         在你的代码中,dst的约束dst_c要求其值在7到9之间,但如果dst的初始值0(在你的代码中未显示)不在这个范围内,或者在随机化过程中其他约束改变了dst的值并使其超出了这个范围,那么约束求解器就会失败。

(4)再分析:针对增加 this.randomize()的方案,在最后一次 randomize(src)的时候,返回结果并没有更新 dst.。说明:randmoize(xxx) with {} 还是可以针对某一随机变量进行随机化操作的。这里与(1)描述似乎存在矛盾,而又不矛盾。

(5)另外,需要注意:这里我们发现 dst 的两次随机,结果没有发生更改。 因为:调用randomize(src)的时候,只会评估dst 的约束求解,并不会更改上一次的随机值。

症状4:

我们在源代码基础之上,修改如下代码:增加对 src 随机变量的 constraint 块约束。

`timescale 1ns/1ps 
`include "uvm_macros.svh"
import uvm_pkg::*;class my_obj1 extends uvm_test;`uvm_component_utils(my_obj1)rand int  src=4;constraint src_c {src inside {[0:3]};}rand int dst=0;constraint dst_c {dst inside {[7:9]};}rand bit [3:0]  crc = 4'b0111;constraint crc_c {crc inside {5,6,7,8};}function new(string name = "my_obj1" , uvm_component parent = null );super.new(name, parent); endfunction // newextern virtual function print ();extern virtual function pure_print ();virtual task run_phase(uvm_phase phase);super.run_phase(phase);this.print();endtask endclass //function my_obj1::print();randomize (src)   with {(src) inside {[5:5]};} ;`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunctionfunction my_obj1::pure_print();`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunction
//module tb();import uvm_pkg::*;
`include "uvm_macros.svh"initial beginrun_test("my_obj1");endendmodule // tb

聪明的朋友们,对于上面的错误,相比大家都已经很清楚了。因为本篇内容的症状3已经做了分析。

但是,我们还是想做点什么。 

修改后:

 分析4:

通过增加this.randomzie(),  仿真可以跑通。这里不过多解释。我们想知道,为什么会发生冲突呢?

这个问题是因为SystemVerilog中的约束随机化的时候,会对相应随机变量的所有牵连约束,进行综合考量。如下三处之间产生了冲突。

第一处:

   rand int  src=4;

第二处:
   constraint src_c {
      src inside {[0:3]};
   }

第三处:

   randomize (src)   with {(src) inside {[5:5]};} ;

所以,我们不要认为:后面的约束会覆盖前面的约束。也即是:第三处约束,会覆盖第二处的约束。这是错误的认识。 覆盖的问题,我们稍后讲解。


http://www.mrgr.cn/news/69660.html

相关文章:

  • JavaAPI(2)
  • 关于git使用的图文教程(包括基本使用,处理冲突问题等等)超详细
  • 在.NET中正确捕获C++程序的cout输出
  • Qt_day4_Qt_UI设计
  • 互联网基础思维
  • 小白速成教程:私有化大模型+知识库
  • 深入解析Python的上下文管理器与资源管理:实现自定义的with语句
  • 简记Vue3(五)—— Pinia
  • windows定时闹钟
  • 丹摩征文活动 |丹摩智算平台:网络安全的守护与挑战
  • 胶囊网络、MobileNet、坐标注意力机制的应用
  • 【大语言模型】ACL2024论文-08 统一的时间知识图谱推理模型:插值与外推
  • 【51单片机输出50ms与200ms方波】
  • [CKS] K8S NetworkPolicy Set Up
  • AI做小红小绿书,自动配图+文案(Coze工作流)
  • 多元正态分布的参数估计1
  • C++ 越来越像函数式编程了!
  • ACL 2024亮点:RAG技术进展与论文解析
  • Js — 节流及底层实现
  • GNN - Transformer 新突破 —— 解锁全局与局部的完美融合!