Tcl · Module 18
Querying Pins
A pin is where an instance connects. Unlike ports, pins live inside the hierarchy — which means almost every pin query needs to say so.
Intermediate16 min readtcledapart-iipinshierarchycollectionsclocks
Part II · Module 18 · Chapter 18.4 · Querying Pins
A port is a connection on the boundary of the whole design. A pin is a connection on an instance inside it. Every flop has a clock pin, every gate has input pins, and most interesting timing questions are about pins rather than ports.
The command looks like get_ports and has one important difference: pins live inside the hierarchy.
1. Pins are named by their instance
A pin's name includes the instance it belongs to:
get_pins -hierarchical * size 7 u_fifo/CLK u_fifo/D u_alu/A u_fifo/u_ctrl/CLK u_fifo/u_ram/CLK u_alu/u_acc_reg/CLK u_alu/u_add/Au_fifo/CLK is the pin CLK on the instance u_fifo. u_fifo/u_ctrl/CLK is the pin CLK on the instance u_ctrl which is inside u_fifo.
The separator is a hierarchy separator — / in the mock, and commonly / in real tools too, though some use a different character. It is the same idea as a filesystem path, and u_fifo/u_ctrl/CLK reads the same way.
This is Chapter 18.1 §4's identity argument made concrete: four different pins here are all called CLK, and only the full path distinguishes them.
2. Why pin queries almost always need -hierarchical
get_pins * size 0Zero. Every pin belongs to some instance, so every pin name contains a separator — and a non-hierarchical query looks only at the current level, where there are no bare pins at all.
3. Selecting clock pins by pattern
The registry's own example, and the one you will type most:
show {get_pins -hierarchical */CLK} [get_pins -hierarchical */CLK] get_pins -hierarchical */CLK size 4 u_fifo/CLK u_fifo/u_ctrl/CLK u_fifo/u_ram/CLK u_alu/u_acc_reg/CLKRead the pattern as a path: */CLK is "anything, then a separator, then CLK". Four pins at three different levels of hierarchy, selected in one line.
Patterns to recognise:
| Pattern | Selects |
|---|---|
*/CLK | a pin named exactly CLK, on any instance |
u_fifo/* | every pin on u_fifo itself |
u_fifo/*/* | pins one level inside u_fifo |
*/*CLK* | any pin whose name contains CLK |
4. Pins have attributes too
Direction, whether the pin is a clock, whether it is on a sequential cell — the properties from Chapter 18.1 §5 apply to pins as much as to cells. They are how you ask what a pin is rather than what it is called.
5. Looking at one instance's pins
When you are investigating a specific cell, listing its pins with their attributes is the fastest orientation there is:
foreach_in_collection p [get_pins -hierarchical "u_fifo/*"] {
puts [format " %-22s direction %-4s is_clock %s" $p \
[get_attribute $p direction] [get_attribute $p is_clock]]
}=== pins of one instance ===
u_fifo/CLK direction in is_clock true
u_fifo/D direction in is_clock false
u_fifo/u_ctrl/CLK direction in is_clock true
u_fifo/u_ram/CLK direction in is_clock trueThe depth difference, measured:
puts " get_pins -hierarchical */CLK -> [n [get_pins -hierarchical */CLK]] (any depth)"
puts " get_pins -hierarchical */*/CLK -> [n [get_pins -hierarchical */*/CLK]] (exactly two levels)"=== one level only, vs any depth ===
get_pins -hierarchical */CLK -> 4 (any depth)
get_pins -hierarchical */*/CLK -> 3 (exactly two levels)Four versus three — the extra one is u_fifo/CLK, which is only one level down. Adding a */ does not mean "deeper than before"; it means "at least this deep", and the shallower matches drop out.
6. Name patterns versus attributes
Here is the comparison that matters. Both of these find the clock pins:
show {get_pins -hierarchical */CLK} [get_pins -hierarchical */CLK]
set clkpins [filter_collection [get_pins -hierarchical *] "is_clock == true"]
show {filter_collection ... is_clock==true} $clkpins get_pins -hierarchical */CLK size 4 u_fifo/CLK u_fifo/u_ctrl/CLK u_fifo/u_ram/CLK u_alu/u_acc_reg/CLK
the clock pins, by attribute rather than by name:
filter_collection ... is_clock==true size 4 u_fifo/CLK u_fifo/u_ctrl/CLK u_fifo/u_ram/CLK u_alu/u_acc_reg/CLKSame four pins — in this design.
7. A practical routine
When you need "the clock pin of every sequential cell", the honest sequence is:
- Find the sequential cells by attribute, not by name — Chapter 18.5 §4.
- Get their pins, and filter those by the clock attribute.
- Check the count against what you expect from the design, before using the result.
set seq [filter_collection [get_cells -hierarchical *] "is_sequential == true"]
if {[sizeof_collection $seq] == 0} {
error "no sequential cells found — is a design loaded?" {} {DESIGN NOSEQ}
}
set clk_pins [filter_collection [get_pins -hierarchical *] "is_clock == true"]
puts " [sizeof_collection $seq] sequential cells, [sizeof_collection $clk_pins] clock pins"Step 3 is the one people skip and the one that catches a wrong attribute name or a design that is not loaded.
8. Exercises
Exercise 1. What is the difference between a port and a pin?
Exercise 2. get_pins * returned zero on a design with thousands of pins. Why?
Exercise 3. Read the pattern */CLK out loud as a path. What does it select?
Exercise 4. Does */CLK match a pin two levels deep? How would you restrict it to one level?
Exercise 5. Why is get_pins -hierarchical */CLK unreliable for finding every clock pin?
Exercise 6. Why is an incomplete result worse than an empty one?
Exercise 7. Write the two-step selection for "every clock pin", using attributes.
Where this fits
Part of the Tcl curriculum.
