刚接触Innovus后端流程的新手,往往会把Floorplan这一步当成"画个框、摆几个memory"的体力活。我当年第一次打开Innovus GUI,看着那块空白画布,也是这么想的——直到后来Place、CTS、Route连续被一个糟糕的Floorplan拖垮,才意识到这个环节比表面看起来要重得多。标题里那句"5分钟搞定Floorplan基础操作"并不夸张,前提是你已经知道每个参数背后的意思。这篇内容就按"先跑通操作、再讲透原理、最后排掉常见的坑"的顺序来写,适合刚接触Innovus、准备把第一个设计从netlist做到可布线阶段的人,也适合带新人的后端工程师当入门讲解材料。
1. 为什么Floorplan是整个后端流程的地基
1.1 新手眼里的Floorplan,和实际上的Floorplan是两回事
很多新手把Floorplan理解成"在画布上把die画出来,把memory拖进去"。听起来没什么错,但这就像说"装修就是买家具"——你买再好的沙发,放到户型不合理、承重墙乱砌的房子里,照样难受到不行。Floorplan阶段定的die尺寸、core区域、macro位置、IO方向,基本决定了后续每个阶段的活动空间;Place阶段工具能做的局部时序优化、拥塞缓解,都是在这个空间里做文章,改不了根本边界。
我见过最典型的案例:某个设计刚开始Place时一切正常,到了Route阶段却怎么都绕不完,打开congestion map一看,问题全集中在两块memory之间不到十根走线通道的区域。源头就是Floorplan阶段那两个memory摆得太近,省了几十微米的面积,赔上了后面几周的修线时间。这种事情在项目里反复出现,所以带新人的第一课,我都会让他们先理解Floorplan决策的连锁反应,而不是急着点GUI。
1.2 Floorplan的输入、输出和它管不到的边界
先明确Floorplan这一步的输入输出,才知道自己手里的材料是什么。
输入:
- 综合后的netlist(包含标准单元实例、macro实例、层级关系)
- 物理库文件:technology LEF(工艺的层、规则、通孔定义)和macro LEF(每个宏单元的形状、pin位置)
- 时序库Liberty文件(做时序分析用,物理操作本身不需要它,但没有它后面跑不了流程)
- SDC约束(定义时钟、输入输出延迟,Floorplan阶段可以先不细看,但IO规划会引用它)
- IO Pad或IO pin的位置定义(由封装和PCB布局决定,通常是团队或封装方给过来的)
- 如果是团队内部项目,还会有一份项目自己的物理约束,比如某些区域禁止放单元、某些macro必须靠近特定IO
输出:
- 初始化了物理信息的Innovus数据库(saveDesign保存的内容)
- Floorplan文件(通常是
.fp或.floorplan后缀,记录die、core、macro坐标、halo、blockage) - 可以导出的DEF文件(物理设计交换格式,用于和其他工具、其他团队协作)
Floorplan不管什么?
- 不负责标准单元的具体摆放(那是Place)
- 不负责时钟树的生成(那是CTS)
- 不负责金属走线连接(那是Route)
但有一点必须强调:Floorplan管不管这些,不代表它不影响这些。恰恰相反,它给后续步骤划定了物理边界和通道条件。你可以理解为它是一个"空间分配方案",具体怎么摆家具、怎么布线,是后面的事情,但空间本身就这么大、通道就这么宽、墙就在那里。
2. 5分钟操作主线:从启动Innovus到保存第一版Floorplan
2.1 前期准备:手里要有能加载的数据
如果你手头已经有一个别人搭好的工程,直接启动Innovus载入就行:
innovus -64然后在GUI里通过File -> Restore Design选择之前的.enc.dat文件,或者通过File -> Import Design把LEF、netlist、SDC依次导入。实际项目里更多是有一个init脚本,把所有的库和文件加载写好了:
source init.tcl这种脚本通常长这样:
set init_mmmc_file scripts/view_definition.tcl set init_verilog ../input/design.v set init_top_cell design_top set init_lef_file {../input/tech.lef ../input/macros.lef} set init_pwr_net VDD set init_gnd_net VSS init_design跑完之后,GUI画布上就会出现一个包含标准单元和macro的初始设计。这时候还没有任何物理形状,但Innovus已经把netlist和物理库对应起来了。对新手来说,最怕的就是一上来自己敲命令,我的建议是:先看公司或团队有没有现成的init脚本,有就直接用,没有就照上面的模板搭一个,一步步来。
2.2 GUI里的基础Floorplan操作步骤
数据加载完成后,进入Floorplan编辑器推荐走GUI,可视化程度高,适合新手建立直觉。不同版本菜单名称略有差异,但逻辑基本一致。
第1步:打开Floorplan设置面板
菜单路径一般是Floorplan -> Plan -> Specify Floorplan,也有可能是在Design -> Floorplan下面。打开后会看到一个对话框,里面有Die Size、Core Size、Utilization等选项。
第2步:设置Die Size和Core区域
Die尺寸通常不是自己随手填的,而是根据封装要求、IO数量、团队规划给定的。比如设计规划定了die大小是2000um x 2000um,就在对应框里填。Core区域则有两种指定方式:直接填core的四个边到die的间距(left/bottom/right/top),或者填Core利用率让工具自动算。新手最容易在这步犯迷糊的是单位,默认是um,别填成nm,否则数字会大得离谱。
第3步:确认Utilization(利用率)
对话框里有一个利用率选项,比如0.7,意思是标准单元加macro的总面积占core可用面积的70%。这个值千万不要拍脑袋填,填太高后面会付出惨痛代价。具体选多少合理,我放在第3章详细讲,这里先给新手一个保守区间:普通逻辑为主的设计0.65到0.75起步,memory密集或模块较多时,往0.6以下压更稳。
第4步:摆放宏单元
点OK之后,画布上就出现了die框和core框。接下来要处理的就是macro。GUI里可以直接用鼠标拖拽macro,也可以双击macro输入精确坐标。我个人的习惯是:先在Display -> Colors里把macro、IO、std cell用不同颜色显示出来,方便看清楚关系;然后按信号的拓扑关系,把memory和IP放到它们对应的逻辑区域附近。每个macro旁边,至少留出能走通信号线的通道,别把所有macro堆在一起。
第5步:处理IO constraint
如果设计有IO pin,需要在Floorplan阶段把pin的位置指定到die的四个边上。Innovus里可以用菜单或命令editIoPin来做,比如把所有IO pin均匀分布在上边:
editIoPin -layer M5 -side top -spacing 10 -assign all这行命令的意思是把所有还没有指定位置的IO pin放到top边,用M5金属层,pin间距10um。新手可以先跑这样一个均匀分布的约束,后续再根据封装要求调整。
第6步:加Halo(预留禁区)
宏单元周围要留一圈标准单元不能进入的区域,叫halo。GUI里可以通过Floorplan -> Place -> Halo配置,也可以用命令:
addHaloToPlace -halo [list 10 10 10 10] -all这表示所有macro周围各留10um的禁区。这一步非常关键,没有halo,后面Place阶段标准单元会贴着macro边缘摆放,DRC和绕线都会出问题。
第7步:保存
最后一步,File -> Save Design或者命令行直接输入:
saveDesign design_floorplan.enc.dat write_floorplan design_floorplan.fpsaveDesign保存的是Innovus完整数据库,write_floorplan导出的是可读的Floorplan文件,后续review和版本对比很有用。
这套流程走下来,快的话确实就是5到10分钟的事。但如果只是机械地点完,没有理解第3步和第6步背后的逻辑,那后面早晚要回来返工。
3. 新手最容易忽略的三件事:利用率、IO方向和电源预留
3.1 Core利用率不是越高越好:那个"看起来省了面积"的陷阱
Core utilization的计算公式很简单:utilization = (标准单元总面积 + macro总面积) / core可用面积。但很多人忽略了一个事实:面积利用率是全局平均值,真实设计里标准单元的分布极其不均匀。
举个具体例子。假设core区域是180um x 180um,总面积32400um²。设计里std cell总面积是20000um²,两个macro各占2000um²,总和是24000um²。那全局利用率就是24000 / 32400,约74%,看起来相当健康。但如果两个macro摆得太靠近,比如只隔了15um,而它们之间有大量总线信号要穿过,这15um通道里的局部单元密度会瞬间飙到95%以上,拥塞指数直接爆表。
我的建议是:第一次做Floorplan,宁可把利用率调低一点,比如0.65左右,后边Place阶段觉得空间充足、时序压力不大,再慢慢收紧。利用率设得太高,面积是漂亮了,但Place工具为了把单元塞进去,会把单元拉得很远,时序路径变长,后面修timing的成本往往是省下的那点面积的十倍不止。
另外,Innovus里随时可以用命令查当前利用率:
get_utilization这个命令返回的是实际利用率,比对话框里的预设值更真实。养成习惯,每调一次die或macro都查一下。
3.2 IO pin和宏摆放方向,直接影响走线能不能通
IO pin的位置一般是封装和PCB定死的,Floorplan阶段更多是"执行"而不是"决定"。但执行也有执行的门道。新手容易犯的错误是:所有IO pin均匀分布在四周,不管内部的逻辑布局。结果就是某个macro的信号要横穿整个die才能到达某个IO,路径又长又绕。
正确的思路是:先看设计的数据流方向。比如一个带SRAM、DSP、CPU core的SoC,通常memory应该靠近访问它的CPU或DSP,而对外接口的IO应该靠近对应的控制逻辑。Floorplan阶段把这种"片区感"建立起来,后边的时序和拥塞才会顺。
宏单元的摆放方向(orientation)也是新手容易忽略的点。宏的pin通常集中在某一两个方向,比如SRAM的地址和数据pin都朝下,那你就要确保这个宏下方留有足够的走线通道,否则信号出来就被别的macro堵住。Innovus GUI里可以打开macro的pin显示,摆放前先看一眼pin的分布方向,再决定这个macro的朝向。这个习惯能省掉后面大量的绕线麻烦。
3.3 电源规划在Floorplan阶段就要有意识
很多新手的想法是:"电源网络不是后边Power Plan阶段才做的吗?"没错,addRing和addStripe确实在Floorplan之后,但你在Floorplan阶段做的决定,会直接影响电源规划能不能顺利落地。
举两个最常见的例子。第一,如果两个macro之间的间距只有10um,那这里的电源stripe宽度和金属层选择就会受限,IR drop容易在这片区域超标。第二,如果你把macro摆得把所有电源通道都堵死了,后续globalNetConnect和power ring的路径会非常别扭。所以Floorplan阶段,即使不做电源,也要在脑中留一根弦:每个区域至少要有能让电源网络穿越的通道。
基础阶段至少应该了解一个命令,把macro的电源地pin连接到全局电源地网络:
globalNetConnect VDD -type pgpin -pin VDD -inst * globalNetConnect VSS -type pgpin -pin VSS -inst *这两行命令通常会在init脚本或Floorplan流程里执行,目的是让所有macro的电源pin和顶层VDD/VSS网络连通,不然后续检查会报一堆浮空pin。
4. 跑完Floorplan之后,先别急着往下走:这几项检查必须过
4.1 可视化检查:眼睛永远是第一道防线
命令和脚本能帮你确认数据正确,但Floorplan的质量,很大程度要靠肉眼和经验。打开GUI后,建议先做一轮系统的目检,重点看五个方面:
- die边界和core边界:确认die的大小是否和规划一致,core区域是否居中、留出的IO区宽度是否足够放置所有IO pin和后续的power ring。
- macro是否出界或互相重叠:有时候拖拽macro时没有吸附到grid上,看起来不重叠,实际边界已经压线了。把图层显示打开,放大看每个macro的boundary。
- IO pin是否落在合理位置:检查IO pin有没有被macro遮挡,或者pin和pin之间间距是否均匀。
- 宏单元之间的通道宽度:重点关注信号密集的区域,比如总线、数据路径区,通道至少要能容纳预期数量的走线。
- halo和blockage是否生效:看macro周围有没有那一圈禁置区域,没有的话趁早加上。
图层显示是新手最容易忽略的好帮手。在菜单Display -> Colors里,可以分别设置macro、std cell、IO、halo、blockage的颜色。我习惯把macro设为深色、halo设为高亮色、std cell区域设为浅色,这样任何重叠和冲突一目了然。
4.2 用命令确认数据:不要只靠感觉
肉眼看完,还要用几个命令把数据固化下来,方便记录和对比。
# 查看设计的整体信息 summary # 查看Floorplan相关报告 report_floorplan # 查看当前利用率 get_utilization # 查看IO pin的位置 report_ioreport_floorplan输出里会包含die尺寸、core尺寸、macro数量、macro坐标、utilization等关键信息。建议每次调完Floorplan都存一份report,和上一版做diff,能快速发现哪些参数被改动了。
另外,summary命令有一个容易被忽略的价值:它会在最后列出warning和error的数量。刚跑完Floorplan时warning多不是问题,但你得知道有哪些warning、是不是会影响后续流程。比如常见的Overlap between macro ... and ...这种warning,就必须处理完再往下走。
5. 我踩过的三个坑,以及现在的修正流程
5.1 坑一:把利用率当作唯一指标,忽略了局部拥塞
我第一个正式项目,Floorplan阶段用了0.8的利用率,当时觉得面积已经这么紧张了,能省一点是一点。结果Place阶段就开始出现congestion warning,到了Route阶段,两块大memory之间只有10um左右的通道,信号线根本绕不过去,最后只能把memory间距拉开、重新跑一遍Floorplan。省的那点面积,在返工成本面前不值一提。
现在的修正流程是:Floorplan定稿前,一定会做一个快速拥塞预估。Innovus里有congestion map功能,即使还没开始Place,也能根据pin density和宏之间的空间估算后续拥塞趋势。看到某个区域颜色发红甚至发紫,就算全局利用率再健康,也要先调整宏间距或增大core区域。
5.2 坑二:宏摆放方向忽略了pin的访问
有次设计里有一个很大的SRAM,我随手按默认方向放在了左下角。到Place阶段才发现这个SRAM的地址总线和数据总线全都朝die外面,等于所有信号都得绕一个大圈才能到达内部的逻辑区。结果不但时序差了,走线资源也浪费了不少。
现在摆放任何宏单元之前,我会先做两个动作:看macro LEF里pin的分布位置,然后在GUI里打开pin显示。摆放时优先考虑让宏的总线方向对准真正使用它的逻辑区域,而不是单纯按"美观"或"空间利用"来排。方向对了,后边少受很多罪。
5.3 坑三:忘了加halo和blockage
一开始我以为只要macro不重叠,Place阶段工具自然会处理单元间距。结果Place一跑完,看到macro边缘密密麻麻贴满了小单元,既影响了macro引线的出pin,又造成了一堆DRC违例,修起来非常痛苦。
后来把addHaloToPlace变成了Floorplan流程的固定步骤,并且加完以后用report_halo确认生效。对某些特别关键的信号密集区,我还会额外加placement blockage,强制让这片区域保持空旷。这个习惯养成了,Place阶段的density问题会明显减少。
6. 基础操作之后,下一步该学什么
6.1 读懂.floorplan文件:这是一份"物理设计合同"
跑完上面的步骤,建议打开导出的.fp文件看一眼。里面每一行都对应你刚刚在GUI里做的每一个操作:die边界、core边界、macro坐标、halo尺寸、IO pin位置、blockage区域。能完整读懂这份文件,说明你对Floorplan的理解已经脱离了"点按钮"的阶段。
更重要的是,这个文件是团队协作和版本管理的关键。Floorplan有任何改动,都可以通过对比.fp文件变化快速定位。对于复杂项目,Floorplan往往不是一次到位的,可能是EDA工程师调一版、封装工程师给一版、项目经理确认一版,最终以文件形式固化下来。
6.2 把操作写成脚本,别只靠GUI
新手阶段用GUI建立直觉完全没问题,但如果以后要面对几十个macro、上千个IO pin的设计,再靠鼠标一个个拖就太慢了。现在就可以把每次重复的动作慢慢沉淀成Tcl脚本,比如:
# floorplan.tcl 示例 set die_w 2000 set die_h 2000 floorPlan -d $die_w $die_h 20 20 20 20 # 摆放指定macro到指定坐标 set_phy_cell_snapping_enabled true move_fp_entity -internal -name sram_0 -pos {300.0 400.0} move_fp_entity -internal -name dsp_0 -pos {600.0 400.0} # 添加halo addHaloToPlace -halo [list 10 10 10 10] -all这样每次改动都能追溯,流程也能持续优化。等脚本跑顺畅了,再回头看"5分钟搞定Floorplan"这个说法,你会觉得真是太保守了——脚本跑起来可能连半分钟都用不了。
最后再分享一个我个人的工作习惯:每次Floorplan定稿,我都会导出一份带图层的平面截图,在开会时和前端、封装、后端的人一起过一遍,看看宏的摆放和信号流方向是否合理。这个过程前后花不了十分钟,但能避免很多后端的深夜加班。Floorplan这个东西,前期多花一点心思,后面就会轻松很多。