FPGA 原型验证专题 15:原型编译器逻辑综合——布尔优化、工艺无关网表,与 Vivado 综合的两级分工
更新时间:2026-09-12。本文是「ASIC FPGA 原型验证系统」专题 06~25 深体系列分册,对应阶段 3(Compiler 逻辑综合)。ID 侧见 16 GateID 与逻辑网表模型 cell/net/ID 分配、映射见 17 info_table 映射表 GateID↔RTLID/回溯/版本,厂商侧见 18 原型约束体系 SDC/XDC/跨片时序/例外 与 19 原型频率与时序收敛 TDM 降频/关键路径。
这一篇在链路里的位置
阶段 3 是 GateID 诞生点:RTL 被翻译成布尔网表,编译器为每个 cell、每条 net 分配 GateID,并回溯建立到 RTL ID/层次的映射(info_table 初稿)。输出的仍是与厂商器件无关的逻辑网表,不是 LUT/FF 原语——那是阶段 4 Vivado 才做的事。
本文要回答的问题
- 逻辑综合内部流水线:与工艺无关的 RTL 优化(布尔化简/常量/死逻辑/资源共享)到网表生成,各做什么?
- 为什么这一步要与具体 FPGA 型号解耦?EDIF/结构化 Verilog 网表长什么样?
- 两级综合到底怎么分工?哪些优化在 Compiler 做、哪些留给 Vivado pack/place/route?
- 多 FPGA 分割后的子设计如何分别落网表?跨片 TDM 逻辑在网表里如何表达?
- dont_touch/插桩信息如何穿过综合而不被优化掉?
- 综合如何同时产出 GateID 与回溯映射(网表单元来自哪些 RTL 行/实例)?
- 为什么不用 Vivado 一步到位:可观测性、多片、映射关系、跨厂商可移植性的需要。
一、阶段 3 在流水线中的位置
先把三个相邻阶段钉死:
| 阶段 | 输入 → 输出 | 回答的问题 |
|---|---|---|
| 1 Elaboration(09 编译器前端展开 Elaboration AST/实例树) | RTL 源码 → 实例树 + RTL ID | 有什么、怎么连 |
| 3 Compiler 逻辑综合(本篇) | 适配/分割后的可综合 RTL → 工艺无关逻辑网表 + GateID + info_table 初稿 | 用什么布尔逻辑实现、属于哪个 RTL 对象 |
| 4 Vivado 综合+P&R(19 原型频率与时序收敛 TDM 降频/关键路径) | 逻辑网表 → LUT/FF/BRAM 原语 → 比特流 | 怎么装进具体型号并跑到目标频率 |
阶段 3 是 RTL 域跨入 Gate 域的分界点:GateID 在本阶段诞生(16 GateID 与逻辑网表模型 cell/net/ID 分配)。它输出的网表只含通用布尔 cell(AND/OR/MUX/FF/三态/黑盒)和网线,不含任何具体型号的 LUT 位型、BRAM 位点——刻意与厂商器件解耦。
二、工艺无关的逻辑优化流水线
Compiler 综合内部分两级:先做与器件无关的 RTL 级/布尔级优化,再落网表。典型 pass:
- 架构级:资源推断(数组→存储候选、case→MUX/译码器、移位寄存器链识别)、资源共享(互斥的加法器共用一个)、FSM 提取与状态编码选择(FSM 设计);
- 常量传播与折叠:参数化后大量输入是常量(09 编译器前端展开 Elaboration AST/实例树),常量路径整条化简——test_mode、静态配置寄存器都在此折叠;
- 死逻辑消除(DCE):输出不可达的逻辑删除。注意这正是观测点杀手(14 可观测性插桩 dont_touch/probe/可见性预算):被 dont_touch/keep 标记的对象在本 pass 跳过;
- 布尔优化:AIG/与非图上的代数化简、相同结构共享(CSE)、MUX 优化;
- 时序/面积权衡:原型目标不是极致面积,优化导向是「保结构、保观测、利于多片」,例如不做跨分割边界的激进打平,必要时弱 retiming。
与 ASIC 综合(芯片侧逻辑综合)最大的取向差异:ASIC 综合以 PPA 最优为目标,Compiler 综合以可映射、可观测、可回映、跨厂商为优先,宁可网表朴素一些。
三、网表表示:cell / net / pin
逻辑网表的对象模型:cell(单元实例:逻辑门、触发器、黑盒)、pin(cell 的端口)、net(连接一组 pin 的网线,可为向量)、port(子网表/层次的对外端口)、constant(0/1 驱动)。两种组织:
- 层次化网表:保留 module 实例边界,网表是「实例含子实例+局部网表」的树;回映友好、黑盒/替换单元边界清晰;
- 扁平网表:全部 cell 在一层、net 全限定命名;交给某些只吃 EDIF 扁平网表的工具时使用。
实践中 Compiler 内部保留层次化视图(锚定 RTL ID),导出时按目标工具需要选择保留层级(write_edif -hier)或打平,并同步产出两种视图间的对应记录。EDIF 是老牌中立格式(library/cell/net 三段式),结构化 Verilog 网表(module + 连续实例化)更易读、易 diff,二者都要带版本头和构建 ID。
四、多片子网表与跨片 TDM 的网表表达
阶段 2 的分区(12 多 FPGA 分区算法 割集/容量/图划分)在这里固化为每片一个子网表:子设计内部逻辑正常落 cell/net;被割开的连接不在两片间直接连,而是:
- 源侧网表自动例化 TDM 发送 wrapper(含发送寄存器、聚合 MUX、帧/训练逻辑),割边信号接其输入;
- 目的侧例化 TDM 接收 wrapper(对齐、解聚合、接收寄存器),输出接原逻辑;
- wrapper 的对外端口成为子网表的物理端口,阶段 4 绑到 SerDes/LVDS 管脚(13 跨 FPGA 互联与 TDM SerDes/跨片同步/降频);
- wrapper 是带特殊属性的黑盒/半黑盒 cell,在 info_table 中标注「跨片 TDM 单元」,回映时其内部活动不归属任何用户 RTL,但其时隙流量要折算回原割边信号(23 Gate→RTL 数据回映 查表/聚合/SAIF)。
五、约束与插桩如何穿透综合
优化会消灭对象,三类信息必须有「穿透通道」:
- dont_touch / keep:作为综合属性挂在实例/net 上,对应的 DCE/打平/合并 pass 读取并跳过;dont_touch 实例作为黑盒原样落入网表,keep net 即使扇出为「仅观测」也强制保留并引出;
- probe 点:14 可观测性插桩 dont_touch/probe/可见性预算 插入的观测寄存器/汇聚 MUX 在网表中显式存在,带 probe 属性和槽位号,GateID 照常分配;
- 时钟/时钟域:时钟网标记为 clock net,不参与普通布尔优化;ICG 已在阶段 2 转 CE(11 ASIC→FPGA 等价单元替换 SRAM/时钟/IO/PHY),这里不能再被「优化回门控时钟」;
- 替换单元(BRAM 替身、行为模型)以黑盒库形式链接,库版本写进网表头。
六、GateID 分配与来源回溯
网表每个 cell、每条 net 在生成时即分配 GateID(编码与遍历见 16 GateID 与逻辑网表模型 cell/net/ID 分配)。更关键的工作是来源回溯:综合每一步变换都带着来源指针——新 cell 记录它由哪个 RTL 实例(RTL ID)的哪段行为(源码文件/行号/信号名)生成;优化合并时来源做并集而不是丢弃。落网表时据此写出 info_table 初稿:每条 GateID → 一个或多个 RTL ID + 关系类型(直接/复制/合并/常量/替换单元)。这张表是阶段 6 回映的全部依据(17 info_table 映射表 GateID↔RTLID/回溯/版本)。
七、与 Vivado 综合的接口:指望什么、不指望什么
喂给阶段 4 的是:逻辑网表(EDIF/结构化 Verilog)+ 约束(18 原型约束体系 SDC/XDC/跨片时序/例外)+ 黑盒库(TDM wrapper、BRAM 模型、trace IP)。职责切分:
| 事项 | Compiler 综合 | Vivado 综合/P&R |
|---|---|---|
| RTL→布尔等价性 | ✅ | —(拿到的已是网表) |
| GateID/回映关系 | ✅ | 无感知,也不能指望它保留 |
| 多片分割与 TDM 生成 | ✅ | 只见单片 |
| 布尔逻辑→LUT/FF pack | — | ✅ |
| BRAM/DSP/BUFG 物理映射 | 给候选/黑盒 | ✅ |
| 布局布线、时序收敛、比特流 | — | ✅ |
铁律:凡需要跨片、需要回映、需要可观测的东西,必须在 Compiler 网表里就存在并打标;Vivado 可能重命名、复制、打包,但无法重建已丢失的语义。为跨厂商可移植(Xilinx/Intel 工具网表方言不同),Compiler 维护自己的中立网表作为唯一真相,厂商格式只是导出后端。
八、常见问题
- 综合后行为差异:多来自 X 态语义分歧(FPGA 触发器有确定初值、ASIC SRAM 读出 X,见 08 不可综合构造识别与存根替换 模拟IP/时钟门控)、敏感列表/锁存器推断差异、有符号运算截断;用 lint + 仿真对拍(11 ASIC→FPGA 等价单元替换 SRAM/时钟/IO/PHY 的替身回归)在综合前拦截;
- 黑盒残留:网表中仍有未链接黑盒时禁止导出(白名单机制,11 ASIC→FPGA 等价单元替换 SRAM/时钟/IO/PHY),否则 Vivado 阶段变成隐式空壳;
- 观测点丢失:keep 属性没穿透到网表(属性写错语言层级)——检查 info_table 中每个 probe 是否有对应 GateID;
- 优化过度改变语义结构:retiming 移动了触发器导致回映对不上——观测相关路径关闭 retiming 或在 info_table 记录移动关系。
九、逻辑综合的优化预算:哪些优化允许、哪些必须禁止
Compiler 的逻辑综合不是把网表简单翻译,它会做一长串与 ASIC 综合器类似的优化;但原型综合的目标函数不同——除了面积速度,还要保可追溯性、保层次锚点、为 TDM 和观测留结构。因此要明确「优化预算」:哪些变换放行、哪些禁止、哪些带条件放行。默认放行:常量传播(常量驱动的逻辑折叠)、死逻辑消除(真正无扇出的内部逻辑,但删除必须进来源台账,见 61 篇)、单元内部的布尔代数简化、等价门合并、D 触发器极性整理——这些不改变层次归属,来源关系可以逐条记录。带条件放行:跨模块边界的优化(寄存器复制、组合逻辑跨层次重组、FSM 重编码)。它们能显著改善时序面积,但会打散「一个 cell 对应一个 RTL 实例局部」的朴素映射;放行条件是来源传播机制能记录每个生成 cell 的全部来源(可能是多个 RTL 对象),且未跨越标记保留的层次边界。FSM 重编码还要把状态寄存器的位语义变化登记,否则波形里看到的二进制状态无法映射回 RTL 的枚举名。默认禁止:基于时序驱动的大规模重定时(retiming,把寄存器跨组合块搬移)会让「这个寄存器是 RTL 里的哪个」彻底失去一一对应,原型 Compiler 一般关闭或只在叶子模块内部允许;名字驱动的网表处理(依赖信号名推断时钟/复位)禁止,时钟识别必须基于显式时钟结构;对 dont_touch 对象和观测汇聚树的一切优化禁止。与下游 Vivado 的分工:Compiler 综合产出工艺无关门级网表,Vivado 再做工艺映射和物理优化。优化预算的原则是「语义保持类优化在 Compiler 做、物理相关优化留给 Vivado」,因为只有语义保持类变换的来源关系值得也能够完整追踪;Vivado 内部的 LUT 打包、布线交换是物理实现细节,不参与 RTL 回映(GateID 锚定的是 Compiler 网表对象经 XDC/属性保护后的对应关系)。每条优化 pass 都应在日志中输出变换计数和样例,回归测试断言「同一 RTL 两次构建,网表结构与 GateID 逐字节一致」——确定性(见 54 篇)从这里开始保障。
十、黑盒、替换模型与 stub 在综合阶段的收口
第 51/52/55 篇处理的替换与黑盒,到逻辑综合阶段要完成最终「收口」:网表里不能再有悬空的抽象对象,每个盒子都必须是 FPGA 上可实现的、端口时序已定义的实体。收口流程有几个检查点。端口完整性:黑盒模型的端口(位宽、方向、时钟归属)必须与 RTL 侧实例严格一致;上游 RTL 改了端口而替换模型没改,展开期可能因为延迟绑定没报错,到综合期才炸——更好的做法是在展开后立即做端口契约比对。收口检查把这件事做成硬错误,列出不匹配的每个端口。时序语义闭合:替换模型引入的延迟(PIPE 桥加几拍、多端口 RAM 仲裁加不定拍)必须以端口协议方式闭合——要么模型内部自包含这些延迟且 DUT 侧握手能容纳(valid/ready 流控),要么在模型包装层补齐与 ASIC 原语一致的外部时序假设。收口报告列出每个黑盒的延迟模型,供 57 篇互联和 63 篇频率预算消费。资源核算:替换模型展开为真实 FPGA 资源(BRAM 个数、GT 个数、LUT 估算),计入分区的资源账本;这是分区器能拿到准确容量数据的前提,因此替换必须先于或伴随分区完成,不能留到 P&R 才发现某个模型超资源。参数传播:ASIC 宏的参数(深度、位宽、端口数)要传播进替换模型的生成参数,且参数映射函数来自版本化的规则库(55 篇);收口时核对生成结果与规则库预测一致,防止「规则说映射成两块 BRAM,实际生成了三块」。stub 的最终标记:纯占位 stub 在网表中打上不可信标签,随 GateID 进入 info_table,使回映和覆盖工具自动把其内部活动排除出 DUT 统计。多实例一致性:同一 RTL 模块被替换后例化几百次时,收口校验所有实例使用同一模型版本;历史事故里出现过「大部分实例用新模型、两个角落实例因库路径残留用了旧模型」,行为差异只在特定流量下显现。收口完成的判据是:网表中每个叶子单元要么是可映射的通用门/时序单元,要么是带完整契约和台账记录的 FPGA IP,没有第三种状态。
十一、综合日志的可读性与失败分诊:从报错到责任边界
大规模网表的综合日志动辄几十万行,出错时能不能快速分诊,决定了 Compiler 团队和 ASIC 设计团队之间的协作摩擦。好的综合系统把日志和报告组织成分诊友好的层次。错误分类即责任归属:每条错误归入固定类别——RTL 可综合性问题(退回设计团队,附文件行号和最小反例)、替换规则缺失/失配(Compiler 规则库责任,附未识别单元的完整类型与参数)、资源超限(分区/选型责任,附超容量的资源维度与数量)、内部工具错误(Compiler 开发责任,附可复现的输入指纹),并直接生成指向对应团队工单系统的模板。最忌讳一条「synthesis failed」让两个团队互相猜。警告的分级与白名单:警告分错误级(多驱动、推断 latch、时钟被数据信号驱动)、评审级(位宽截断、无 default case、未连接端口)、信息级;项目维护一份带注释的白名单,每条被接受的警告记录原因和失效条件,新增警告在门禁里高亮——51 篇讲的交付门禁在这里与综合闭环。结构报告:除了错误,每次综合产出结构化报告:实例/单元/net 计数、按层次和类型的分布、优化删除了哪些对象及原因、替换模型清单、黑盒延迟清单、TDM 插入点、dont_touch 清单。这份报告是 61 篇 info_table 的姊妹文档,回答「网表是怎么来的」。最小复现:RTL 触发的综合崩溃要能自动削减(delta debugging 思路)——工具尝试逐级删除实例/模块直到错误消失,给出触发问题的最小设计切片,这让上游团队拿到的是「这 50 行触发问题」而不是「整个芯片构建失败」。趋势看板:构建时间、资源、警告数、删除对象数随提交的趋势曲线;非预期变化(同样的 RTL,某版突然多删了一批信号)往往先于功能故障暴露工具回归。综合阶段是三方交接最密集的位置,它的可观测性工程做扎实,整个原型流程的大部分等待时间和扯皮成本都会下降。
十二、综合器的确定性与可复现构建
第八节强调了常见问题,这里单独深挖一个在多团队、长周期项目中会升级为信任危机的主题:为什么同一份输入必须产出同一份网表,以及工程上怎么保证。先厘清「相同输入」的完整定义:RTL 与适配层源码的精确版本、规则库版本、综合器二进制版本、参数与宏配置、目标器件型号与速度等级、约束文件、随机种子(如有)、以及综合器可能依赖的环境(语言区域、线程数规约方式、许可证特性开关)。其中任何一项漂移,「不可复现」就不是工具的错而是构建系统的漏洞。成熟流程把这些全部写进构建清单并作为 manifest 的一部分。并行综合的确定性陷阱:多线程优化的归约顺序若不确定(如哈希遍历、任务完成顺序合并),网表和 GateID 会随机器负载变化。要求工具支持确定性模式(固定内部调度、并行只用于无状态子任务、合并阶段全排序),回归测试做「同机连跑两次逐字节比对」和「不同机器/不同线程数交叉比对」两层。为什么逐字节而不是「功能等价」:功能等价的两份网表仍可能有不同 GateID、不同结构指纹,导致下游所有版本资产(采集配置、历史数据、时序基线)无法对齐,64 篇的版本绑定也失去对象;可追溯性目标决定了比较标准必须是结构逐字节一致。工具版本升级的管理:综合器升级是高风险事件——即使声称兼容,优化策略变化会改变网表、时序和资源。流程上要求新版本在隔离分支跑完整回归(结构 diff、关键时序对比、黄金场景重放),通过后整体切换并在 manifest 标注,禁止工程师机器各自升级。输出可审计性:每次构建除网表外产出「配方文件」(上面所有输入的哈希)、综合日志摘要和工具自报版本;给定任意历史比特流,都能用配方重放出同结构网表——这条能力是 69 篇签核证据链的起点。当工具确实有 nondeterministic bug 时:记录触发条件、锁定工具版本或规避选项、在结构 diff 中识别「只在已知无关区域抖动」并经人工签字接受,但绝不把未知的不确定性默默吞下。可复现不是洁癖,而是让「这次运行」能在半年后被重建、被审计、被信任的前提。
十三、逻辑综合与 ASIC 综合的对照:思路迁移与误区
有 ASIC 综合经验的工程师接手原型 Compiler 时,迁移最快、也最容易把 ASIC 的默认假设误用,这里做一次系统对照。目标函数不同:ASIC 综合在给定工艺库和时序约束下优化功耗、性能、面积(PPA),可以自由重定时、跨边界合并,因为下游的物理设计和签核都基于综合后的网表,不需要还原 RTL;原型综合的第一目标是可追溯与确定性,时序优化让位于「每个生成对象来历清楚」,许多 ASIC 里的高收益变换在此被禁用或限制。工艺库不同:ASIC 面对连续驱动强度的标准单元库,原型面对 LUT/FF/BRAM/DSP 这类粗粒度固定资源,且最终工艺映射由厂商工具完成;Compiler 的网表停在与工艺无关的门级抽象,过早针对具体 FPGA 优化反而损害跨平台复用。时序处理不同:ASIC 综合依赖精确线载模型和物理反标迭代,原型的物理延迟要等布局布线才知道,Compiler 不承诺时序收敛,只保证结构和约束正确传递;因此不能拿 ASIC 综合后的时序报告习惯要求原型综合阶段给结论。调试方式不同:ASIC 综合问题主要看时序和面积报告,原型综合还要回答「为什么这个信号没了」「这个 ID 对应哪个 RTL」,日志和台账是一等输出。可迁移的真本事:优化 pass 的基本原理(常量传播、死代码消除、资源共享、状态机优化)、硬件描述语义的精确理解、对推断失败的敏感度、结构化 RTL 风格的审美,这些在两个世界完全通用,且是原型 Compiler 开发最需要的功底。最危险的误区是把「优化掉了多少逻辑」当作综合器好坏的指标——在原型语境里,过度优化意味着层次消失、映射变难、观测点失效;好的原型综合器有时甚至要「克制优化」以保住追溯链。理解这层角色差异后,ASIC 背景工程师可以把重心从「榨干每一皮秒」调整为「在确定性、可追溯和足够好的时序面积之间维持工程平衡」。
十四、综合阶段常见问题的快速分诊表
给一线工程师一份按症状索引的分诊表,作为 59 篇的工具页。展开就失败、报层次/例化名错误:回 51/54 篇查交付门禁和命名规范,先别看综合选项。报未知原语/黑盒无模型:替换规则缺口,走 55 篇规则提案流程,不要在网表上手改。综合通过但存储数量远超预期:多半是推断失败回退成 LUT 实现,查存储模板、写穿透配置和复位风格(52、55 篇)。乘法器未进 DSP:查位宽、输入寄存器位置、复位与累加结构是否符合硬核模板。GateID/映射表对不上、未映射率突增:先查输入配方(规则库版本、参数),再查是否违反确定性构建(59 篇第十二节),最后怀疑工具缺陷。同输入两次结果不同:确定性模式未开或环境泄漏,立即停用该构建做发布,复现并定位后再恢复。某版网表突然大改但 RTL 改动很小:查规则库/工具版本是否漂移、指纹 diff 是否显示子树异常。资源报超限但分区预期有余量:替换模型资源核算与实际不一致,更新规则库的资源预测。时序在综合阶段看似很差:正常,物理延迟未定时不下结论,等实现报告(62、63 篇)。怀疑综合引入功能错误:先用综合前门级/行为仿真与替换模型测试比对,再查优化台账中被删除/合并的对象,不要直接在布局后网表里找逻辑 bug。分诊的总原则不变:把问题先归类到输入、规则、确定性、物理实现四个抽屉之一,再在抽屉内深入,能避免大量在错误层级上的空转。最后提醒一句:综合阶段的每一个警告都值得读一遍,警告与错误的区别只在于「这次有没有挡住构建」,并不代表风险大小——许多后来上板的疑难,回溯到综合日志都能找到当时被忽略的那行提示。让读日志成为每次构建后的肌肉记忆,是 Compiler 使用者和维护者共同的基本功。综合阶段越透明、分诊越迅速,后面分区、实现、上板各环节的隐性返工就越少;这条不起眼的纪律,最终决定了整条原型流水线的平均周转速度。
知识脉络

与系列及现有篇目的衔接
- 前置:09 编译器前端展开 Elaboration AST/实例树、12 多 FPGA 分区算法 割集/容量/图划分、14 可观测性插桩 dont_touch/probe/可见性预算
- 同阶段:16 GateID 与逻辑网表模型 cell/net/ID 分配、17 info_table 映射表 GateID↔RTLID/回溯/版本
- 厂商侧:18 原型约束体系 SDC/XDC/跨片时序/例外、19 原型频率与时序收敛 TDM 降频/关键路径
- ASIC 综合背景:芯片侧 逻辑综合、综合入门
总结
一句话总结:阶段 3 是原型链路里 RTL 域跨入 Gate 域的分界点,由原型编译器把阶段 2 适配、分割后的可综合 RTL 综合成一张与具体 FPGA 型号无关的逻辑网表(通用布尔 cell+net,EDIF/结构化 Verilog,内部保持层次化视图、按需导出扁平),并在此分配 GateID、带来源指针写出 info_table 初稿;内部流水线先做存储/MUX/FSM 推断、资源共享,再做常量传播、死逻辑消除、布尔化简,取向与 ASIC 综合相反——保结构、保观测、保回映、跨厂商优先于极致 PPA;多片分割在此固化为每片一个子网表,割边两端自动例化带特殊标注的 TDM 收发 wrapper 作为子网表物理端口;dont_touch/keep/probe/时钟信息以综合属性穿透各优化 pass,被替换单元以带库版本的黑盒链接;它与 Vivado 的两级分工是:Compiler 管 RTL→布尔等价、GateID 与回映关系、多片与 TDM,Vivado 管 pack 成 LUT/FF/BRAM、布局布线和比特流——凡需跨片、回映、观测的语义必须在 Compiler 网表中存在并打标,Vivado 无法重建已丢失的信息;常见坑(X 态语义分歧、黑盒残留、keep 没穿透、retiming 挪动触发器)分别靠综合前对拍、黑盒白名单禁导出、info_table 逐 probe 核对和观测路径关 retiming 来防。