首先,得先看看QuartusII的编译过程是个怎么样的,要了解这个过程很简单,看看下面这张图,谁都不陌生:
当我们点全编译之后,下面的几个过程就会一个一个打上勾,而我们编译的过程也就是和这个运行过程是一致的:先是分析综合,再是布局布线,然后是汇编(这里不是指汇编语言的汇编,而是说将布局布线后的“电路”汇编成可下载到芯片内的“程序”,即.sof文件,在配置FPGA时候使用到的文件后缀),还有时序分析以及生成网表。
我们仔细看它编译的过程会发现其中耗时最多的是分析综合和布局布线(这点从上图右侧的时间标注也能看出来),所以我们想提高编译速度也应该从这点入手。
Quartus也有相关的自动增量编译的设置,如下图:
第一个是多核处理器的设置(最多使用到16核,对于常见笔记本的4核处理器,一般会自动用到2个核),这样可以提高整体的速度;第二个则是采用Smart Compilation,智能编译方式,它可以完成的功能——如果设计源文件没有改动,那Quartus将不再进行分析综合,而直接进入布局布线阶段。另外,还有一个设置也可以勾选上:
Rapid recompile,即如果设计没有修改那不进行重新编译。
这个在Quartusii13中没有。
我的是Quartusii13的,我这个版本没有这个选项。
从编译过程,我们再来看看我们的设计流程:
可以发现,其实设计过程和编译过程是一样的。而增量编译的原理就是,减少每次编译里我们设计已经完成的部分,进而不需要再重复设计者认为已经完成的工作。说得再直白一点:我们设计者手动得将整个工程分成N个子模块(此处指的是逻辑模块),并设定各个模块的状态(已经完成了,不需要更改了,编译时就采用上一次的结果)(具体操作细节看后文),这样编译器在分析综合的时候便可以对那些不需修改的部分直接采用上次的结果。布局布线的时候也是一样的,如果该子模块不需要更改了就采用上次的结果,如需更改再重新进行布局布线,只不过布局布线的过程要相比分析综合复杂一些。
而上面提到的将整个工程手动分成N个模块,我们就要用到Quartus提供的两个高级工具——Design Partitions和LogicLock Regions。
本篇,来仔细看看怎么使用增量编译。
增量编译主要用到的两个工具——Design Partition和LogicLock。
首先要提出一个概念,网上大多对增量编译的简要说明是:采用LogicLock进行增量编译。这是错误的看法!LogicLock并不是增量编译的一部分,只是在增量编译过程中建议使用LogicLock!(与自身使用经验和结果契合)
另外,上一篇里面提到关于增量编译原理个人的理解:将整个工程分成多个“逻辑区域”,然后每次编译中通过设定各个区域的网表类型来决定本次编译是否对该区域重新执行,“增量编译”是针对整个工程在设计过程中后一次编译与前一次编译的一个“增量”过程,其实Altera的官方名称应该叫——“渐进式编译模式”。
那从对原理的理解就可发现,其实我们只要用到Design Partition就可以完成“增量编译”了。下面简单介绍如何使用Design Partition工具:
首先,得对整个工程进行一次全编译(也可不编译,只进行顶层模块的分析,如下图有左边标出的小图标则可点开分析顶层模块下的子模块),经Analysis过程Quartus可自动分析出整个工程顶层模块下含有哪些子模块;
然后,便通过Design Partition对子模块进行“逻辑分区”。一般情况下,我们可以直接将上一步中分析出的子模块设定成“逻辑区域”;
设定好了以后打开Design Partition Window可看到如下图:
它的结构图与Project Navigator里的很像,有一个TOP模块,下面还有我们设定的各个小区域。表中的各列参数则是对各区域形式的一个设定,其中最关键的一个设定是Netlist Type,它有四个可选值——Source File,Post-Synthesis,Post-fit,Empty(如上图中所标1,2,3,4,上图是为了将各Type全面的显现出来,而不是最终设定)。它们各自的含义是:
Source File:如果源代码未修改,则仅不重新Analysis,还需进行Synthesis和Fitter;
Post-Synthesis:如果源代码未修改,不需重新Analysis、Synthesis,结果只进行Fitter;
Post-Fit:如果源代码未修改,保留前次Analysis、Synthesis、Fitter结果;
Empty:标志为空分区,编译时将忽略此分区。
这样我们就很明白了,其实要想达到“增量编译”的目的,只需将各个子模块设置在Design Partition里,并将未进行修改的各个模块设定成Post-fit,而修改过的模块设定为Source File。需要注意的是,顶层模块TOP的状态也需设定为Post-fit。
大家可以试试效果,个人试验的效果很显著……原来编译一次需5分多钟,这样的方法如果只改变一个分区的内容,只需1分多钟。(本人使用经验,对一些分区进行锁定之后,功能出现了一些问题,如alter 的三速以太网IP核,尚无发现解决本法,可能锁定出现一些问题)
我们先来搞清楚两个概念——“逻辑分区”和“物理分区”。
前面所讲到的Design Partition只是将设计进行“逻辑分区”,直白点说就是将我们的设计分成N个小的模块,每个模块有着单独的逻辑和功能,它告诉编译器,这部分逻辑是一个分区A,那部分逻辑是另一个分区B,在进行这样的分区之后,编译器在整个工程的综合、布局布线上面并不会有什么太大的变化,这个逻辑上的分区只是用来让用户清楚,哪部分逻辑是分区A的,哪部分逻辑是分区B的。之后用户就可通过设定A、B分区的属性类型来告诉编译器,哪部分已经不需要重新综合、布局布线了;哪部分已经修改了,需要重新进行综合等等。
而我们来看看LogicLock的作用,是对设计进行“物理分区”,更准确的说,它是对目标器件进行“物理分区”,然后将逻辑上的功能模块分配到一定的分区内。也就是说,我们先对目标器件进行物理区域划分,把它分成几个“地盘”,然后选择一个逻辑功能模块分配到某个“地盘”里,告诉编译器,以后这部分逻辑功能就只能在这个“地盘”里面布局布线了。同样的,用户可以对各个模块进行属性上的设定,告诉编译器以什么样的形式在“地盘”里面进行布局布线。
下面简单介绍下LogicLock的使用,我们前面已经用Design Partition进行了“逻辑分区”,我们可以用同样的方法,在设计的树形结构里面右键,然后如下图:
把各个子模块加入到LogicLock Region里面之后如下图:
里面有两个主要的参数,Size和State:Size有两个选项,Auto、Fixed;而State也有两个选项,Locked、Floating。但是并不是有着四个组合,其实只有着下面三种状态:
第一种,Auto+Floating:由编译器自动选择区域大小和位置;(在Chip Planner里面由虚线显示)
第二种,Fixed+Floating:由编译器选择位置,但由用户设定区域大小;(在Chip Planner里面由短实线显示)
第三种,Fixed+Locked:区域大小和位置都由用户来设定。(在Chip Planner里面由实线显示)
那我们来说说LogicLock在增量编译里面有什么作用呢?还是需要强调一下,增量编译不是一定非要用到LogicLock,但Quartus推荐在增量编译时使用LogicLock!为什么呢?因为它可以让增量编译的思想贯彻得更彻底。
我们想想在前面用Design Partition时出现的一种情况:改动后的模块逻辑功能上变化比较大,影响了其它“逻辑分区”的布局布线,这样未改动部分也需要进行重新编译了。但如果这个时候使用的是LogicLock,由于每个逻辑功能模块都分配了一定的“物理区域”,改动后的模块再怎么变也是在它自己的“地盘”里,不会影响到别的“地盘”的布局布线。()
但LogicLock也会带来一定的负面影响,最直接的,一般情况下,时序分析后的Fmax都要更低一些。这是为什么呢?其实想想也能知道,如果没有使用LogicLock,编译器可以自动从全局出发去做出做大的优化,而我们人为地进行了物理分区限定,那即使可能每个小模块做到了很好的优化,但是由于各个区域之间的布局布线受到了限制,那自然会有所影响。但也不能如此绝对地断定,如果在占用资源很庞大的情况下,使用这种方法还能带来意想不到的效果。
最后结合自身的经验总结一下:为什么design partition 和logiclock结合使用的原因如下,通常在一个大的项目中,通过自上而下的模块化设计方法,将设计好的多个模块分配给多个设计人员,设计人员在拿到自己的设计任务之后,完成设计任务,如果不使用design partition 和logiclock功能,那么将多个设计好的模块在组合成最终设计项目时,使用quartus在进行最终综合编译时,quartus编译器将不分主次进行全局的优化,导致此前综合通过子模块可能在集成之后将出现问题(本人在使用到10%的逻辑资源时在整合其他模块时候就遇到过此问题,新引入的模块导致时序不收敛了)。此时如果只是使用design partition,试想一下情况,模块A和B分别由设计人员a和b进行设计,此时a和b设计人员都对自己设计的模块只是使用了design partition而没有使用logiclock,那么quartus在编译优化模块A和B时候讲默认为整个FPGA的资源都是可以使用的,将在整个FPGA资源的基础上进行优化,然而在对A和B模块进行整合时,极有可能出现这样的情况,FPGA内部某个资源(如LAB,RAM,DSP...)同时被A和B模块使用到了,导致A或B需要重新布局布线,之前的优化的结果也烟消云散,因此,使用logiclock对模块在FPGA上进行“物理分区”将避免FPGA内同一个资源被多个模块用到,助力最后模块的整合,加速生成最终的项目。