2. TLM-2.0标准:核心接口定义、发起者与目标端、传输描述与时间标记

TLM-2.0 是 SystemC 标准中用于事务级建模的核心规范,它定义了发起者与目标端之间的通信契约、传输描述方法以及时间标记机制。理解 TLM-2.0 的核心接口是构建硬件加速验证环境的基础。

2.1 核心接口定义

TLM-2.0 定义了三种核心接口,分别对应不同的传输模式。这些接口通过 tlm_fw_transport_if 和 tlm_bw_transport_if 两个基类实现,形成发起者与目标端之间的双向通道。

接口名称 方向 传输模式 典型应用场景
nb_transport_fw 发起者 → 目标端 非阻塞(Non-blocking) 流水线事务、高吞吐量加速器通信
nb_transport_bw 目标端 → 发起者 非阻塞(回呼) 延迟响应、中断通知、完成回调
b_transport 发起者 → 目标端 阻塞(Blocking) 简单读写、CPU 访存模型、调试接口
关键点: 非阻塞接口 nb_transport_fw 和 nb_transport_bw 必须成对实现,构成完整的双向通信;阻塞接口 b_transport 是单向调用,目标端在函数返回前完成传输。

2.2 发起者与目标端

TLM-2.0 将通信实体严格区分为两类角色,这种区分决定了接口的调用方向和数据流控制权。

  • 发起者(Initiator): 主动发起事务的模块。它调用 b_transport 或 nb_transport_fw 向目标端发送请求。发起者必须实现 nb_transport_bw 回调接口以接收目标端的响应。
  • 目标端(Target): 被动响应事务的模块。它实现 b_transport 和 nb_transport_fw 接口,处理来自发起者的请求,并通过 nb_transport_bw 返回状态或数据。
适配器视角: 在硬件加速场景中,发起者通常是 CPU 模型或测试激励发生器,目标端是硬件加速器模型或总线桥接器。TLM 适配器常作为发起者与目标端之间的协议转换层。
TLM-2.0 发起者与目标端通信结构 发起者 Initiator 调用 nb_transport_fw 或 b_transport 实现 nb_transport_bw 目标端 Target 实现 nb_transport_fw 和 b_transport 调用 nb_transport_bw nb_transport_fw (非阻塞请求) nb_transport_bw (非阻塞响应) b_transport (阻塞传输) 发起者主动调用,目标端被动响应;nb_transport 支持双向非阻塞通信

2.3 传输描述与通用事务对象

TLM-2.0 使用 tlm_generic_payload 作为标准事务对象,封装了传输所需的所有属性。该对象通过指针传递,避免数据拷贝,适合高性能硬件加速场景。

属性 类型 描述
command tlm_command 读写命令:TLM_READ_COMMAND / TLM_WRITE_COMMAND
address uint64 目标地址,支持 64 位地址空间
data_ptr unsigned char* 指向数据缓冲区的指针
data_length uint64 传输数据长度(字节数)
response_status tlm_response_status 传输结果状态:TLM_OK_RESPONSE / TLM_ERROR_RESPONSE 等
dmi_allowed bool 是否允许直接内存接口(DMI)访问
byte_enable_ptr unsigned char* 字节使能掩码指针(可选)
streaming_width uint64 流式传输宽度(可选)
性能优化: 在硬件加速适配器中,data_ptr 通常指向 DMA 缓冲区或加速器本地存储器,避免数据在发起者和目标端之间多次拷贝。dmi_allowed 标志可用于启用直接内存访问路径。

2.4 时间标记与相位管理

TLM-2.0 通过 sc_time 和相位(Phase)机制实现时间精确的事务建模。时间标记决定了事务在仿真时间轴上的位置,相位则描述事务在非阻塞传输中的生命周期阶段。

2.4.1 时间标记

  • 阻塞传输: b_transport 通过引用参数 sc_time &delay 传递延迟时间。目标端在函数返回前将延迟累加到该参数上,发起者负责将延迟加入仿真时间。
  • 非阻塞传输: nb_transport_fw 和 nb_transport_bw 通过 sc_time 参数传递时间偏移,结合相位指示事务的当前状态。

2.4.2 标准相位定义

相位枚举 缩写 含义
BEGIN_REQ BR 请求开始:发起者开始发送事务请求
END_REQ ER 请求结束:目标端确认接收请求完成
BEGIN_RESP BRP 响应开始:目标端开始返回响应数据
END_RESP ERP 响应结束:发起者确认接收响应完成
非阻塞传输相位时序(nb_transport) 时间 → 发起者 目标端 BEGIN_REQ END_REQ BEGIN_RESP END_RESP nb_transport_fw(BR) 处理 nb_transport_bw(BRP) 相位序列:BEGIN_REQ → END_REQ → BEGIN_RESP → END_RESP

2.5 传输描述代码示例

以下代码展示了发起者使用阻塞传输和非阻塞传输的典型实现模式:

// 阻塞传输示例:发起者调用 b_transport
void initiator_module::blocking_write(uint64_t addr, unsigned char* data, unsigned int len) {
    tlm_generic_payload trans;
    sc_time delay = SC_ZERO_TIME;

    trans.set_command(TLM_WRITE_COMMAND);
    trans.set_address(addr);
    trans.set_data_ptr(data);
    trans.set_data_length(len);
    trans.set_response_status(TLM_INCOMPLETE_RESPONSE);

    // 调用目标端的 b_transport
    target_socket->b_transport(trans, delay);

    // 检查响应状态
    if (trans.get_response_status() != TLM_OK_RESPONSE) {
        SC_REPORT_ERROR("TLM", "Blocking write failed");
    }

    // 累加延迟到仿真时间
    wait(delay);
}

// 非阻塞传输示例:发起者调用 nb_transport_fw
tlm_sync_enum initiator_module::nb_write(uint64_t addr, unsigned char* data, unsigned int len) {
    tlm_generic_payload trans;
    sc_time delay = SC_ZERO_TIME;
    tlm_phase phase = BEGIN_REQ;

    trans.set_command(TLM_WRITE_COMMAND);
    trans.set_address(addr);
    trans.set_data_ptr(data);
    trans.set_data_length(len);
    trans.set_response_status(TLM_INCOMPLETE_RESPONSE);

    // 调用目标端的 nb_transport_fw
    tlm_sync_enum status = target_socket->nb_transport_fw(trans, phase, delay);

    if (status == TLM_UPDATED && phase == END_REQ) {
        // 目标端立即接受请求,等待响应回调
        wait(delay);
        return TLM_ACCEPTED;
    }
    return status;
}
注意事项: 在非阻塞传输中,发起者必须正确处理 tlm_sync_enum 返回值(TLM_ACCEPTED、TLM_UPDATED、TLM_COMPLETED),并根据相位变化管理事务生命周期。忽略返回值可能导致仿真死锁或时序错误。

2.6 核心接口对比总结

特性 b_transport(阻塞) nb_transport(非阻塞)
调用方式 同步阻塞,函数返回时传输完成 异步非阻塞,通过相位和回调完成
时间标记 引用参数 sc_time &delay 值参数 sc_time,结合相位传递
事务生命周期 单次调用完成 多阶段:请求→响应,可流水线化
硬件加速适用性 适合简单读写、调试接口 适合流水线加速器、高吞吐场景
实现复杂度 低,易于理解和使用 高,需要管理相位和回调