【UVM】 -- 对寄存器建模的方法RAL(Register Abstraction Layer,寄存器抽象层)

说明

验证需要包含对寄存器和存储器的验证,寄存器用来描述芯片配置信息和状态信息

自己实现

可通过启动读写寄存器的sequence来完成。

sequence产生的寄存器事务传递给driver,driver来写入寄存器的值或者读取寄存器的值,monitor再从接口上获取信息,判断是哪个寄存器和它的值,这是一种简单的检测寄存器的方法,但是在其他组件中难以启动或者查看某些寄存器的值,在某种情况下 scoreboard想查看寄存器中某个的状态,则不知道什么时候去触发这个,只能通过事务状态来启动sequence 驱动到driver,然后用monitor获取,这种做法相当繁琐。

寄存器建模RAL

RAL提供了一套数据结构,对寄存器进行建模,实例化后作为组件的一部分。scoreboard就可以通过寄存器模型来访问DUT中的寄存器。使用RAL提供的API来访问,write写, read读。这个过程是寄存器模型自己完成的。

寄存器模型想要访问DUT中的寄存器还需要一个事务转换器adapter,因为寄存器模型产生的事务类型可能与sequencer能接收的类型不一致。转换器需要自己完成。RAL模型产生的事务借助agent来访问DUT中寄存器/存储器,这种为frontdoor模式,第二种是RAL通过DUT的设计层次路径直接访问DUT中的寄存器,为backdoor模式。

工作模式

frontdoor

当在scoreboard或其他组件中调用api的时候,register_model.reg_name.read(…)或者register_model.reg_name.write(…)的时候,寄存器模型会根据寄存器名称产生uvm_reg_item的事务对象,产生的名字会根据寄存器名称reg_name自动生成,接着将对象类型转换为uvm_reg_bus_op类型对象,并将该对象传入转换器中,然后转换为sequencer可以接收的事务类型(用户自定义类型),sequencer将数据发给driver,进而操作DUT,操作的结果会在寄存器模型中体现,如读出的值会返回给寄存器模型,这里的整个过程由寄存器模型实现,需要消耗仿真时间。

backdoor

通过寄存器的层次结构直接引用DUT中的寄存器,将返回值返给寄存器模型,backdoor模式不需要消耗仿真时间。

register model在env中进行例化,其他组件使用句柄引用

寄存器模型

寄存器模型的构成图如下:

转换器

转换器继承UVM的基类uvm_reg_adapter

转换器类需要重载两个函数

1、reg2bus 由寄存器模型的事务转换成自己定义类型的事务,转换为自动发给sequencer,

2、bus2reg 将自定义事务对象转换为寄存器模型类型的事务,发给寄存器模型,

这两个函数UVM平台自动调用。

REGISTER MODEL 和ADAPTER以及 SEQUENCER的链接

借助寄存器模型中的map来实现,其中map有一个adpter句柄和一个sequencer句柄,将adpater对象赋值给该句柄即可。

在测试平台中加入寄存器模型

为DUT创建寄存器模型,包含每一个寄存器。

比如DUT有两个寄存器和一个memary,如下图所示:

 封装REG类

//为每个寄存器进行建模型
class config_reg_c externs uvm_reg
 
    rand uvm_reg_filed f1 //建立第一个域
    rand uvm_reg_filed f2
    rand uvm_reg_filed f3
    rand uvm_reg_filed f4
    virtual function void bulid();//bulid方法,非build_phase
    //实例化
    f1 = uvm_reg_field::type_id::create(“f1”);
    f2 = uvm_reg_field::type_id::create(“f2”);
    f3 = uvm_reg_field::type_id::create(“f3”);
    f4 = uvm_reg_field::type_id::create(“f4”);
    //调用域的config,
    //配置域的一些属性
    f1.configure(this,1,0,”RW”,0,’h0,1,1,1);//第一个参数是哪个寄存器,第二个是该域有几位,
                                            //第三个该field最低位在寄存器中位置,第四个参
                                            //数表示域访问类型,第五个复位后的默认值,第
                                            //六个表示是否可以被复位,第七个表示该域是否
                                            //可以随机化,最后一个该field是否可以单独操作
 
    `uvm_object_utils(config_reg_c),
    function new(string name = “config_reg_c”)
        //第二个参数是寄存器总位宽,第三个是是否支持覆盖率统计,
        super.new(name,8,UVM_NO_COVERAGE);
    endfunction
endclass

其中存储器需要从uvm_mem扩展。

以上就完成寄存器建模的工作。

封装寄存器模型类

class reg_model_c extends uvm_reg_blocks;
 
        rand config_reg_c config_reg;
        rand mode_reg_c model_reg;
        data_mem_c   data_mem;
        virtual function void bulid();//build方法,非build_phase
        //实例化
        config_reg = config_reg_c::type_id::create(“config_reg”,get_full_name());
        config_reg. configure(this,null ,” config_reg”); //第三个参数是指定该寄存器
                                                         //在HDL路径, 这个参数路径
                                                         //用于backdoor的访问,
        config_reg.build();
        //其他寄存器用同样方法创建
        //创建map,第一个参数为名字,第二个为基地址,第三个系统总线位宽,
        //单位为字节,第四个为大小端
        default_map = create_map(“default_map”,0,1,UVM_LITTLE_ENDIAN);
        //添加寄存器,第一个参数为添加的reg名,第二个为reg偏移地址,
        //用基地址和偏移地址结合表示实际地址,
        default_map.add_reg(“config_reg”,‘h001c,”RW”);
        `uvm_object_utils(reg_model_c),
        function new(string name = “reg_model_c”)
            super.new(name,UVM_NO_COVERAGE),第二个参数是是否支持覆盖率统计,
        endfunction
end class

创建为实现前门操作的转换器

uvm_reg_adapter扩展,然后重载两个函数。

在ENV中实例化寄存器模型和转换器

在env中实例化,创建,调用config_reg.bulid()函数就是在执行reg类中的bulid方法。

调用lock函数则锁定,不可再编辑reg model ,调用reset函数完成初始化。

connect_phase中,调用map函数进行连接,最后调用reg_model.default_map.set_auto_predict(1)开启预测功能。

最后在env中,将转换器、sequencer、与寄存器的map建立关联。在需要进行寄存器读写的地方进行API访问,比如在scoreboard调用寄存器模型,则在env中还需要将寄存器模型赋值给scoreboard中例化的寄存器模型句柄

 

寄存器模型的基本数据结构

寄存器模型API

read/write 方法 均支持前门后门访问,

使用前门访问的时候,read/write会产生事务,通过转换器送到sequencer再送到driver,最终到达DUT,访问DUT内部寄存器值之后,将返回来的结果通过predict自动更改期望值和镜像值,最终使得期望值和镜像值,与DUT内部的寄存器值保持一致。

后门操作的时候,直接通过层次路径,读取写入DUT内部的值,然后直接修改期望值和镜像值。

peek/poke

peek几乎相当于read的后门操作,poke几乎相当于write的后门模式,

peek/poke不模拟寄存器的行为而是直接进行操作。

randomize : 随机化后会赋值给期望值。

update: 将期望值写入DUT内部寄存器当中,然后比较期望值和镜像值是否相同,不同则更新镜像值。

mirror,:从DUT中读出,写入期望值和镜像值。

 寄存器模型API汇总

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值