十二 · 2023年06月29日

有点儿东西—PCIe链路层里的ACK/NAK

✎ 编 者 按 

    读cocotbext-pcie源码,有部分牵涉到数据链路层。虽然自工作以来接触到PCIe还是蛮多的,但一般往往专注在TLP层,对于数据链路层还是接触的比较少的。PCIe Spec洋洋洒洒数千页,也不会从头到尾去通读整个协议。对于cocotbext-pcie里面牵涉到的链路层的ACK/NAK,牵涉到的PCIe背景,聊做记录。

    本文仅结合PCIe Spce与cocotbext-pcie做记录。

》ACK/NAK

    与TCP协议般,PCIe协议在数据链路层采用滑动窗口ACK/NAK协议来保证数据传输。对于传输层下发的TLP报文,数据链路层会做一次封装:

image.png

    ACK/NAK报文格式定义如下:

image.png

    关于滑动窗口机制,往上随便搜下还是蛮多的,不做过多啰嗦。链路层的滑动窗口正是基于TLP Sequence Number。

    TLP Sequence Number定义为12 bits。对于发送端而言,其会维护两个变量:

  • NEXT_TRANSMIT_SEQ:用于存储下一个待发送TLP报文所使用的TLP Sequence Number。初始化时赋值为0.
  • ACKD_SEQ: 记录从ACK、NAK中返回的 Sequence Number。初始化时赋值为0xfff。

    对于发送端,规定:

    (NEXT_TRANSMIT_SEQ - ACKD_SEQ) mod 4096 >= 2048

     若上面的条件满足则停止从传输层接收TLP,等待该条件不再成立。

    也就意味着在pending中的报文不超过2048(牵涉到报文重传)。

    那么由此发送端对于收到的ACK/NAK中协议牵涉到的处理流程Spec定义为:

image.png

    由于发送端窗口中pending待确认的报文不会超过2048,故若上面1式不成立,那么则意味着用到了尚未使用到的sequence,表示为错误的TLP报文,同样单次增加的ACKD也不会超过2048,否则也应标为错误的TLP。

    在式3中,如果条件不成立,则意味着可以窗口前移,可以从replay buffer中移出已发送成功的数据,设置ACKD\_SEQ等变量。在cocotbext-pcie中关于dllp的处理也和spec保持一致:

image.png

    而对于接收端,其定义了:

  • NEXT\_RCV\_SEQ:下一个待接收TLP的Sequence Number。

    其处理流程为:

image.png

    这里可以看到,仅当收到的TLP报文的Sequence Number等于NEXT_REC_SEQ时,才会被接收。注意红框中,若条件满足则认为是重复的报文,此时则应发送ACK DLLP报文,否则认为是错误的报文,则应发送NAK。

    来看cocotbext-pcie中的处理:

image.png

    这里在563行取了<而非<=,或可有误。当收到的是期望的报文时(555行),则会更新next_recv_seq、清除nak_scheduled,拉起ack_latency_timer(不必每个TLP均发起一个ACK,但又要确保按照Spec中规定的间隔时间来发送ACK)。而如果收到的是一个重复的TLP(563行),此时将send_ack触发条件拉起,表示要立即发送ACK,而同时关掉ack_latency_timer,避免超时条件触发后多发ACK。否则(567行)将会发送NAK报文。

》One More Thing

    关于接收端的ack_latency,协议中有详细的规定,其与flow control定义有相似之处,放在后面结合cocotbext-pcie进行梳理。

☆ END ☆

作者:玉骐
原文链接:Spinal FPGA
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注Spinal FPGA欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息