这一篇在干嘛?
前面章节讲的优化手段零散,本章用一个完整例子串起来:SRC(简单 RISC 计算机)处理器在 Xilinx Virtex-2 上从 63.6 MHz 一路优化到 135 MHz。跟着数据走一遍,你就知道每次优化的收益和代价长什么样。
17.1 SRC 处理器架构
SRC 是学术界广泛使用的微处理器教学模型(出自 Heuring 和 Jordan 的《Computer Systems Design and Architecture》)。它结构通用、没有商用处理器那些复杂优化,非常适合做流水线实现的示范。
基本配置:
- 32 位机器,32 个通用寄存器(5 位寄存器地址);
- 2³² 字节主存(任意 32 位寄存器可寻址);
- 1 个 32 位程序计数器(PC)、1 个 32 位指令寄存器(IR)。
指令分四类:load/store(访存)、branch(分支)、简单算术(add/sub/invert)、位操作与移位。
图17-1 SRC 的寄存器组与主存结构
五级流水线
流水线(pipeline)把一条指令的执行切成多个阶段,每级之间用一层寄存器隔开,让每级只承担一小段延迟,从而提高时钟频率:
图17-2 SRC 主流水线:各功能级之间由寄存器层分隔
理想情况下每个时钟周期完成一条指令(实际会因流水线停顿略高一点,本例中忽略)。这个实现有三个值得注意的细节:
- 寄存器堆和系统主存在 FPGA 外部——如果需要大容量系统内存,用外部存储芯片比塞进 FPGA 更划算(block RAM 资源有限)。
- 每级之间都有明确的寄存器层,反馈信号(Feedback)也是寄存器。任何进入某级的信号都清楚属于哪一级,设计变复杂时 timing 依然井井有条——这是良好的流水线编码习惯。
- 寄存器模块参数化:
DRegister的第一个参数是位宽,同一个模块可在所有位宽场合复用。
(顶层流水线的完整代码见原书附录 B。)
17.2 综合优化
目标器件 XC2V250(Virtex-2,成熟工艺、特性表征完善),第一版综合约束 50 MHz:
表17-1 初始综合结果
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 63.6 MHz | Slack = 4.3 ns |
| LUT | 1386 | 45% 利用率 |
| 寄存器 | 353 | 11% 利用率 |
关键观察:因为 50 MHz 约束很松,综合工具把逻辑实现成串行紧凑的结构,关键路径上堆了 23 级逻辑:
图17-3 约束宽松时,关键路径被实现成 23 级串行逻辑
这告诉我们一个重要事实:综合结果不是唯一的,它会跟着时序约束走。约束松,工具就省面积;约束紧,工具就换面积换速度。
17.2.1 速度换面积
把约束推到 100 MHz,综合工具自动把关键路径展开成并行结构:
表17-2 提高目标频率后
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 97.6 MHz | Slack = -2.4 ns |
| LUT | 1538 | 50% 利用率 |
| 寄存器 | 358 | 11% 利用率 |
面积只涨了约 9%,速度涨了 50% 以上。为什么不成 1:1?因为时序只由最差路径决定——工具只展开了真正成为瓶颈的路径。原来那条 23 级逻辑的路径被重映射为并行结构:
图17-4 原关键路径被展开成并行逻辑
17.2.2 流水线重定时
提速后瓶颈转移:新的关键路径变成从 IR2(指令寄存器第二级)经第 2 级到 X3 的反馈路径:
图17-5 新关键路径位于第 2 级内部
解决手段是流水线重定时(pipelining / rebalancing):把寄存器 X3 往第 2 级里推,让逻辑围绕多路选择器(mux)重新配平。由于寄存器要从 mux 输出复制到多个输入,寄存器用量几乎翻倍,而逻辑量几乎不变:
表17-3 启用流水线后
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 100.7 MHz | Slack = 0.1 ns |
| LUT | 1554 | 50% 利用率 |
| 寄存器 | 678 | 22% 利用率 |
注意一个细节:约束一旦满足,综合工具就停止流水线操作以节省寄存器。如果把约束再推到 110 MHz,工具会继续加寄存器:
表17-4 更高约束下的额外流水线
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 111.2 MHz | Slack = 0.1 ns |
| LUT | 1683 | 54% 利用率 |
| 寄存器 | 756 | 24% 利用率 |
结论:工具的优化深度永远以”恰好满足约束”为目标,想要多快,就把约束定多高(合理范围内)。
17.2.3 物理综合
物理综合(physical synthesis)让综合工具利用物理布局信息来优化——逻辑在芯片上摆在哪里、布线多长,都会反馈到优化决策里。开启后直接瞄准 120 MHz 并轻松收敛:
表17-5 Synplify Premiere 物理综合结果
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 122 MHz | Slack = 0.2 ns |
| LUT | 1632 | 53% 利用率 |
| 寄存器 | 772 | 25% 利用率 |
以上结果全部是工具自动完成、无人工干预。但 SRC 这种流水线划分清晰的设计,还有人工引导的空间——这就是下面的 Floorplan(物理规划)优化。
17.3 Floorplan 优化
Floorplan(版图规划/物理约束)是设计者手动告诉布局工具”这块逻辑摆在哪个区域”。设计已经被干净地切成流水级,天然适合按流水线拓扑来规划物理区域。
17.3.1 按流水级分区的 Floorplan(第一版)
流水级 2~4 的自然数据流向如下:
图17-6 第 2~4 级之间的自然数据流
第一版 Floorplan 顺着数据流把各流水级划成竖条区域(竖条方便 FPGA 内部进位链 carry chain 的走向),数据从左往右流,级间留一点空间放寄存器。观察到多数长路径位于第 1、2、3 级之间,就给这三级各自划区:
图17-7 按流水级划分的初始 Floorplan
表17-6 初始 Floorplan 结果(约束提到 125 MHz)
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 123 MHz | Slack = -0.17 ns |
| LUT | 1840 | 59% 利用率 |
| 寄存器 | 492 | 16% 利用率 |
结果并不比默认物理综合好多少。原因有三:约束的元素组太大、物理区域纵横比(aspect ratio,区域长宽比)过高、没有只聚焦真正时序紧的路径。教训:粗粒度的大区域 Floorplan 收益有限,必须聚焦到关键路径。
17.3.2 关键路径 Floorplan:抽象 1
迭代思路:找到关键路径 → 把这些组件圈进指定区域。本例关键路径在第 2 级周围的寄存器之间。最差路径穿过第 2 级:
图17-8 最差路径穿过第 2 级
这次只约束第 2 级,再按需纳入周边的源寄存器 IR2 和目的寄存器 X3、Y3:
图17-9 聚焦第 2 级的 Floorplan,区域更小、纵横比更方正
表17-7 聚焦后的 Floorplan 结果
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 127.6 MHz | Slack = 0.16 ns |
| LUT | 1804 | 58% 利用率 |
| 寄存器 | 559 | 18% 利用率 |
125 MHz 达标了。相比第一版,这个 Floorplan 更聚焦问题区域,且区域形状更接近正方形,布线更容易。
17.3.3 关键路径 Floorplan:抽象 2
更进一步:只圈关键路径上的逻辑元素本身,对其他路径几乎不加约束。默认实现中,关键路径在第 2 级与反馈寄存器 IR2 之间,且报告显示约 50% 的延迟是纯布线延迟——这是 Floorplan 能发挥的直接信号。
默认跑出的前两条关键路径是 IR2→Y3 和 IR2→X3。只把这两条路径的元素圈进比上一版更小的区域:
图17-10 只约束关键路径元素的 Floorplan
表17-8 关键路径 Floorplan 结果(约束 135 MHz)
| 指标 | 数值 | 备注 |
|---|---|---|
| 速度 | 135 MHz | Slack = 0.0 ns |
| LUT | 1912 | 62% 利用率 |
| 寄存器 | 686 | 22% 利用率 |
收敛后关键路径又转移了——现在是从 Y3 经第 3 级到 Z4:
图17-11 约束旧关键路径后,瓶颈转移到 Y3→Z4 路径
此时布线延迟已降到总延迟的 40%(逻辑延迟占 60%)。继续做 Floorplan 也许还有提升,但边际收益明显递减,投入产出比不高,可以收手了。
全程优化轨迹
| 步骤 | 速度 | LUT | 寄存器 |
|---|---|---|---|
| 初始综合(50 MHz 约束) | 63.6 MHz | 1386 | 353 |
| 约束提到 100 MHz | 97.6 MHz | 1538 | 358 |
| 流水线重定时 | 100.7 MHz | 1554 | 678 |
| 额外流水(110 MHz 约束) | 111.2 MHz | 1683 | 756 |
| 物理综合 | 122 MHz | 1632 | 772 |
| 按级分区 Floorplan | 123 MHz | 1840 | 492 |
| 聚焦第 2 级 Floorplan | 127.6 MHz | 1804 | 559 |
| 关键路径 Floorplan | 135 MHz | 1912 | 686 |
从 63.6 MHz 到 135 MHz,翻了一倍多——代价是 LUT 利用率从 45% 涨到 62%。
要点小结
- 综合结果跟着时序约束走:约束松则串行省面积,约束紧则并行换速度。
- 工具的流水线/重定时优化以”恰好满足约束”为限,想要更高性能就把约束定更高。
- 物理综合利用布局信息优化,通常优于纯逻辑综合。
- 粗粒度的大区域 Floorplan 收益有限;聚焦关键路径、区域方正才有效。
- 每轮优化后关键路径会转移,迭代圈定新瓶颈,直到布线延迟占比下降、边际收益递减。
常见坑
第一次做 Floorplan 就把整个模块甚至整个流水级圈成一个大区域,结果时序没改善、面积还涨了(本章 123 MHz 那一步就是教训)。Floorplan 的正确姿势是”小而准”:只圈当前最差路径上的元素,区域尽量方正,其他路径不约束。另外别忘了每轮优化后关键路径会转移,要用新报告重新定位,而不是抱着旧路径反复调。
通关标准:
学完本篇你应该能做到:① 看懂综合报告中的速度/LUT/寄存器/Slack 数据,判断当前瓶颈是逻辑延迟还是布线延迟;② 按本章顺序组合使用”提约束→流水线重定时→物理综合→Floorplan”的优化路径;③ 理解 Floorplan 的迭代方法——从大分区到聚焦关键路径,并知道何时该收手。
自测:为什么把约束从 50 MHz 提到 100 MHz,面积只涨 9% 速度却涨 50%?
时序只由最差路径决定,工具只展开那些真正成为瓶颈的路径(如原 23 级串行逻辑被重映射为并行结构),其余非关键路径仍保持紧凑实现。所以面积增长远小于频率增长。
自测:流水线重定时后寄存器为什么几乎翻倍?
把寄存器往前推、围绕 mux 重新配平时,mux 的输出寄存器需要复制到多个输入分支,每个输入都要有配套寄存器,所以寄存器数量大幅增加,而逻辑量几乎不变。
自测:第一版"按流水级分区"的 Floorplan 为什么效果不好?
三个原因:约束的元素组太大、物理区域纵横比过高(细长条不利于布线)、没有只聚焦时序真正紧的路径。改成只圈关键路径元素、区域方正之后性能才明显提升。
自测:报告显示关键路径"50% 延迟是布线延迟"说明什么?
说明布线是主要瓶颈,物理摆放有优化空间——正是做关键路径 Floorplan 的最佳时机。反之如果延迟几乎全是逻辑延迟,Floorplan 收益就有限,应该改架构或流水线。
自测:最后一轮 Floorplan 后布线延迟降到 40%,为什么不再继续优化?
边际收益递减:剩余路径的逻辑延迟占 60%,继续 Floorplan 只能挤压那 40% 的布线部分,而每轮迭代都要重新定位转移后的关键路径,投入产出比已经很低。