CXL 协议架构:事务层、链路层、物理层分层模型
各位同学,今天我们聊聊 CXL 协议的分层架构。
很多刚接触 CXL 的朋友,上来就看报文、抓 trace,结果一头雾水。说白了,就是没搞懂这三个分层到底各自管什么事。我个人习惯,拿到一个协议,先看它的剥洋葱结构。CXL 也不例外,它就是这么一层层堆叠起来的。
三层模型:从宏观到微观
CXL 协议栈分三层,从下往上分别是:
- 物理层:管信号的。电信号怎么传、时钟怎么对齐、眼图是否合格,这块说了算。它直接决定了链路的“通断”。
- 链路层:管可靠性和流量。它负责把物理层扔过来的比特流,拼成完整的 flit,还要检查有没有传错、要不要重传。
- 事务层:管语义和命令。你发的是一个读请求,还是写请求,是 CXL.io 还是 CXL.mem,它来定义和解析。
这就像你寄快递。事务层好比“我要发一个包裹”,链路层是“打包、贴单号、选快递公司”,物理层就是“快递小哥开着三轮车送到你家门口”。每一层只关心自己那一亩三分地,职责清晰。
事务层:CXL 的“大脑”
事务层是离软件最近的一层。它定义了所有 CXL 事务的种类和格式。CXL 有三大类事务:
- cxl.io:类似 PCIe 的事务,用于配置、枚举、DMA。说白了,管理通道。
- cxl.mem:内存语义的事务,读、写、预取。这是加速器访问主机内存的主干道。
- cxl.cache:缓存一致性的事务,用于维护设备缓存和主机缓存的数据同步。
你看,CXL 不是简单地把 PCIe 改了改,而是把三种不同的协议揉在一起。
| 事务类型 | 主要职责 | 典型报文 |
|---|---|---|
| cxl.io | 配置与控制 | 配置读写、地址映射、中断 |
| cxl.mem | 内存访问 | MemRd、MemWr、MemPrefetch |
| cxl.cache | 缓存一致性 | SnpData、SnpInv、CacheWrBack |
为什么会需要三种?你想想看,一个智能网卡,它既要被主机配置(cxl.io),又要快速读写主机内存(cxl.mem),还要维护自己内部缓存和 CPU 缓存不打架(cxl.cache)。少了哪一个,应用场景都玩不转。
避坑指南:我曾经在调试一个 FPGA 加速卡时,发现 cxl.mem 读请求一直超时。查了半天,发现是事务层没有把请求的地址对齐到 64 字节。CXL 的 flit 边界要求很严格,不对齐的事务,链路层直接丢弃。
链路层:负责“不出错”
链路层是承上启下的关键。它把事务层的数据包,加上 CRC、序列号、重传机制,封装成一个个的 flit。
Flit 是什么?就是 CXL 链路层传输的最小数据单元。它的大小固定,通常是 68 字节(有效载荷)加上 4 字节的 CRC。
链路层有几个核心产物:
- Flit 封装:把事务层的数据切片、组装成 flit 头部 + 数据 + 尾部 CRC。
- CRC 校验:每个 flit 都带一个循环冗余校验码,确保数据传输没损坏。
- 重传机制:发现 CRC 错误或序列号不连续,就发起重传。CXL 的重传是选择性重传,不是全重传,效率很高。
- 流控:通过信用量(credit)机制,防止发送方把接收方缓冲区撑爆。
我习惯把链路层看作是“搬运工”。事务层说“我要发这个包裹”,链路层就说“好,我帮你打包、编号、贴上防拆标签,再找个靠谱的货车送出去”。如果半路上包裹散了,链路层还负责重新发一份。
注意:CXL 的链路层和 PCIe 的链路层不完全一样。PCIe 用 TLP 和 DLLP,CXL 统一用 flit。而且 CXL 的链路层支持更细粒度的流控和更快的重传。你如果拿 PCIe 那套思维去分析 CXL,会吃大亏。
物理层:信号与电气的“硬骨头”
物理层最底,也最枯燥。但我得说,大部分现场问题,根上都出在这一层。
CXL 的物理层基于 PCIe 的物理层,但做了增强。它支持多个 Lane(数据通道),每个 Lane 是一对差分信号。主要关注:
- 链路训练:上电后,两端需要握手、协商速率、对齐比特流。
- 时钟方案:CXL 支持独立的参考时钟,也支持无参考时钟(SRIS),影响抖动。
- 电气参数:电压摆幅、均衡、去加重,全都在这里决定。
嗯,这里要注意。CXL 的物理层支持两种模式:PCIe 模式和 CXL 模式。在 CXL 模式下,链路层 flit 的边界是 68 字节;在 PCIe 模式下,它退化成标准的 PCIe 链路。你设计芯片时,必须能自动检测对方是 CXL 还是 PCIe 设备。
我还记得有一次,客户反映 CXL 链路总是在高负载时断连。我用示波器抓了眼图,发现信号质量在长距离走线后恶化严重。最后协商只能降速到 16 GT/s。物理层不好,上层一切免谈。
三层如何协作?一图胜千言
下面这张图,是我自己总结的 CXL 协议栈三层结构以及数据流动的最简模型。
分层的好处是什么?
说白了,就是解耦。每一层可以独立演进,不影响其他层。
- 物理层未来支持更高速率(比如 32 GT/s、64 GT/s),上层不用改。
- 链路层改进了重传算法,吞吐提升,事务层照样发命令。
- 事务层增加了新的 cxl.mem 命令类型,链路层只管打包,不关心语义。
我在做芯片验证时,最喜欢的就是这种分层设计。我可以先单独验证链路层的 CRC 和重传,没问题了再接上事务层。如果不分层,所有逻辑混在一起,定位一个 bug 要花三倍时间。
总结关键点:
- 事务层定义“做什么”——cxl.io、cxl.mem、cxl.cache。
- 链路层定义“怎么传得稳”——flit、CRC、重传、流控。
- 物理层定义“信号怎么在线上跑”——电气、训练、速率。
- 调试故障时,先看物理层通不通,再看链路层有没有错,最后才分析事务层对不对。
我记得有一次线上研讨会,有工程师问:“我怎么才能快速判断是链路层问题还是物理层问题?” 我的回答很简单:看一下链路的 Link Status 寄存器。如果它显示 Retrain 次数多,先查物理层;如果它显示重传率偏高但链路没掉,那多半是链路层的 buffering 配置有问题。
总之,搞懂这三层模型,你才算真正踏进了 CXL 的大门。后面我们深入报文细节时,会反复用到这些概念。