CXL协议层次:物理层、链路层、事务层、协议层简介

开始折腾CXL之前,咱们得先搞清楚它到底是怎么分层的。

我个人习惯把CXL协议栈看作一栋四层楼。从地基到顶层,分别是物理层、链路层、事务层和协议层。每一层各司其职,又相互配合。

你想想看,如果不是把功能拆得这么清楚,端到端的延迟根本没法优化。因为你不知道瓶颈到底卡在哪一层。

整体架构概览

这张图展示了CXL协议的四层模型。我每次做延迟分析,都会先拿这张图对照一下。

CXL协议四层架构图 CXL协议栈四层模型 协议层 (Protocol Layer) ◆ CXL.cache / CXL.mem / CXL.io 事务定义 事务层 (Transaction Layer) ◆ 请求/响应/数据 三类Flit封装 链路层 (Link Layer) ◆ 流量控制 / CRC校验 / 重传机制 物理层 (Physical Layer) ◆ PCIe 5.0/6.0电气规范 / 32 GT/s速率 优化起点:协议层 优化终点:物理层

嗯,这里要注意,自上而下是协议定义,自下而上是信号传输。延迟就是从顶层到底层再回来的总时间。

物理层:信号的地基

物理层是最底层。说白了,就是铜线上的电压变化和时钟同步。

CXL复用PCIe的物理层。我接触过的项目中,多数跑在PCIe 5.0上,单通道32 GT/s。换算一下,x16就是双向64 GB/s的带宽。

延迟敏感的地方在哪?

  • 链路训练:上电时双方协商速率、宽度。我记得有一次调试,链路死活跑不到Gen5,最后发现是参考时钟抖动超标。
  • 均衡:高频信号在PCB上衰减严重。物理层用TX EQ和RX EQ来补偿。EQ没调好,误码率就高,重传就多,延迟自然就上去了。

我踩过的坑

曾经有个项目,CXL往返延迟比预期多了20 ns。查了很久,发现是物理层的去加重系数配置错了,导致接收端眼图闭合。重新校准EQ后,延迟立刻降下来了。

所以,别小看物理层。它决定了信号能不能干净地传过去。

链路层:可靠传输的保障

链路层在物理层之上。它负责把物理层传过来的比特流变成可靠的数据包。

主要干三件事:

  1. 流控:发送方不能把接收方撑爆。链路层用信用量(Credit)机制来调节。接收方告诉你,“我还有X个缓存”,你才能发。
  2. CRC校验与重传:每个数据包都带校验码。如果物理层传错了,链路层发现CRC不匹配,就要求重传。
  3. Flit封装:把事务层的请求/响应打包成固定大小的Flit(流量单元)。CXL 2.0的Flit是528字节。
链路层功能对延迟的影响
信用量申请每次传输前需要信用量握手,增加1~2个周期
CRC计算发送端计算、接收端验证,消耗几个时钟
重传一次重传增加约30~50 ns,要尽量避免
Flit组装/解包串并转换,固定延迟约10 ns

实战经验

我建议在链路层重点监控CRC错误率。如果超过10^-12,就要检查信号完整性。错误率高,重传就多,延迟会雪崩式增长。

事务层:消息的分类与路由

事务层在链路层之上。它不管信号怎么传,也不管可靠性。它只做一件事:把高层命令打包成标准格式。

CXL的事务层定义了三种事务类型:

  • 请求(Request):读、写、原子操作等。
  • 响应(Response):对请求的结果(完成、错误等)。
  • 数据(Data):读回来的数据,或要写出去的数据。

每个事务都被封装成一个或多个Flit,交给链路层去传。

为什么事务层对延迟重要?

  • 因为事务层的消息优先级是CXL.cache优化的关键。CXL.cache的Snoop消息必须优先处理,否则缓存一致性会出问题。
  • 事务层的乱序处理能力也很关键。多个请求可以同时在路上跑,不用等前一个完成再发下一个。

我记得在某次测试中,把Snoop消息的事务优先级调高了一级,端到端延迟直接从120 ns降到了95 ns。这就是事务层的威力。

协议层:缓存一致性的业务逻辑

协议层是最顶层。它定义了“谁可以拥有数据”、“数据状态是什么”、“怎么通知别人缓存失效”。

CXL.cache就工作在这一层。它定义了三种缓存状态:

状态含义谁拥有数据
M (Modified)数据已修改,且只有本缓存有最新副本加速器
S (Shared)数据干净,加速器和主机都有副本双方
I (Invalid)数据无效,不可用无

协议层的延迟,主要来自状态转换和Snoop广播。

  • 加速器要读一个M状态的行,得先等主机把数据写回来。这一来一回,几十ns就没了。
  • Snoop广播要通知所有缓存:“你手里的数据可能过期了”。广播的范围越大,延迟越高。

避坑指南

我曾经遇到过一种情况:加速器频繁修改同一块缓存行,导致主机端不断收到Snoop,产生大量缓存行写回。

这就是协议层的”伪共享”问题。解决办法是把热点数据按缓存行对齐,或者用S状态代替M状态。

四层之间的延迟拆解

讲了这么多,咱们把每层的延迟贡献列一下。我用的是PCIe 5.0 x16的典型数值。

层次典型延迟(单向)优化空间
协议层20 ~ 40 ns大:减少Snoop广播、优化状态机
事务层10 ~ 15 ns中:调整优先级、Flit打包策略
链路层10 ~ 15 ns小:减少重传、优化信用量管理
物理层15 ~ 20 ns小:EQ调优、PCB走线

你算算看,全链路单向大约55 ~ 90 ns。如果是读请求,要来回(协议层→事务层→链路层→物理层→对端物理层→链路层→事务层→协议层),总延迟在110 ~ 180 ns之间。

我个人习惯在做延迟测量时,先在协议层打时间戳。然后逐层下探,看延迟差在哪里。

比如:协议层到事务层用了10 ns,事务层到链路层又用了10 ns。加起来就20 ns了。如果协议层到物理层总体要40 ns,那中间多出来的20 ns,多半是流控或缓冲造成的。

小结一下

CXL的四个层次,每一层都有自己的“延迟税”。

  • 物理层收的是信号的税。信号质量差,税就高。
  • 链路层收的是可靠性的税。流控和重传是固定的开销。
  • 事务层收的是消息调度的税。排队等处理是延迟大头。
  • 协议层收的是一致性的税。状态转换和Snoop是绕不开的。

后面咱们的优化方法,就是针对这四层,一层一层地“减税”。