01signal.com

在 SDC 时序约束中使用通配符与 -hierarchical

本页是另一页的补充内容,建议你先阅读那页再回来读本页。这两页都属于一个关于时序的系列文章,该系列解释了时序计算背后的理论、展示了如何编写多条时序约束,并讨论了时序收敛(timing closure)的原则。

除非万不得已,不要使用简单的搜索模式

本页介绍如何在 SDC 格式的时序约束中使用通配符。尽管通配符可以用于多个 Tcl 命令,但本页重点讨论那些通常支持 -hierarchical 选项的命令:get_cells、get_pins 和 get_nets。这些 Tcl 命令的用法在另一个页面中已有说明。注意,有些 FPGA 工具并不对这三个命令都支持 -hierarchical。

遗憾的是,这三个命令的搜索能力相当有限,而且容易让人困惑:如果不准确理解通配符的工作方式,搜索结果可能会出乎意料。尤其是使用 -hierarchical 时,结果常常令人惊讶,如下文所示。

因此,只要所用 FPGA 工具在相应命令上支持-filter 选项,就应该优先使用它。在工具不支持的情况下,才别无选择地使用简单通配符。

本页中的示例都基于与另一相关页面相同的 Verilog 代码。

简单的搜索模式

用于查找逻辑元件及其它对象的命令,可以带搜索模式,也可以不带。不带搜索模式时,会找到所有相关对象。例如,要查找顶层层次中的所有引脚:

get_pins

而下面这条命令则查找整个 FPGA 设计中的所有引脚:

get_pins -hierarchical

如果使用了搜索模式,结果就会被限制在该模式内。例如,要查找一个名字已知、在层次结构中位置也已知的特定引脚:

> get_pins foo_reg_reg/Q
foo_reg_reg/Q
> get_pins pll_i/clk_in1
pll_i/clk_in1
> get_pins pll_i/inst/clk_in1
pll_i/inst/clk_in1

模式中也可以包含通配符。例如:

> get_pins foo_reg_reg/*
foo_reg_reg/Q foo_reg_reg/C foo_reg_reg/CE foo_reg_reg/D foo_reg_reg/R

> get_pins pll_i/*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
> get_pins pll_i/inst/*
pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2
> get_pins pll_i/*/*
pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2
> get_pins pll_i/*/clk*
pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2

通配符的行为

通配符有两种:

但这两个通配符都不会匹配层次结构分隔符。换句话说,* 和 ? 都不能替代 /(在 Quartus 中则是 |)。无论是否使用 -hierarchical 选项,这一点对通配符始终成立(但要注意,如果使用 -filter 或 -regexp,情况就不同了)。

因此,对象在层次结构中的精确位置必须显式地写出来:

> get_pins */clk_*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
> get_pins */*/clk_*
pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2

注意,不同工具使用的层次结构分隔符可能不同。如前所述,Quartus 使用竖线(|)而不是 / 作为分隔符。

-hierarchical 选项允许在设计的整个层次结构中的任何位置查找逻辑元件。这就不需要指定对象在层次结构中的精确位置,也可以用一条命令在整个 FPGA 设计中进行查找。

现在,我们把同样的表达式与 -hierarchical 一起再运行一遍:

> get_pins -hierarchical */clk_*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2 pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2
> get_pins -hierarchical */*/clk_*
WARNING: [Vivado 12-508] No pins matched '*/*/clk_*'.

-hierarchical 的含义是:搜索模式会在设计层次结构的各个位置依次应用。在上面的例子中,*/clk_* 首先在顶层层次应用,于是找出 pll_i/clk_in1 等;同一模式随后又在 pll_i/ 内部应用,于是找出 pll_i/inst/clk_in1 等。

但为什么 */*/clk_* 在使用 -hierarchical 后反而找不到任何东西?同样的模式在不使用该选项时明明能找出一些结果。使用 -hierarchical 后,搜索结果不是理应更多吗?

使用 -hierarchical 会限制搜索模式

奇怪的是,-hierarchical 选项不仅改变了搜索模式的适用范围,还会限制哪些模式是合法的。遗憾的是,当使用了非法的模式时,工具并不会报错,而是直接返回“什么都没有找到”。

这三个 Tcl 命令(get_cells、get_pins 和 get_nets)各自都有限制搜索模式的规则。要了解具体限制,请参考你所使用的 FPGA 工具的文档。下面是标准的解释(详见 Synopsys 的文档)。

注意,人们常把 -hierarchical 简写为 -hier,两者的含义完全相同。

get_cells -hierarchical

当 get_cells 与 -hierarchical 一起使用时,模式只匹配对象的名称。如果模式中含有层次结构分隔符,结果将始终为空。例如:

> get_cells -hierarchical *_buf
pll_i/inst/clkf_buf pll_i/inst/clkout1_buf pll_i/inst/clkout2_buf
> get_cells -hierarchical inst/*_buf
WARNING: [Vivado 12-180] No cells matched 'inst/*_buf'.

注意,如果模式中含有 /,那就是一种错误用法,因为这类模式永远找不到任何东西。但工具不会报错,只会返回空结果。

由于模式中不允许出现层次结构分隔符,get_cells 只能有以下几种用途:

下面这个示例展示了如何为所有具有特定命名格式的 cell 声明伪路径:

set_false_path -to [get_cells -hierarchical *metaguard*]

使用这类时序约束时,只需要让所有作为亚稳态保护(metastability guard)的寄存器名字中都包含 metaguard 即可。但这条约束的风险在于,这个表达式可能无意中匹配到 FPGA 设计中某个不相关的逻辑元件。因此,最好选择一个比 metaguard 更少见的关键词。

get_nets -hierarchical

get_nets 遵循与 get_cells 相同的规则:不使用 -hierarchical 时,get_nets 查找顶层层次中与模式匹配的所有网络;使用 -hierarchical 时,模式只匹配对象的名称,如果模式中含有层次结构分隔符,结果始终为空。

> get_nets pll_i/clk_i*
pll_i/clk_in1
> get_nets clk_i*
WARNING: [Vivado 12-507] No nets matched 'clk_i*'.
> get_nets -hierarchical clk_i*
pll_i/clk_in1 pll_i/inst/clk_in1
> get_nets -hierarchical pll_i/clk_i*
WARNING: [Vivado 12-507] No nets matched 'pll_i/clk_i*'.

get_pins -hierarchical

当 get_pins 与 -hierarchical 一起使用时,模式会匹配引脚的完整名称,例如 baz_reg/Q、clkout1_buf/I 等等。此时,/ 被视为名字的一部分,而不是层次结构分隔符。换句话说,cell 名称与引脚标识符之间的字符可以被通配符替代。这只对最后一个层次结构分隔符成立,而且只有在使用 -hierarchical 时才如此。

例如:

> get_pins -hierarchical clkout1_buf/*
pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I
> get_pins -hierarchical clkout1_bu*
pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I
> get_pins -hierarchical clkout1_buf
WARNING: [Vivado 12-508] No pins matched 'clkout1_buf'.

注意,clkout1_bu* 匹配到了 clkout1_buf/O(以及其它)。* 之所以能替代 /O,完全是因为使用了 -hierarchical。

与 get_cells 一样,如果模式中含有层次结构分隔符,结果通常为空。这与上面的例子并不矛盾:如前所述,最后一个 / 被视为引脚名称的一部分。

> get_pins pll_i/inst/clkout1*/I
pll_i/inst/clkout1_buf/I
> get_pins -hierarchical pll_i/inst/clkout1*/I
WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/clkout1*/I'.

> get_pins -hierarchical pll_i/inst/*/*
WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/*/*'.
> get_pins -hierarchical pll_i/*/*/*
WARNING: [Vivado 12-508] No pins matched 'pll_i/*/*/*'.
> get_pins -hierarchical pll_i/*/*
WARNING: [Vivado 12-508] No pins matched 'pll_i/*/*'.

> get_pins -hierarchical pll_i/*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
> get_pins pll_i/*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2

注意,当不使用 -hierarchical 时,通配符永远不匹配层次结构分隔符,哪怕是最后一个 / 也不行:

> get_pins pll_i/inst/clkout1_buf/I
pll_i/inst/clkout1_buf/I
> get_pins pll_i/inst/clkout1_buf/*
pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I
> get_pins pll_i/inst/clkout1_bu*
WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/clkout1_bu*'.
> get_pins pll_i/inst/clkout1_bu*/*
pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I

从这些例子可以清楚地看出,get_pins 是多么令人困惑。和前文建议的一样:如果工具支持 -filter 或 -regexp,就果断改用它们。

小结

尽管通配符是一种查找逻辑元件的方法,但搜索结果往往并不符合人们的自然预期。同样,-hierarchical 选项在某些场景下确实有帮助,但它既会对搜索模式带来限制,还会让行为变得更加难以捉摸。

因此,建议使用其它方法来选择逻辑元件:如果 FPGA 工具支持 -filter、-regexp 或 -of_objects,那么其中某个选项很可能是更好的选择。只有在这些选项都不可用、或者在具体场景中都不适用时,使用简单通配符才有意义。在这种情况下,务必格外警惕搜索模式的确切含义。

本页由机器从英文翻译而来。如有疑问,请参阅原文
Copyright © 2021-2026. All rights reserved. (dcc38493)