PCIE背景知识学习(11)
TLP
TLP可以被基于地址路由(Memory或IO),可以被基于ID路由(Bus—Device—Function),或者还可以被隐式路由(routed implicitly)。
只有TLP会被Switch和RC进行路由,它们起源于源端口的事务层,结束于目的端口的事务层。
发送方
设备 A 的 Device Core 向它的 PCIe 接口发送一个请求(具体 Device Core 是如何给 PCIe 接口发送请求的,这并不是 PCIe 协议或者本书的讨论范畴)。这个请求中包括:
目标地址或者 ID(也就是路由信息)
源端信息,例如 Requester ID 和 Tag
事务类型/数据包类型(需要执行的命令,例如一个内存读取 MRd)
数据荷载大小 payload size 和数据荷载内容(如果 TLP 需要带数据)
流量类型(Traffic Class,用于分配数据包的优先级)
请求的自身属性(No Snoop 无窥探、Relaxed Ordering 宽松排序,等等)
基于这个请求,事务层将会组建 TLP Header,并在其后附上数据荷载(如果有),以及如果启用并支持可选项的话也可以再附上 ECRC(End-to-End CRC)。随后 TLP 就会被放入一个虚拟通道 Buffer。这个虚拟通道会根据事务排序规则来管理 TLP 的顺序,并在向下转发 TLP 到数据链路层之前,确认接收方有足够的 Buffer 来接收一个 TLP。
当 TLP 到达数据链路层,它会被分配一个序列号(Sequence Number),并基于 TLP 的内容和序列号来计算出一个 LCRC(Link CRC)来附加在原 TLP 后。然后会将经过这些处理过程之后的 TLP 保存一个副本,这个副本会保存在数据链路层的重传 Buffer(Replay Buffer,也可称为 Retry Buffer)中,这是为了应对传输出错的情况。与此同时,这个 TLP 也会被向下转发至物理层。
物理层将会进行一系列的操作来准备对这个数据包进行串行传输,包括字节条带化(Byte Striping)、扰码(Scrambling)、编码(Encoding)以及并串转换(Serializing)。对于 Gen1 和 Gen2 的设备,当进行 8b/10b 编码时,会将 STP 和 END 这两个控制字符分别加在 TLP 的首端和尾端。最后,这个数据包通过链路进行传输。在 Gen3 操作模式中,STP 令牌(STP token)会被添加在 TLP 的首端,但是并不会在尾端加上 END,而是在 STP 令牌中包含 TLP 大小的信息来判断 TLP 的尾部位置。
接收方
在接收方(本例中是 Device B),为了发送包所做的一切准备现在都必须撤销。物理层将对比特流进行串并转换(deserialize)、对串并转换后的符号进行解码,然后再进行字节反条带化(un-stripes)。控制字符将被移除,因为它们仅在物理层有意义,然后这个数据包就会被向上转发至数据链路层。
数据链路层将会计算 CRC(具体一点是 LCRC)并与 TLP 中的 CRC 进行比较。如果 CRC 比较结果相同,那么就再检查序列号(Sequence Number)。如果都没有出现错误,那就把 CRC 和序列号都从 TLP 剥除,并随后将 TLP 向上转发给接收方事务层,与此同时要通过返回给发送方一个 Ack DLLP 来通知发送方这个 TLP 被成功接收。相反地,如果前面的过程中检查出了错误,那么就要返回给发送方一个 Nak DLLP,这样发送方将会使用它的重传 Buffer 来对 TLP 进行重传。
在事务层,TLP 被进行解码,并将 TLP 内的信息传递给 Device Core 来进行相应的操作。如果当前接收设备就是数据包的最终目的地,那么它可以检查 ECRC 错误,并在发现任何 ECRC 错误时报告给 Device Core。