UVM寄存器篇之三:寄存器模型的集成(上)

本文转自:http://www.eetop.cn/blog/html/28/1561828-6266220.html

我们在上一节大致了解了与寄存器相关的流程,包括寄存器描述文件和UVM寄存器模型生成。从上节给的寄存器模型流程图中我们可以看到,接下来需要考虑选择与DUT寄存器接口一致的总线UVC,该UVC会提供硬件级别的访问方式。要完成一次硬件级别的总线传输,往往需要考虑给出地址、数据队列、访问方式等,而寄存器模型可以使得硬件级别的抽象级可以上升到寄存器级别。由此带来的最直观的好处在于,以往写的由具体地址来指定的寄存器,将由寄存器名称来替代,同时寄存器模型封装的一些函数使得可以对域做直接操作,这一升级使得转变后的测试序列更易读。而当伴随着项目变化,无论寄存器基地址如何变化,以寄存器级别实现的配置序列都要比以硬件级别的序列可维护性更好。

那么如何将寄存器模型与总线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)访问两种方式。

总线UVC实现

MCDF访问寄存器的总线接口时序较为简单。控制寄存器接口上首先需要在每一个时钟解析cmd,当cmd为写指令时,即需要把数据cmd_data_in写入到cmd_addr对应的寄存器中;当cmd为读指令时,即需要从cmd_addr对应的寄存器中读取数据,在下一个周期,cmd_addr对应的寄存器数据被输送至cmd_data_out接口。

按照上面的时序,我们接下来给出一段8位地址线,32位数据线的总线UVC实现代码。

上面给出的代码囊括了mdf_bus_agent的所有组件:sequence item、sequencer、driver、monitor和agent。我们这些代码的部分实现给出解释:

  • mcdf_bus_trans包括了可随机化的数据成员cmd、addr、wdata和不可随机化的rdata。rdata之所以没有声明为rand类型,是因为它应从总线读入或者观察,不应随机化。

  • mcdf_bus_monitor会观测总线,其后通过analysis port写出到目标analysis组件,在本节中它稍后将连接到uvm_reg_predictor。

  • mcdf_bus_driver主要实现了总线驱动和复位功能,通过模块化的方法reset_listener()、drive_bus()、drive_write()、drive_read()和drive_idle()可以解析mcdf_bus_trans中的三种命令模式IDLE、WRITE和READ,并且在READ模式下,将读回的数据通过item_done(rsp)写回到sequencer和sequence一侧。建议读者在通过clone()命令创建RSP对象后,通过set_sequence_id()和set_transaction_id()两个函数保证REQ和RSP的中保留的ID信息一致。

猜你喜欢

转载自blog.csdn.net/qq_41394155/article/details/82757043
今日推荐