CXL协议层次:物理层、链路层、事务层、协议层简介
开始折腾CXL之前,咱们得先搞清楚它到底是怎么分层的。
我个人习惯把CXL协议栈看作一栋四层楼。从地基到顶层,分别是物理层、链路层、事务层和协议层。每一层各司其职,又相互配合。
你想想看,如果不是把功能拆得这么清楚,端到端的延迟根本没法优化。因为你不知道瓶颈到底卡在哪一层。
整体架构概览
这张图展示了CXL协议的四层模型。我每次做延迟分析,都会先拿这张图对照一下。
嗯,这里要注意,自上而下是协议定义,自下而上是信号传输。延迟就是从顶层到底层再回来的总时间。
物理层:信号的地基
物理层是最底层。说白了,就是铜线上的电压变化和时钟同步。
CXL复用PCIe的物理层。我接触过的项目中,多数跑在PCIe 5.0上,单通道32 GT/s。换算一下,x16就是双向64 GB/s的带宽。
延迟敏感的地方在哪?
- 链路训练:上电时双方协商速率、宽度。我记得有一次调试,链路死活跑不到Gen5,最后发现是参考时钟抖动超标。
- 均衡:高频信号在PCB上衰减严重。物理层用TX EQ和RX EQ来补偿。EQ没调好,误码率就高,重传就多,延迟自然就上去了。
我踩过的坑
曾经有个项目,CXL往返延迟比预期多了20 ns。查了很久,发现是物理层的去加重系数配置错了,导致接收端眼图闭合。重新校准EQ后,延迟立刻降下来了。
所以,别小看物理层。它决定了信号能不能干净地传过去。
链路层:可靠传输的保障
链路层在物理层之上。它负责把物理层传过来的比特流变成可靠的数据包。
主要干三件事:
- 流控:发送方不能把接收方撑爆。链路层用信用量(Credit)机制来调节。接收方告诉你,“我还有X个缓存”,你才能发。
- CRC校验与重传:每个数据包都带校验码。如果物理层传错了,链路层发现CRC不匹配,就要求重传。
- 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是绕不开的。
后面咱们的优化方法,就是针对这四层,一层一层地“减税”。