🔥点击查看精选 PCIe 系列文章🔥
🔥点击进入【芯片设计验证】社区,查看更多精彩内容🔥
📢 声明:
- 🥭 作者主页:【MangoPapa的CSDN主页】。
- ⚠️ 本文首发于CSDN,转载或引用请注明出处 https://mangopapa.blog.csdn.net/article/details/128940275。
- ⚠️ 本文为非盈利性质,目的为 个人学习记录 及 知识分享。因个人能力受限,存在协议解读不正确的可能。若您参考本文进行产品设计或进行其他事项并造成了不良后果,本人不承担相关法律责任。
- ⚠️ 若本文所采用图片或相关引用侵犯了您的合法权益,请联系我进行删除。
- 😄 欢迎大家指出文章错误,欢迎同行与我交流 ~
- 📧 邮箱:mangopapa@yeah.net
- 💬 直达博主:loveic_lovelife 。(搜索或点击扫码)
1. PCIe 6.0 Flit 概述
PCIe Flit Mode 时,以 Flit 为最小单位进行 Packets 传输。
PCIe 6.0 Flit 由 236B TLP + 6B DLP + 8B CRC + 6B FEC 共 256B 组成,在物理层的逻辑子层进行 Flit 打包及解包(Packing / Unpacking)。Flit 格式如下图所示。
PCIe Flit Packing 流程如图 2 所示。先从 Transaction Layer 及 Data Link Layer 拿到待传输的 TLP 及 DLLP 并按一定规则填充到 TLP Bytes 及 DLP Bytes,然后基于 236B TLP Bytes 及 6B DLP Bytes 计算出 8B CRC,最后三者作为输入计算出 6B ECC。至此,完整的 Flit 打包完毕。
PCIe Flit Unpacking 流程如图 3 所示,其是 Flit Packing 的逆过程。
Flit Packing、Unpacking 过程中,CRC 及 ECC Bytes 长度固定且计算较为成熟,按照既定规则去算去填充/解析即可,比较新的是 TLP 及 DLP Bytes 填充/解析。打包解包过程中涉及到 TLP 的切片、拼接及 NOP 规划填充,涉及 DLP 中的 Flit 状态指示、新的 Ack/Nak 机制、新的 Flow Control DLLP 等等,都需要花些精力去研究。
2. TLP Bytes
我们知道,PCIe 的 DLLP、CRC 及 FEC 均为定长,但不同类型、不同载荷的 TLP 长度是不定的,需要根据具体长度对 TLP 进行切片或者将多个 TLP 拼接。
PCIe TLP 填充到 Flit TLP Bytes 时,有几条常规情况下的规则:
-
同一 TLP 可以放到多笔 Flit 中。 比如 TLP0 Size 超出 236B,那么只能对其进行拆分,放到多笔 Flit 中进行发送;比如 TLP1 Size 为 16B,前 8B 位于 Flit0 TLP Bytes 的末尾,后 8B 位于 Flit1 TLP Bytes 的起首。无论那种情况,均需确保被拆分的 TLP 位于前后相邻的 Flit 中。
-
一笔 Flit 中可以填充多笔 TLP。 TLP Size 大小不一,在 236B TLP Bytes 范围内,允许填充多笔 TLP。注意,填充 TLP 的最大数目是有要求的,即每 Half-Flit 中的 TLP 数目不能超过 8,相关讨论见:《讨论:为什么每 Half-Flit 中的 TLP 数目不能超过 8 个?》 。对于接收端而言,若接收端在 Half-Flit 中检测到了超过 8 笔 TLP,可以记录并上报错误。
-
TLP 在 Flit 内的起始位置不受限于任何边界约束。 PCIe Webinar Q&A 中是这么说的,但这么说并不严谨,这么说容易被曲解为 TLP 可以在 TLP Bytes 中任一 Byte 位置起始。考虑到 TLP 和 NOP Size 均为 DW 整数倍,TLP 的起始位置只可能出现在 DW Boundary 上。如果某 TLP 之前为 NOP,还需确保 TLP 起始位置 4DW 边界对齐。
-
当 Transaction Layer 没有 TLP 要传输时,填充 NOP TLP(1DW)。一旦开始插入 NOP TLP,在下一 4DW Boundary 之前的 TLP Bytes 均需填充 NOP。也就是说,NOP 之后的 TLP 要求 4DW 边界对齐,即边界对齐的 4DW 之内,可以全部为 TLP,可以全部为 NOP,可以为 TLP -> NOP,但不允许出现 NOP -> TLP 的转换。
还有一些 TLP 出粗情况下的必要但不太常用的规则:
-
Nullified 或 Poisoned TLP 问题。
-
如果当前 Flit 最后一笔 TLP 为 Poisoned 或 Nullified TLP,需要通过 DLP Bytes 发送 Flit_Marker,通过 Flit_Marker 中的 Flit_Statue 将该 TLP 标记为 Posioned 或 Nullified(作用同 Non-Flit Mode 时的 EDB)。若某 Poisoned / Nullfied TLP 跨过当前 Flit 延续到了下一 Flit,这两笔 Flit 的 Flit_Marker 中 Flit_Status 都要对 Poisoned 或 Nullified 状态进行指示。
-
接收端接收到 Nullfied 状态的 TLP 后,将其作废,并释放其早前占用的 Credits。
-
若发送端发送 TLP 过程中发现某 TLP Nullfied 或 Poisoned,当前 Flit 中该 TLP 之后的 TLP Bytes 全部填充 NOP TLP。
-
-
其他。 我们看到一条补充一条。
释义:
Nullified
,作用同 Non-Flit Mode 时的 EDB,常用于 Switch Cut-Through Mode。TLP 边收边发,收到最后发现 TLP 有问题,就得通过 EDB 来告知下游设备将其作废。Poisoned
,Switch 转发 TLP 过程中发现 Data Payload 出错,但又不得不继续传递该 TLP,则将 TLP Header 中的 EP 位置一,告知下游数据出错。
3. DLP Bytes
DLP Bytes 共 6B,按照作用可以分为两部分:
- DLP[0:1]。该部分有以下作用:
- 指示当前及前一 Flit 的类型(IDLE, NOP 或 Payload Flit)。
- 指示 DLP[2:5] 中 DLLP Payload 的类型(DLLP Payload 或 Optimized_Update_FC/Flit_Marker)。
- Flit 粒度 Ack/Nak 机制的实现。
- DLP[2:4]。该部分为 DLLP Payload,携带了 PCIe DLLP,比如 Flow Control DLLP、Flit_Marker 及其他 Vendor 自定义的 DLLP 等。
虽然一个 Flit 中的 DLP Bytes 远少于 TLP Bytes,但为了准备这 6B DLP 而下的功夫却要比 236B TLP 多。
4. CRC Bytes
CRC Bytes 共 8B,由 236B TLP + 6B DLP 作为输入计算得到。
5. ECC Bytes
FEC 是指前向纠错,ECC 是指算出来的纠错码。PCIe Flit Mode 采用 3 路交织的方式对 236B TLP + 6B DLP + 8B CRC 进行计算。
6. 参考
- PCI Express 6.0 Base Spec
|
🔥 精选往期 PCIe 协议系列文章🔥
⬆️ 返回顶部 ⬆️