PCI-Express-Technology(五)

https://github.com/ljgibbslf/Chinese-Translation-of-PCI-Express-Technology-/blob/main/5%20TLP%20%E5%85%83%E7%B4%A0.md

5.1 基于数据包协议的介绍(Introduction to Packet-Based Protocol)

5.1.1 概括(General)

不同于并行总线,PCIe 这样的串行总线不使用总线上的控制信号来表示某时刻链路上正在发生什么。相反地,PCIe 链路上的发送方发出的比特流必须要有一个预期的大小,还要有一个可供接收方辨认的格式,这样接收方才能理解比特流的内容。此外,PCIe 在传输数据包时并不使用任何直接握手机制(immediate handshake)。

除了逻辑空闲符号(Logical Idle symbol)和 Ordered Set 的物理层包外,在活跃的 PCIe 链路上传输的信息的基本组块被称为 Packet(包),包是由符号组成的。链路上交换的两类主要的数据包为高层的 TLP(Transaction Layer Packet,事务层包),和低层的用于链路维护的包称为 DLLP(Data Link Layer Packet,数据链路层包)。这些包和它们的传输流如图 5‑1 所示。物理层的 Ordered Set 也是一种包,但是它并不像 TLP 和 DLLP 一样会被封装上包起始符号和包结束符号(也就是前面章节所讲的组帧符号),并且 Ordered Set 也并没有像 TLP 和 DLLP 一样的字节条带化过程,相反地,Ordered Set 会在链路的每个通道(lane)上都复制一份,而不是像字节条带化一样把信息按字节分配到各个通道上。

图 5‑1 TLP 和 DLLP 包

5.1.2 使用基于数据包协议的动机

使用基于包的协议(Packet-Based Protocol)有三个明显的优点,特别是对于数据完整性(data integrity)来说:

5.1.2.1 精心定义的数据包格式

像 PCI 这种早期的总线,它们允许总线上不确定数据量大小的传输,这使得只要传输没有结束就无法识别出数据荷载(payload)的边界。此外,任何一个设备都可以在此次传输完成前终止这个传输,这使得发送方很难去计算并传输一个覆盖了整个数据荷载的校验和或者 CRC。相反地,PCI 使用了一种简单的奇偶校验的方案,并在每个数据阶段(data phase)进行奇偶校验。(这里如果没理解请参阅 Chapter 1 内的 PCI 相关内容)

相比之下,PCIe 包具有一个已知的大小和格式。位于包的开头的部分为 Header,它用来指示这个包的类型,并包含了必需字段(required field)和可选字段(optional field)。除了地址字段以外,Header 中的其他字段长度都是固定的,地址字段可以为 32bit 也可以为 64bit。一旦一次传输开始,接收方不能暂停或者提前终止它。这种结构化的格式使得我们可以在 TLP 中加入一些信息来更有利于进行可靠的传输,例如加入组帧符号(framing symbol)、CRC、以及一个包的序列号(Sequence Number)。

5.1.2.2 使用组帧符号定义包的边界

在 PCIe Gen1 和 Gen2 操作模式中使用的是 8b/10b 编码,因此在这 Gen1 和 Gen2 中每个 TLP 和 DLLP 在发送前都会使用起始符号(Start)和结束符号(End)这两种控制符号来进行组帧,这样就可以给接收方清晰地定义出包的边界。这是在 PCI 和 PCI-X 上的重大改进,在 PCI 和 PCI-X 中使用一个单独的 FRAME# 信号来指示一个事务的开始和结束,如果 FRAME# 出现了毛刺,或者其他的控制信号出现了毛刺,那么都有可能造成目标设备对总线行为的误解。一个 PCIe 接收方必须在最后的链路活动开始或结束之前,就正确完成一个完整 10bit 符号的译码,这样接收方能更容易识别不期望出现或者无法识别的符号,并且将其作为一个错误来处理。

对于 PCIe Gen3 使用的 128b/130b 编码来说,控制字符不再被使用,并且也没有组帧符号了。对于更多的关于 Gen3 编码与早期版本的差异的内容,请参阅 Chapter 12“Physical Layer-Logical(Gen3)”。

5.1.2.3 使用 CRC 保障整个数据包的正确传输

在 PCI 体系结构中,会在地址阶段(address phase)和数据阶段(data phase)中使用奇偶校验边带(side-band)信号,但是在 PCIe 中则不同。PCIe 中使用带内(in-band)的 CRC 值来验证整个数据包是否进行了无错误的传输。同时 TLP 还会被发送方的数据链路层添加上一个序列号(Sequence Number),这使得当这个序列号的数据包传输出错时可以很简单的定位到它,并进行自动的重传。发送方会在自己的 Retry Buffer 内保存每个 TLP 的一个副本,直到接收方确认了这个 TLP 成功无错传输后才会将副本清除。这种 TLP 的确认机制被称为 Ack/Nak 协议(更多内容请参阅 Chapter 10 “Ack/Nak Protocol” ),它用来形成基础的链路级 TLP 错误检测和纠正机制。这种 Ack/Nak 协议提供的错误恢复机制使得我们可以在问题发生的地方或者链路上及时的解决问题,但是这也要求有一个本地的硬件解决方案来支持这种协议。

5.2 TLP 细节(TLP Details)

在 PCIe 中,高层次事务起源于发送方的 Device Core,终止于接收方的 Device Core。事务层会处理这些请求,其中,发送端的事务层组装 TLP,接收端的事务层解析 TLP。在这个过程中,每个设备的数据链路层和物理层也会参与包的组装。

5.2.1 TLP 的组包和拆包

如图 5‑2 所示的是链路的发送端组装 TLP 和接收端拆解 TLP 的一般流程。现在让我们讲一讲从一个包的生成,到它被传送到接收端的 Device Core 的各个步骤。下面列出了 TLP 组包和拆包的关键阶段,列出的编号与图 5‑2 中的编号相对应。

图 5‑2 PCIe TLP 的组包与拆包

发送方
  1. 设备 A 的 Device Core 向它的 PCIe 接口发送一个请求(具体 Device Core 是如何给 PCIe 接口发送请求的,这并不是 PCIe 协议或者本书的讨论范畴)。这个请求中包括:
  • 目标地址或者 ID(也就是路由信息)

  • 源端信息,例如 Requester ID 和 Tag

  • 事务类型/数据包类型(需要执行的命令,例如一个内存读取 MRd)

  • 数据荷载大小 payload size 和数据荷载内容(如果 TLP 需要带数据)

  • 流量类型(Traffic Class,用于分配数据包的优先级)

  • 请求的自身属性(No Snoop 无窥探、Relaxed Ordering 宽松排序,等等)

  1. 基于这个请求,事务层将会组建 TLP Header,并在其后附上数据荷载(如果有),以及如果启用并支持可选项的话也可以再附上 ECRC(End-to-End CRC)。随后 TLP 就会被放入一个虚拟通道 Buffer。这个虚拟通道会根据事务排序规则来管理 TLP 的顺序,并在向下转发 TLP 到数据链路层之前,确认接收方有足够的 Buffer 来接收一个 TLP。

  2. 当 TLP 到达数据链路层,它会被分配一个序列号(Sequence Number),并基于 TLP 的内容和序列号来计算出一个 LCRC(Link CRC)来附加在原 TLP 后。然后会将经过这些处理过程之后的 TLP 保存一个副本,这个副本会保存在数据链路层的重传 Buffer(Replay Buffer,也可称为 Retry Buffer)中,这是为了应对传输出错的情况。与此同时,这个 TLP 也会被向下转发至物理层。

  3. 物理层将会进行一系列的操作来准备对这个数据包进行串行传输,包括字节条带化(Byte Striping)、扰码(Scrambling)、编码(Encoding)以及并串转换(Serializing)。对于 Gen1 和 Gen2 的设备,当进行 8b/10b 编码时,会将 STP 和 END 这两个控制字符分别加在 TLP 的首端和尾端。最后,这个数据包通过链路进行传输。在 Gen3 操作模式中,STP 令牌(STP token)会被添加在 TLP 的首端,但是并不会在尾端加上 END,而是在 STP 令牌中包含 TLP 大小的信息来判断 TLP 的尾部位置。

接收方
  1. 在接收方(本例中是 Device B),为了发送包所做的一切准备现在都必须撤销。物理层将对比特流进行串并转换(deserialize)、对串并转换后的符号进行解码,然后再进行字节反条带化(un-stripes)。控制字符将被移除,因为它们仅在物理层有意义,然后这个数据包就会被向上转发至数据链路层。

  2. 数据链路层将会计算 CRC(具体一点是 LCRC)并与 TLP 中的 CRC 进行比较。如果 CRC 比较结果相同,那么就再检查序列号(Sequence Number)。如果都没有出现错误,那就把 CRC 和序列号都从 TLP 剥除,并随后将 TLP 向上转发给接收方事务层,与此同时要通过返回给发送方一个 Ack DLLP 来通知发送方这个 TLP 被成功接收。相反地,如果前面的过程中检查出了错误,那么就要返回给发送方一个 Nak DLLP,这样发送方将会使用它的重传 Buffer 来对 TLP 进行重传。

  3. 在事务层,TLP 被进行解码,并将 TLP 内的信息传递给 Device Core 来进行相应的操作。如果当前接收设备就是数据包的最终目的地,那么它可以检查 ECRC 错误,并在发现任何 ECRC 错误时报告给 Device Core。

5.2.2 TLP 结构

一个事务层包 TLP 中每个字段域的基本用法在表 5‑1 中进行了定义。

img

表 5‑1 TLP Header 的 Type 字段定义了事务不同种类

下面对表 5‑1 中的内容进行复述。

  • Header

  • 协议层次:事务层

  • 该组件用法:大小为 3 或 4DW(12 或 16Bytes)。Header 的格式会随类型而变化,但是 Header 也定义了一些参数,包括:

    • 事务类型(Transaction Type)

    • 目标地址、ID 等

    • 传输数据量大小(如果有数据)、字节使能(Byte Enable)

    • 属性(Attribute)

    • 流量类型(Traffic Class)

  • Data

  • 协议层次:事务层

  • 该组件用法:可选的 1-1024DW 大小的数据荷载,具体的大小由字节使能或者字节对齐的开始和结束地址来进行描述。需要注意指定的长度不能为 0,但是一个 0 长度的读取可以通过指定长度为 1DW 然后将字节使能全部置为 0 来进行近似处理(在某些情况下会使用)。来自 Completer 的结果数据虽然是未定义的种类,但是 Requester 并不使用它,因此就和指定 0 长度的目的等效了。

  • Digest/ECRC

  • 协议层次:事务层

  • 该组件用法:可选的功能。当需要使用时,ECRC 的大小永远为 1DW。

5.2.3 通用 TLP Header 格式(Generic TLP Header Format)

5.2.3.1 概括(General)

如图 5‑3 中,展示了一个 4DW 的通用 TLP Header 的格式和内容。在本节内,会对几乎所有事务的 TLP Header 中的公共字段进行总结,并会在稍后讨论与特定事务类型相关 Header 格式差异。

 

 

img

图 5‑3 通用 TLP Header 的各字段域

5.2.3.2 通用 Header 各字段摘要

表 5‑2 中对通用 TLP Header 中的每个字段的大小和用途进行了总结。需要注意的是,在图 5‑3 中被标注为“R”的字段是保留字段(reserve),应该被置为 0。

Header 中的字段名Header 中的位置字段作用
Fmt[2:0] 格式 (Format) Byte 0 Bit 7:5 这些 bit 的编码信息是关于 Header 的大小,以及这个 TLP 中是否存在数据荷载部分:
000b:3DW Header,无数据荷载
001b:4DW Header,无数据荷载
010b:3DW Header,有数据荷载
011b:4DW Header,有数据荷载
100b:1DW,属于 Prefix TLP 不难发现,除了 Prefix TLP 外,只要 Fmt[0]=0 那么就是 3DW Header,反之则为 4DW Header。若 Fmt[1]=0 那么就无数据荷载,反之则有数据荷载。 对于低于 4GB 的地址,必须使用 3DW Header。协议规定,如果使用 4DW Header 但是地址小于 4GB,也就是说将 64bit 地址的高 32bit 置为 0,那么这种情况下接收方的行为是未进行定义的(undefined)。
Type[4:0] 类型 Byte 0 Bit 4:0 这些 bit 编码的信息是 TLP 的不同事务类型。Type 字段用来跟 Fmt[1:0]字段一起指定了事务类型、Header 大小、以及是否存在数据荷载。更多详细信息请参阅“Generic Header Field Details”一节。
TC[2:0] 流量类型 (Traffic Class) Byte 1 Bit 6:4 这些 bit 表示将应用于这个 TLP 和与之完成相关(如果需要完成包)的流量类型:
000b:Traffic Class 0(默认)
001b:Traffic Class 1 ……
111b:Traffic Class 7 TC 0 是默认类型,而 TC 1-7 是用来提供差异化的服务。更多信息请参阅“Traffic Class”一节。
Attr[2] 属性 (Attribute) Byte 1 Bit 2 这个第三位的 Attribute 位(它共有 3 位)用于表示这个 TLP 是否使用基于 ID 的排序(ID-based Ordering)。更多内容请参阅“ID Based Ordering”一节。
TH TLP 处理提示 (TLP Processing Hints) Byte 1 Bit 0 它用于表示何时 TLP 中会包含 TLP 提示(TLP Hints),以便让系统了解如何更好的处理这个 TLP。更多内容请参阅“TPH(TLP Processing Hints)”。(XIL暂不支持此功能)
TD TLP 摘要 (TLP Digest) Byte 2 Bit 7 如果 TD=1,那么这个 TLP 中将包括可选的 4Byte TLP Digest 字段,也就是 ECRC 值。 它有一些规则:
所有的接收者都必须要通过这个 bit 来检查是否存在 Digest 字段。
如果一个 TLP 的 TD=1,但是它又没有 Digest,那么它将被当做畸形 TLP(Malformed TLP)处理。
如果接收设备支持 ECRC 校验,且此 TLP 内 TD=1,那么这个接收设备必须进行校验。
如果一个作为 TLP 最终目的地的设备并不支持 ECRC 校验(因为这是可选功能),那么它必须要忽略 Digest 字段。 更多内容请参阅“CRC”和“ECRC Generating and Checking”这两节。
EP 受污染的数据 (Poisoned Data) Byte 2 Bit 6 如果 EP=1,那么就认为所有伴随此数据的数据都是无效的,尽管相关事务依然允许正常的完成。关于 Poisoned 数据包的更多内容,请参阅“Data Poisoning”一节。
Attr[1:0] 属性 (Attributes) Byte 2 Bit 5:4

Bit 5 = Relax Ordering(宽松排序):

当它被置为 1 时,这个 TLP 会启用 PCI-X 的宽松排序。

如果它为 0,则是用 PCI 的严格的 PCI 排序(strict PCI ordering)。

Bit 4 = No Snoop(无窥探):当置为 1 时,Requester 的意思是这个 TLP 不会存在 host cache 一致性的问题(host cache coherency issues),因此系统硬件可以通过跳过普通处理器对这个请求的 cache 窥探,以此来节省时间。而当这一位被置为 0 时,需要进行 PCI-type 的 cache 窥探保护。

AT[1:0] 地址类型 (Address Type) Byte 2 Bit 3:2

涉及虚拟地址和物理地址的转换,虚拟地址中的一部分由物理地址映射;转换规则参考<Address Tranlation Services>

对于 Memory 和 Atomic 请求来说,这个字段用于支持虚拟化系统(virtualized system)的地址转换。这个地址转换协议由一个单独的规范进行描述,被称为 Address Translation Services,可以看到该字段的编码为:
00 = 默认/未转换(Default/Untranslated)
01 = 转换请求(Translation Request)
10 = 已转换(Translated)
11 = 保留 reserve

Length[9:0] 长度 Byte 2 Bit 1:0 Byte 3 Bit 7:0 TLP 数据荷载传输量的大小,单位为 DW,编码方式为:
00 0000 0001b = 1DW
00 0000 0010b = 2DW ……
11 1111 1111b = 1023DW
00 0000 0000 = 1024DW
Last DW BE[3:0] 末尾 DW 的字节使能 (Last DW Byte Enable) Byte 7 Bit 7:4 这个字段中的 4 个高有效的 bit,与数据荷载中最后一个 DW 中的 4 个 Byte 一一对应。
Bit 7 = 1:末尾 DW 的 Byte 3 是有效的;否则为无效的。
Bit 6 = 1:末尾 DW 的 Byte 2 是有效的;否则为无效的。
Bit 5 = 1:末尾 DW 的 Byte 1 是有效的;否则为无效的。
Bit 4 = 1:末尾 DW 的 Byte 0 是有效的;否则为无效的。
1st DW BE[3:0] 第一个 DW 的字节使能 (First DW Byte Enable) Byte 7 Bit 3:0 这个字段中的 4 个高有效的 bit,与数据荷载中第一个 DW 中的 4 个 Byte 一一对应。
Bit 3 = 1:末尾 DW 的 Byte 3 是有效的;否则为无效的。
Bit 2 = 1:末尾 DW 的 Byte 2 是有效的;否则为无效的。
Bit 1 = 1:末尾 DW 的 Byte 1 是有效的;否则为无效的。
Bit 0 = 1:末尾 DW 的 Byte 0 是有效的;否则为无效的。

表 5‑2 通用 TLP Header 的各字段摘要

在数据流中有三种通用模型用于事务排序:

\1. 强排序(Strong Ordering**)**:对于在PCIe结构中传输的拥有相同TC的多个事务流,PCIe要求使用强排序规则。拥有相同TC的事务们也会被映射到同一个给定VC,因此每个VC中也要应用强排序规则。因此,当多个TC都被映射到同一个VC时,这些TC的所有事务都会被当做同一个TC来进行处理,即使不同的TC之间不存在排序关系。(按照先来后到处理)

\2. 弱排序(Weak Ordering**)**:除非事务需要重新排序,否则它们将维持原来的顺序。由于某些给定的事务模型(例如Producer/Consumer模型)相关的依赖性,维持事物间的强排序关系可能会导致所有的事务都被阻塞。而被阻塞的事务中,有些与依赖关系并不相关联,它们就可以安全地被重新排在阻塞的事务之前。

\3. 宽松排序(Relaxed Ordering**)**:在且仅在某些可控的情况下,事务可以被重新排序,它的好处是可以像弱排序模型一样提升性能,但是它仅在软件指定是才会这样做,以此来避免依赖问题。而它的缺点则是仅有部分事务可以得到性能上的优化。软件要启用宽松排序(RO,Relaxed Ordering)也需要一些额外开销。

5.2.4 通用 TLP Header 详细说明(Generic TLP Header Details)

在接下来的几个小节中,我们将对图 5‑3 中展示的 TLP Header 的每一个字段都进行细节描述。

5.2.4.1 Header 的 Type/Format 字段编码含义

表 5‑3 中总结了 TLP Header 中 Type 字段和 Fmt 字段(Format)的编码含义。

TLP 事务种类Fmt[2:0]Type[4:0]
Memory Read 请求 (MRd) 000=3DW,无数据 001=4DW,无数据 0 0000
Memory Read Locked 请求 (MRdLk) 000=3DW,无数据 001=4DW,无数据 0 0001
Memory Write 请求 (MWr) 010=3DW,有数据 011=4DW,有数据 0 0000
IO Read 请求 (IORd) 000=3DW,无数据 (IO 请求为 3DW Header) 0 0010
IO Write 请求 (IOWr) 010=3DW,有数据 (IO 请求为 3DW Header) 0 0010
配置 Type 0 Read 请求 (CfgRd0) 000=3DW,无数据 0 0100
配置 Type 0 Write 请求 (CfgWr0) 010=3DW,有数据 0 0100
配置 Type 1 Read 请求 (CfgRd1) 000=3DW,无数据 0 0101
配置 Type 1 Write 请求 (CfgWr1) 010=3DW,有数据 0 0101
Message 请求 (Msg) 001=4DW,无数据 1 0 rrr* (见表 4‑10)
Message 带数据的请求 (MsgD) 011=4DW,有数据 1 0 rrr* (见表 4‑10)
完成包 Completion (Cpl) 000=3DW,无数据 0 1010
完成包带数据 (CplD) 010=3DW,有数据 0 1010
锁定的完成包 (CplLk) 000=3DW,无数据 0 1011
锁定的完成包带数据 (CplDLk) 010=3DW,有数据 0 1011
获取和增加原子操作请求 (Fetch and Add AtomicOP Request) 010=3DW,有数据 011=4DW,有数据 0 1100
无条件的交换原子操作请求 (Unconditional Swap AtomicOP Request) 010=3DW,有数据 011=4DW,有数据 0 1101
对比和交换原子操作请求 (Compare and Swap AtomicOP Request) 010=3DW,有数据 011=4DW,有数据 0 1110
本地 TLP 前缀 (Local TLP Prefix) 100=TLP Prefix 0L3L2L1L0
端到端 TLP 前缀 (End-to-End TLP Prefix) 100=TLP Prefix 1E3E2E1E0

表 5‑3 TLP Header 的 Type 字段和 Fmt 字段编码含义

5.2.4.2 Digest/ECRC 字段

TLP 的 Digest 位表示是否存在 ECRC(End-to-End CRC)。如果当前支持这个可选的特性,并且软件也启用了它,那么设备将会给自己产生的所有 TLP 都计算并且添加上一个 ECRC。需要注意,使用 ECRC 要求设备含有可选的 Advanced Error Reporting 寄存器,这是因为它的能力(Capability)和控制寄存器就位于 Advanced Error Reporting 寄存器中。

l ECRC 的生成和检查

ECRC 覆盖了所有在跨 Fabric 转发时不需要更改的字段。然而,当一个数据包在拓扑结构中移动时,有两个 bit 是可以合法的进行改变的:

  • Type 字段的 Bit 0:在一个配置事务通过一个 Bridge 时,这个配置事务有可能从 Type 1 变成 Type 0,因为这个 Bridge 的次级总线有可能就是配置事务的目标总线。在这个情况下,Type 地段的 bit 0 的值就会从 1 变成 0。

  • EP(Error/Poisoned)bit:当一个 TLP 在网络结构中移动时,如果与这个数据包相关的数据被认为是损坏的,那么就有可能引发这个 bit 值的改变。这是一种可选的特性,称为错误转发(error forwarding)。

 谁来检查 ECRC

ECRC 的预定目标是 TLP 的最终接收者。对 LCRC(Link CRC)的校验是用来验证在当前给定链路上的传输没有出错,但是会在 Switch/Bridge 的出口端口(egress port)重新计算一个 LCRC,然后再转发给下一级链路,也就是说同一个 LCRC 的作用范围不会跨 Switch/Bridge,那么这将会使得 Switch/Bridge 这些路由元件内部发生的错误被掩盖。为了解决这个问题,就在 TLP 在 Requester 到 Completer 的整个传输过程中都加上一个不会改变的 ECRC(也就是这个过程中 ECRC 都不会被其他设备重新计算和替换)。当目标设备检查 ECRC 时,任何在整个传输过程中发生的错误都会极容易被发现。

关于 ECRC 校验中 Switch 的作用,PCIe 协议做了两个声明:

  • 如果一个 Switch 支持 ECRC 校验,那么它需要对 TLP 目的地为 Switch 自身时,对这个 TLP 中的 ECRC 进行校验。如果 TLP 的目的地并不是 Switch 自身,那么 Switch 必须在保持 ECRC 不变的前提下对其进行转发,把 ECRC 作为 TLP 不可分割的一部分。“On all other TLPs a Switch must preserve the ECRC (forward it untouched) as an integral part of the TLP.”

  • 注意,Switch 也可以对通过它的 TLP 进行 ECRC 检查。由 Switch 发现的 ECRC 错误的报告方法和其他设备一样,但是这不会改变 TLP 通过 Switch 的继续传输。“Note that a Switch may perform ECRC checking on TLPs passing through the Switch. ECRC Errors detected by the Switch are reported in the same way any other device would report them, but do not alter the TLPs passage through the Switch.”

5.2.4.3 使用字节使能(Using Byte Enables)
l 整体说明

类似 PCI 一样,对于有时传输大小或者起始/结束地址不是 DW 对齐时,PCIe 也需要一种机制来根据需要协调其 DW 对齐地址。为了达到这个目的,PCIe 利用了 2 个字节使能(Byte Enable)字段,如图 5‑3 中和表 5‑2 中所介绍,分别是首 DW 字节使能(First DW Byte Enable)和尾 DW 字节使能(Last DW Byte Enable),它们使得 Requester 可以对第一个 DW 和最后一个 DW 真正有效传输的字节进行限定。

l 字节使能规则
  1. 字节使能地各个 bit 是高有效的。如果某个字节使能 bit 值为 0,那么就表示数据荷载中相应的字节不应该被 Completer 使用,因为这个字节是无效的。若某个字节使能 bit 值为 1,那么就说明相应的字节应该被 Completer 使用。

  2. 如果有效的数据全都在一个单独的 DW 中,那么尾 DW 字节使能(Last DW Byte Enable)必须为 0000b。

  3. 如果 Header 中的 Length 字段表示了这次传输数据量大于 1DW,那么首 DW 字节使能(First DW Byte Enable)至少要有 1 个 bit 是有效的。

  4. 如果 Header 中的 Length 字段表示了这次传输数据量大于等于 3DW,那么首 DW 字节使能和尾 DW 字节使能都必须是相连的 bit 为 1。在这种情况中,字节使能仅能用来提供有效起始地址和结束地址与 DW 对齐地址的字节偏移量。

  5. 如果传输数据量大小为 1DW,那么才能允许只有首 DW 字节使能内是不连续为 1 的情况。

  6. 如果传输数据量大小为 1-2DW,那么才能允许首 DW 字节使能和第二 DW 字节使能内都是不连续为 1 的情况。

  7. 如果一个写请求,其 Length 字段表示其数据传输长度为 1DW,但是它的字节使能均为无效,这种情况对 Completer 不会有影响。

  8. 如果一个读请求,其 Length 字段表示其需要的数据传输长度为 1DW,但是没有字节使能有效,那么 Completer 会返回一个 1DW 数据荷载,这种数据荷载是未定义数据(undefined data)。这种情况可能被用作一种刷新机制(Flush mechanism),它利用事务排序规则,在这个 undefine data 的读请求完成包返回之前,强制之前发出的所有 posted write 输出到内存中。

字节使能示例

如图 5‑4 展示了字节使能字段是如何使用的。注意,数据传输长度必须从第一个 DW 中的任何有效字节延伸至最后一个 DW 中的任何有效字节。因为数据传输量大于 2DW,字节使能就只能用来标识这次传输中起始地址的位置(2d)和结束地址的位置(34d)。

img

图 5‑4 首 DW 字节使能和尾 DW 字节使能字段的使用

5.2.4.4 事务描述符字段(Transaction Descriptor Fields)

当事务在 Requester 和 Completer 之间移动时,必须要能够对各个事务进行唯一的标识,因为在任何时刻的 Requester 中都有可能有许多的拆分事务在排队。为了更好的进行标识,PCIe 协议在 TLP Header 中定义了多个重要字段,来组成一个唯一的事务描述符(Transaction Descriptor),如图 5‑5 所示。

img

图 5‑5 事务描述符字段

虽然事务描述符在 TLP Header 中并不是位置全连续的字段,但是这些不连续字段合起来可以一起描述事务的关键属性,包括:

l 事务 ID(Transaction ID)

事务 ID 由 Requester ID(Requester 的 BDF)和 TLP 的 Tag 字段共同组成。

l 流量类型(Traffic Class)

流量类型(Traffic Class,TC)是由 Requester 的 Device Core 来添加进 TLP 的,并且在拓扑结构中从 Requester 传输到 Completer 的过程中 TC 都不发生改变。在拓扑结构的每个链路中,TC 都映射到其中一个虚拟通道(Virtual Channel)。

l 事务属性(Transaction Attributes)

用于表示基于 ID 的排序(ID-based Ordering)、宽松排序(Relaxed Ordering)以及无窥探(No Snoop)的 bit 也存在于请求包中,被发送给 Completer。

5.2.4.5 带有数据荷载的 TLP 的一些额外规则

当一个 TLP 带有数据荷载时,就要遵从如下规则:

  1. Length 字段仅表示数据荷载的长度。

  2. 数据荷载的首字节(紧挨着 Header 的字节)的地址永远是最低位的。

  3. Length 字段永远表示的是整数 DW 的传输长度。对于不满整数 DW 的情况是使用首 DW 字节使能和尾 DW 字节使能来进行表示的。

  4. 在协议中有声明,当一个 Completer 在响应一个单独的 Memory 请求时如果返回了多个 TLP,那么中间的(也就是非首尾的)TLP 的数据荷载的地址必须结束于 RC 的 64byte 或 128byte 自然对齐的边界上。具体是那种边界是由一个可配置位称为 RCB(读完成边界,Read Completion Boundary)来控制的。所有的其他设备遵循 PCI-X 协议,并会将这种情况的 TLP 截断在 128byte 自然对齐边界上。

  5. 当发送 Message 请求时,Length 字段是保留字段,除非 Message 是带有数据荷载的,也就是 MsgD。

  6. TLP 的数据荷载一定不能大于设备控制寄存器(Device Control Register)中的最大数据荷载字段(Max_Payload_Size)。因为只有写事务会带有数据荷载,因此这种限制并不应用于读请求。接收方需要在被写入时检查是否存在 Max_Payload_Size 的违例,如果存在则认为这是一个畸形 TLP(Malformed TLP)。

  7. 接收方还需要检查 Length 字段和 TLP 实际传输的数据荷载长度。如果二者不相同则认为这是一个畸形 TLP(Malformed TLP)。

  8. 请求包中的起始地址和传输长度的组合信息,一定不能造成跨 4KB 边界的 Memory 访问。虽然这种检查是可选的,但是一旦发现了跨 4KB 边界访问的情况就认为这是一个畸形 TLP(Malformed TLP)。

5.2.5 具体的 TLP 格式:请求 TLP 和完成 TLP

在本节中,将会描述用来构成具体的一些事物类型的 TLP 3DW Header 和 4DW Header。许多通用的字段就如前文所述,因此我们把重点放在那些需要根据具体事务类型进行具体处理的字段上。接下来的几个小节是关于 TLP Header 的详细描述,相关的 TLP 类型为:1)IO Request,2)Memory Requests,3)Configuration Requests,4)Completions,以及 5)Message Request。

posted @   NoNounknow  阅读(245)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示