2. PrimeTime工作环境与复杂SoC数据准备

在复杂SoC的时序收敛流程中,PrimeTime(后文简称PT)并不是一个"打开就能跑"的孤立工具,它需要一整套与设计环境严格对齐的输入:工艺库、网表、约束、寄生参数以及运行环境变量。数据准备阶段的任何一处错位——库版本不一致、SDC作用域写错、多电压域UPF未加载——都会在后续时序分析中表现为难以定位的违例或虚假通过。本节围绕"如何把PT启动起来并喂给它正确的数据"展开,重点讲清启动方式、库加载、网表与SDC读入顺序,以及多电压域和层次化设计下的脚本组织方法。

一、启动方式与运行环境

PT的启动有两种典型形态:交互式shell与批处理脚本。交互式适合调试约束、探查路径;批处理适合回归与签核。无论哪种方式,第一步都是确认工具版本与工艺库版本匹配,例如使用 pt_shell -version 查看版本,并核对库文件是否来自同一PDK release。

# 交互式启动
pt_shell -f setup.tcl

# 批处理启动(推荐用于回归)
pt_shell -batch -f run_pt.tcl | tee pt.log

启动后需要设置的关键环境变量包括:search_path(库与网表搜索路径)、link_path(链接库路径)、target_library(目标工艺库)、link_library(链接库,通常包含 * 与IO库)、symbol_library(符号库,仅用于图形界面)。其中 link_library 中的 * 表示"已加载的设计优先",这是层次化设计链接的关键。

建议在脚本开头统一设置 sh_command_abort_on_error true,让命令出错时立即终止,避免错误被后续命令掩盖。

二、加载设计库与读入网表

库加载顺序直接影响链接结果。推荐顺序为:先设 target_library 与 link_library,再 read_verilog 或 read_db 读入网表,最后 link_design 完成链接。若设计包含多个电压域,还需在链接前读入UPF。

set target_library "sc9_cln40ll_base_ssg_0p99v_125c.db"
set link_library   "* sc9_cln40ll_base_ssg_0p99v_125c.db \
                    sc9_cln40ll_io_ssg_0p99v_125c.db"
set search_path    ". ./libs ./netlist ./sdc ./upf"

read_verilog ./netlist/soc_top.v
read_verilog ./netlist/cpu_core.v
link_design soc_top

链接完成后,用 list_designs 与 current_design 确认顶层设计正确,用 report_design 检查是否有未解析的实例(unresolved reference)。若出现 Linking failed,优先检查 link_library 是否包含对应单元库,以及网表模块名与库单元名是否大小写一致。

三、读入SDC与多电压域处理

SDC读入必须在 link_design 之后,因为约束中的 get_cells、get_pins 需要设计已链接才能解析。对于多电压域设计,UPF应在SDC之前加载,使电源域信息先建立,SDC中的电压相关约束才能正确作用。

read_upf ./upf/soc_top.upf
read_sdc ./sdc/soc_top.sdc
check_timing
report_clock -skew
report_case_analysis

多电压域下需要特别关注三类问题:一是跨电压域路径的level shifter是否被正确插入并约束;二是isolation cell的使能信号是否有时序约束;三是retention寄存器的save/restore路径是否被覆盖。可用 report_power_domain 查看域划分,用 report_level_shifter 检查电平转换器插入情况。

四、层次化设计的脚本组织

复杂SoC通常包含CPU、GPU、DDR、外设等多个子系统,若把所有约束写在一个SDC里,维护成本极高。工程化做法是按层次拆分:顶层SDC负责时钟定义、IO约束、跨模块时序例外;各子系统SDC负责内部路径约束,通过 source 逐层引入。

# soc_top.sdc
source ./sdc/clocks.sdc
source ./sdc/io.sdc
source ./sdc/cpu_core.sdc
source ./sdc/ddr_ctrl.sdc
source ./sdc/exceptions.sdc

脚本组织建议遵循"三段式":环境段(库、路径、变量)、构建段(读网表、链接、读UPF/SDC)、分析段(check_timing、report_*)。每段之间用 echo 打印阶段标记,便于日志定位。对于回归,可将不同corner封装为独立脚本,通过 -f 传入,避免变量污染。

PrimeTime 数据准备与脚本组织流程 ① 环境段 pt_shell -batch -f run_pt.tcl set search_path set target_library set link_library "* ..." sh_command_abort_on_error true 版本匹配 · 路径正确 ② 构建段 read_verilog soc_top.v read_verilog cpu_core.v link_design soc_top read_upf soc_top.upf read_sdc soc_top.sdc 链接成功 · UPF先于SDC ③ 分析段 check_timing report_clock -skew report_power_domain report_level_shifter report_case_analysis 约束完整 · 域划分正确 层次化 SDC 组织与多电压域检查 soc_top.sdc 时钟 · IO · 例外 cpu_core.sdc 内部路径约束 ddr_ctrl.sdc 内部路径约束 exceptions.sdc 跨模块例外 source source source 多电压域关键检查项 Level Shifter 跨域路径是否插入 Isolation Cell 使能信号时序约束 Retention Reg save/restore路径 Power Domain 域划分与电压

五、常见数据准备错误与排查

实际工程中,数据准备阶段的错误往往以"时序结果异常"的形式暴露。以下三类最为典型:

  • 链接失败:link_design 报 unresolved reference。检查 link_library 是否包含所有引用库,网表模块名是否与库单元名一致,以及 search_path 是否覆盖网表目录。
  • SDC未生效:report_clock 显示无时钟。检查 read_sdc 是否在 link_design 之后,SDC中 get_cells 的层次路径是否与当前设计匹配。
  • UPF未加载:report_power_domain 为空。检查 read_upf 是否在 link_design 之后、read_sdc 之前,UPF文件中的domain名是否与设计一致。
多电压域设计中,若UPF在SDC之后加载,SDC中与电压相关的约束(如 set_voltage)可能被忽略,导致时序分析使用错误的电压值。务必保证加载顺序为:link_design → read_upf → read_sdc。

六、可复用的数据准备检查清单

为便于工程落地,下面给出一份可直接用于回归脚本的检查清单,覆盖从启动到约束加载的关键节点:

检查项 命令/方法 通过标准
工具版本与库版本匹配 pt_shell -version + 库release note 版本号一致
库路径设置正确 echo $target_library 路径存在且可读
网表链接成功 link_design + report_design 无unresolved reference
UPF加载成功 report_power_domain 域列表与预期一致
SDC约束完整 check_timing 无unconstrained endpoint
时钟定义正确 report_clock -skew 时钟频率/周期符合预期
跨域路径已约束 report_level_shifter 跨域路径均有LS或例外

把上述检查项封装为 check_data_ready.tcl,在每次回归前自动执行,可以显著减少因数据准备不当导致的无效迭代。数据准备做扎实,后续的时序分析与优化才有可靠的基础。