寄存器模型概览
硬件中的各个功能模块可以由处理器来配置功能以及访问状态,而与处理器的对话即是通过寄存器的读写来实现的。
寄存器的硬件实现是通过触发器,而每一个比特位的触发器都对应着寄存器的功能描述(function specification)。一个寄存器一般由32个比特位构成,将单个寄存器拆分后,又可以分为多个域(field),不同的域往往代表着某一项独立的功能。单个的域可能由多个比特位构成,也可能有单一比特位构成,这取决于该域的功能模式可配置的数量。
而不同的域,对于外部的读写而言,又大致可以分为WO(write-only,只写),RO(read-only,只读), RW(read and write,读写),除了这些常见的操作属性以外,还有一些特殊行为(quirky)的寄存器,例如读后擦除模式(clean-on-read,RC),只写一次模式(write-one-to-set,W1S)。
MCDF的寄存器模块描述,将0x00功能寄存器和0x10状态寄存器位用图来表示。通常来讲,一个寄存器有32位宽,寄存器按照地址索引的关系式按字对其(word-align)的,上图中的寄存器有多个域,每个域的属性也可以不相同,reserved域表示的是该域所包含的比特位暂时保留以作日后功能的扩展使用,而对保留域的读写不起任何作用,即无法写入而且读出值也是它的复位值。
上面的这些寄存器按照地址排列,即可构成寄存器列表,我们称之为寄存器块(register block)。实际上寄存器模块除了包含寄存器,也可以包含存储器,因为它们的属性都近乎于读写功能,以及表示为同外界通信的接口。
将这些寄存器有机的组合在一起,MCDF的寄存器功能模块即可由这样一个register block来表示:
一个寄存器可以由多个域构成,而单个域可以包含多个比特位;一个功能模块中的多个寄存器可以组团构成一个寄存器模型(register model)。上图中除了包含DUT的寄存器模块(由硬件实现),还有属于验证环境的寄存器模型。
这两个模块包含的寄存器信息是高度一致的,属于验证环境的寄存器模型也可以抽象出一个层次化的寄存器列表,该列表所包含的地址、域、属性等信息都与硬件一侧的寄存器内容一致。
对于功能验证而言,可以将总线访问寄存器的方式抽象为寄存器模型访问的方式,这种方式使得寄存器后期的地址修改(例如基地址更改)或者域的添加都不会对已有的激励构成影响,从而提高已有的测试序列的复用性。
中心化管理方式
中心化管理的寄存器描述文件,可以使通过软件建立寄存器模型和硬件寄存器的内容属性保持一致,通常使用XML格式的寄存器描述文件,或Execl(CSV)和DOC格式。采用中心化管理的原因是单一源的管理方式可以尽量降低出现分歧或错误的可能。
寄存器描述文档使用了结构化的文档描述方式,通过数据结构化的存储方式,可以在硬件和软件开发过程中以不同的方式来使用寄存器描述文档:
- 系统工程师会撰写并维护寄存器描述文件,而后归置到中心化存储路径供其他的工程师使用。
- 硬件工程师会利用寄存器描述文档生成寄存器硬件模块(包含各个寄存器的硬件实现和总线访问模块)。
- 验证工程师会利用寄存器描述文档来生成UVM寄存器模型,一共验证过程中的激励使用、寄存器测试和功能覆盖率收集。
- 软件工程师会利用该文件生成用于软件开发的寄存器配置的头文件(header file),从而提高软件开发的可维护性。
- 寄存器描述文件也可以用来生成文档,实现更好的可读性。
uvm_reg相关概念
在构建UVM寄存器模型的过程中,需要了解与模型构建相关的类和他们的功能:
类名 | 功能 |
---|---|
uvm_reg_field | 用来针对寄存器功能域来构建对应的比特位 |
uvm_reg | 与寄存器相匹配,其内部可以例化和配置多个uvm_reg_field对象 |
uvm_mem | 匹配硬件存储模型 |
uvm_reg_map | 用来指定寄存器列表中各个寄存器的偏移地址访问属性以及对应的总线 |
uvm_reg_block | 可以容纳多个寄存器(uvm_reg)、存储器(uvm_mem),寄存器列表(uvm_reg_map) |
MCDF寄存器模型实例
class ctrl_reg extends uvm_reg;
`uvm_object_utils(ctrl_reg)
uvm_reg_field reserved;
rand uvm_reg_field pkt_len;
rand uvm_reg_field prio_level;
rand uvm_reg_field chnl_en;
function new(string name = "ctrl_reg");
super.new(name, 32, UVM_NO_CONVERAGE);
endfunction
virtual function build();
reserved = uvm_reg_field::type_id::create("reserved");