Using wildcards and -hierarchical in SDC timing constraints

This page is an add-on to another page that should be read before this one. Both pages are part of a series of pages, which explain the theory behind timing calculations, show how to write several timing constraints and discuss the principles of timing closure.

Don't use simple search patterns unless you must

This page explains how to use wildcards for writing timing constraints in SDC format. Even though wildcards can be used with several Tcl commands, this page focuses on commands that usually support the the "-hierarchical" option: get_cells, get_pins and get_nets. These Tcl commands are explained on a different page. Note however that some FPGA tools don't support "-hierarchical" with all of these three commands.

Unfortunately, the search capability of these three commands is quite limited and possibly confusing: Without understanding exactly how the wildcard works, the search results can be unexpected. In particular, when "-hierarchical" is used, the results can be surprising, as shown below.

For this reason, it's always better to use the "-filter" option when the specific FPGA tool supports it for the relevant command. In the absence of such support, there is no choice but using the simple wildcards.

All examples in this page are based upon the same Verilog code as that other related page.

Simple search patterns

The commands that find logic elements and other objects can be used with or without a search pattern. Without a search pattern, all relevant objects are found. For example, in order to find all pins at the top-level hierarchy:


And the command that finds all pins in the entire FPGA design is:

get_pins -hierarchical

If a search pattern is used, the results are limited to this pattern. For example, to find one specific pin with a known name and a known position in the hierarchy:

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

The pattern can also include wildcards, for example:

> 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

The behavior of the wildcard

There are two common wildcards:

However, these two wildcards never apply to the hierarchy separator. In other words, "*" and "?" don't substitute a "/" (or a "|" with Quartus). This is always true with wildcards, regardless if the "-hierarchical" option is used or not (but note that if "-filter" or "-regexp" are used, it's a different story).

As a result, the object's exact position in the hierarchy must be explicitly written:

> 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

Note that different tools may use different characters for the hierarchy separator. As just mentioned, Quartus uses the pipe character ("|"), and not "/", for this purpose.

The "-hierarchical" option allows finding logic elements anywhere in the design's hierarchy. This eliminates the need to specify the exact position in the hierarchy, and also allows finding logic elements across the entire FPGA design with a single command.

So let's repeat the same expressions with "-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_*'.

The "-hierarchical" means that the search pattern is applied in all positions in the design's hierarchy. In the example above, "*/clk_*" was first applied both at the top-level hierarchy, so "pll_i/clk_in1" was found for example. The same pattern was then applied inside "pll_i/", so "pll_i/inst/clk_in1" was found.

But why was nothing found with "*/*/clk_*" when "-hierarchical" was applied? The same pattern yielded some search results without this option. Shouldn't there always be more search results when "-hierarchical" is used?

Using -hierarchical restricts the search pattern

Oddly enough, the "-hierarchical" option doesn't only change where the search pattern is applied, but it also limits which patterns are allowed. Unfortunately, the tools don't respond with an error when an illegal pattern is used. Instead, the response is that nothing is found.

Each of the three Tcl commands (get_cells, get_pins and get_nets) has its own rule that restrict the search pattern. To find out the exact limitations, refer to the documentation of your FPGA tool. The standard interpretation (as detailed in Synopsys' documentation) is outlined below.

Note that the abbreviation "-hier" is often used instead of "-hierarchical". The meaning is exactly the same.

get_cells -hierarchical

When get_cells is used with -hierarchical, the pattern matches only with the name of the object. If there is a hierarchy separator in the pattern, the result is always empty. For example:

> 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'.

Note that it's an error if there is a "/" in the pattern, because nothing is ever found with a pattern like this. However, the tools don't respond with an error, but instead the command yields no results.

Because the hierarchy separator is not allowed in the pattern, get_cells is limited to the following possibilities:

This example shows how to declare false paths for all cells with a specific name format:

set_false_path -to [get_cells -hierarchical *metaguard*]

With a timing constraint like this, it's enough to use a name that includes the word "metaguard" for all registers that are used as metastability guards. The risk with this timing constraint is however that the expression can unintentionally match with an unrelated logic element somewhere in the FPGA design. It's therefore better to choose something that is less common that "metaguard".

get_nets -hierarchical

get_nets follows the same rule as get_cells: Without -hierarchical, get_nets finds all nets at the top-level hierarchy that match with the pattern. With -hierarchical, the pattern matches only the with the name of the object. If there is a hierarchy separator in the pattern, the result is always empty.

> get_nets pll_i/clk_i*
> 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

When get_pins is used with -hierarchical, the pattern matches with the full name of the pin, e.g. baz_reg/Q, clkout1_buf/I etc. The "/" is considered part of the name, and not a hierarchy separator. In other words, the character that is between the name of the cell and the pin's identifier can be substituted by a wildcard. This is true only regarding the last hierarchy separator and only when -hierarchical is used.

So, for example:

> 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'.

Note that clkout1_bu* matched with clkout1_buf/O (among others). The "*" can be substituted with "/O", only because of -hierarchical.

As with get_cells, if there is a hierarchy separator in the pattern, the result is always empty. This doesn't contradict the example above: As mentioned, the last "/" is considered as a part of the pin's name.

> get_pins pll_i/inst/clkout1*/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

Note that when -hierarchical is not used, a wildcard is never matched with a hierarchy separator, even not the last one:

> get_pins 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

It is evident from these examples how confusing get_pins is. As before, use -filter or -regexp instead, if these are supported.


Even though wildcards are available as a method for finding logic elements, the search results are not always what is naturally expected. Likewise, the -hierarchical option can be helpful is some scenarios, but this possibility comes with a restriction on the search pattern and with even more confusing behavior.

It's therefore recommended to use other methods for selecting logic elements: If -filter, -regexp or -of_objects are supported by the FPGA tools, one of these options is probably a better solution. The use of simple wildcards makes sense only if none of these other options is available, or if none is useful in the specific scenario. In this situation, it's important to be extra vigilant regarding the meaning of the search pattern.

Copyright © 2021-2023. All rights reserved. (bae74bd8)