4. 模式定义与功能约束
多模式多角STA的核心难点并不在于“跑一次时序”,而在于同一份网表在不同工作模式下会呈现完全不同的时序拓扑。测试模式(scan/test)下时钟由ATE或扫描链驱动,功能模式(functional)下时钟来自PLL或外部晶振,低功耗模式(low-power)下部分电源域关断、时钟被门控或分频。如果把这些模式混在同一个约束文件里,PrimeTime会得到互相矛盾的时钟定义、错误的case值传播路径,最终导致setup/hold报告不可信。因此,模式定义的本质是:为每一种工作场景建立一套自洽的时钟、case analysis、例外约束与隔离边界。
一、模式划分与时钟定义
模式划分应遵循“一个模式对应一种真实工作场景”的原则。典型SoC至少需要定义三类模式:功能模式、扫描测试模式、低功耗模式。每种模式必须独立定义时钟源、时钟频率、时钟不确定性(uncertainty)和时钟延迟(latency)。
以功能模式为例,假设系统时钟由PLL产生,输入参考时钟为24MHz,PLL倍频后输出800MHz,分频后得到400MHz、200MHz、100MHz三路时钟。在PrimeTime中应这样定义:
create_clock -name ref_clk -period 41.667 [get_ports clk_ref]
create_clock -name sys_clk -period 1.25 [get_pins pll/CLKOUT]
create_clock -name cpu_clk -period 2.5 [get_pins div2/Q]
create_clock -name peri_clk -period 5.0 [get_pins div4/Q]
create_clock -name slow_clk -period 10.0 [get_pins div8/Q]
扫描测试模式下,时钟不再来自PLL,而是由ATE直接驱动scan_clk端口,频率通常较低(如50MHz),且所有功能时钟必须被禁用或隔离。此时应重新定义:
create_clock -name scan_clk -period 20.0 [get_ports scan_clk]
set_clock_groups -asynchronous \
-group {scan_clk} -group {ref_clk sys_clk cpu_clk peri_clk slow_clk}
低功耗模式下,部分电源域关断,时钟被门控。此时需要定义门控时钟的使能条件,并对关断域设置false path或disable timing。例如:
create_clock -name lp_clk -period 5.0 [get_pins clk_gate/Q]
set_clock_gating_check -setup 0.1 -hold 0.05 [get_cells clk_gate]
set_false_path -from [get_clocks ref_clk] -to [get_clocks lp_clk]
二、Case Analysis:模式专属的常量传播
Case analysis用于在特定模式下将某些控制信号固定为常量,从而剪除不可达的时序路径。例如测试模式下,功能使能信号func_en应固定为0,扫描使能scan_en固定为1;低功耗模式下,电源域使能pd_en固定为0或1取决于具体域。
在PrimeTime中,case analysis通过set_case_analysis实现。关键原则是:case值必须与模式定义一致,且不能在同一模式下对同一信号设置冲突值。例如:
# 功能模式
set_case_analysis 1 [get_ports func_en]
set_case_analysis 0 [get_ports scan_en]
set_case_analysis 1 [get_ports pd_en]
# 扫描测试模式
set_case_analysis 0 [get_ports func_en]
set_case_analysis 1 [get_ports scan_en]
set_case_analysis 1 [get_ports pd_en]
# 低功耗模式
set_case_analysis 1 [get_ports func_en]
set_case_analysis 0 [get_ports scan_en]
set_case_analysis 0 [get_ports pd_en]
需要注意的是,case analysis会直接影响时钟传播。如果某个时钟在case条件下被阻断,PrimeTime会将该时钟域标记为“unclocked”,此时必须确认这是预期行为,否则应检查case值是否设置错误。
三、模式专属约束与模式间隔离
不同模式下的时序例外(exception)必须严格隔离。例如,功能模式下的多周期路径(multicycle path)在扫描模式下可能完全不适用;扫描模式下的false path在功能模式下可能掩盖真实违例。因此,建议为每个模式建立独立的约束文件,并通过set_active_scenarios或set_operating_conditions进行场景管理。
模式间隔离的另一个关键点是时钟组(clock group)的定义。对于异步时钟域,必须使用set_clock_groups -asynchronous明确声明,避免PrimeTime对异步跨域路径进行无意义的时序分析。同时,对于同一时钟在不同模式下的不同频率,应通过set_clock_groups -physically_exclusive或-logically_exclusive进行互斥声明。
四、模式约束的验证与检查
约束定义完成后,必须进行一致性检查。PrimeTime提供了check_timing命令,可以报告未约束的时钟、未设置的case值、冲突的例外等。典型检查项包括:
check_timing -verbose:报告所有未约束的端点、未定义的时钟、未设置的输入延迟等。report_case_analysis:列出当前模式下所有case analysis设置,确认无冲突。report_clock -skew -groups:检查时钟组划分是否合理,是否存在未声明的异步跨域。report_exceptions -ignored:报告被忽略的例外约束,通常意味着约束条件与当前模式不匹配。
以下SVG展示了三种模式在时钟源、case值、例外约束和隔离边界上的关系,帮助理解模式切换时约束如何整体迁移。
从图中可以看出,三种模式在时钟源、case值、例外约束和隔离边界四个维度上形成互斥关系。功能模式使用PLL输出时钟,扫描模式使用ATE时钟,低功耗模式使用门控时钟;case值在三种模式下完全不同;例外约束和隔离边界也各自独立。这种“模式-约束”的映射关系必须在约束文件中显式表达,不能依赖工具自动推断。
五、模式约束的工程实践要点
在实际项目中,模式约束的管理通常采用“主约束+模式覆盖”的方式。主约束文件定义所有模式共用的基础约束(如端口延迟、驱动能力、负载模型),模式覆盖文件则定义该模式特有的时钟、case和例外。通过source命令按顺序加载,后加载的约束会覆盖先加载的同名约束。
需要特别注意的是,set_case_analysis具有全局性,一旦设置会影响整个设计。因此,在切换模式时,必须先清除上一模式的case设置,再设置新模式的case值。推荐使用remove_case_analysis -all或reset_case_analysis进行清理。
set_clock_groups -asynchronous -group {scan_clk} -group {sys_clk cpu_clk peri_clk},或使用set_false_path切断功能时钟路径。
最后,模式约束的验证应纳入回归流程。每次约束变更后,至少运行一次check_timing和report_exceptions -ignored,确保没有遗漏或冲突。对于低功耗模式,还需额外检查门控时钟的setup/hold检查是否被正确执行,以及隔离单元的电平转换约束是否完整。
模式定义与功能约束是多模式多角STA的基石。只有把每种模式的时钟、case、例外和隔离边界都定义清楚,后续的时序分析结果才具有工程可信度。建议在项目早期就建立模式矩阵表,并随着设计迭代持续维护,避免约束腐化。