寄存器模型-2

寄存器模型与总线UVC实现桥接呢?下图中添加了更多的细节来表示寄存器桥接(adapter)的作用。

  • 从激励的流向来看,寄存器序列(而不是总线序列)会将带有目标寄存器的相关信息存放到uvm_reg_item实例中,送往adapter。

  • adapter在接收到uvm_reg_item之后,需要从中抽取出总线UVC所需的信息,同时生成总线UVC需要的bus_seq_item类型。在完成了数据内容抽取和二次写入之后,bus_seq_item由adapter送往了总线UVC。

  • 总线UVC从bus_seq_item获取了地址、数据、操作模式等信息之后会发起总线的读写访问。对于写访问而言,如果总线上有反馈信号来标示访问是否成功,则该标示应当由总线sequencer按照item response的路径返回至adapter,adapter也应对该反馈信号做出处理。这一反馈路径在读访问时也会将总线读回的数据返回至adapter,并最终交回到与寄存器操作有关的方法返回值。

 对于寄存器模型而言,它生成之时并不会有adapter伴随。实际上adapter的上层UVM寄存器包是一个标准包,但下层即各个总线UVC,考虑到总线协议的不同带来的总线sequence item的不同、以及不同公司、团队开发的同一种总线UVC也存在不小差异,因此adapter开发的责任就落到了总线UVC本身。而实际情况是,目前大多数商业总线UVC并没有自带寄存器adapter,而多数自研的总线UVC也并未顾及到adapter的开发。这里,路桑提倡总线UVC的开发也应当将adapter一并囊括进去,这样就将寄存器模型与总线UVC集成时的各自边界划分的很清晰,否则只能由TB构建者来实现不同总线的adapter,这无疑增加了额外的TB构建开销。

但有时候,事实如此,读者现阶段如果要集成寄存器模型,恐怕仍然需要掌握实现adapter的一些基本技巧,同时理解adapter充当抽象层转化的原理。我们贯穿本章的材料依然是MCDF寄存器模块,以及接下来的较为简单的访问寄存器的总线UVC和对应的adapter实现。希望通过本节内容,读者可以懂得依靠adapter来实现的前门(front-door)访问和后门(back-door)访问两种方式。

在具备了MCDF总线UVC之后,需要实现adapter。每一个总线对应的adapter所完成的桥接功能即是在uvm_reg_bus_op(寄存器操作transaction)和具体总线的transaction(这里指mcdf_bus_trans)之间的转换。uvm_reg_adapter类以及通过稍后的adapter集成,使得用户在开发某一个总线adapter类型时,只需要下面几点:

  • uvm_reg_bus_op与总线transaction中各自的数据映射。

  • 实现reg2bus()和bus2reg()两个函数,这两个函数即实现了不同transaction之间的数据映射。

  • 如果总线支持byte访问,可以使能supports_byte_enable;如果总线UVC要返回response数据,则应当使能provides_responses

前门访问

利用寄存器模型,我们可以更方便地对寄存器做操作。接下来我们分别两种访问寄存器的方式,即前门访问(front-door)和后门访问(back-door)。前门访问,顾名思义指的是在寄存器模型上做的读写操作,最终会通过总线UVC来实现总线上的物理时序访问,因此是真实的物理操作;而后门访问,指的是利用UVM DPI (uvm_hdl_read()、uvm_hdl_deposit()),将寄存器的操作直接作用到DUT内的寄存器变量,而不通过物理总线访问。

下面给出一段进行前门访问的例码。下面的这个sequence,继承于uvm_reg_sequence,其除了具备一般uvm_sequence的预定义方法外,还具有跟寄存器操作相关的方法。下面对寄存器操作的例码中,用户可以看到两种方式:

  • 第一种即uvm_reg::read()/write()。在传递时,用户需要注意将参数path指定为UVM_FRONTDOOR。uvm_reg::read()/write()方法可传入的参数较多,除了status和value两个参数需要传入,其它参数如果不指定,可采用默认值。

  • 第二种即uvm_reg_sequence::read_reg()/write_reg()。在使用时,也需要将path指定为UVM_FRONTDOOR。

    后门访问

    在进行后门访问时,用户首先需要确保寄存器模型在建立时,是否将各个寄存器映射到了DUT一侧的HDL路径。下面的例码即实现了寄存器模型与DUT各个寄存器的映射:

  • 后门访问的路径地址:reg_backdoor_access.dut+$sformatf()内容

    例码中通过uvm_reg_block::add_hdl_path(),将寄存器模型关联到了DUT一端,而通过uvm_reg::add_hdl_path_slice完成了将寄存器模型各个寄存器成员与HDL一侧的地址映射。例如在稍后对寄存器SLV0_RW_REG进行后门访问时,UVM DPI函数会通过寄存器HDL路径“reg_backdoor_access.dut.regs[0]”映射到正确的寄存器位置,继而对其进行读值或者修改。另外,寄存器模型build()函数最后一句,以lock_model()结尾,该函数的功能是结束地址映射关系,并且保证模型不会被其它用户修改。

    在寄存器模型完成了HDL路径映射后,我们才可以利用uvm_reg或者uvm_reg_sequence自带的方法进行后门访问,下面仍然给出一段后门访问的例码。类似于前门访问,后门访问也有几类方法提供:

  • uvm_reg::read()/write(),在调用该方法时需要注明UVM_BACKDOOR的访问方式。

  • uvm_reg_sequence::read_reg()/write_reg(),在使用时也需要注明UVM_BACKDOOR的访问方式。

  • 另外,uvm_reg::peek()/poke()两个方法,也分别对应了读取寄存器(peek)和修改寄存器(poke)两种操作,而用户无需指定访问方式尾UVM_BACKDOOR,因为这两个方法本来就只针对于后门访问。

前门访问和后门访问的比较

下面的表总结了前门访问和后门访问的主要差别:

  从面的差别可以看出,后门访问较前门访问更便捷一些更快一些,但如果单纯依赖后门访问也不能称之为“正道”。实际上,利用寄存器模型的前门和后门访问两种混合方式,对寄存器验证的完备性更有帮助。下面给出一些实际应用的场景:

  • 通过前门访问的方式,先验证寄存器访问的物理通路工作正常,并且有专门的寄存器测试的前门访问用例,来遍历所有的寄存器。在前门访问被验证充分的前提下,可以在后续测试中使用后门访问来节省访问多个寄存器的时间。

  • 如果DUT实现了一些特殊寄存器,例如只能写一次的寄存器等,我们建议用物理方式去访问以保证反映真实的硬件行为。

  • 寄存器随机设置的精髓不在于随机可设置的域值,而是为了考虑日常不可预期的场景,先通过后门访问随机化整个寄存器列表(在一定的随机限制下),随后再通过前门访问来配置寄存器。这么做的好处在于,不再只是通过设置复位之后的寄存器这种更有确定性的场景,而是通过让测试序列一开始的寄存器值都随机化来模拟无法预期的硬件配置前场景,而在稍后设置了必要的寄存器之后,再来看是否会有意想不到的边界情况发生。

  • 有的时候,即便通过先写再读的方式来测试一个寄存器,也可能存在地址不匹配的情况。譬如寄存器A地址本应该0x10,寄存器B地址本应该为0x20;而在硬件实现用,寄存器A对应的地址位0x20,寄存器B对应的地址位0x10。像这种错误,即便通过先写再读的方式也无法有效测试出来,那么不妨在通过前门配置寄存器A之后,再通过后门访问来判断HDL地址映射的寄存器A变量值是否改变,最后通过前门访问来读取寄存器A的值。上述的方式是在之前前门测试的基础之上又加入了中途的后门访问和数值比较,可以解决地址映射到内部错误寄存器的问题。

  • 对于一些状态寄存器,在一些时候外界的激励条件修改会依赖这些状态寄存器,并且在时序上的要求也可能很严格。例如,上面MCDF的寄存器中有一组状态寄存器表示各个channel中FIFO的余量,而channel中FIFO的余量对于激励驱动的行为也很重要。无论是前门访问还是后门访问,都可能无法第一时间反映FIFO在当前时刻的余量。因此对于需要要求更严格的测试场景,除了需要前门和后门来访问寄存器,也需要映射一些重要的信号来反映第一时间的信息。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值