2. UCIe协议栈概述:分层讲解物理层、链路层、事务层的功能与职责
做UCIe延迟测量,首先得搞清楚协议栈长什么样。说白了,UCIe协议栈分了三层——物理层、链路层、事务层。每一层干的事不一样,对延迟的贡献也不一样。我刚开始接触UCIe时,以为延迟主要来自物理层,结果一测发现链路层和事务层才是大头。嗯,这章我们就一层一层拆开来看。
核心观点:UCIe延迟 = 物理层固定开销 + 链路层处理开销 + 事务层协议开销。每一层的延迟特性不同,测量方法也不同。
2.1 协议栈整体架构
先看全局。UCIe协议栈从下往上分别是物理层、链路层、事务层。数据从发送端的事务层打包,经过链路层加校验和流控,最后由物理层送到线上。接收端反过来,物理层收信号,链路层做校验,事务层解包交给上层协议。
延迟会在这三层里逐级累加。我个人习惯把延迟分成两类:一类是固定延迟,比如物理层的串并转换;另一类是可变延迟,比如链路层的重传和事务层的排队。测量时尤其要关注可变延迟,它会影响延迟分布的上限。
下面这张图展示了三层架构以及每层的典型延迟范围,你一看就明白了。
2.2 物理层——固定延迟的基石
物理层是UCIe协议栈的最底层,负责把数字信号变成线上的电信号,再在接收端把信号变回来。主要模块包括时钟数据恢复(CDR)、串并转换、信号驱动和接收均衡。
物理层的延迟有两个特点:一是固定,二是很小。CDR锁定时间、串并转换的时钟周期数、PCB走线的传播时间,这些东西一旦设计完成,基本不会变。我在项目中遇到过一块板子,物理层延迟比datasheet大了将近1ns,最后发现是CDR的参考时钟抖动偏大,导致锁定时间拉长了。嗯,所以物理层虽然延迟固定,但质量不好的时钟能把固定值推高。
测量物理层延迟时,我建议直接在芯片的引脚处打时间戳,不要经过封装再量。你想想看,封装走线本身就有几十ps的延迟,虽然不大,但积少成多。
测量要点:物理层延迟可以用TDR(时域反射计)或片上环路(loopback)来标定。Loopback模式下,数据从发送端到接收端走的是片内路径,可以排除PCB走线的影响,单独测出物理层的内部延迟。
2.3 链路层——可靠性的代价
链路层在物理层之上,负责保证数据传输的可靠性。主要工作是加CRC校验、处理流量控制、以及出错后的重传。
链路层的延迟比物理层大一个数量级,而且带有一定的随机性。CRC计算本身只需要几个时钟周期,延迟是确定的。但重传就不一样了——一旦CRC校验失败,接收端会发起重传请求,发送端需要重新发送数据包。这一来一回,延迟就多了几十个时钟周期。
我曾经在一个项目中踩过坑:链路层重传率在正常条件下只有0.1%,但一旦链路出现信号完整性波动,重传率飙到5%,延迟上限直接翻倍。当时排查了好久,最后发现是物理层的均衡参数没调好,导致误码率偏高。
避坑指南:我曾经在测量链路层延迟时忽略了一个细节——流量控制的等待时间。当接收端buffer满时,发送端会被暂停,暂停时间取决于buffer清空速度。这个等待时间不算在重传里,但同样会贡献延迟。测量时一定要区分“正常流控等待”和“重传等待”,两者对延迟分布的影响不同。
链路层延迟的测量,我习惯在链路层入口和出口分别打时间戳,记录每一笔数据经过链路层的总时间。同时统计重传次数和流控等待周期,这样能清楚知道延迟是花在了哪里。
2.4 事务层——延迟的大头
事务层是协议栈的最上层,直接和上层协议(比如PCIe、CXL)打交道。它的工作是做协议转换、数据打包和解包、事务排序以及缓存管理。
事务层的延迟是三层中最大的,也是变化最大的。原因很简单——协议转换需要时间,缓存排队需要时间,事务调度也需要时间。你想想看,从一个协议格式转换成UCIe格式,中间要查表、要映射、要打包,几十个ns就出去了。
我见过一个案例,事务层的缓存配置不合理,导致高优先级事务被低优先级事务堵住了,延迟从80ns飙升到200ns。后来调整了缓存分配策略,把高优先级事务的专用通道加宽,延迟才降回来。我个人习惯在事务层设计时留出足够的缓存余量,宁多勿少。
事务层的延迟还与包大小有关。大包需要拆成多个flit传输,拆包和重组都会增加延迟。测量时最好分别测小包和大包的延迟,做到心中有数。
关键数据:事务层延迟通常占UCIe端到端延迟的60%–70%。如果端到端延迟超标,优先排查事务层的协议转换和缓存排队。
2.5 延迟在各层的分布与测量要点
为了让你看得更清楚,我把各层的延迟特征、典型范围和关键测量点整理成了表格。对照表格做测量计划,不容易漏项。
| 协议层 | 延迟特性 | 典型范围 | 关键测量点 | 注意事项 |
|---|---|---|---|---|
| 物理层 | 固定,亚ns级 | 0.5 – 5 ns | 芯片引脚、CDR输出 | 时钟质量影响实际值 |
| 链路层 | 半确定,重传会抖动 | 5 – 20 ns | 链路层入口/出口 | 区分流控等待和重传 |
| 事务层 | 可变,协议依赖 | 30 – 100 ns | 事务层入口/出口 | 缓存配置影响明显 |
| 端到端合计 | 混合特性 | 35 – 125 ns | 发送端事务层入 → 接收端事务层出 | 逐层拆分后汇总 |
测量时,我建议先在物理层做一次标定,拿到固定延迟基准。然后逐层向上测链路层和事务层,每测一层就把前一层的延迟减掉,这样得到的就是每一层自己的净延迟。说白了,就是层层剥离的方法。
另外,要注意延迟的统计分布。只看平均值不够,还要看P99和P99.9。尤其是链路层的重传和事务层的排队,会把P99拉高很多。
个人做法:我会在每一层都放一个时间戳计数器,分辨率至少到1ns。测试时跑100万笔数据,把延迟分布画出来,看均值、标准差和尾延迟。这样哪一层有问题,一眼就看得出来。
好了,这一章我们把UCIe协议栈的三层拆开看了一遍,每层的功能、延迟来源和测量要点都聊了。下一层一层测下去,你就知道延迟到底花在了哪里。