棋子 · 2024年12月24日

PCIe 学习(四)

3 数据链路层

数据链路层是 PCIe 协议的中间一层,起着承上启下的作用。

3.1 DLLP

本节分析一下数据链路层的数据包(Data Link Layer Packet,DLLP)。

DLLP 只用于链路两端的数据链路层通信。DLLP 的主要用途是 TLP 流量控制,链路初始化,电源管理,事务层与物理层之间信息传递等。与 TLP 不同的是,DLLP 不需要路由,只是在一条链路的两端传递。

image.png

DLLP 的大小固定,只有 6-Byte 的有效信息。其中 Byte-0 是 DLLP 类型编码,Byte-1/2/3 根据 DLLP 不同类型有不同含义,Byte-4/5 是 16-bit 的 CRC。

Image

Gen 5 中的 DLLP 类型编码整理如下表:

image.png

表中带有 MR 的 DLLP 都是为多根虚拟化(MR-IOV)准备的,暂且忽略。

Ack/Nak DLLP 格式

Ack/Nak DLLP 用于数据链路层的 Ack/Nak 协议。

Image

AckNak_Seq_Num 字段指示哪些 TLP 被影响,成功(Ack)或者不成功(Nak)。下一节详细分析数据链路层的 Ack/Nak 协议。

NOP DLLP 格式

接收端接收到 NOP,检查 CRC,然后放弃该 DLLP,不做任何动作。

Image

InitFC1/InitFC2/UpdateFC 格式

InitFC1/InitFC2 用于流量控制的初始化;UpdateFC 用于更新流量控制的信用值。

Image

Image

Byte-0 的高 4-bit 指示是哪种子缓冲区。

DataFC 字段指示事务层中 Data 缓冲区的信用值,HdrFC 指示 Header 缓冲区的信用值。

DataScale 和 HdrScale 字段分别是 Data 和 Header 缓冲区信用值放大系数。

V[2:0]字段是虚拟通道(VC)的 ID。

Image

各字段具体含义可参考流量控制一节。

PM DLLP 格式

PM DLLP 是一组 DLLP 的统称,用于电源管理。Byte-0 的最第三位是不同的编码,目前 Gen 5 中的 PM DLLP 包括:PM_Enter_L1,PM_Enter_L23,PM_Active_State_Request_L1,PM_Request_Ack。

具体含义留到电源管理章节分析。

Image

Vendor-specific DLLP 格式

Vendor-specific DLLP 的 Byte-1/2/3 定义取决于产商。

Image

Data Link Feature DLLP 格式

Image

Feature Support 字段指示发送端口支持的特性,该值与其 Data Link Feature Capability 寄存器对应。

Image

3.2 ACK/NAK 协议

3.2.1 Ack/Nak 协议原理

数据链路层的一个重要职责是保证 TLP 正确传输。尤其是 Posted 类型的事务,请求者发出事务后就认为事务结束,但完成者是否真的接收到了事务吗?

数据链路层在向物理层传输 TLP 之前,给 TLP 前面加上序列号(Sequence Number),后面加上 LCRC。序列号是连续递增的,每个 TLP 分配一个。有了序列号和 LCRC,链路两端的数据链路层可以使用 Ack/Nak 协议来保证链路上的传输。

Image

发送端为每个 TLP 加上序列号和 LCRC,同时将要发送的数据包存储在本地(数据链路层)的重试缓冲区(Replay Buffer)。接收端解析收到的数据包,首先计算 LCRC,如果没发现有错误,向发送端发送 Ack DLLP,如果有错误,向发送端发送 Nak DLLP。不管是 Ack DLLP 还是 Nak DLLP,其中都包含有序列号。

Image

这里需要注意,接收端并不是对每个接收到的 TLP 都会返回 Ack/Nak DLLP,为了节省链路资源,通常是是攒齐了几个再发 Ack/Nak DLLP。发送端在接到 Ack DLLP 后,得到其中的序列号,知道此序列号之前的 TLP 都已经被正确接收,因此将本地 Replay Buffer 中保存的这些 TLP 都清除掉;如果是接收到 Nak DLLP,说明此 DLLP 中的序列号之后的 TLP 中,至少有一个发生传输错误,因此需要将序列号之后的 TLP 全部重新传输一次。

Image

上图是 Ack/Nak DLLP 的格式,Byte-0 是 Ack/Nak 的编码。Byte-2 和 3 是序列号字段,共有 12-bit,因此序列号的最大数值是 4095。初始化后,序列号计数器从 0 开始递增,到了 4095 后,下一个序列号是 0,也就是说序列号的数值是回滚(Roll-back)式的。所以,对于发送端来说,有可能发生上一次正确接收的序列号是 4093,下一个 Ack/Nak 返回的序列号是 2 的这种情况。

LCRC 是 32-bit,对序列号和整个 TLP 进行校验。DLLP 的 CRC 是 16-bit,是对 DLLP 的校验。不要混淆了两个 CRC。

为了实现 Ack/Nak 机制,PCIe 设备需要在数据链路层实现相关的逻辑设计。

Image

3.2.2 发送端设计

对于发送端,需要实现:

  • 12-bit 的 NEXT_TRANSMIT_SEQ 计数器。此计数器生成将分配给下一个传入 TLP 的序列号。在系统复位期间,此计数器值复位成 0,随后在系统正常工作期间递增,到了 4095 后回滚到 0,继续递增
  • LCRC 生成器,用于产生 32-bit 的 CRC,对序列号和 TLP 进行校验
  • Replay Buffer,此缓冲区按照传输顺序存储 TLP,包括序列号和 LCRC。当发送端接收到 Ack 时,它从重试缓冲器中清除序列号等于或早于 Ack 中编号的 TLP。通过这种方式,该设计允许一个 Ack 代表几个成功的 TLP,从而减少了必须发送的 Ack 的数量。如果接收到 Nak,在 Nak 中的序列号仍然指示接收到的最后一个成功传输的数据包。因此,即使接收到 Nak 也会导致发射端的 Replay Buffer 中清除 TLP,即 Nak DLLP 中的序列号之前的 TLP(包含该序列号指示的 TLP)都会从 Replay Buffer 中清除,而序列号之后的 TLP 会被重新传输
  • REPLAY_TIMER 计数器,代表的是计时器。如果超时,说明发送端发送了一个或多个 TLP,但是在预期的时间内没有得到 Ack 或者 Nak。超时会触发 Replay Buffer 中的所有内容被重新传输,并重置此计数器
  • 2-bit 的 REPLAY_NUM,用于跟踪接收到 Nak 或 REPLAY_TIMER 超时后的重试次数。当 REPLAY_NUM 计数从 11b 回滚到 00b(表示 4 次尝试传递同一组 TLP 失败)时,数据链路层自动强制物理层重新训练链路(LTSSM 进入恢复状态)
  • 12-bit 的 ACKD_SEQ 寄存器,用于保存最近一次接收到的 Ack/Nak DLLP 中的序列号
  • DLLP CRC 检查模块,校验接送端返回的 Ack/Nak DLLP 中的 CRC 值
3.2.3 接收端设计

对于接收端,需要实现:

  • LCRC 检查模块,校验 TLP 的 LCRC 值
  • 12-bit 的 NEXT_RCV_SEQ 计数器,用于跟踪预期序列号,验证顺序数据包接收。在系统复位时或数据链路层处于非活动状态时,它被初始化为 0,并且对于转发到事务层的每个良好 TLP,它会递增一次
  • 序列号检查模块
  • NAK_SCHEDULED 标志,当接收端准备返回 Nak 给发送端时,置高该标志位,当接收端成功的接收到 TLP 时,清除该标志位
  • AckNak_LATENCY_TIMER,每当接收端成功接收到尚未确认的 TLP 时,此计时器就会运行。一旦计时到期,接收端就需要发送一个 Ack 或 Nak。
  • Ack/Nak 生成器,对正常接收的 TLP 产生 Ack,对失败的 TLP 产生 Nak。
3.2.4 PCIe 数据包优先级

实际上,PCIe 是双单工传输,从 PCIe 组件角度看需要实现上述的全部逻辑。

到这里,我们总结一下 PCIe 链路上的数据包,有 TLP/DLLP/Ordered Sets 三种,Ordered Sets 是在物理层,后面再讲。PCIe 协议建议的处理优先级如下(从高到底):

  1. Completion of any TLP or DLLP currently in progress (highest priority)
  2. Ordered Sets
  3. Nak DLLP
  4. Ack DLLP
  5. Flow Control
  6. Replay Buffer re‐transmissions
  7. TLPs that are waiting in the Transaction Layer
  8. All other DLLP transmissions (lowest priority)
3.2.5 直通模式

最后,提一下 Switch 的直通模式(Cut-Through Mode)。对于 Switch,只是负责转发 TLP,正常做法是 Switch 的 TLP 从入口(Ingress)进入 Switch,Switch 检查接收到的 TLP,如果没有传输问题,则向出口(Egress)转发 TLP。如果 TLP 的数据载荷很大,这种方式无疑会增加延迟。另外一种选择是,Switch 很快从 TLP Header 中得到路由信息(PCIe 是串行总线,TLP Header 先于 Data 传输),接下来 Switch 可以假设数据包是好的,直接向出口转发。这种方式就是 Switch 直通模式。

不过直通模式存在一个问题,如果随后在 Switch 入口端口发生了传输错误,入口可以发送 Nak 要求重新传输。但是对于出口端口,该如何处理?不能简单粗暴的清除出口的 Replay Buffer,因为出口端口的链路对端还在等待继续接收。这时出口需要向对端指出该 TLP“失效(nullified)”。失效数据包以 EDB 符号而不是 END 符号终止,TLP 的 32 位 LCRC 从原始计算值反转(1 的补码)。接收到无效数据包的接收端则会直接丢弃该数据包,不做任何处理。

下面是一个 Switch 直通的示例,TLP 传输方向从左向右。

  1. 一个 TLP 发送到 Switch 的 Ingress 端口,该 TLP 在传输过程中被损坏,但是现在还不知道
  2. Switch 解析 TLP Header,向 Egress 端口转发
  3. Switch 接收到完整的 TLP,通过 LCRC 发现传输错误,向上游发送 Nak
  4. 在 Switch 的 Egress 端口,Switch 用 EDB 替换坏 TLP 末端的 END 帧符号,并反转计算的 LCRC 值。TLP 现在变成“失效”,Switch 将其从 Replay Buffer 中丢弃。
  5. Switch 下游的 EP 检测到 EDB 符号和反转的 LCRC,知道这是一个无效数据包,直接丢弃数据包。注意,EP 不会返回 Nak。
  6. Image

END

作者:老秦谈芯
文章来源:老秦谈芯

推荐阅读

更多 IC 设计干货请关注IC设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
20362
内容数
1310
主要交流IC以及SoC设计流程相关的技术和知识
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息