TLM反向路径中载荷暂停与恢复的实现问题咨询
AMBA TLM 2.0反向路径载荷暂停后恢复的规范解决方案
问题核心
在AMBA TLM 2.0的非阻塞反向传输(nb_transport_bw)流程中,发起端返回TLM_ACCEPTED表示暂无法处理响应载荷时,若缺少规范的通知机制,目标端会停止调用nb_transport_bw,导致载荷无法恢复传输。需基于TLM事务机制解决,禁止使用SystemC引脚信号。
规范解决方案
方案1:通过正向路径发送就绪通知
TLM 2.0允许发起端通过正向路径(nb_transport_fw)向目标端发送控制类事务,以此通知目标端自身已准备好接收反向响应。具体实现步骤:
- 定义自定义TLM扩展,标记事务为“反向路径就绪通知”;
- 发起端处理完成、具备接收响应能力时,构造携带该扩展的空事务,通过正向路径发送给目标端;
- 目标端识别到就绪通知后,恢复发送之前暂停的反向响应载荷。
修改后代码示例
// 自定义TLM扩展,用于标记就绪通知 struct ReadyNotification : public tlm::tlm_extension<ReadyNotification> { virtual tlm::tlm_extension_base* clone() const override { return new ReadyNotification(*this); } virtual void copy_from(const tlm::tlm_extension_base& ext) override {} }; struct Target { void neg_clock_edge() { tlm::tlm_sync_enum response = upstream_socket.nb_transport_bw(payload, phase); if (response == tlm::TLM_ACCEPTED) { // 保存暂停的反向载荷和阶段,等待就绪通知 pending_bw_payload = &payload; pending_bw_phase = phase; } } tlm::tlm_sync_enum nb_transport_fw(ARM::AXI::Payload& payload, ARM::AXI::Phase& phase) { ReadyNotification* ext = nullptr; payload.get_extension(ext); if (ext) { // 收到发起端就绪通知,恢复发送反向载荷 if (pending_bw_payload) { upstream_socket.nb_transport_bw(*pending_bw_payload, pending_bw_phase); pending_bw_payload = nullptr; } return tlm::TLM_COMPLETED; } // 处理正常正向事务逻辑... return tlm::TLM_COMPLETED; } ARM::AXI::Payload* pending_bw_payload = nullptr; ARM::AXI::Phase pending_bw_phase; }; struct Initiator { tlm::tlm_sync_enum nb_transport_bw(ARM::AXI::Payload& payload, ARM::AXI::Phase& phase) { // 暂无法处理,保存载荷并启动延迟通知进程 pending_payload = &payload; pending_phase = phase; sc_core::sc_spawn(sc_bind(&Initiator::notify_target_ready, this)); return tlm::TLM_ACCEPTED; } void notify_target_ready() { // 模拟处理延迟,比如等待10ns sc_core::wait(10, sc_core::SC_NS); // 构造就绪通知事务 ARM::AXI::Payload ready_payload; ARM::AXI::Phase phase = ARM::AXI::BEGIN_REQ; ReadyNotification* ext = new ReadyNotification(); ready_payload.set_extension(ext); // 通过正向路径发送通知 downstream_socket->nb_transport_fw(ready_payload, phase); // 释放扩展资源 ready_payload.clear_extension(ext); delete ext; } ARM::AXI::Payload* pending_payload = nullptr; ARM::AXI::Phase pending_phase; };
方案2:目标端周期性重试反向传输
根据TLM 2.0规范,TLM_ACCEPTED的含义是“接收方暂无法处理,但发送方可稍后重试”。目标端可在时钟边沿周期性尝试调用nb_transport_bw,直到发起端返回TLM_UPDATED或TLM_COMPLETED。
修改后Target代码示例
struct Target { void neg_clock_edge() { if (pending_bw_payload) { // 重试发送暂停的反向载荷 tlm::tlm_sync_enum response = upstream_socket.nb_transport_bw(*pending_bw_payload, pending_bw_phase); if (response != tlm::TLM_ACCEPTED) { pending_bw_payload = nullptr; } } else { // 处理新的反向响应 tlm::tlm_sync_enum response = upstream_socket.nb_transport_bw(payload, phase); if (response == tlm::TLM_ACCEPTED) { pending_bw_payload = &payload; pending_bw_phase = phase; } } } ARM::AXI::Payload* pending_bw_payload = nullptr; ARM::AXI::Phase pending_bw_phase; };
为什么不能用SystemC信号
TLM是事务级建模抽象,核心是通过事务交互传递数据和控制信息。使用SystemC引脚信号会打破TLM的抽象层级,降低模型的可移植性、复用性,不符合AMBA TLM 2.0的规范设计意图。
内容的提问来源于stack exchange,提问作者Olumide
相关产品推荐
相关产品推荐

