当前位置: 首页 > news >正文

UVM寄存器模型与通道机制

接续UVM基础入门文章。


前言

重点讲述UVM常用的接口连接方式。


寄存器模型:

UVM寄存器模型(Register Model)是一组高级抽象的类,用于对DUT(Design Under Test)中具有地址映射的寄存器和存储器进行建模,通过提供寄存器操作的抽象接口进行读写操作,这样简化了对寄存器的验证。

寄存器模型模拟了DUT内部的存储器件,一个简单的寄存器模型如图:

上述的图中可以看出寄存器模型的大致框架,内部含有众多寄存器和存储器,这些元件通过地址图与DUT内部的寄存器形成映射关系。

不过寄存器的保留域可以不用管,无法写入,读出的数据是复位值,在提取寄存器功能点时也常常忽略保留域。

寄存器读写:

寄存器模型与DUT的数据交互复杂多样,整体方式其实就是通过前门访问和后门访问。

前门访问过程:

1.测试用例或者参考模型会调用寄存器模型的read() 或者 write() 方法,指定为前门访问方式。一旦寄存器模型被上层调用后,这个寄存器模型就会产生一个有关读写操作事务。

2.寄存器模型通过调用adapter的reg2bus函数将寄存器读写事务转换成总线事务。

3.该总线事务会交给关联的sequencer发送给driver,然后再驱动给DUT。

4.monitor监测响应,然后给到端口传出去,这个端口可以是analysis_port端口。

5.寄存器模型通过analysis_port端口获取响应后调用adapter的bus2reg函数将事务转换成寄存器操作

6.寄存器模型自动更新镜像值

后门访问过程:

1. 在寄存器模型中,通过 add_hdl_path() 或 add_hdl_path_slice() 为内部的每个寄存器或字段域指定对应的RTL信号路径,这个过程理解为映射。

2. 调用寄存器模型的read() 或者  write() 函数,方式指定为后门路径。

3.通过DPI-C接口或者force/release直接修改或者读取对应路径的寄存器值.

4.写入的数值或者读出的数值都会自动更新到寄存器镜像里。

如图所示:

红色线条表示的是参考模型写数据到DUT内部的路径,绿色线条表示参考模型从DUT寄存器里读出数据,黑色线条表示后门访问。

参考模型一般都不会写数据,想要读寄存器数据可以通过前门后门或者读取镜像值来获取数据。

通道机制:

在UVM的端口连接机制中,最为常用的有3种端口连接机制。

一对一接口:

1.put_port:在完成transaction的打包后,通过port.put(trans)将事务发送出去。(blocking_put_port接口也属于put_port的一种,属于阻塞接口,不支持反向)

2.get_port:在需要transaction的时候,通过port.get(trans)获取事务。(get_blocking_prot就是get_port的一种,它属于阻塞端口)

一对多接口:

analysis_port接口为广播接口,可以向所有组件发送事务信息。

接口转接:

tlm_fifo作为中间传输的缓存器,可以用于不同接口之间的连接。当存在两个接口的定义不相同时,通过将接口连接到fifo对应的接口上实现转接。

tlm_fifo分为有ap端口的fifo 和没有ap端口的fifo。

通常agent发送的transaction不止一个组件使用,因此在agent中通常使用的analysis_port实现广播,而在参考模型或者记分板中并不需要广播功能。

因此在不需要广播功能的组件中,通常可以不用analysis_port端口。

以agent到scoreboard的端口连接为例简单的讲述一下常用的接口连接机制:

1.多对一连接:

analysis_port------env.tlm_fifo------scoreboard.get_blocking_port。

这属于不同类型的接口连接,由于scoreboard不是时刻都需要事务的,因此需要一个缓冲功能的接口。

analysis_port--------scoreboard.tlm_fifo

由于fifo中自带了get()函数,通常也可以省略get_blocking_port接口,直接在scoreboard里面实例化两个fifo存储数据用于对比。

虽然使用fifo简单易懂,但是很多时候一个组件需要获取多组数据的情况,这种情况下例化很多fifo是不现实的。

原因在于如果不同agent之间发送事务的phase不同,而scoreboard里面没有选择合适的phase,那么环境的调试将会变得十分困难。

而且想要从fifo里面获取数据需要在特定的phase里面执行。

analysis_port ------------- scoreboard.imp

imp,我在B站上看到的视频解释为通道的意思,如果组件中有多个imp接口的话,需要使用·uvm_analysis_imp_decl宏定义创建多个imp类去分别对应不同的通道,还要再组件中定义具有相同后缀名的函数。

2.一对一连接:

常见一对一的端口连接方式有:

阻塞式单向传输uvm_blocking_put_port(发送) + uvm_blocking_put_imp(接收)

阻塞式双向传输uvm_blocking_transport_port(发送) + uvm_blocking_transport_imp(接收)

非阻塞式单向传输uvm_nonblocking_put_port(发送) + uvm_nonblocking_put_imp(接收)

例如:

class scoreboard extends uvm_component;`uvm_component_param_utils(scoreboard #(transaction))// 定义两个IMP端口:一个接收预期数据,一个接收实际数据uvm_blocking_put_imp #(transaction, scoreboard #(transaction)) expected_imp;uvm_blocking_put_imp #(transaction, scoreboard #(transaction)) actual_imp;// 存储预期和实际数据的队列transaction expected_queue[$];transaction actual_queue[$];function new(string name = "scoreboard", uvm_component parent = null);super.new(name, parent);expected_imp = new("expected_imp", this);actual_imp = new("actual_imp", this);endfunction// 实现expected_imp的put方法virtual task put(transaction tr);`uvm_info("SCOREBOARD", $sformatf("Received Expected Data: %0h", tr.data), UVM_MEDIUM);expected_queue.push_back(tr);endtask// 实现actual_imp的put方法virtual task put(transaction tr);`uvm_info("SCOREBOARD", $sformatf("Received Actual Data: %0h", tr.data), UVM_MEDIUM);actual_queue.push_back(tr);endtask// 比对逻辑(可在run_phase或单独的任务中调用)task compare();if (expected_queue.size() != actual_queue.size()) begin`uvm_error("SCOREBOARD", "Mismatch in number of transactions!");end else beginforeach (expected_queue[i]) beginif (expected_queue[i].data !== actual_queue[i].data) begin`uvm_error("SCOREBOARD", $sformatf("Data mismatch at index %0d!", i));endendendexpected_queue.delete();actual_queue.delete();endtask
endclass

总结

不同种类的端口一般不能直接相连,需要FIFO转接,或者将两个要相连的端口类型声明为一致的。


文章转载自:

http://hJMlupmS.hjssh.cn
http://6L66ENj4.hjssh.cn
http://L5zbkecQ.hjssh.cn
http://Vk1jkkyT.hjssh.cn
http://PrWsjvxb.hjssh.cn
http://4kpD3RTl.hjssh.cn
http://zl6qot6k.hjssh.cn
http://uUd85kh8.hjssh.cn
http://9Wvkbz8K.hjssh.cn
http://YpiMksEP.hjssh.cn
http://fM31bgu4.hjssh.cn
http://XrpO6rEQ.hjssh.cn
http://Z67Ogfc2.hjssh.cn
http://aWeaMcXy.hjssh.cn
http://QgZXFSa2.hjssh.cn
http://kgDKlmj7.hjssh.cn
http://OkB2zh4H.hjssh.cn
http://vgVcNNoo.hjssh.cn
http://4pEQv9OC.hjssh.cn
http://MvIZMZaA.hjssh.cn
http://pded9rjv.hjssh.cn
http://nStaZgfe.hjssh.cn
http://A1S6pVff.hjssh.cn
http://IJsaPe8J.hjssh.cn
http://9MRHXRGS.hjssh.cn
http://BDP3I1Yf.hjssh.cn
http://nr3X0431.hjssh.cn
http://EH4T5yRH.hjssh.cn
http://EPZrsiPH.hjssh.cn
http://Zml9ozFz.hjssh.cn
http://www.dtcms.com/a/381342.html

相关文章:

  • 一个简单的GPU压力测试脚本-python版
  • Linux x86 stability和coredump
  • Claude-Flow AI协同开发:从“CTO”到“人机共生体”的AI协同开发
  • CPR_code
  • 【连接器专题】FPC连接器基础及连接器选型指南
  • 精准、可控、高一致性:谷歌Nano Banana正在终结AI“抽卡”时代
  • 操作系统实时性的影响因素总结
  • 国际避税方法有哪些
  • 开发避坑指南(47):IDEA 2025.1.3 运行main函数报错:CreateProcess error=206, 文件名或扩展名太长的解决方案
  • 《苍穹外卖》项目日记_Day9
  • 文件检查与拷贝-简化版
  • 电容式原理检测微小位移的技术方案以及芯片方案
  • 嵌入式系统内存分段核心内容详解
  • AI生成内容检测的综合方法论与技术路径
  • 材料基因组计划(MGI)入门:高通量计算与数据管理最佳实践
  • 系统地总结一下Python中关于“遍历”的知识点
  • Android面试指南(九)
  • Halcon编程指南:符号与元组操作详解
  • 嵌入式第五十二天(GIC,协处理器,异常向量表)
  • 嵌入式学习day48-硬件-imx6ul-key、中断
  • 查找算法和递推算法
  • Webman 微服务集成 RustFS 分布式对象存储
  • 基于51单片机的太阳能锂电池充电路灯
  • 【人工智能通识专栏】第十三讲:图像处理
  • 滚动分页查询-通俗解释
  • 电缆工程量计算-批量测量更轻松
  • UDS NRC速查
  • L2-【英音】地道语音语调--语调
  • 13.渗透-.Linux基础命令(五)-用户管理(修改用户密码)
  • 解决串口数据乱序问题