第二章:虚拟通道(VC)基础
各位同学,今天我们来聊聊虚拟通道。说实话,VC这个概念刚接触时容易让人犯晕。我当年第一次看PCIe Spec时,也被TC、VC这些缩写搞得一头雾水。但等你真正理解了,就会发现它其实没那么复杂。
一、什么是虚拟通道?
虚拟通道,英文叫Virtual Channel,简称VC。说白了,它就是在物理链路上虚拟出来的多条独立数据通路。
你想想看,一条PCIe链路,物理上只有一组差分对(或者多组)。但通过VC机制,我们可以让不同类型的数据走不同的“虚拟车道”。就像一条高速公路,虽然路面只有一条,但我们可以划分出快车道、慢车道、应急车道。
核心要点:VC是PCIe实现QoS(服务质量)的基础设施。没有VC,所有流量都挤在同一条通道里,高优先级的数据也得排队等低优先级的发完。
我在项目中遇到过这样一个场景:一个存储系统里,同时有控制命令和大量数据在传输。如果没有VC,控制命令可能被数据流堵住,导致响应超时。配置了VC后,控制命令走高优先级VC,数据走低优先级VC,问题就解决了。
二、Traffic Class(TC)是什么?
TC是流量类别,它是数据包的一个标签。每个TLP(事务层包)头部都有一个3位的TC字段,取值范围0~7。
| TC值 | 典型用途 | 优先级 |
|---|---|---|
| 0 | 默认流量(Best Effort) | 最低 |
| 1~2 | 批量数据传输 | 低 |
| 3~4 | 交互式流量 | 中 |
| 5~6 | 实时流量 | 高 |
| 7 | 管理/控制流量 | 最高 |
注意,TC本身不决定数据怎么走。它只是一个标签。真正决定数据走哪条通道的,是TC到VC的映射关系。
三、TC与VC的映射关系
这是本章的重点。TC和VC之间不是一一对应的关系,而是一种多对一的映射。
具体来说:
- 一个TC只能映射到一个VC
- 一个VC可以接收多个TC的流量
- VC0是强制存在的,且必须接收TC0的流量
- 其他VC是可选的
举个例子:
// 一个典型的映射配置
TC0 -> VC0
TC1 -> VC0
TC2 -> VC1
TC3 -> VC1
TC4 -> VC2
TC5 -> VC2
TC6 -> VC3
TC7 -> VC3
这个配置的意思是:TC0和TC1的流量都走VC0,TC2和TC3走VC1,以此类推。
我的经验:配置映射时,建议把优先级相近的TC映射到同一个VC。比如把控制类流量(TC7)单独放一个VC,数据类流量(TC0~TC2)放另一个VC。这样隔离效果最好。
四、VC仲裁机制
好了,现在多个VC的数据都要通过同一条物理链路发送。谁先发?谁后发?这就涉及到VC仲裁。
PCIe支持两种仲裁方式:
- 严格优先级仲裁(Strict Priority):高优先级VC永远优先发送,直到它没有数据了,才轮到低优先级VC。
- 轮转仲裁(Round Robin):每个VC轮流发送,大家机会均等。
还有一种混合模式:加权轮转(Weighted Round Robin)。给每个VC分配一个权重,权重高的VC发送机会更多。
我曾经踩过一个坑:在一个视频采集卡项目中,我用了严格优先级仲裁。结果高优先级VC一直有数据,低优先级VC的数据被活活饿死了。后来改成加权轮转,给高优先级VC分配70%的带宽,低优先级30%,问题就解决了。
注意:严格优先级仲裁可能导致低优先级VC的“饿死”现象。如果你的系统里所有VC都有数据要发,一定要小心配置仲裁策略。
五、VC初始化流程
VC不是上电就有的。它需要经过初始化才能使用。流程如下:
- 第一步:链路训练完成后,默认只有VC0可用
- 第二步:软件通过配置空间,使能其他VC
- 第三步:配置TC到VC的映射表
- 第四步:配置仲裁策略
- 第五步:等待VC状态变为“就绪”
嗯,这里要注意:VC的初始化必须在链路稳定之后进行。我见过有人在上电后立即配置VC,结果配置没生效,因为链路还没训练完成。
六、本章知识结构图
下面这张图展示了VC、TC、仲裁之间的关系:
从这张图可以看得很清楚:多个TC映射到同一个VC,然后多个VC通过仲裁器竞争物理链路的使用权。
七、实际配置中的注意事项
最后,分享几个我在实际项目中总结的经验:
- VC数量不是越多越好:每个VC都需要额外的缓冲资源。我见过有人配置了8个VC,结果FPGA资源不够用了。
- VC0不能禁用:这是Spec规定的。所有设备必须支持VC0。
- 仲裁策略要匹配业务:实时性要求高的用严格优先级,公平性要求高的用轮转。
- 映射关系要提前规划:不要在系统运行时频繁修改映射表,容易出问题。
避坑指南:我曾经在一个项目中,把TC0~TC7全部映射到了VC0。结果VC0的缓冲被撑爆了,导致丢包。后来把流量分散到4个VC上,问题就解决了。记住:VC的作用就是分流,别把所有鸡蛋放在一个篮子里。
好了,关于VC的基础知识就讲到这里。下一章我们会深入VC的配置寄存器,看看软件层面怎么操作这些VC。
公众号:蓝海资料掘金营,微信deep3321