这是因为 FPGA 工具链的工作原理。有几个主要步骤:综合、映射、布局和布线。合成是唯一类似于编译的。合成也是唯一最容易并行化的步骤(每个模块可以独立于其他模块进行合成),因此它通常只是运行工具所需总时间的一小部分。当这些任务在整个设计中起作用时,您可以将映射、布局和布线与链接进行某种程度的比较。然而,链接基本上是一个微不足道的操作,主要涉及从编译器读取所有目标代码,修复一些地址,并写出可执行文件。每次重新运行软件工具时,可能只需要重新编译几个文件,但需要重新链接整个输出文件。但这很快,因为链接器没有做任何特别复杂的事情。
另一方面,映射、布局和布线是高度计算密集型的,不容易并行化,而且它们也非常不容易以增量方式进行。映射从综合(与门、或门、多路复用器、触发器、加法器等)中获取“高级”网表,并将其转换为设备原语(LUT、触发器、进位链等)。布局然后决定将每个原语放置在设备上的哪个位置,路由确定如何使用互连网络路由所有连接。所有这些都是时序驱动的——这些工具试图映射、布局和布线所有逻辑,以便满足所有时序约束。这是一个比简单地将一堆 C 转换成一堆程序集复杂得多的问题。
逐步执行此操作意味着跟踪您在 HDL 级别上的更改在最终布线设计中的结果。这是非常重要的事情,而且几乎不可能做好。这些工具基本上需要将旧的综合网表与新的网表进行比较,向下传播更改,并希望事情最终能够解决,并且能够满足时序约束。
我有一些关于增量构建出错的个人经验。最近,我不得不删除并重新创建一个英特尔 FPGA 项目,因为它在更改一些时序约束后拒绝重新放置特定寄存器,因为增量构建认为由于生成该寄存器的逻辑没有改变,所以寄存器没有必须移动。这是在我浪费了几个小时尝试各种晦涩的指令组合以试图让工具合作之后,我才意识到问题的真正所在。