前几天老师需要一个设计数据,是有关一个大的FPGA工程中小模块的编译报告,由于时间有点久远,之前的小模块工程已经不知道在哪里了(自己也觉得这里做的很不好,虽然模块小,但设计之初也都是经过仔细设计仿真验证的,应该做好存档才对)……好吧,虽然没了也没关系,其实也很简单,把大工程copy一下,然后把子模块置顶,重新编译不就好了嘛。
可编译后问题来了,报错了!而且有点莫名其妙,一开始有点懵,不知道出在哪里……
Error: Partition hierarchy "PN_gen:inst2" does not exist in the current design or refers to an inferred hierarchy
Error: Partition hierarchy "TS_gen:inst5" does not exist in the current design or refers to an inferred hierarchy
几个错误都很相似,大致的意思就是说划分的“****”这些模块不存在当前的设计里面。这里就觉得奇怪了,出现错误的这些模块本来就是原来大工程下的其它子模块,当然不包括在现在的设计里面了,怎么还报错呢??
双击红色的ERROR提示没有反应,于是又再右键错误->help:
大致意思就是设定的区域划分没有实体……建议删除或者重建区域划分。看完之后,还是一头雾水……原本该是个很简单的操作,怎么出现这样的错误呢?首先静下来想想,不能慌,总结下这个问题,我个人获得以下这些信息:
(1)双击红色ERROR提示没反应,说明肯定不是设计文件出的错,应该是某个编译设置或者是综合设置不对;
(2)help和ERROR提示中有个关键词——“Partition”,中文解释也就是区域划分的意思,总觉得在哪里见过,可又想不太起来。
怀疑是编译设置部分出的问题那就先打开qsf文件看看!(qsf属于命令行文件,我们通过Quartus软件上进行的设置操作都会以命令的形式写入到这个文件里)虽然里面大部分内容可能大家不是很熟悉,不过不要紧,通过单词和变量大致猜猜某个命令是和什么有关的还是没问题的。打开后我就看到下面一堆的命令:(图中为之后注释掉的内容)
为什么会注意到这些?很简单,关键字PARTITION,还有出错的各个模块名称。然后分析下这些命令才让我想起来,原来这些是当时由于工程较大,采用了Quartus的增量编译时进行逻辑区域划分时设置的!
找到错误就好办了,把这部分命令注释掉,再编译就没有问题了。
本文暂时先不对Quartus的增量编译介绍了,想先总结总结在这个问题里面,出现错误时应该遵循的某些分析方法和流程。
第一、出错后我们的第一反应都会是双击ERROR提示看看会跳到哪里……的确,这是最直接的方法,而且一般设计上的大部分问题都可以通过这种方法来解决;
第二、当自己对这个错误不熟悉的时候,可以在ERROR提示处右键->help,然后会弹出Altera给出的关于这类错误的解释,不过它能做的只是解释这个错误类型,但肯定不可能针对你的工程给出什么解释;
第三、对于错误提示的内容,在不熟悉的时候应该要看出里面的“关键词”,进而缩小我们分析的范围;
第四、学会查看qsf文件的命令内容,当设计文件没问题的时候,很可能是里面的某个命令导致了你的错误;
最后,呵呵,大家都知道,利用网络资源,有海量的大牛们都在网上呢!!你解决不了的问题,肯定有人已经遇到过或者解决了~~
下面开始来仔细研究研究这个增量编译。
首先,得先看看QuartusII的编译过程是个怎么样的,要了解这个过程很简单,看看下面这张图,谁都不陌生:
当我们点全编译之后,下面的几个过程就会一个一个打上勾,而我们编译的过程也就是和这个运行过程是一致的:先是分析综合,再是布局布线,然后是汇编(这里不是指汇编语言的汇编,而是说将布局布线后的“电路”汇编成可下载到芯片内的“程序”),还有时序分析以及生成网表。
我们仔细看它编译的过程会发现其中耗时最多的是分析综合和布局布线(这点从上图右侧的时间标注也能看出来),所以我们想提高编译速度也应该从这点入手。
Quartus也有相关的自动增量编译的设置,如下图:
第一个是多核处理器的设置,这样可以提高整体的速度;第二个则是采用Smart Compilation,智能编译方式,它可以完成的功能——如果设计源文件没有改动,那Quartus将不再进行分析综合,而直接进入布局布线阶段。另外,还有一个设置也可以勾选上:
Rapid recompile,即如果设计没有修改那不进行重新编译。
从编译过程,我们再来看看我们的设计流程:
可以发现,其实设计过程和编译过程是一样的。而增量编译的原理就是,减少每次编译里我们设计已经完成的部分,进而不需要再重复设计者认为已经完成的工作。说得再直白一点:我们设计者手动得将整个工程分成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分多钟。
关于LogicLock的使用将在后面的文章中继续分析探讨。
悲剧啊……跳闸啦,刚码到一半……又要重新码啊……
我们先来搞清楚两个概念——“逻辑分区”和“物理分区”。
前面所讲到的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,编译器可以自动从全局出发去做出做大的优化,而我们人为地进行了物理分区限定,那即使可能每个小模块做到了很好的优化,但是由于各个区域之间的布局布线受到了限制,那自然会有所影响。但也不能如此绝对地断定,如果在占用资源很庞大的情况下,使用这种方法还能带来意想不到的效果