✨前言:
在PCIe通信过程中,事务层数据包(Transaction Layer Packets,简称TLP)扮演着非常重要的角色。TLP用于在设备之间传递数据和控制信息,它们是PCIe的基本信息传输单元。
TLP可分为几个部分,最核心的是TLP Header,它负责携带有关数据包的关键信息,包括数据包类型、长度以及传输方向等等。下面是TLP Header的详细结构以及各部分的作用:
格式(Format)和类型(Type)字段:这个字段由多个比特组成,两者相结合定义了TLP的类型,例如内存读取、内存写入、I/O操作等等。格式字段告诉我们这个TLP是32位还是64位地址,而类型字段告诉我们是进行读取还是写入等操作。
长度(Length)字段:长度字段告知接收设备这个TLP包含了多少个数据载荷(Data Payload)DWORDs(32-bit words)。这对于正确解析TLP非常重要。
请求者ID(Requester ID)和目标ID(Completer ID)字段:这些字段包含了发起TLP的设备和预期接收这个TLP的设备的ID。在回应一个操作时,这两个字段会互换其值。
标记(Tag)字段:标记字段用于将具体的TLP关联到发起它的特定事务。这对于支持多个并发事务的设备来说尤其重要。
第一和最后的DW地址(First and Last DW Byte Enables)字段:对于内存写入操作,这些字段指示了在数据包的第一个和最后一个DWORD中,哪些字节是有效的。这对于包括不是4字节倍数的内存写入操作很重要。
地址(Address)字段:对于需要访问特定硬件地址的操作(例如内存读/写),此字段包含所需的地址。其精确格式和长度(32-bit或64-bit)取决于TLP的格式和类型
✨TLP格式
事务层包(TLP)的一般格式如下图所示:
TLP Header为3DW或者4DW,Data Payload为1-1024DW,最后的TLP Digest(ECRC)是可选的,为1DW。
TLP Header在整个TLP的位置如下图所示,需要注意的是,TLP Header的格式和内容都会随着TLP的类型和路由方式的改变而改变。
TLP的类型和路由方式由Fmt和Type所决定,这在前面关于TLP路由的文章中已经详细的介绍过。上图显示的是各种不同格式的TLP Header的相同的部分。
每一个Field的作用与意义如下表所示:
✨Byte Enable
下面分别详细地介绍一下Byte Enable,在PCIe中Data Payload的单位是DW,也就是说数据大小(地址)需要以DW作为对齐。但是很多情况下,数据的大小并不是DW的整数倍,因此PCIe引入了Byte Enable来解决这一问题。
使用Byte Enable需要遵循一下原则:
· Byte Enable为高电平有效,低电平(0)表示Data Payload的对应Byte将被认为是无效的,即不被Completer使用。
· 如果有效数据小于1DW,则Last DW Byte Enable应全部为0。
· 如果Data Payload大于1DW,则First DW Byte Enable至少有一位是有效的。
· 如果Data Payload大于或等于3DW,则First DW Byte Enable和Last DW Byte Enable当中的有效位必须是连续的。即这种情况下,Byte Enable只能用于调整起始地址和结束地址。
· 如果Data Payload等于1DW,则First DW Byte Enable中的有效位可以是不连续的。
· 如果Data Payload等于2DW,则First DW Byte Enable和Last DW Byte Enable中的有效位都可以是不连续的。
· 写请求中的DW等于1,但是First DW Byte Enable中没有任何一位是有效的,也是允许的,但是这样的请求对于Completer没有任何作用。
· 如果读请求DW等于1,但是First DW Byte Enable中没有任何一位是有效的,此时Completer会返回1DW的Data Payload,只是其中的数据都是无效的。这一方式常备用于Flush Mechanism。
一个简单的Byte Enable使用的例子,如下图所示:
🌟Byte Enable的作用
Byte Enable的主要作用是提供字节级别的访问控制,这使得PCIe能够更加灵活和高效地处理数据。它的存在允许:
非对齐访问:使PCIe能够处理非对齐的内存地址访问请求,这是在现代计算系统中常见的需求。
部分字节操作:支持对小于4字节的数据进行写入操作,这有助于减少不必要的数据传输,提高系统的数据处理效率。
数据保护:确保在执行部分字节写入时,同一DWORD内的其他字节内容不会被意外修改,保护了数据的完整性。
总的来说,Byte Enable信号在PCIe架构中提供了重要的字节级别精度和灵活性,是优化数据传输、提高效率和保护数据完整性的关键机制。
🌟关于TLP的Data Payload有:
· Data Payload的大小由TLP Header中的Length决定。
· Data Payload的数据采用的是Little Endian,即低字节存放于低地址中。
· Data Payload的大小并不是有效的数据的大小,有效数据的大小是由Data Payload和Byte Enable共同决定的。
· 当TLP类型为Message时,Length一般是保留的(Reserved),除非该Message是带有数据的(MsgD)。
· TLP的Data Payload大小不得超过Max_Payload_Size的值,该值位于Device Control Register中。对于比较大的数据量,因此只能分多次进行发送。对于读请求来说,并没有Data Payload,也就是说该规则并不适用于读请求。
· 需要特别注意的是,起始地址和结束地址之间不能够跨越4KB的地址边界。
📌下面详细解释为什么buffer bound to 4KB address boundary对系统至关重要:
内存管理和系统架构
计算机的内存管理单元 (MMU)通常以页面为单位管理物理内存,而操作系统中的常见页面大小就是4KB。不允许TLP跨越4KB边界有助于:确保TLP对应的数据传输在同一个内存页面内,简化内存的管理与分配。 有助于避免产生额外的页面错误或页面交换行为,尤其是在对物理地址访问时。
缓存一致性 多核处理器和系统中的缓存通常按照缓存行(cache
line)进行组织,而缓存行的大小通常不会超过4KB。确保数据传输不跨越4KB边界有助于:保持缓存行内的数据一致性,避免一个TLP操作需要更新多个缓存行所带来的复杂性。 减少缓存同步协议所需要处理的情况,降低系统的复杂度。
错误检测和处理 硬件通常会实施一些错误检测和纠正机制,比如ECC(错误校验和纠正)。这些机制也以物理页面为基础。不跨越4KB边界有助于:在发生错误时,能够准确地定位到错误发生的页面,并进行处理,而不涉及多个页面。 降低出现多位错误的可能性,增强数据的可靠性。
总之,为了保证内存、缓存和错误管理的效率与简洁性,PCIe规范要求TLP的data
payload在进行数据传输时不得跨越4KB边界。这规则不适用于读请求的TLP,因为读请求的TLP本身不携带data
payload,而是请求从远端设备获取数据,返回的是Completion with Data的TLP,它们遵守相同的数据载荷规则。
✨小结:
本章主要介绍TLP Header的构成,下一章再详细介绍TLP Header的格式和作用。