(二)UVM_RAL 寄存器模型之基础夯实

目录

一,为何应用寄存器模型

二,寄存器模型基础概念

2.1  uvm_reg_field

2.2  uvm_reg

2.3  uvm_reg_block

2.4  uvm_reg_map

2.5  uvm_reg_file

2.6  uvm_mem

三,一个完备的寄存器模型

三, 如何instance到UVM验证环境


RAL(Register Abstract Layer,寄存器抽象层),也被称之为寄存器模型,顾名思义就是对寄存器这个部件的建模。本文主要内容包括:为何应用寄存器模型,UVM寄存器模型基础概念,如何构建寄存器模型,如何将寄存器模型实例到验证环境中。

一,为何应用寄存器模型

前面,我们提到,寄存器的使用,在如今的design 中十分普遍。对于实际的DUT, 我们可以选择不同的配置组合,达到DUT 实现不同的功能,比如配置不同的寄存器功能,实现不同的状态机跳转,进而实现不同的功能。有些人把这种design 方式,称之为 基于寄存器的设计。我们身为DV人员,当然着重关注我们验证人员该关注的事情。

寄存器设计,作为DUT 设计的一部分,当然在整个design Verification 过程中,也是验证人员必须面对和打交道的一部分。对REG 的读写配置,包括验证覆盖率的统计,都是值得验证人员该花功夫考虑的问题,也是项目signoff 阶段,项目验收的环节之一。

大部分DUT设计,对于内部寄存器的access, 大部分公司都会选择当今比较流行总线方式。一方面,选取标准的寄存器配置总线协议,可以加速项目迭代;另一方面,选取标准的协议,一般都会购买第三方IP,可以保证很好的quality。比如:I2C,SPI,AXI,AHB 、APB等总线 ,复杂到PCIE、SATA、GMI 等复杂协议。

实际激励中,不仅包括接口正常transaction,还有寄存器的读写激励,所以有必要针对寄存器的access , 构建寄存器访问机制,方便验证环境的搭建和集成,加速项目的验收。

为什么要对寄存器建模,可能是初学者问得较多的问题。简单地说,寄存器建模要做的事情,就是在软件的世界里面,复刻RTL中的寄存器。既然是面向软件世界做的事情,自然就是为软件所用要么方便软件观测,要么方便软件使用。这里的软件,指的是整个验证环境所构造出来的面向对象的世界。有了寄存器模型,软件世界中的参考模型(reference model)可以很方便的获取到当前RTL的功能配置和状态,也可以很方便的收集到对寄存器各个域段甚至位的测试覆盖情况等。

二,寄存器模型基础概念

2.1  uvm_reg_field

这是寄存器模型中的最小单位。什么是reg_field?假如有一个状态寄存器,

 如上的状态寄存器共有四个域,分别是empty、full、overflow、underflow。这四个域对应寄存器模型中的uvm_reg_field。名字reserved”的并不是一个域。

uvm_reg_field 源码分析: 

1)属性声明

2)方法声明

2.2  uvm_reg

它比uvm_reg_field高一个级别,依然是比较小的单位。一个寄存器中至少包一个uvm_reg_field。

uvm_reg源码概览: 

1)属性声明

2)方法声明

   extern virtual function void set_offset (uvm_reg_map    map,
   /*local*/ extern virtual function void set_parent (uvm_reg_block blk_parent,
   /*local*/ extern virtual function void add_field  (uvm_reg_field field);
   /*local*/ extern virtual function void add_map    (uvm_reg_map map);
   extern virtual function string get_full_name();
   extern virtual function uvm_reg_block get_parent ();
   extern virtual function uvm_reg_block get_block  ();
   extern virtual function uvm_reg_file get_regfile ();
   extern virtual function int get_n_maps ();
   extern virtual function void get_maps (ref uvm_reg_map maps[$]);
   /*local*/ extern virtual function uvm_reg_map get_local_map   (uvm_reg_map map,
   /*local*/ extern virtual function uvm_reg_map get_default_map (string caller = "");
   extern virtual function string get_rights (uvm_reg_map map = null);
   extern virtual function int unsigned get_n_bits ();
   extern virtual function int unsigned get_n_bytes();
   extern virtual function void get_fields (ref uvm_reg_field fields[$]);
   extern virtual function uvm_reg_field get_field_by_name(string name);
   extern virtual function uvm_reg_addr_t get_offset (uvm_reg_map map = null);
   extern virtual function uvm_reg_addr_t get_address (uvm_reg_map map = null);
   extern virtual function int get_addresses (uvm_reg_map map = null,
   extern virtual function void set (uvm_reg_data_t  value,
   extern virtual function uvm_reg_data_t  get(string  fname = "",
   extern virtual function uvm_reg_data_t  get_mirrored_value(string  fname = "",
   extern virtual function bit needs_update(); 
   extern virtual function void reset(string kind = "HARD");
   extern virtual function uvm_reg_data_t
   extern virtual function bit has_reset(string kind = "HARD",
   extern virtual function void
   extern virtual task write(output uvm_status_e      status,
   extern virtual task read(output uvm_status_e      status,
   extern virtual task poke(output uvm_status_e      status,
   extern virtual task peek(output uvm_status_e      status,
   extern virtual task update(output uvm_status_e      status,
   extern virtual task mirror(output uvm_status_e      status,
   extern virtual function bit predict (uvm_reg_data_t    value,
   /*local*/ extern virtual function bit Xcheck_accessX
   extern virtual function bit do_check(uvm_reg_data_t expected,
   extern virtual task do_write(uvm_reg_item rw);
   extern virtual task do_read(uvm_reg_item rw);
   extern virtual function void do_predict
   extern virtual task backdoor_read(uvm_reg_item rw);
   extern virtual task backdoor_write(uvm_reg_item rw);
   extern virtual function uvm_status_e backdoor_read_func(uvm_reg_item rw);
   extern virtual protected function void add_coverage(uvm_reg_cvr_t models);
   extern virtual function bit has_coverage(uvm_reg_cvr_t models);
   extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on);
   extern virtual function bit get_coverage(uvm_reg_cvr_t is_on);
   extern virtual function void            do_print (uvm_printer printer);
   extern virtual function string          convert2string();
   extern virtual function uvm_object      clone      ();
   extern virtual function void            do_copy    (uvm_object rhs);
   extern virtual function bit             do_compare (uvm_object  rhs,
   extern virtual function void            do_pack    (uvm_packer packer);
   extern virtual function void            do_unpack  (uvm_packer packer);

2.3  uvm_reg_block

它是一个比较大的单位,在其中可以加入许多的uvm_reg,也可以加入其他的uvm_reg_block。一个寄存器模型中至少包含一个uvm_reg_block。

同uvm_reg派生的类一样,每一个由uvm_reg_block派生的类也要定义一个build函数,一般在此函数中实现所有寄存器的实例化。

一个uvm_reg_block中一定要对应一个uvm_reg_map,系统已经有一个声明好的default_map,只需要在build中将其实例化。这个实例化的过程并不是直接调用uvm_reg_map的new函数,而是通过调用uvm_reg_block的create_map来实现,create_map有众多的参数,其中第一个参数是名字,第二个参数是基地址,第三个参数则是系统总线的宽度,这里的单位是byte而不是bit,第四个参数是大小端,最后一个参数表示是否能够按照byte寻址

随后实例化invert并调用invert.configure函数。这个函数的主要功能是指定寄存器进行后门访问操作时的路径。其第一个参数是此寄存器所在uvm_reg_block的指针,这里填写this,第二个参数是reg_file的指针(7.4.2节将会介绍reg_file的概念)这里暂时填写null,第三个参数是此寄存器的后门访问路径,关于这点请参考7.3节,这里暂且为空。当调用完configure时,需要手动调用
invert的build函数,将invert中的域实例化。
 

最后一步则是将此寄存器加入default_map中。uvm_reg_map的作用是存储所有寄存器的地址,因此必须将实例化的寄存器加入default_map中,否则无法进行前门访问操作。add_reg函数的第一个参数是要加入的寄存器,第二个参数是寄存器的地址,这里是16’h9,第三个参数是此寄存器的存取方式。

uvm_reg_block 源码概览:

1)属性声明

2)方法声明

   extern virtual function uvm_reg_map create_map(string name,
   extern virtual function void set_parent(uvm_reg_block parent);
   extern virtual function void lock_model();
   extern virtual function string get_full_name();
   extern virtual function uvm_reg_block get_parent();
   extern virtual function void get_blocks (ref uvm_reg_block  blks[$],
   extern virtual function void get_maps (ref uvm_reg_map maps[$]);
   extern virtual function void get_registers (ref uvm_reg regs[$],
   extern virtual function void get_fields (ref uvm_reg_field  fields[$],
   extern virtual function void get_memories (ref uvm_mem mems[$],
   extern virtual function void get_virtual_registers(ref uvm_vreg regs[$],
   extern virtual function void get_virtual_fields (ref uvm_vreg_field fields[$],
   extern virtual function uvm_reg_block get_block_by_name (string name);  
   extern virtual function uvm_reg_map get_map_by_name (string name);
   extern virtual function uvm_reg get_reg_by_name (string name);
   extern virtual function uvm_reg_field get_field_by_name (string name);
   extern virtual function uvm_mem get_mem_by_name (string name);
   extern virtual function uvm_vreg get_vreg_by_name (string name);
   extern virtual function uvm_vreg_field get_vfield_by_name (string name);
   extern virtual protected function void add_coverage(uvm_reg_cvr_t models);
   extern virtual function bit has_coverage(uvm_reg_cvr_t models);
   extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on);
   extern virtual function bit get_coverage(uvm_reg_cvr_t is_on = UVM_CVR_ALL);
   extern virtual function void sample_values();
   extern virtual function uvm_path_e get_default_path();
   extern virtual function void reset(string kind = "HARD");
   extern virtual function bit needs_update();
   extern virtual task update(output uvm_status_e       status,
   extern virtual task mirror(output uvm_status_e       status,
   extern virtual task write_reg_by_name(
   extern virtual task read_reg_by_name(
   extern virtual task write_mem_by_name(
   extern virtual task read_mem_by_name(
   extern virtual task readmemh(string filename);
   extern virtual task writememh(string filename);
   extern virtual function void   do_print      (uvm_printer printer);
   extern virtual function void   do_copy       (uvm_object rhs);
   extern virtual function bit    do_compare    (uvm_object  rhs,
   extern virtual function void   do_pack       (uvm_packer packer);
   extern virtual function void   do_unpack     (uvm_packer packer);
   extern virtual function string convert2string ();
   extern virtual function uvm_object clone();

2.4  uvm_reg_map

每个寄存器在加入寄存器模型时都有其地址,uvm_reg_map就是存储这些地址,并将其转换成可以访问的物理地址(因为加入寄存器模型中的寄存器地址一般都是偏移地址,而不是绝对地址)。当寄存器模型使用前门访问方式来实现读或写操作时,uvm_reg_map就会将地址转换成绝对地址,启动一个读或写的sequence,并将读或写的结果返回。在每个reg_block内部,至少有一个(通常也只有一个)uvm_reg_map。

   extern virtual function void add_reg (uvm_reg           rg,
   extern virtual function void add_mem (uvm_mem        mem,
   extern virtual function void add_submap (uvm_reg_map    child_map,
   extern virtual function void set_sequencer (uvm_sequencer_base sequencer,
   extern virtual function void set_submap_offset (uvm_reg_map submap,
   extern virtual function uvm_reg_addr_t get_submap_offset (uvm_reg_map submap);
   extern virtual function void   set_base_addr (uvm_reg_addr_t  offset);
   extern virtual function void reset(string kind = "SOFT");
   /*local*/ extern virtual function void add_parent_map(uvm_reg_map  parent_map,
   /*local*/ extern virtual function void Xverify_map_configX();
   /*local*/ extern virtual function void m_set_reg_offset(uvm_reg   rg,
   /*local*/ extern virtual function void m_set_mem_offset(uvm_mem mem,
   extern virtual function string get_full_name();
   extern virtual function uvm_reg_map get_root_map();
   extern virtual function uvm_reg_block get_parent();
   extern virtual function uvm_reg_map           get_parent_map();
   extern virtual function uvm_reg_addr_t get_base_addr (uvm_hier_e hier=UVM_HIER);
   extern virtual function int unsigned get_n_bytes (uvm_hier_e hier=UVM_HIER);
   extern virtual function int unsigned get_addr_unit_bytes();
   extern virtual function uvm_endianness_e get_endian (uvm_hier_e hier=UVM_HIER);
   extern virtual function uvm_sequencer_base get_sequencer (uvm_hier_e hier=UVM_HIER);
   extern virtual function uvm_reg_adapter get_adapter (uvm_hier_e hier=UVM_HIER);
   extern virtual function void  get_submaps (ref uvm_reg_map maps[$],
   extern virtual function void  get_registers (ref uvm_reg regs[$],
   extern virtual function void  get_fields (ref uvm_reg_field fields[$],
   extern virtual function void  get_memories (ref uvm_mem mems[$],
   extern virtual function void  get_virtual_registers (ref uvm_vreg regs[$],
   extern virtual function void  get_virtual_fields (ref uvm_vreg_field fields[$],
   extern virtual function uvm_reg_map_info get_reg_map_info(uvm_reg rg,  bit error=1);
   extern virtual function uvm_reg_map_info get_mem_map_info(uvm_mem mem, bit error=1);
   extern virtual function int unsigned get_size();
   extern virtual function int get_physical_addresses(uvm_reg_addr_t        base_addr,
   extern virtual function uvm_reg get_reg_by_offset(uvm_reg_addr_t offset,
   extern virtual function uvm_mem    get_mem_by_offset(uvm_reg_addr_t offset);
   extern virtual task do_bus_write (uvm_reg_item rw,
   extern virtual task do_bus_read (uvm_reg_item rw,
   extern virtual task do_write(uvm_reg_item rw);
   extern virtual task do_read(uvm_reg_item rw);
   extern virtual function string      convert2string();
   extern virtual function uvm_object  clone();
   extern virtual function void        do_print (uvm_printer printer);
   extern virtual function void        do_copy   (uvm_object rhs);
   //extern virtual function bit       do_compare (uvm_object rhs, uvm_comparer comparer);
   //extern virtual function void      do_pack (uvm_packer packer);
   //extern virtual function void      do_unpack (uvm_packer packer);

2.5  uvm_reg_file

UVM还提供了uvm_reg_file类。这个类更像是一个对象容器,可以用来装载多个寄存器(uvm_reg)和其他uvm_reg_file,以便对相同规格的寄存器进行多次例化。

   extern virtual function string        get_full_name();
   extern virtual function uvm_reg_block get_parent ();
   extern virtual function uvm_reg_block get_block  ();
   extern virtual function uvm_reg_file  get_regfile     ();
   extern virtual function void          do_print (uvm_printer printer);
   extern virtual function string        convert2string();
   extern virtual function uvm_object    clone      ();
   extern virtual function void          do_copy    (uvm_object rhs);
   extern virtual function bit           do_compare (uvm_object  rhs,
   extern virtual function void          do_pack    (uvm_packer packer);
   extern virtual function void          do_unpack  (uvm_packer packer);

2.6  uvm_mem

在同一类族中,UVM还提供了uvm_mem类,用于对连续地址存储空间的建模。uvm_mem对象也可以被集成到uvm_reg_block中,并通过uvm_reg_map做地址映射,

  extern virtual function void set_offset (uvm_reg_map    map,
   /*local*/ extern virtual function void set_parent(uvm_reg_block parent);
   extern virtual function string get_full_name();
   extern virtual function uvm_reg_block get_parent ();
   extern virtual function uvm_reg_block get_block  ();
   extern virtual function int get_n_maps ();
   extern virtual function void get_maps (ref uvm_reg_map maps[$]);
   extern virtual function string get_rights (uvm_reg_map map = null);
   extern virtual function string get_access(uvm_reg_map map = null);
   extern virtual function void get_virtual_registers(ref uvm_vreg regs[$]);
   extern virtual function void get_virtual_fields(ref uvm_vreg_field fields[$]);
   extern virtual function uvm_vreg get_vreg_by_name(string name);
   extern virtual function uvm_vreg_field  get_vfield_by_name(string name);
   extern virtual function uvm_vreg get_vreg_by_offset(uvm_reg_addr_t offset,
   extern virtual function uvm_reg_addr_t  get_offset (uvm_reg_addr_t offset = 0,
   extern virtual function uvm_reg_addr_t  get_address(uvm_reg_addr_t  offset = 0,
   extern virtual function int get_addresses(uvm_reg_addr_t     offset = 0,
   extern virtual task write(output uvm_status_e       status,
   extern virtual task read(output uvm_status_e        status,
   extern virtual task burst_write(output uvm_status_e      status,
   extern virtual task burst_read(output uvm_status_e      status,
   extern virtual task poke(output uvm_status_e       status,
   extern virtual task peek(output uvm_status_e       status,
   extern virtual task do_write (uvm_reg_item rw);
   extern virtual task do_read  (uvm_reg_item rw);
   extern virtual protected task backdoor_read(uvm_reg_item rw);
   extern virtual task backdoor_write(uvm_reg_item rw);
   extern virtual function uvm_status_e backdoor_read_func(uvm_reg_item rw);
   extern virtual protected function void add_coverage(uvm_reg_cvr_t models);
   extern virtual function bit has_coverage(uvm_reg_cvr_t models);
   extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on);
   extern virtual function bit get_coverage(uvm_reg_cvr_t is_on);
   extern virtual function void do_print (uvm_printer printer);
   extern virtual function string convert2string();
   extern virtual function uvm_object clone();
   extern virtual function void do_copy   (uvm_object rhs);
   extern virtual function bit do_compare (uvm_object  rhs,
   extern virtual function void do_pack (uvm_packer packer);
   extern virtual function void do_unpack (uvm_packer packer);

三,一个完备的寄存器模型

注意:多个寄存器及其访问译码表最终构成寄存器组。在同个数字系统不同总线视角下,寄存器组可以映射到不同的基地址(base)。因此,一个寄存器组除了可以包含多个寄存器,还可以有多个译码表。 

三, 如何instance到UVM验证环境

试想,如果仅仅是简单把寄存器模型集成到验证环境,那么只要例化寄存器模型就可以了。

现在主要的问题是,建立怎样的机制才可以让寄存器模型“实时”复刻RTL寄存器的值。

 为了解决这个问题,UVM引入Prediction机制,而且用到了两个新的组件:Adapter和Predictor。请看下节内容。

好的,这是一个关于UVM寄存器模型的问题。您需要创建一个包含test_set和reserved字段的寄存器模型,并将其添加到uvm_reg_block中。test_set字段的存取方式为RW,reserved字段的存取方式为RO。然后,您需要使用uvm_reg_map将寄存器模型映射到物理地址,并使用configure()方法配置寄存器模型的默认值和访问权限。 以下是一个示例代码,用于创建一个包含test_set和reserved字段的寄存器模型,并将其添加到uvm_reg_block中: ```systemverilog class my_reg_block extends uvm_reg_block; my_reg_model my_reg; uvm_reg_map reg_map; // Constructor function new(string name = "my_reg_block", uvm_component parent=null); super.new(name, parent); // Create register model my_reg = my_reg_model::type_id::create("my_reg"); // Add fields to register model my_reg.test_set = uvm_reg_field_rw #(.size(4))::type_id::create("test_set", 0, my_reg, null); my_reg.reserved = uvm_reg_field_ro #(.size(28))::type_id::create("reserved", 4, my_reg, null); // Add register model to block add_reg(my_reg, 0); // Create register map reg_map = uvm_reg_map::type_id::create("reg_map", null, UVM_LITTLE_ENDIAN); // Add register to map reg_map.add_reg(my_reg, 0); // Set default value and access policy my_reg.set_access("RW", "test_set"); my_reg.set_access("RO", "reserved"); my_reg.set_default(32'h00000000); // Add map to block add_map(reg_map); endfunction endclass ``` 在上述代码中,my_reg_block类继承自uvm_reg_block类,并包含一个my_reg_model类型的寄存器模型my_reg,以及一个uvm_reg_map类型的寄存器映射reg_map。在构造函数中,首先使用my_reg_model::type_id::create()方法创建my_reg寄存器模型,并使用uvm_reg_field_rw和uvm_reg_field_ro类创建寄存器字段test_set和reserved,并将它们添加到my_reg寄存器模型中。 然后,使用add_reg()方法将my_reg寄存器模型添加到my_reg_block中。接下来,使用uvm_reg_map::type_id::create()方法创建寄存器映射reg_map,并使用reg_map.add_reg()方法将my_reg寄存器模型添加到reg_map中。 接下来,使用my_reg.set_access()方法设置寄存器模型字段的访问权限,使用my_reg.set_default()方法设置寄存器模型的默认值。 最后,使用add_map()方法将reg_map寄存器映射添加到my_reg_block中。这样,就可以将my_reg寄存器模型映射到物理地址,并对它们进行读写操作。 希望这个示例代码可以帮助您创建一个包含test_set和reserved字段的寄存器模型,并将其添加到uvm_reg_block中,并使用uvm_reg_map和configure()方法配置寄存器模型的默认值和访问权限。如果您还有其他问题,可以继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那么菜

你的鼓励和批评是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值