本篇不是最近总结系列的一部分,只不过因为跟前两篇的讨论内容一脉相承,因此放在一起吧。
本篇可以视为继续上一篇的讨论,对于不关键的配置寄存器我们可以通过白噪声的方式来提高系统健壮性测试和覆盖率收集速度,那么对于关键的不能带流改配的配置寄存器,应该如何尽可能的覆盖所有可能场景?此外,目前基于sv的验证方法学均为随机验证而非定向验证,那么对于寄存器配置而言,应该如何体现随机验证思想呢?
寄存器域的随机性
使用ralgen生成的寄存器本身是rand属性的,也就是说其自身是可以通过约束随机的方式在用例中进行随机性配置的,比如下面这个寄存器:
class ral_reg_REG_PRJ_sys_cfg_base_config extends uvm_reg;
rand uvm_reg_field mode;
rand uvm_reg_field kernel_size;
rand uvm_reg_field stride;
function new(string name = "REG_PRJ_sys_cfg_base_config");
super.new(name, 32,build_coverage(UVM_NO_COVERAGE));
endfunction: new
virtual function void build();
this.mode = uvm_reg_field::type_id::create("mode",,get_full_name());
this.mode.configure(this, 2, 0, "RW", 1, 2'h0, 1, 1, 0);
this.kernel_size = uvm_reg_field::type_id::create("kernel_size",,get_full_name());
this.kernel_size.configure(this, 20, 2, "RW", 1, 20'hab, 1, 1, 0);
this.stride = uvm_reg_field::type_id::create("stride",,get_full_name());
this.stride.configure(this, 3, 22, "RW", 1, 3'h1, 1, 1, 0);
endfunction: build
`uvm_object_utils(ral_reg_REG_PRJ_sys_cfg_base_config)
endclass : ral_reg_REG_PRJ_sys_cfg_base_config
this.mode.configure(this, 2, 0, "RW", 1, 2'h0, 1, 1, 0);
ralgen -all_fields_rand -full64 -t top_module -I reg -uvm top_module.ralf
寄存器随机的策略选择
基于对配置寄存器进行随机的思路,在用例中通常来说我们有两种策略选择:
这两种方式没有对错之分,个人而言我觉得第二种方式更加符合随机测试的本质,更加容易冲击到各类配置组合的场景,所以选取了第二种随机策略。那么基于这种策略,应当如何对组织寄存器呢?要明确的是,即使对所有寄存器进行全随机,一般而言也不是不加约束的随机。比如某个field的位宽为3bit,而只允许配置0~5这6种情况,6/7为禁止配置值,那么就需要对这个field添加额外的constraint。鉴于大部分寄存器其实都是这个情况,尤其很多寄存器之间还有关联约束(reg A == 0 -> reg B == 2),因此从生成的uvm_reg_block派生出一个新的reg_block无疑是个很好的选择。对于派生的reg_block,其基本的内容如下:
class rand_ral_block_REG_PRJ_sys_cfg extends ral_block_REG_PRJ_sys_cfg;
function new(string name = "rand_ral_block_REG_PRJ_sys_cfg");
super.new(name);
endfunction
constraint field_value_cons{
this.base_config_mode.value dist {'0:/10, ['0:'1]:/80, '1:/10}; //default: 2'h0
this.base_config_stride.value dist {'0:/10, ['0:'1]:/80, '1:/10}; //default: 3'h1
this.cfg_info0_layer_field0.value dist {'0:/10, ['0:'1]:/80, '1:/10}; //default: 3'h1
...
this.cal_config_cal_round.value dist {'0:/10, ['0:'1]:/80, '1:/10}; //default: 3'h0
this.cal_config_cvt_mode.value dist {'0:/10, ['0:'1]:/80, '1:/10}; //default: 3'h0
}
`uvm_object_utils(rand_ral_block_REG_PRJ_sys_cfg)
endclass: rand_ral_block_REG_PRJ_sys_cfg
每个field的随机策略均是,最大值最小值各占10%,中间区域共占80%。之后基于这个全随机的子类,需要去梳理每个field真正的随机情况并修改派生的ral_model,比如增加约束:
this.base_config_mode.value == 1'b1 -> this.base_config_stride.value == 2;
this.base_config_mode.value == 1'b0 -> this.base_config_stride.value dist {1:/10, 2:/10};
脚本化操作
基于以上的策略,对于每一个ral_model.sv可以进行脚本化操作,在同目录下生成rand_ral_model.sv文件,脚本使用为:
./gen_ral_rand.py xx/xx/ral_model.sv
set_type_override_by_type(ral_block_XXXXX::get_type(), rand_ral_block_XXXXX::get_type());
系列文章入口——
【芯片验证】sva_assertion: 15道助力飞升的断言练习 |
【芯片验证】可能是RTL定向验证的巅峰之作 |
【芯片验证】RTL仿真中X态行为的传播 —— 从xprop说起 |
【芯片验证】年轻人的第一个systemVerilog验证环境全工程与解析 |
【芯片设计】verilog中有符号数和无符号数的本质探究 |
【芯片设计】论RTL中always语法的消失术 |
【芯片设计】代码即注释,注释即代码 |
【芯片设计】700行代码的risc处理器你确实不能要求太多了 |
入职芯片开发部门后,每天摸鱼之外的时间我们要做些什么呢 |
如何计算系统的outstanding 和 burst length? |
芯片搬砖日常·逼死强迫症的关键词不对齐事件 |
熟人社会里,一群没有社会价值的局外人 |