2. PCIe事务层协议:TLP包格式、Memory Read/Write事务、Completion事务、原子操作
事务层(Transaction Layer)是PCIe协议栈的最顶层,负责将来自设备核心或软件的数据请求封装为事务层包(TLP,Transaction Layer Packet),并通过数据链路层和物理层进行传输。TLP是PCIe通信的基本单元,理解其格式与事务类型是进行DMA延迟分析与故障定位的基础。
2.1 TLP包格式
每个TLP由前缀(Prefix,可选)、TLP头(Header)、数据负载(Data Payload,可选)和CRC校验(Digest,可选)四部分组成。其中TLP头是固定存在的,其长度根据地址格式分为3DW(Double Word,4字节)或4DW两种。
2.1.1 TLP头通用字段
| 字段 | 位宽(bit) | 说明 |
|---|---|---|
| Fmt[1:0] | 2 | 格式编码:00=无数据3DW头,01=无数据4DW头,10=有数据3DW头,11=有数据4DW头 |
| Type[4:0] | 5 | 事务类型编码:00000=MRd,00001=MRdLk,00100=MWr,01010=Cpl,01011=CplD等 |
| TC[2:0] | 3 | 流量类别(Traffic Class),用于QoS和虚拟通道仲裁 |
| TD | 1 | TLP Digest存在标志:1表示末尾有ECRC |
| EP | 1 | 中毒位(Poisoned):1表示数据负载已损坏,接收方应丢弃 |
| Attr[2:0] | 3 | 属性:顺序模型(Relaxed Ordering/ID-Based Ordering)、无侦听(No Snoop)等 |
| Length[9:0] | 10 | 数据负载长度,单位是DW。0x3FF表示1024 DW(4096字节) |
| Requester ID[15:0] | 16 | 请求者标识:Bus[7:0] + Device[4:0] + Function[2:0] |
| Tag[7:0] | 8 | 事务标签,用于匹配请求与完成(Completion) |
| Last DW BE[3:0] / First DW BE[3:0] | 4+4 | 字节使能(Byte Enable),指示数据负载中哪些字节有效 |
2.1.2 TLP包结构SVG图
2.2 Memory Read/Write事务
Memory Read(MRd)和Memory Write(MWr)是PCIe DMA操作中最核心的两类事务。DMA引擎通过MRd从系统内存读取数据,通过MWr将数据写入系统内存。
2.2.1 Memory Read事务(MRd)
- 方向:由DMA引擎(Requester)发起,目标为系统内存(Completer)。
- TLP特征:无数据负载(Fmt=00或01),Type=00000。
- 关键字段:Address(目标内存地址)、Length(读取的DW数量)、Tag(用于匹配后续的Completion)。
- 完成机制:MRd必须等待Completer返回一个或多个Completion with Data(CplD)事务,才能完成读取操作。这是DMA读延迟的主要来源。
2.2.2 Memory Write事务(MWr)
- 方向:由DMA引擎(Requester)发起,目标为系统内存(Completer)。
- TLP特征:携带数据负载(Fmt=10或11),Type=00100。
- 关键字段:Address、Length、Data Payload、Last/First DW BE。
- 完成机制:MWr是Posted事务,即Requester发出后不需要等待Completion即可继续发送后续事务。这使MWr具有比MRd更低的延迟,但也带来了数据一致性风险。
2.2.3 Memory Read/Write事务流程SVG图
2.3 Completion事务
Completion事务是Non-Posted请求(如MRd、I/O Read、Configuration Read)的响应。Completion分为两种:Completion without Data(Cpl)和Completion with Data(CplD)。
2.3.1 Completion事务关键字段
| 字段 | 说明 |
|---|---|
| Requester ID | 原始请求者的Bus/Device/Function,用于路由Completion回正确的请求者 |
| Tag | 与原始请求的Tag匹配,请求者通过Tag识别对应的Completion |
| Completion Status[2:0] | 000=成功(SC),001=不支持请求(UR),010=配置请求重试(CRS),100=完成者异常(CA) |
| Byte Count[11:0] | 本次Completion返回的字节数,用于DMA引擎计算剩余数据量 |
| Lower Address[6:0] | Completion数据在原始请求地址空间中的偏移,用于处理拆分响应 |
2.3.2 Completion事务拆分与合并
PCIe协议允许Completer将一个大MRd请求拆分为多个CplD返回,也允许将多个小MRd合并为一个CplD。拆分行为受RCB(Read Completion Boundary)和MPS(Max Payload Size)约束。
- RCB:通常为64字节或128字节,Completer不能跨越RCB边界返回数据。
- MPS:单个CplD的数据负载不能超过MPS。
- 拆分示例:一个256字节的MRd请求,如果MPS=128字节,则Completer会返回2个CplD,每个携带128字节数据。
2.4 原子操作
PCIe原子操作(Atomic Operations)是PCIe 3.0引入的扩展功能,允许设备在不经过软件锁或中断的情况下,对系统内存执行读-修改-写操作。原子操作通过单个TLP完成,无需多次往返,显著降低了同步延迟。
2.4.1 原子操作类型
| 操作类型 | TLP Type编码 | 功能描述 |
|---|---|---|
| FetchAdd (AtomicOp) | 1 10000 | 从目标地址读取值,加上操作数,再将结果写回。返回原始值。 |
| Swap (AtomicOp) | 1 10001 | 从目标地址读取值,将操作数写入目标地址。返回原始值。 |
| CAS (Compare & Swap) | 1 10010 | 比较目标地址的值与比较操作数,如果相等则写入交换操作数。返回原始值。 |
2.4.2 原子操作TLP格式
原子操作TLP使用4DW头(64位地址),并携带数据负载。其头部的Fmt/Type字段与普通MRd/MWr不同,用于标识原子操作类型。原子操作是Non-Posted事务,需要等待Completion返回结果。
// 原子操作TLP头示例(FetchAdd,64位地址)
// 4DW头,携带数据
Fmt = 11 (有数据4DW头)
Type = 10000 (FetchAdd)
Requester ID = 0x0010 (Bus 0, Device 2, Function 0)
Tag = 0x3A
Address[63:0] = 0x00000000_7FFF_2000 // 目标内存地址
AtomicOp Data (操作数) = 0x00000001 // 加1操作
2.4.3 原子操作与普通DMA读-修改-写对比SVG图
2.5 本章小结
- TLP包格式是PCIe通信的基础,Fmt/Type、Length、Tag、Requester ID是解析和故障定位的核心字段。
- Memory Read(MRd)是Non-Posted事务,必须等待Completion,延迟较高;Memory Write(MWr)是Posted事务,延迟较低但需注意数据一致性。
- Completion事务的Status字段是诊断DMA读错误的第一线索,Byte Count和Lower Address用于验证数据完整性。
- 原子操作通过单次TLP实现读-修改-写,可将同步延迟降低约66%,适用于高性能DMA系统中的无锁同步场景。