IC验证学霸笔记4——UVM--TLM通信
TLM通信
在芯片开发流程中,有两个地方对项目的助推起到了关键作用: 系统原型&芯片验证
系统原型一般通过硬件功能描述文档模拟硬件行为, 行为要求不同于RTL模型。 系统原型提供一个准确到硬件比特级别、 按照地址段访问、 不依赖于时钟周期的模型, 该模型通常基于SystemC语言,而系统原型中各模块通过TLM可以实现宽松时间范围内的数据包传输。
芯片验证是在RTL模型初步建立后, 通过验证语言和方法学如SV/UVM来构建验证平台。该平台的特点是验证环境整体基于面向对象开发,组件之间的通信基于TLM, 而在driver与硬件接口之间需将TLM抽象事务降解到基于时钟的信号级别。
芯片验证是在RTL模型初步建立后, 通过验证语言和方法学如SV/UVM来构建验证平台。该平台的特点是验证环境整体基于面向对象开发,组件之间的通信基于TLM, 而在driver与硬件接口之间需将TLM抽象事务降解到基于时钟的信号级别。
系统原型阶段和芯片验证阶段均使用了TLM通信方式。前者是为了更快地实现硬件原型之间的数据通信,后者是为了更快地实现验证组件之间的数据通信。
仿真速度是TLM对项目进度的最大贡献,同时TLM传输中的事务又可以保证足够大的信息量和准确性。
TLM并不是某一种语言产物,而是作为一种提高数据传输抽象级的标准存在。
高抽象级的数据通信,可以用来表示宽松时间跨度内的硬件通信数据,而通过降低颗粒硬件周期内的数据打包为一个大数据,非常有利于整体环境的仿真速度。
TLM的运用越来越广泛,包括emulator同硬件仿真器的协同仿真框架中,也建议使用这种方式来降低混合环境之间的通信频率,以便提高整体的运算效率。
TLM 是一种基于事务 (transaction) 的通信方式, 通常在高抽象级语言如 SystemC 或SV/UVM中作为模块之间的通信方式。TLM成功地将模块内的计算和模块之间的通信从时间跨度方面剥离开了。 在抽象语言建模体系中, 各模块通过一系列并行的进程实现, 同时利用通信和计算模拟出正确的行为。
要提高系统模型的仿真性能, 需要考虑两个方面: 建模自身的运算优化, 模型之间的通信优化。前者依靠开发者的经验和性能分析工具来逐步优化模型,后者则可以通过将通信频率降低、 内容体积增大的方式减少由不同进程之间同步带来的资源损耗。TLM 正是从通信优化角度提出的一种抽象通信方式。
TLM通信需要两个通信的对象,这两个对象分别称为initiator和 target。区分它们的方法在于,谁先发起通信请求,谁就属于initiator,而谁作为发起通信的响应方,谁就属于target。
通信发起方并不代表了transaction的流向起点,即不一定数据是从initiator流向target, 也可能是从target流向了initiator,因此按照transaction的流向,我们又可以将两个对象分为producer和consumer。区分它们的方法是,数据从哪里产生,它就属于producer, 而数据流向了哪里,它就属于consumer。
initiator与target的关系同producer与consumer的关系不是固定的。
有了两个参与通信的对象之后,用户需要将TLM通信方法在target端中实现,以便于initiator将来作为发起方可以调用target的通信方法,实现数据传输。
initiator与target的关系同producer与consumer的关系不是固定的。
有了两个参与通信的对象之后,用户需要将TLM通信方法在target端中实现,以便于initiator将来作为发起方可以调用target的通信方法,实现数据传输。
在target实现了必要的通信方法之后,最后一步我们需要将两个对象进行连接,这需要在两个对象中创建TLM端口,继而在更高层次中将这两个对 象进行连接。
因此我们可以将 TLM 通信步骤分为:
1 分辨出 initiator和target, producer和consumer。
2 在 target 中实现 TLM 通信方法。
3 在两个对象中创建 TLM 端口。
4 在更高层次中将两个对象的端口进行连接。
2 在 target 中实现 TLM 通信方法。
3 在两个对象中创建 TLM 端口。
4 在更高层次中将两个对象的端口进行连接。
从数据流向来看, 传输方向可以分为单向(unidirection)和双向 (bidirection):
• 单向传输:由initiator发起request transactio;
• 双向传输:由initiator发起request transaction, 传送至target; 而target在消化 了request transaction后,会发起response transaction, 继而返回给initiator。
• 双向传输:由initiator发起request transaction, 传送至target; 而target在消化 了request transaction后,会发起response transaction, 继而返回给initiator。
端口的按照类型可以划分为三种:
• port: 经常作为initiator的发起端, initiator凭借port才可以访问target的TLM通信方法。
• export: 作为initiator和target中间层次的端口。
• imp: 只能作为target接收request的未端, 它无法作为中间层次的端口, 所以imp的连接无法再次延伸。
如果将传输方向和端口类型加以组合,综合下来, TLM 端口一共分为 6 类:
• uvm_UNDIR_port #(trans_t) uvm_单双向_端口类型 # (类型参数)
• uvm_UNDIR_export # (trans_t)
• uvm_UNDIR_imp # (trans_t,imp_parent_t)
• uvm_BIDIR_port # (req_trans_t, rsp_trans_t)
• uvm_BIDIR_export #(req_trans_t, rsp_trans_t)
• uvm_BIDIR_imp # (req_trans_t, rsp_trans_t, imp_parent_t)

• uvm_UNDIR_export # (trans_t)
• uvm_UNDIR_imp # (trans_t,imp_parent_t)
• uvm_BIDIR_port # (req_trans_t, rsp_trans_t)
• uvm_BIDIR_export #(req_trans_t, rsp_trans_t)
• uvm_BIDIR_imp # (req_trans_t, rsp_trans_t, imp_parent_t)
就单向端口而言,声明 port 和 export 作为 request 发起方,需要指定 transaction 类型参数, 而声明 imp 作为 request 接收方, 不但需要指定 transaction 类型参数, 还需要指定它所在的 component 类型。 就声明双向端口而言, 指定参数需要考虑双向传输的因素, 将传输类型 transaction 拆分为 request transaction 类型和 response transaction 类型。
TLM 端口连接的一般做法:
TLM 端口连接的一般做法:
• 在 initiator 端例化 port, 在中间层次例化 export, 在 target 端例化 imp;
• 多个 port 可以连接到同一个 export或imp; 但单个 port或export 无法连接多个imp 。这可以理解为多个initiator 可以对同一个 target 发起 request, 但是同一个initiator 无法连接多个target。
• port 应为 request 起点, imp 应为 request 终点, 而中间可以穿越多个层次。 基于单元组件的自闭性考虑, 笔者建议在穿越的中间层次声明 export, 继而通过层层连接实现数据通路。
• port 可以连接 port 、 export 或 imp: export 可以连接 export 或 imp; imp 只能作为数据传送的终点, 无法扩展连接。
• 多个 port 可以连接到同一个 export或imp; 但单个 port或export 无法连接多个imp 。这可以理解为多个initiator 可以对同一个 target 发起 request, 但是同一个initiator 无法连接多个target。
• port 应为 request 起点, imp 应为 request 终点, 而中间可以穿越多个层次。 基于单元组件的自闭性考虑, 笔者建议在穿越的中间层次声明 export, 继而通过层层连接实现数据通路。
• port 可以连接 port 、 export 或 imp: export 可以连接 export 或 imp; imp 只能作为数据传送的终点, 无法扩展连接。
从示例中可以得出关于建立TLM通信的常规步骤:
• 定义TLM传输中的数据类型,上面分别定义了request类和response 类。
• 分别在各个层次的component中声明和创建TLM端口对象。
• 通过connect()函数完成端口之间的连接。
• 在imp端口类中要实现需要提供给initiator的可调用方法。例如,在 comp2中由于有一个uvm_nonblocking_put_imp #(request, comp2) nbp_imp, 因此需要实现两个方法try_pu( )和can_put();而comp4中有一个uvm blocking_get_imp #(request, comp4) bg_imp, 则需要实现对应的方法get()。
• 需要注意的是,必须在imp端口类中实现对应方法,否则端口即使连接也无法实现数据传输。
#深度学习##做项目##芯片IC验证工程师##你为什么选择硬件行业##你的秋招进展怎么样了#• 定义TLM传输中的数据类型,上面分别定义了request类和response 类。
• 分别在各个层次的component中声明和创建TLM端口对象。
• 通过connect()函数完成端口之间的连接。
• 在imp端口类中要实现需要提供给initiator的可调用方法。例如,在 comp2中由于有一个uvm_nonblocking_put_imp #(request, comp2) nbp_imp, 因此需要实现两个方法try_pu( )和can_put();而comp4中有一个uvm blocking_get_imp #(request, comp4) bg_imp, 则需要实现对应的方法get()。
• 需要注意的是,必须在imp端口类中实现对应方法,否则端口即使连接也无法实现数据传输。
注:优秀验证学员随堂笔记,已经征求到学生的同意,会持续给牛友们分享!
大家看完记得 一键三连!多多支持