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 适配器常作为发起者与目标端之间的协议转换层。
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 | 响应结束:发起者确认接收响应完成 |
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,结合相位传递 |
| 事务生命周期 | 单次调用完成 | 多阶段:请求→响应,可流水线化 |
| 硬件加速适用性 | 适合简单读写、调试接口 | 适合流水线加速器、高吞吐场景 |
| 实现复杂度 | 低,易于理解和使用 | 高,需要管理相位和回调 |