一、脚本整体作用
这份脚本用于使用 Synopsys Design Compiler 对顶层设计 my_top 进行逻辑综合。
整体流程如下:
1 | 设置设计名和运行目录 |
二、初始化设置
原脚本:
1 | #------------------------------ |
1. 设置顶层设计名
1 | set DESIGN_NAME my_top |
表示当前要综合的顶层模块名是:
1 | my_top |
这个名字需要和 RTL 文件里的顶层模块名保持一致。
例如 RTL 中应该有:
1 | module my_top (...); |
2. 设置运行标签
1 | set TAG ${DESIGN_NAME}_syn_basicrun |
TAG 用来区分不同综合实验的输出目录。
这里最终结果目录类似:
1 | ./results/my_top_syn_basicrun |
以后如果要区分不同实验,可以改成:
1 | set TAG ${DESIGN_NAME}_syn_timing_opt |
3. 设置 CPU 核数
1 | set CORE_NUM 16 |
表示 DC 最多使用 16 个 CPU 核心进行综合。
这样可以提高综合速度。
4. 定义 WORK 设计库
1 | define_design_lib WORK -path ./WORK |
WORK 是 DC 用来保存中间设计数据的工作库。
可以理解为:
1 | WORK = DC 保存 analyze / elaborate 中间结果的地方 |
5. 创建结果目录
1 | set RESULTS_DIR ./results/${TAG} |
作用是:
- 设置结果目录路径;
- 如果目录不存在,就自动创建。
最终各种 .rpt、.v、.ddc 文件都会输出到这个目录。
三、库文件路径设置
原脚本:
1 | #----------------------------- |
1. 设置搜索路径
1 | set_app_var search_path "$search_path ../../library/std/NLDM" |
search_path 用来告诉 DC 去哪里找文件。
这里把下面这个目录加入搜索路径:
1 | ../../library/std/NLDM |
这个目录通常用于存放 .db 标准单元库文件。
2. 设置目标标准单元库
1 | set_app_var target_library "svt_ssg_0p72v_m40c.db" |
target_library 是综合最终映射到的真实标准单元库。
例如 RTL 中写:
1 | assign y = a & b; |
综合后可能变成:
1 | AND2_X1 U1 ( |
这里的 AND2_X1 就来自 target_library。
3. 设置综合库
1 | set_app_var synthetic_library "standard.sldb dw_foundation.sldb" |
synthetic_library 是 DC 用于优化高级运算结构的库。
例如:
1 | assign sum = a + b; |
DC 可能会先把它识别成:
- 加法器
- 乘法器
- 比较器
- 移位器
然后借助 standard.sldb 或 dw_foundation.sldb 做优化。
其中:
| 库 | 作用 |
|---|---|
standard.sldb |
DC 基础综合库 |
dw_foundation.sldb |
DesignWare 基础库,包含加法器、乘法器、比较器等高级组件 |
4. 设置链接路径
1 | set_app_var link_path "* $target_library $synthetic_library"; |
link_path 用于告诉 DC 在链接设计时去哪里找模块和库单元。
其中:
1 | * |
表示当前 DC 内存中已经读入的设计。
所以这句话可以理解为:
1 | link 时,既要查找当前读入的 RTL 设计,也要查找 target_library 和 synthetic_library。 |
四、读取、展开和链接 RTL
原脚本:
1 | #----------------------------- |
1. analyze
1 | analyze -f sverilog -vcs "./sources/${DESIGN_NAME}.sv" |
作用是读取并分析 RTL 文件。
因为:
1 | set DESIGN_NAME my_top |
所以实际读取的是:
1 | ./sources/my_top.sv |
参数说明:
| 参数 | 作用 |
|---|---|
analyze |
读入 HDL 源码 |
-f sverilog |
指定文件格式为 SystemVerilog |
-vcs |
使用更接近 VCS 的语法兼容方式解析 |
"./sources/${DESIGN_NAME}.sv" |
RTL 文件路径 |
2. elaborate
1 | elaborate ${DESIGN_NAME} |
作用是展开顶层设计。
例如 RTL 中:
1 | module my_top (...); |
elaborate my_top 之后,DC 会建立完整层次结构:
1 | my_top |
简单理解:
1 | analyze = 读代码 |
3. current_design
1 | current_design ${DESIGN_NAME} |
指定当前正在操作的设计是:
1 | my_top |
后面的命令,例如:
1 | link |
都会默认作用在当前设计上。
4. link
1 | if {[link]==0} { |
link 的作用是检查并连接设计中的所有引用。
它会检查:
- 子模块是否能找到
- 库单元是否能找到
- DesignWare 模块是否能找到
- 顶层和子模块连接是否能解析
link_path设置是否完整
如果找不到某个模块,可能会报:
1 | Unable to resolve reference |
这通常说明:
- 子模块文件没有读入;
search_path设置不对;link_path缺少库;- 模块名写错。
五、综合前检查和保存中间文件
原脚本:
1 | #---------------------------- |
1. 综合前 check_design
1 | check_design -nosplit > ${RESULTS_DIR}/check_design.precompile.rpt |
作用是检查综合前的设计结构是否健康。
主要检查:
- 是否有未连接端口;
- 是否有未驱动信号;
- 是否有多驱动信号;
- 是否有组合环路;
- 是否有 unresolved reference;
- 是否有不合理的层次结构;
- 是否有不完整的设计单元。
-nosplit 表示报告长行不拆开,方便查看和 grep 搜索。
输出文件:
1 | check_design.precompile.rpt |
表示综合前设计检查报告。
2. 输出 precompile 文件
1 | write_file -hierarchy -format ddc -output ${RESULTS_DIR}/${DESIGN_NAME}.precompile.ddc |
这两条命令用于保存综合前状态。
| 文件 | 作用 |
|---|---|
.precompile.ddc |
DC 内部格式文件 |
.precompile.v |
综合前展开后的 Verilog 文件 |
注意:
1 | precompile.v 还不是最终门级网表。 |
它只是 RTL 被 DC 展开后的中间结果。
六、添加时钟约束
原脚本:
1 | #----------------------------- |
1. 创建主时钟
1 | create_clock -period 1.0 [get_ports clk] |
表示给端口 clk 创建一个周期为 1.0 ns 的时钟。
换算频率:
1 | 1 / 1.0 ns = 1 GHz |
2. 创建其他时钟
1 | create_clock -period 1.2 [get_ports clk1] |
表示 clk1、clk2、clk3、clk4 的周期都是 1.2 ns。
换算频率约为:
1 | 1 / 1.2 ns ≈ 833.33 MHz |
3. 多时钟设计注意点
脚本中只是创建了多个时钟,但还没有说明时钟之间的关系。
如果这些时钟是完全异步的,应该加:
1 | set_clock_groups -asynchronous \ |
否则 DC 可能会默认它们之间存在时序关系,分析一些不该分析的跨时钟路径。
如果 clk1 到 clk4 是由 clk 分频或倍频得到的,则不能简单设为异步,应该使用:
1 | create_generated_clock |
七、执行综合
原脚本:
1 | #----------------------------- |
compile_ultra 的作用
1 | compile_ultra |
compile_ultra 是 DC 中常用的高强度综合优化命令。
它会根据当前约束进行综合,主要包括:
- 将 RTL 映射成标准单元;
- 优化组合逻辑;
- 优化寄存器附近路径;
- 尽量满足时序;
- 尽量减少面积;
- 调用 DesignWare 优化高级运算;
- 可能进行层次打散和跨层次优化。
简单理解:
1 | compile_ultra = 逻辑综合 + 优化 + 映射标准单元 |
八、综合后输出文件
原脚本:
1 | #----------------------------- |
1. 输出 postcompile 文件
1 | write_file -format verilog -hierarchy -output ${RESULTS_DIR}/${DESIGN_NAME}.postcompile.v |
这时设计已经经过 compile_ultra 综合。
输出文件:
| 文件 | 说明 |
|---|---|
.postcompile.v |
综合后的 Verilog 文件 |
.postcompile.ddc |
综合后的 DC 内部格式文件 |
2. 修正规范命名
1 | change_names -rules verilog -hierarchy |
综合后的网表中可能出现反斜杠、特殊字符等名称。
例如:
1 | \abc[0] |
这类名字虽然 DC 能识别,但有些后端工具或仿真工具处理起来不方便。
change_names 的作用是:
1 | 把设计中的名字转换成更标准的 Verilog 命名格式。 |
3. 输出 mapped 文件
1 | write_file -format verilog -hierarchy -output ${RESULTS_DIR}/${DESIGN_NAME}.mapped.v |
输出最终门级网表和 DDC 文件。
其中:
1 | mapped.v |
通常就是交给后端 APR 工具使用的门级网表。
九、综合后设计检查
原脚本:
1 | check_design -nosplit > ${RESULTS_DIR}/check_design.mapped.rpt |
这次 check_design 是在综合后执行的。
它主要检查综合后的 mapped netlist 是否健康,例如:
- 标准单元实例是否完整;
- 有没有未连接网络;
- 有没有多驱动网络;
- 端口连接是否合理;
change_names后名字是否合法;- 最终网表是否适合后端读入。
综合前后两次 check_design 区别
| 阶段 | 文件 | 检查对象 | 重点 |
|---|---|---|---|
| 综合前 | check_design.precompile.rpt |
RTL 展开后的设计 | RTL 结构有没有问题 |
| 综合后 | check_design.mapped.rpt |
mapped 门级网表 | 最终网表有没有问题 |
一句话记忆:
1 | 第一次检查 RTL,第二次检查网表。 |
十、设计相关报告
原脚本:
1 | #----------------------------- |
1. report_design
1 | report_design -nosplit > ${RESULTS_DIR}/design.rpt |
作用是报告当前设计的基本信息。
通常包括:
- 当前设计名;
- 设计属性;
- 是否被综合;
- 使用的库;
- 设计状态信息。
输出文件:
1 | design.rpt |
2. report_hierarchy
1 | report_hierarchy -full -noleaf -nosplit > ${RESULTS_DIR}/hier.rpt |
作用是报告设计层次结构。
参数说明:
| 参数 | 作用 |
|---|---|
-full |
输出完整层次信息 |
-noleaf |
不显示 leaf cell,只显示模块层次 |
-nosplit |
长行不拆分 |
输出文件:
1 | hier.rpt |
通过这个报告可以看到:
1 | my_top |
如果综合后层次被 ungroup 打散,也可以在这个报告中观察到。
3. report_resources
1 | report_resources -hierarchy > ${RESULTS_DIR}/resources.rpt |
作用是报告综合中使用的资源。
常见资源包括:
- 加法器;
- 乘法器;
- 比较器;
- MUX;
- DesignWare 组件;
- 寄存器;
- 存储结构。
输出文件:
1 | resources.rpt |
这个报告可以帮助你判断:
1 | RTL 中的加法、乘法、比较等结构有没有被 DC 正确识别。 |
十一、面积报告
原脚本:
1 | #area |
report_area
1 | report_area -hier -nosplit > ${RESULTS_DIR}/area.rpt |
作用是输出面积报告。
参数说明:
| 参数 | 作用 |
|---|---|
-hier |
按层次显示面积 |
-nosplit |
长行不拆分 |
输出文件:
1 | area.rpt |
面积报告通常会包含:
- combinational area;
- noncombinational area;
- buffer / inverter area;
- total cell area;
- 各模块层次面积占比。
通过 area.rpt 可以判断哪个模块面积最大,后续可以针对性优化。
十二、功耗报告
原脚本:
1 | #power |
1. 清除已有 switching activity
1 | reset_switching_activity |
作用是清除之前设置过的翻转活动信息。
例如清除通过以下方式导入或设置的活动信息:
1 | set_switching_activity |
2. 输出默认功耗报告
1 | report_power -hier -nosplit > ${RESULTS_DIR}/power.default.rpt |
作用是在默认 switching activity 条件下输出功耗报告。
输出文件:
1 | power.default.rpt |
这份报告可以理解为:
1 | 没有额外指定输入翻转率时,工具默认估算出来的功耗。 |
3. 设置非时钟输入翻转率
1 | set_switching_activity -toggle_rate 0.25 [remove_from_collection [all_inputs ] [get_ports clk*]] |
这句表示:
给所有非时钟输入端口设置 toggle rate = 0.25。
拆开理解:
1 | [all_inputs] |
表示所有输入端口。
1 | [get_ports clk*] |
表示所有名字以 clk 开头的端口。
1 | [remove_from_collection [all_inputs] [get_ports clk*]] |
表示:
1 | 所有输入端口 - 时钟端口 |
也就是给数据输入、控制输入设置翻转率,而不设置时钟端口。
4. 输出 0.25 输入翻转率下的功耗报告
1 | report_power -hier -nosplit > ${RESULTS_DIR}/power.0p25intoggle.rpt |
输出文件:
1 | power.0p25intoggle.rpt |
这份报告表示:
1 | 假设非时钟输入 toggle_rate = 0.25 时的功耗估计。 |
5. 两份功耗报告的区别
| 报告 | 条件 | 用途 |
|---|---|---|
power.default.rpt |
默认活动率 | 看工具默认估算功耗 |
power.0p25intoggle.rpt |
非时钟输入 toggle rate = 0.25 | 看输入翻转对功耗的影响 |
一般来说,设置输入翻转后,dynamic power 可能会变大。
十三、Design Compiler 对象查询说明
原脚本注释:
1 | #design compiler objects |
1. DC 中常见对象
DC 中很多命令的操作对象都是 collection。
常见对象包括:
| 命令 | 获取对象 |
|---|---|
get_ports |
获取端口 |
get_pins |
获取 pin |
get_cells |
获取 cell 或 instance |
get_nets |
获取 net |
get_clocks |
获取 clock |
get_designs |
获取 design |
2. 示例
1 | get_cells my* |
获取名字以 my 开头的 cell 或 instance。
1 | get_ports rst* |
获取名字以 rst 开头的端口。
1 | get_pins */CDN |
获取所有层次下名为 CDN 的 pin。
3. collection 是什么
collection 可以理解为 DC 中的一组对象集合。
例如:
1 | [get_ports clk*] |
返回的不是普通字符串,而是一个端口对象集合。
所以很多 DC 命令中会看到:
1 | remove_from_collection |
十四、时钟报告
原脚本:
1 | #clock |
1. report_clock
1 | report_clock -attributes -nosplit > ${RESULTS_DIR}/clock.rpt |
作用是报告当前设计中的时钟信息。
通常包括:
- 时钟名称;
- 时钟周期;
- 时钟端口;
- 波形;
- 时钟属性;
- 是否为 generated clock。
输出文件:
1 | clock.rpt |
这个报告可以检查:
1 | create_clock 有没有生效。 |
2. report_clock_gating
1 | report_clock_gating -nosplit > ${RESULTS_DIR}/clock_gating.rpt |
作用是报告 clock gating 相关信息。
如果设计或综合中使用了 ICG / clock gating cell,可以通过它查看:
- clock gating 结构;
- clock gating cell;
- enable 信号;
- gating 检查信息。
输出文件:
1 | clock_gating.rpt |
如果没有启用 clock gating,这个报告可能比较少或为空。
十五、时序和约束报告
原脚本:
1 | #timing |
1. report_constraints
1 | report_constraints -all_violators -nosplit > ${RESULTS_DIR}/all_violators.rpt |
作用是报告所有违反约束的路径或对象。
重点看:
- setup violation;
- hold violation;
- max transition violation;
- max capacitance violation;
- max fanout violation;
- design rule violation。
输出文件:
1 | all_violators.rpt |
这个报告可以快速判断:
1 | 综合后设计还有哪些约束没有满足。 |
2. report_timing
1 | report_timing -max_paths 100 -input_pins -capacitance -net -transition_time -nosplit > ${RESULTS_DIR}/timing.rpt |
作用是输出详细时序路径报告。
参数说明:
| 参数 | 作用 |
|---|---|
-max_paths 100 |
最多输出 100 条关键路径 |
-input_pins |
显示 cell 输入 pin 信息 |
-capacitance |
显示电容信息 |
-net |
显示 net 延迟信息 |
-transition_time |
显示转换时间 |
-nosplit |
长行不拆分 |
输出文件:
1 | timing.rpt |
时序报告中重点看:
- startpoint;
- endpoint;
- path group;
- data arrival time;
- data required time;
- slack;
- 哪些 cell / net 延迟最大。
3. slack 怎么看
时序报告中通常会看到:
1 | slack (MET) 0.05 |
或者:
1 | slack (VIOLATED) -0.03 |
含义:
| slack | 含义 |
|---|---|
| 正数 | 时序满足,还有余量 |
| 0 | 刚好满足,几乎没有余量 |
| 负数 | 时序违例,需要优化 |
十六、QoR 报告
原脚本:
1 | #qor |
report_qor
1 | report_qor > ${RESULTS_DIR}/qor.rpt |
QoR 是 Quality of Results 的缩写。
report_qor 用来汇总设计综合质量。
通常包括:
- WNS:Worst Negative Slack
- TNS:Total Negative Slack
- Number of violating paths
- 面积信息
- 设计规则违例
- 时序状态
- 层次和路径组概况
输出文件:
1 | qor.rpt |
这个报告适合用来快速判断综合结果好不好。
十七、最终会生成哪些文件
根据脚本,${RESULTS_DIR} 目录下会生成以下文件。
1. 中间设计文件
| 文件 | 作用 |
|---|---|
${DESIGN_NAME}.precompile.ddc |
综合前 DC 内部格式 |
${DESIGN_NAME}.precompile.v |
综合前展开后的 Verilog |
${DESIGN_NAME}.postcompile.v |
综合后 Verilog |
${DESIGN_NAME}.postcompile.ddc |
综合后 DDC |
${DESIGN_NAME}.mapped.v |
最终门级网表 |
${DESIGN_NAME}.mapped.ddc |
最终 DDC 文件 |
2. 检查报告
| 文件 | 作用 |
|---|---|
check_design.precompile.rpt |
综合前设计检查 |
check_design.mapped.rpt |
综合后网表检查 |
3. 分析报告
| 文件 | 作用 |
|---|---|
design.rpt |
设计基本信息 |
hier.rpt |
设计层次结构 |
resources.rpt |
资源推断情况 |
area.rpt |
面积报告 |
power.default.rpt |
默认功耗报告 |
power.0p25intoggle.rpt |
设置输入翻转率后的功耗报告 |
clock.rpt |
时钟报告 |
clock_gating.rpt |
时钟门控报告 |
all_violators.rpt |
所有约束违例 |
timing.rpt |
详细时序路径 |
qor.rpt |
综合质量汇总 |
十八、建议检查顺序
综合跑完后,建议按下面顺序检查结果。
1. 先看 log
1 | grep -i "Error" dc.log |
重点确认没有严重错误。
2. 看综合前检查报告
1 | less check_design.precompile.rpt |
重点看:
- unresolved reference;
- multiple drivers;
- undriven nets;
- unconnected ports;
- combinational loop。
3. 看综合后检查报告
1 | less check_design.mapped.rpt |
确认最终网表结构健康。
4. 看 QoR
1 | less qor.rpt |
快速查看整体质量,例如 WNS、TNS、面积、违例数量。
5. 看时序
1 | less timing.rpt |
重点看:
- slack 是否为负;
- 最差路径在哪里;
- 哪个模块是关键路径来源;
- 是 cell delay 大还是 net delay 大。
6. 看面积和功耗
1 | less area.rpt |
重点看:
- 哪个模块面积最大;
- 动态功耗和静态功耗占比;
- 输入翻转率变化后功耗是否明显上升。
十九、这份脚本可以改进的地方
当前脚本已经能完成基础综合,但还可以补充一些约束和检查。
1. 补充时钟不确定性
1 | set_clock_uncertainty 0.05 [all_clocks] |
用于考虑时钟抖动、偏差等不确定因素。
2. 补充输入输出延迟
1 | set_input_delay 0.2 -clock clk [remove_from_collection [all_inputs] [get_ports clk*]] |
这样可以让 DC 考虑外部电路到芯片输入、芯片输出到外部电路的时序预算。
3. 说明多时钟关系
如果多个时钟异步:
1 | set_clock_groups -asynchronous \ |
如果是分频时钟,需要使用:
1 | create_generated_clock |
4. 补充设计规则约束
1 | set_max_transition 0.1 [current_design] |
这些可以帮助控制 transition、fanout 和 capacitance。
5. 补充 SDC 输出
1 | write_sdc ${RESULTS_DIR}/${DESIGN_NAME}.sdc |
输出综合约束文件,方便后端 APR 使用。
二十、一句话总结
这份脚本的作用是:
使用 Design Compiler 读取
my_top.sv,设置标准单元库和时钟约束,执行compile_ultra逻辑综合,输出最终门级网表mapped.v,并生成设计、层次、面积、功耗、时钟、时序和 QoR 等报告。
最重要的几个输出文件是:
1 | mapped.v |
其中:
1 | mapped.v :后端 APR 主要输入 |
二十一、查看一个设计的log
注意power报告仅仅可以作为相对参考:1)计算功耗通常使用ff的环境(而不是ss)2)计算功耗用的翻转因子最好来自真实场景,例如仿真环境的波形(后续介绍);3)在综合过程中主要关注低阈值cell的使用比例(后续介绍)
area.rpt 面积报告简要总结
该报告用于查看综合后设计的面积和资源使用情况。
设计规模
综合后设计包含:
- 端口数:395
- 网络数:10763
- Cell 总数:10465
- 组合逻辑 cell:9377
- 时序逻辑 cell:1088
- Buffer / Inverter:1818
- Macro / Black Box:0
其中 Macro/Black Box = 0 说明设计中没有未展开的黑盒模块,网表完整性较好。
面积组成
主要面积如下:
| 类型 | 面积 |
|---|---|
| Combinational area | 2690.92 |
| Buf/Inv area | 244.92 |
| Noncombinational area | 872.20 |
| Macro/Black Box area | 0 |
| Total cell area | 3563.13 |
其中组合逻辑面积占比较大,说明设计主要面积来自组合逻辑。
Noncombinational area 主要对应寄存器、触发器等时序单元面积。
线网面积
报告中显示:
1 | Net Interconnect area: undefined |
说明当前综合阶段还没有真实物理布线信息,因此线网面积无法准确估算。真实连线面积需要后端布局布线后才能得到。
DesignWare / Synthetic 资源
报告中出现:
DW01_add:DesignWare 加法器,面积约 31.53DW_mult_uns:DesignWare 无符号乘法器,面积约 905.98
其中 DW_mult_uns 占 cell area 的 13.9%,说明乘法器是面积占比较大的模块。
总结
本设计综合后总 cell 面积约为 3563.13,其中组合逻辑面积占主要部分。设计中没有 black box,说明综合展开较完整。DesignWare 资源中乘法器面积较大,是后续面积优化时需要重点关注的部分。
power report 功耗报告简要总结
这两份报告分别是:
power.default.rpt:默认 switching activity 下的功耗估算power.0p25intoggle.rpt:给非时钟输入设置toggle_rate = 0.25后的功耗估算
两份报告的工作电压都是:
1 | Global Operating Voltage = 0.72V |
- 单位说明
报告中需要特别注意单位:
1 | Dynamic Power Units = 1mW |
因此:
Switch Power单位是 mWInt Power单位是 mWTotal Power单位是 mWLeak Power单位是 nW
所以 Leak Power = 37.573 表示的是:
1 | 37.573 nW |
不是 37.573 mW,漏电功耗实际非常小。
- 默认功耗报告
power.default.rpt 中:
| 类型 | 数值 |
|---|---|
| Switch Power | 0.314 mW |
| Int Power | 2.918 mW |
| Leak Power | 37.573 nW |
| Total Power | 3.232 mW |
其中 Int Power 占主要部分,说明标准单元内部动态功耗较大。
- 设置输入翻转率后的功耗报告
power.0p25intoggle.rpt 中:
| 类型 | 数值 |
|---|---|
| Switch Power | 0.393 mW |
| Int Power | 3.140 mW |
| Leak Power | 37.362 nW |
| Total Power | 3.533 mW |
这份报告是在给非时钟输入设置:
1 | set_switching_activity -toggle_rate 0.25 [remove_from_collection [all_inputs] [get_ports clk*]] |
之后得到的结果。
- 两份报告对比
| 报告 | Switch Power | Int Power | Leak Power | Total Power |
|---|---|---|---|---|
| default | 0.314 mW | 2.918 mW | 37.573 nW | 3.232 mW |
| input toggle = 0.25 | 0.393 mW | 3.140 mW | 37.362 nW | 3.533 mW |
可以看到,设置输入翻转率后:
1 | Total Power: 3.232 mW → 3.533 mW |
总功耗增加约:
1 | 3.533 - 3.232 = 0.301 mW |
增长比例约为:
1 | 0.301 / 3.232 ≈ 9.3% |
- 结论
设置输入翻转率后,Switch Power 和 Int Power 都有所增加,说明输入信号活动增强后,内部逻辑翻转也增加,从而导致动态功耗上升。
但 Leak Power 基本不变,因为漏电功耗主要和工艺角、电压、温度、cell 类型有关,和输入翻转率关系不大。
这两份 power report 可以用于比较不同 switching activity 下的功耗变化,但由于综合阶段没有真实后端寄生参数,也不一定有真实 VCD / SAIF 波形,因此只能作为相对参考。
DC 功耗报告字段总结
- 功耗类型区别
| 名称 | 中文理解 | 来源 | 是否和翻转有关 |
|---|---|---|---|
Switch Power |
网络翻转功耗 | net 线网电容充放电 | 有关 |
Int Power |
单元内部功耗 | 标准单元内部节点翻转、短路电流、内部电容 | 有关 |
Leak Power |
漏电功耗 / 静态功耗 | 晶体管关断时的漏电流 | 基本无关 |
Total Power |
总功耗 | 三者相加 | 综合结果 |
- 各项含义
Switch Power
Switch Power 是线网翻转功耗,主要来自 net 上电容的充放电。
例如信号从 0 → 1 或 1 → 0 时,线网和负载电容会充放电,从而产生功耗。
主要影响因素:
- 信号翻转率
- 线电容
- 负载电容
- 电压
- 频率
Int Power
Int Power 是标准单元内部功耗。
当 cell 输入变化时,cell 内部节点会翻转,同时可能产生短路电流,因此会消耗功耗。
例如:
- DFF 内部锁存结构翻转
- MUX 内部节点翻转
- AND / OR / XOR 等逻辑门内部翻转
该项属于动态功耗的一部分。
Leak Power
Leak Power 是漏电功耗,也叫静态功耗。
即使电路不翻转,只要上电,也会存在漏电。
主要来源包括:
- 亚阈值漏电
- 栅漏电
- 结漏电
主要影响因素:
- 工艺角
- 电压
- 温度
- 阈值电压类型
- cell 数量和类型
注意:Leak Power 的单位通常是 nW,不是 mW。
Total Power
Total Power 是总功耗,近似为:
1 | Total Power = Switch Power + Int Power + Leak Power |
Results & Analyze 结果分析笔记
- 本页主要内容
综合运行结束后,需要重点查看以下报告:
clock.rpt:查看时钟定义是否正确clock_gating.rpt:查看是否生成 clock gating 结构all_violators.rpt:查看所有时序/约束违例timing.rpt:查看详细关键路径qor.rpt:查看综合质量汇总
- clock.rpt:时钟信息
clock.rpt 中显示设计里有多个时钟:
| 时钟 | 周期 | 频率 |
|---|---|---|
clk |
1.00 ns | 1 GHz |
clk1 |
0.80 ns | 1.25 GHz |
clk2 |
0.80 ns | 1.25 GHz |
clk3 |
0.80 ns | 1.25 GHz |
clk4 |
0.80 ns | 1.25 GHz |
说明综合脚本中的 create_clock 约束已经生效。
- clock_gating.rpt:时钟门控情况
clock_gating.rpt 中显示:
- Clock gating elements:0
- Gated registers:0
- Ungated registers:1088
- Total registers:1088
说明当前综合结果中没有识别或生成 clock gating 结构,所有 1088 个寄存器都是 ungated registers。
这意味着该设计暂时没有通过 clock gating 来降低动态功耗。
- all_violators.rpt:时序违例情况
all_violators.rpt 中显示存在 setup 违例,主要集中在:
clk1path groupclk3path group
其中 clk1 组中,部分 endpoint 例如:
1 | u_my_calc_result1_ff_reg_45_/D |
required path delay 约为:
1 | 0.77 ns |
actual path delay 约为:
1 | 0.85 ns |
slack 约为:
1 | -0.09 ns |
说明 clk1 时钟域中,数据路径延迟超过了要求时间,存在 setup violation。
clk3 组中,部分 endpoint 例如:
1 | u_my_calc_result3_ff_reg_48_/D |
required path delay 约为:
1 | 0.77 ns |
actual path delay 约为:
1 | 0.87 ns |
slack 约为:
1 | -0.11 ns |
说明 clk3 时钟域违例更严重一些。
- timing.rpt:局部时钟组结果
右下角 timing summary 中显示 clk path group:
- Levels of Logic:5
- Critical Path Length:0.25 ns
- Critical Path Slack:0.74 ns
- Critical Path Clock Period:1.00 ns
- Total Negative Slack:0
- No. of Violating Paths:0
说明 clk 时钟组本身时序是满足的,而且 slack 还有较大余量。
也就是说,当前主要问题不在 clk 域,而是在 clk1 和 clk3 相关路径。
- qor.rpt:QoR 汇总
qor.rpt 用来快速查看综合结果质量。
图中显示 setup 方向有违例:
- WNS 约为
-0.11 ns - TNS 约为
-7.01 ns - Number of Violating Paths:86
hold 方向没有违例:
- Hold WNS:0.00
- Hold TNS:0.00
- Hold Violating Paths:0
说明当前设计主要是 setup timing 没过,hold timing 没问题。
- DRC 情况
右下角 Design Rules 显示:
- Total Number of Nets:10763
- Nets With Violations:0
- Max Trans Violations:0
- Max Cap Violations:0
说明当前没有明显的设计规则违例,例如 transition 和 capacitance 约束没有问题。
- 重点结论
本次综合结果的主要问题是 setup timing violation。
违例主要集中在:
clk1时钟域的result1_ff路径clk3时钟域的result3_ff路径
这些路径很可能和 my_calc 模块中的乘法、乘加/乘减逻辑有关。
其中:
1 | clk1 group slack ≈ -0.09 ns |
说明 clk3 组违例略严重。
- 后续优化方向
可以考虑以下优化方法:
- 放宽时钟周期,例如把 0.80 ns 放宽到更大;
- 对乘法器或乘加路径增加 pipeline;
- 优化
my_calc中result1、result3相关逻辑; - 检查是否需要使用更快的标准单元;
- 检查是否约束过紧,例如 uncertainty、input/output delay 是否合理;
- 如果是多时钟路径,需要确认 clock group 或 generated clock 约束是否正确;
- 如果某些路径不需要单周期完成,可以考虑 multicycle path。
- 一句话总结
综合结果中,clk 时钟域满足时序且 DRC 无明显违例,但 clk1 和 clk3 时钟域存在 setup violation,最差 slack 约为 -0.11 ns,问题主要集中在 my_calc 的 result1_ff 和 result3_ff 相关路径,需要进一步做时序优化。