title: A7项目(2)—设计导入
date: 2026-02-15 17:20:26
updated: 2026-02-15 17:20:26
tags:
- A7项目
categories:
- A7项目
toc: true # 是否显示目录

1、设计导入

很多公司都有专门做逻辑综合的工程师。综合工程师需要把综合后的Netlist和Constraint(sdc时序约束文件)发给数字后端工程师。随后我们作为数字后端工程师就可以开始干活了。

时钟约束sdc主要内容如下:
1)timing相关基本单位设置
2)max_fanout,max_transition设定
3)设置模块端口port的驱动(时钟和data 分开设,因为时钟会更快)
4)设置output的load
5)创建时钟,定义好时钟周期(频率=1.0/T,其中T为时钟周期)
6)时序例外,比如set_multicycle_path,set_false_path等
7)模块接口的input delay和output 约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
set sdc_version 1.7

# 设置基本单位
set_units -time ns -resistance kOhm -capacitance pF -voltage V -current mA

# fanout和transition约束(这个我们在PR flow中也会设置)
set_max_fanout 32 [current_design]
set_max_transition 0.4 [current_design]

set_driving_cell -lib_cell CKBD4BWP40P140 -pin Z -from_pin I -input_transition_rise 0.15 -input_transition_fall 0.15 [get_ports CLKIN]

# 模块port的驱动指定
set_driving_cell -lib_cell BUFFD4BWP40P140 -pin Z -from_pin I -input_transition_rise 0.3 -input_transition_fall 0.3 [remove_from_collection [all_inputs] [get_ports CLKIN]]
set_load -pin_load 0.02 [all_outputs]

# 最核心的定义,创建时钟,并指定时钟周期
set clock_period 1.0
create_clock [get_ports CLKIN] -period $clock_period

# 创建虚拟时钟,为了后面给io port端口约束inputoutput delay
create_clock -name VCLK -period $clock_period

# 多周期路径设定
set_multicycle_path 2 -setup -from [get_ports DFTSE]
set_multicycle_path 1 -hold -end -from [get_ports DFTSE]
set_multicycle_path 2 -setup -from [get_ports DFTRSTDISABLE]
set_multicycle_path 1 -hold -end -from [get_ports DFTRSTDISABLE]
set_multicycle_path 2 -setup -from [get_ports DFTRAMHOLD]
set_multicycle_path 1 -hold -end -from [get_ports DFTRAMHOLD]

# ----------------------------------------------------------------------
# Define cycle percentage expressions
# ----------------------------------------------------------------------

# Temporary variables used during constraint generation e.g. $cycle20, $cycle60
# reduce the i incr value to 1 to create a complete $cycle00 .. $cycle99 range
for {set i 0} {$i < 100} {incr i 5} {
set cycle[format "%#02d" $i ] [expr 0.01 * ${i} * ${clock_period}]
}

# ----------------------------------------------------------------------
# DFT ports
# ----------------------------------------------------------------------

# input delay和output delay设定
set_input_delay -clock VCLK $cycle20 [get_ports DFTSE]
set_input_delay -clock VCLK $cycle60 [get_ports DFTRSTDISABLE]
set_input_delay -clock VCLK $cycle20 [get_ports DFTRAMHOLD]

注释代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
set sdc_version 1.7

# 设置基本单位
## 军师深度批注:这是定义整个芯片世界的“物理法则”。
## 指定了时间=纳秒(ns),电容=皮法(pF)。这意味着下面代码里出现的所有数字 1.00.4,都是以纳秒为单位。
set_units -time ns -resistance kOhm -capacitance pF -voltage V -current mA

# fanout和transition约束(这个我们在PR flow中也会设置)
## 军师深度批注:【最大扇出 (Max Fanout)】—— 规定一个逻辑门最多只能连接 32 个下级门。
## 就像一个老师最多只能同时对 32 个学生喊话,带的人太多,信号就会严重衰减。
set_max_fanout 32 [current_design]

## 军师深度批注:【最大转换时间 (Max Transition)】—— 规定信号从 01 的翻转时间不能超过 0.4ns
## 这就好比汽车换挡,离合器“半联动”的状态不能持续太久,否则齿轮(晶体管)会剧烈发热甚至烧毁。
set_max_transition 0.4 [current_design]

## 军师深度批注:【驱动单元 (Driving Cell)】—— 告诉后端工具,外界是用多大的“发动机”把信号推进芯片的。
## 这里给时钟引脚 CLKIN 强行绑定了台积电库里的专用时钟缓冲器 (CKBD4BWP40P140),上升/下降极其凌厉 (0.15ns)。
set_driving_cell -lib_cell CKBD4BWP40P140 -pin Z -from_pin I -input_transition_rise 0.15 -input_transition_fall 0.15 [get_ports CLKIN]

# 模块port的驱动指定
## 军师深度批注:把除了 CLKIN 之外的所有普通输入引脚,挂上普通的缓冲器 (BUFFD4BWP40P140),速度稍慢一点 (0.3ns)。
set_driving_cell -lib_cell BUFFD4BWP40P140 -pin Z -from_pin I -input_transition_rise 0.3 -input_transition_fall 0.3 [remove_from_collection [all_inputs] [get_ports CLKIN]]

## 军师深度批注:【负载电容 (Load)】—— 告诉工具芯片输出脚外面接的“大门”有多重 (0.02pF)。
## 如果不设这个,工具会以为外面是零阻力的真空环境,算出来的速度全是虚假的,流片回来一接外设直接死机。
set_load -pin_load 0.02 [all_outputs]

# 最核心的定义,创建时钟,并指定时钟周期
## 军师深度批注:🔥 高能预警!1.0ns 的周期意味着这颗芯片的频率是 1GHz!
## 在数字后端里,这是一个极具挑战性的性能靶心,你后面的时序收敛将会是一场恶战。
set clock_period 1.0
create_clock [get_ports CLKIN] -period $clock_period

# 创建虚拟时钟,为了后面给io port端口约束inputoutput delay
## 军师深度批注:【虚拟时钟 (Virtual Clock)】—— 凭空捏造一个“影子时钟”。
## 因为我们要约束外部信号什么时候到达,必须得有一个绝对的“世界标准时间”作为参考系。
create_clock -name VCLK -period $clock_period

# 多周期路径设定
## 军师深度批注:【多周期路径 (Multicycle Path)】—— 给测试信号 (DFT) 发特权通行证。
## 它们不需要跑 1GHz 那么快。-setup 2 告诉工具:建立时间放宽到第 2 个周期再查(给 2.0ns 的宽裕时间)。
set_multicycle_path 2 -setup -from [get_ports DFTSE]

## 军师深度批注:【极其老道的保命写法规】 -hold 1 强行把保持时间检查点拉回第 1 个周期!
## 如果不加这句,Hold 检查也会跟着推迟,导致后端工具疯狂瞎插 Buffer(缓冲器),直接把你的芯片面积撑爆!
set_multicycle_path 1 -hold -end -from [get_ports DFTSE]
set_multicycle_path 2 -setup -from [get_ports DFTRSTDISABLE]
set_multicycle_path 1 -hold -end -from [get_ports DFTRSTDISABLE]
set_multicycle_path 2 -setup -from [get_ports DFTRAMHOLD]
set_multicycle_path 1 -hold -end -from [get_ports DFTRAMHOLD]

# ----------------------------------------------------------------------
# Define cycle percentage expressions
# ----------------------------------------------------------------------

# Temporary variables used during constraint generation e.g. $cycle20, $cycle60
# reduce the i incr value to 1 to create a complete $cycle00 .. $cycle99 range
## 军师深度批注:【TCL 动态脚本艺术】—— 这是一个自动生成百分比变量的 for 循环。
## 它会根据上面的 1.0ns 周期,自动算出 $cycle20 就是 0.2ns
## 为什么这么写?如果以后老板说降频到 500MHz,你只需要把上面的 clock_period 改成 2.0。下面的延迟参数会自动跟着按比例放大!这就是顶级架构师的自动化思维。
for {set i 0} {$i < 100} {incr i 5} {
set cycle[format "%#02d" $i ] [expr 0.01 * ${i} * ${clock_period}]
}

# ----------------------------------------------------------------------
# DFT ports
# ----------------------------------------------------------------------

# input delay和output delay设定
## 军师深度批注:【输入延迟 (Input Delay)】—— 明确告诉工具,DFTSE 这个信号,会在影子时钟 VCLK 敲响之后的 0.2ns ($cycle20) 准时到达芯片大门口。
set_input_delay -clock VCLK $cycle20 [get_ports DFTSE]
set_input_delay -clock VCLK $cycle60 [get_ports DFTRSTDISABLE]
set_input_delay -clock VCLK $cycle20 [get_ports DFTRAMHOLD]

综合后的netlist如下。top module名字叫cortexa7core,module中的各个信号即为我们这个模块的所有io端口。

Netlist本质是一个电路图,只不过以netlist的形式呈现出来,作为后端布局布线的输入设计文件。所以netlist代表的是逻辑连接关系。下图的Netlist和Schematic(电路原理图)是等价的。

而我们后端要做的是基于这个逻辑连接实现实际的物理金属连接。所以数字后端实现也叫物理实现或物理设计(Physical Implementation /Physical Design)。

这里可以把这个netlist理解成盖房子前要有的设计图纸,而后端实现要做的工作就是基于设计的图纸把房子给盖出来。

有了netlist和constraint,我们就可以做设计导入了。

设计导入的脚本非常简单,就下面几句话。核心命令就是init_design。

这个脚本中读取了一个innovus支持的globals文件,它的内容包含以下几大部分。

而这个globals文件中又包含了一个mmmc的文件,这个文件内容的准备包含6大步骤,具体如下图所示。

以上信息配置完成后,我们就可以source我们scripts目录下的01_innovus_import_design.tcl 。

当然,我们新手可以打开01_innovus_import_design.tcl ,一步步执行里面的脚本命令。

设计导入完成后, 效果图如下图所示。

设计导入后我们最好检查下导入的设计是否代码上的设计问题,比如是否有multi-driver问题,io port悬空等问题。

使用的命令如下:

1
checkDesign -netlist

执行后的结果如下图所示:

这里举一三个常见的警告。

1)没有tie cell的警告
比如下面这个报告有instance的某些pin要连接到tie cell上(接0或接1信号),却没有找到tie cell。而且设计中有多个这样的信号,所以对应的是TieLo的net,但是工具没有看到有对应的TieLo cell。

之所以有这个警告,是因为在设计导入我们还没让工具加tie cell,这步是在后续的place阶段完成的。所以这个警告是正常的。

2)High Fanout Net和cell有Dont use 属性的警告
在设计导入阶段,不论是clock或者是data,都是允许存在高扇出的net。为什么呢?

因为此时clock一定是高扇出net,因为RTL代码中一定是一个clock port直接接到所有的sink上。一个设计中的sink是寄存器的CLK pin和memory的CLK pin,所以一般都有好几万的sink。时钟信号的high fanout处理就是后续时钟树综合要解决的问题。

data上如果有高扇出的net,也是没有问题的。因为在PR flow中除了CTS阶段外,其他任何阶段涉及到时序的优化都会帮我们解决data path上的高扇出net问题。

对于下图中报告的macro有dont use属性是正常的。这是因为macro相当于是第三方IP,供我们调用的,我们是无法更改它内部的东西,工具更无法针对它做任何的优化。如果能优化那才会出事,就无法保证第三方IP的功能。

3) output port floating(悬空问题)
由于实际项目中经常也会出现一些设计实际用不到的一些port。这是因为前端在做代码集成时是根据当前的spec需求,拿着原来的RTL进行集成的,所以难免会出现当前设计中有些port是用不到的情况。这就像我们买来一部手机,里面有些功能对我们来说可能一辈子都用不到。

2、查看设计

设计导入成功后,我们可以通过查看设计来了解当前设计的规模,设计中各个子功能模块以及memory的数量。

上图中的Terms是指设计中的io port端口,Nets是这些io port对应的net。

ESC 关闭 | 导航 | Enter 打开
输入关键词开始搜索