- 是什么?
RAL Model 对应于 DUT 中的寄存器,RAL Model 中有 DUT 每一个 寄存器的副本,它是真实硬件寄存器在软件环境中的行为模型;硬件寄存器的一个或多个 bit 的拼接称为一个域 ( field );多一个 field 形成一个 reg;多个 reg 构成一个块 ( block )。uvm library 已经为我们定义好了上述几个概念,我们在使用时只需继承即可。
- 优势?
a.方便对 DUT 中寄存器进行读写;
b.在软件仿真时,可以不耗时的获取寄存器的值(直接从 RAL Model 中获取);
c.可以很方便的正对寄存器的 coverage 验证点的收集。
RAL Model
task my_model::main_phase(uvm_phase phase);
…
reg_model.version.read(status, value, UVM_FRONTDOOR);
reg_model.version.write(status, value, UVM_FRONTDOOR);
…
endtask
只要一条语句就可以实现上述复杂的过程。像启动 sequence 及将读取结果返回这些事情,都会由寄存器模型来自动完成。在没有寄存器模型之前,只能启动 sequence 通过前门(FRONTDOOR)访问的方式来读取寄存器,局限较大,在 scoreboard(或者其他 component )中难以控制。而有了寄存器模型之后,scoreboard 只与寄存器模型打交道,无论是发送读的指令还是获取读操作的返回值,都可以由寄存器模型完成。有了寄存器模型后,可以在任何耗费时间的phase中使用寄存器模型以前门访问或后门(BACKDOOR)访问的方式来读取寄存器的值,同时还能在某些不耗费时间的 phase(如 check_phase)中使用后门访问的方式来读取寄存器的值。
使用ralgen自动产生sv文件
一般寄存器模型的代码是不用自己写的,有很多专门的工具可以生成,例如s家的工具 ralgen
配置文件demo.ralf 如下
block b1 {
bytes 3;
register r {
bytes 1;
field WDT_EN @'h5 {
bits 1;
reset 'h0;
access rw;
enum { ENABLE = 1, DISABLE = 0 };
}
field DATA_TEST @'h5 {
bits 2;
reset 'h0;
access rw;
enum { ENABLE = 1, DISABLE = 0 };
}
}
}
使用命令
ralgen -t b1 -embed_enum_in_flds -uvm demo.ralf
生成文件如下
`ifndef RAL_B1
`define RAL_B1
import uvm_pkg::*;
class ral_fld_b1_r_WDT_EN extends uvm_reg_field;
`uvm_object_utils(ral_fld_b1_r_WDT_EN)
function new(string name = "WDT_EN");
super.new(name);
endfunction : new
typedef enum bit[0:0] {
ENABLE = 1,
DISABLE = 0
} WDT_EN_values;
endclass : ral_fld_b1_r_WDT_EN
class ral_fld_b1_r_DATA_TEST extends uvm_reg_field;
`uvm_object_utils(ral_fld_b1_r_DATA_TEST)
function new(string name = "DATA_TEST");
super.new(name);
endfunction : new
typedef enum bit[1:0] {
ENABLE = 1,
DISABLE = 0
} DATA_TEST_values;
endclass : ral_fld_b1_r_DATA_TEST
class ral_reg_b1_r extends uvm_reg;
rand ral_fld_b1_r_WDT_EN WDT_EN;
rand ral_fld_b1_r_DATA_TEST DATA_TEST;
function new(string name = "b1_r");
super.new(name, 8,build_coverage(UVM_NO_COVERAGE));
endfunction: new
virtual function void build();
this.WDT_EN = ral_fld_b1_r_WDT_EN::type_id::create("WDT_EN",,get_full_name());
this.WDT_EN.configure(this, 1, 5, "RW", 0, 1'h0, 1, 0, 0);
this.DATA_TEST = ral_fld_b1_r_DATA_TEST::type_id::create("DATA_TEST",,get_full_name());
this.DATA_TEST.configure(this, 2, 5, "RW", 0, 2'h0, 1, 0, 0);
endfunction: build
`uvm_object_utils(ral_reg_b1_r)
endclass : ral_reg_b1_r
class ral_block_b1 extends uvm_reg_block;
rand ral_reg_b1_r r;
rand ral_fld_b1_r_WDT_EN r_WDT_EN;
rand ral_fld_b1_r_WDT_EN WDT_EN;
rand ral_fld_b1_r_DATA_TEST r_DATA_TEST;
rand ral_fld_b1_r_DATA_TEST DATA_TEST;
function new(string name = "b1");
super.new(name, build_coverage(UVM_NO_COVERAGE));
endfunction: new
virtual function void build();
this.default_map = create_map("", 0, 3, UVM_LITTLE_ENDIAN, 0);
this.r = ral_reg_b1_r::type_id::create("r",,get_full_name());
this.r.configure(this, null, "");
this.r.build();
this.default_map.add_reg(this.r, `UVM_REG_ADDR_WIDTH'h0, "RW", 0);
this.r_WDT_EN = this.r.WDT_EN;
this.WDT_EN = this.r.WDT_EN;
this.r_DATA_TEST = this.r.DATA_TEST;
this.DATA_TEST = this.r.DATA_TEST;
endfunction : build
`uvm_object_utils(ral_block_b1)
endclass : ral_block_b1
`endif
backup:
包括各个寄存器字段描述、寄存器、寄存器组、寄存器地址映射等信息。
前门和后门访问
前门访问需要adapter