第二讲:UCIe协议简介——背景、物理层、链路层、协议层

各位好,这一讲咱们聊聊UCIe协议。说实话,我在刚开始接触UCIe的时候,也被它那分层结构搞得晕头转向。后来调试多了才明白,每一层都有它自己的脾气和使命。

UCIe,全称Universal Chiplet Interconnect Express。说白点,就是让不同厂家生产的小芯片(chiplet)能高速、低延迟地互相通信。为什么需要它?因为随着芯片越做越大、制程越来越贵,把一个大芯片拆成几个小芯片再拼起来,成了划算的做法。但怎么拼?各家标准不统一,UCIe就是来解决这个问题的。

UCIe的三大层结构

UCIe协议栈分三层:物理层、链路层、协议层。每层各司其职,往下看。

UCIe协议栈分层架构 协议层 CXL.io / CXL.mem / CXL.cache / PCIe Flit打包,事务层请求/响应,与Cache Coherency直接相关 链路层 CRC校验,重传控制,流量控制 Link Initialization & Training,L0 / L1 / L2状态管理 物理层 D2D接口:标准封装/先进封装 差分时钟、数据线、边带信号 16/32/64 lane支持,最高32 GT/s数据速率 数据从上往下封装,自下而上传输

物理层:连接的根基

物理层是UCIe的最底层,负责芯片之间的电气连接。这个大家比较熟悉,但它有几个关键点我得提醒你注意。

D2D接口类型:UCIe定义了两种封装方式——标准封装(Standard Package)和先进封装(Advanced Package)。标准封装用传统的PCB走线或基板,距离远一点,但功耗和延迟稍微大些。先进封装则用硅中介层(Interposer)或桥接芯片,距离更短,信号质量更好。我做过一个项目,因为选了标准封装但lane数配得不够,结果仿真发现眼图睁不开——嗯,后来老老实实加了两条lane才解决。

特性标准封装先进封装
信号距离5mm-25mm0.1mm-2mm
最高速率20-24 GT/s32 GT/s
每lane功耗~1pJ/bit~0.5pJ/bit
适用场景多芯片模组高带宽片内互联

时钟与数据:UCIe物理层使用差分时钟(Differential Clock),一般是一对差分线。数据lane采用8b/10b编码(早期的),或者128b/130b编码(高数据率版本)。编码的目的是保证DC平衡和足够多的跳变沿用于时钟恢复。

电源域:每个die可能有独立的电源域,物理层需要处理跨域的信号电平。曾经一次调试,两片die的电源域压差达到了30mV,结果眼高不够,数据丢包。从那以后我学乖了,电源完整性仿真一定要做足。

链路层:可靠传输的保障

链路层在我眼里是UCIe中最“聪明”的一层。它不仅做流控,还负责重传和错误检测。

核心功能一:Link Initialization & Training(LIT)

每当系统上电,两端的链路层要“握手”。过程包括:发送训练序列,协商lane宽度(比如初始是16 lane,降级后可以变成8 lane或4 lane),对齐lane-to-lane skew。

我经历过一次:某个die的时钟恢复PLL锁相环锁定时间比预期长了500ns,导致链路层训练超时。最后在firmware里加了retry逻辑才搞定。说白了,LIT的时序一定要留余量。

核心功能二:CRC与重传

每个Flit(流控制单元)都带32位CRC。发送端把Flit发出去,接收端计算CRC,如果匹配则回复ACK,否则回复NAK,发送端就重传那个Flit。记住:重传缓冲区的大小要和期望的Max Latency匹配。如果buffer太小,遇到连续错误就直接丢死了。

  • 流量控制:基于Credit的机制,每个VC(Virtual Channel)单独管理。发端只有拿到接收端的Credits才发数据。
  • 状态管理:链路有L0(正常运作)、L1(低功耗待机)、L2(最低功耗关机)。切换时要保持Flit边界对齐。

注意:链路层的重传和流控都是和协议层Flit边界强绑定的。如果你发现数据链路丢包,先查CRC是否正确,再看Credit余额是否归零。别上来就怀疑协议层,这是新手常犯的错。

协议层:与Cache Coherency的接口

协议层,说白了就是“上层协议”和物理层之间的翻译官。在UCIe里,协议层支持多种协议格式:CXL(Compute Express Link)、PCIe(传统外设协议),以及用户自定义的Raw Protocol。

CXL vs PCIe:CXL又细分为CXL.io、CXL.mem、CXL.cache。其中,CXL.mem和CXL.cache是Cache Coherency功能的核心。CXL.io则用于配置和枚举,和PCIe的TLP格式很像。

协议类型用途是否参与Coherency
CXL.io配置、MMIO访问、中断否
CXL.mem主存访问(Load/Store)是(内存语义)
CXL.cache处理器缓存管理(Snoop)是(缓存一致性)
Raw Protocol自定义数据包依赖实现

在协议层,数据被封装成Flit格式。每个Flit的大小是固定的(标准是68B或80B,取决于是否包含CRC/Credit开销)。Flit内部包含Header、Payload和Footer。Header里指明了是哪个通道、哪个VC、什么操作类型。Coherency相关的操作(比如SnpCurr、MemRd)就在Header里标记。

小提示:调试Cache Coherency问题的时候,一定要学会看Flit Header。我一般在仿真时打印出每个Flit的Header字段,找到“ReqID”、“Opcode”、“Address”这三个字段,就能定位到是哪条缓存线、哪个core发起的请求。有一次问题出在“SnpCurr”响应没有及时确认,导致sender重发,结果引起了线上冲突。说白了,看Flit比看wireshark还管用。

总结一下

UCIe的三层架构,每一层的设计意图都很明确:物理层负责电气信号,链路层负责可靠传输,协议层负责语义转换。我在调试工作中,最常用的就是沿着这三层逐一排查。先看物理层有没有同步,再看链路层CRC有没有错,最后看协议层的Flit格式对不对。

这三层的关系,就像寄快递:物理层是卡车和路,链路层是快递小哥(保证不丢件),协议层是背后的物流系统(知道包裹里装的是什么,该送到哪个架位)。你想想看,不管是Cache Coherency还是普通Memory访问,最终都要老老实实走完这三层。