Maggie
Maggie

2019年10月14日 阅读143


UVM寄存器模型regmodel

本文来自于猴哥验证公众号。

 从这一期开始我们聊一聊regmodel这个话题,regmodel涉及的方方面面很多,我们分几期展开描述。

1. regmodel是什么?

 对于初入验证这个坑的小伙伴来说,regmodel还比较陌生,存在和设计里面的寄存器怎么个关系理解不太清晰的情况。 

 字面上看regmodel就是寄存器的模型,这个寄存器是设计里面的控制寄存器组,并不是Verilog的reg信号类型。

  一个寄存器设计中是实现一个或者多个功能,比如:

  reg[15:0]  src_addr;

  这是一个16位源地址的控制寄存器。

  regmodel是一个模型,它是验证环境的一部分,可以看做是DUT设计里面寄存器组在环境中的抽象。

  regmodel的内容来源于DUT,是模块设计在环境中的一个映射,模块设计在实现的映射就是DUT代码咯,这个概念之前有不少小伙伴没太搞懂,大家注意一下。

 regmodel和DUT之间的连接一个是前门方式也就是通过总线的访问,另外一个是后门方式,这个问题我们后面再展开讲。

 所以,regmodel和DUT设计其实是寄存器组的两个表现,它们是一致的,但是一个是环境中的抽象组件,一个是实际的rtl代码,通过行为方式将它们联系起来,保持一致性。

2. 为什么使用regmodel?

  regmodel是随验证方法学发展起来的,OVM里面是叫RGM,VMM里面是regmodel,后来UVM采用了VMM的方式。

  SOC系统中寄存器是非常关键的一个部分,系统中的各项功能都是根据寄存器的配置来实现的。因此寄存器验证涉及到两个方面,一个是对寄存器本身的验证,一个是寄存器的使用。

寄存器本身的验证包括reset 默认值的检查,寄存器的读写属性检查,不使用regmodel的时候一般怎么来做呢?

 `define  SRC_ADDR 16'h10  // 宏定义src_addr寄存器的地址

//dut reset

reg_read(`SRC_ADDR, data );  //读取默认值

reg_write(`SRC_ADDR,0 );     //写0

reg_read(`SRC_ADDR, data );  //读取检查是不是0

reg_write(`SRC_ADDR,16'h55AA );     //写55AA

reg_read(`SRC_ADDR, data );  //读取检查是不是55AA

reg_write(`SRC_ADDR,16'hAA55 );     //写AA55

reg_read(`SRC_ADDR, data );  //读取检查是不是AA55

reg_write(`SRC_ADDR,16'hFFFF );     //写AA55

reg_read(`SRC_ADDR, data );  //读取检查是不是AA55

以上是一个简单的寄存器测试流程,地址使用宏定义传递给task,对寄存器做默认值检查,写0写全1,写全翻转值检查。

这是一个比较纯粹的RW寄存器的测试,那么还有其它属性的寄存器,比如有效位小于寄存器宽度的,寄存器属性只读,只写,读清0,写清0。

对于这些属性,就需要做个class或者struct表示这些属性,然后在寄存器处理的时候根据各个属性做对于的处理操作。

这些处理方式对于寄存器来说都是固定的,而各个公司的处理存在实现的差异,那么使用统一的代码来完成这个任务,就会大大提高效率,这只是regmodel的一个功能而已。

使用寄存器做功能验证,不使用regmodel的情况下,大多会采用宏定义地址方式,这个地址值可以由脚本生成,由于宏定义是一个全局的数值,复用性大打折扣。

对于模块级验证SRC_ADDR是'h10地址,到子系统的时候需要加上偏移,这样宏定义变成如下情况:

`define SRC_ADDR  X0_BASE+'h10

如果子系统上例化了2个这样的模块,那么宏定义变成如下情况:

`define X0_SRC_ADDR  X0_BASE+'h10

`define X1_SRC_ADDR  X1_BASE+'h10

到系统级宏定义又变成如下情况:

`define X0_SRC_ADDR  SYS_BASE+X0_BASE+'h10

`define X1_SRC_ADDR  SYS_BASE+X1_BASE+'h10

如果两个系统在一个环境里呢?又要加区分了

`define S0_X0_SRC_ADDR  SYS0_BASE+X0_BASE+'h10

`define S0_X1_SRC_ADDR  SYS0_BASE+X1_BASE+'h10

`define S1_X0_SRC_ADDR  SYS1_BASE+X0_BASE+'h10

`define S1_X1_SRC_ADDR  SYS1_BASE+X1_BASE+'h10

那么对于寄存器操作的sequence复用起来比较困难,再增加一层宏定义处理方式,如果要实现模块到系统的复用,那么必须在一开始做好规划,而且不能有大的改动。

还有一个情况,现在SOC系统一般都是多核异构的系统,存在多个master都会对同一模块操作。不同的master寄存器映射关系又存在不同,那么宏定义又变成如下:

`define X0_CPU_SRC_ADDR  X0_CPU_BASE+'h10

`define X1_CPU_SRC_ADDR  X1_CPU_BASE+'h10

`define X0_DSP_SRC_ADDR  X0_DSP_BASE+'h10

`define X1_DSP_SRC_ADDR  X1_DSP_BASE+'h10

再加上系统级,双系统......

微信图片_20191014200632.jpg

所以regmodel要解决的另外一个问题就是地址问题,通过分block,分subsystem管理寄存器地址,由regmodel自己去解析对于的address信息,提高抽象行为。

regmodel带来了很多好处,我们都怎么来使用它呢?同样的它也有自己的局限性,那都是些什么问题呢?这些都会在后续文章中一一展开描述。

0 个评论

要回复文章请先登录注册