Skip to content
VLSI Mentor

Tcl · Module 18

Querying Ports

Ports are where a block meets the rest of the chip, so almost every constraint starts by selecting one. Two things make that harder than it looks: brackets, and silence.

Intermediate17 min readtcledapart-iiportscollectionsglobbuses

Part II · Module 18 · Chapter 18.3 · Querying Ports

A port is a connection at the boundary of a design — the pins of the block as seen from outside. Clocks arrive on ports, data arrives on ports, and nearly every timing constraint you will write begins by selecting one.

The command is simple. Two things about it are not: bus names contain brackets, and a pattern that matches nothing says nothing.

1. Selecting ports

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
proc show {label h} {
    puts [format "  %-34s size %-2s  %s" $label [sizeof_collection $h] [collection_to_list $h]]
}
show {get_ports *}              [get_ports *]
show {get_ports clk}            [get_ports clk]
show {get_ports data*}          [get_ports data*]
show {get_ports nosuch}         [get_ports nosuch]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  get_ports *                        size 8   clk reset_n {data_in[0]} {data_in[1]} {data_in[2]} {data_in[3]} {data_out[0]} {data_out[1]}
  get_ports clk                      size 1   clk
  get_ports data*                    size 6   {data_in[0]} {data_in[1]} {data_in[2]} {data_in[3]} {data_out[0]} {data_out[1]}
  get_ports nosuch                   size 0

Four queries. The pattern is an ordinary glob — the same string match patterns from Chapter 13.10, not a regular expression.

Two things in that output are worth stopping on.

The braces around {data_in[0]} are Tcl's list quoting, printed because the name contains characters that need protecting — exactly as in Chapter 15.2 §4. They are not part of the port name.

The last row produced nothing at all. Size 0, no error, no message. That is §5 and it is the most important line in the chapter.

2. Ports have a direction

The attribute you will reach for first:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach_in_collection p [get_ports *] {
    puts [format "  %-14s %s" $p [get_attribute $p direction]]
}

Direction is why you constrain input and output ports differently — an input delay describes when data arrives, an output delay when it must leave. Selecting by direction rather than by name pattern is Chapter 18.7's subject, and it is more reliable than hoping every input is called *_in*.

3. Bus names: the first bracket problem

Bus bits have names like data_in[0], and [ is special in Tcl. Written bare in a script, it is command substitution — Chapter 2.5:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
invalid command name "0"
    while executing
"0"

Tcl tried to run a command called 0. This is not an EDA problem; it is the most basic Tcl rule meeting a naming convention from hardware.

The fix is braces, which suppress substitution entirely (Chapter 2.8):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
get_ports {data_in[0]}

Make this a reflex: any design-object name containing brackets goes in braces. That covers bus bits, and it costs nothing when the name has no brackets.

4. Bus patterns: the second bracket problem

Braces fix the substitution. They do not make the brackets ordinary, because [...] is also a glob metacharacter — a character class.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
set name {data_in[0]}
foreach pat {{data_in[*]} {data_in\[*\]} {data_in*} {data_in[0]}} {
    puts [format "  string match %-18s -> %s" $pat [string match $pat $name]]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  the port name is       : data_in[0]
  string match data_in[*]         -> 0
  string match data_in\[*\]       -> 1
  string match data_in*           -> 1
  string match data_in[0]         -> 0

5. The empty result

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  get_ports nosuch                   size 0

No error. No warning. A collection of zero ports, returned as calmly as a collection of eight.

This is the central hazard of EDA scripting, and Chapter 18.8 is devoted to it. The short version: a constraint applied to zero ports constrains nothing, the flow reports success, and every number downstream is computed against a design that was never constrained.

Guard it where it matters:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
set clk_port [get_ports clk]
if {[sizeof_collection $clk_port] == 0} {
    error "no port matched 'clk' — check the port name" {} {DESIGN NOPORT}
}
create_clock -name core -period 2.0 $clk_port

Four lines instead of one, and the difference between a run you can trust and a run you cannot.

6. Finding the real names

Most empty results are a name that is nearly right. Before guessing again, look:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts [collection_to_list [get_ports *]]

On a real design that is a long list, so narrow it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts [collection_to_list [get_ports *clk*]]     ;# anything clock-ish
puts [collection_to_list [get_ports *rst*]]     ;# reset, by either spelling
puts [collection_to_list [get_ports *reset*]]

Designs disagree about clk versus clock, rst_n versus reset_n versus resetb. Searching for the substring beats guessing the whole name, and it takes one line at the prompt — which is exactly what Chapter 17.2 §6 said the console is for.

7. A pattern worth keeping

A small helper that makes every port query fail loudly:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
proc need_ports {pattern {what "port"}} {
    set c [get_ports $pattern]
    if {[sizeof_collection $c] == 0} {
        error "no $what matched '$pattern'" {} [list DESIGN NOMATCH $pattern]
    }
    return $c
}

create_clock -name core -period 2.0 [need_ports clk "clock port"]

This is Chapter 14.11's boundary check applied to design queries: validate at the point of entry, with a message naming the pattern that failed. Having written it once, every query in the script can use it.

8. Exercises

Exercise 1. What does get_ports select, and what does it not?

Exercise 2. Why do the braces appear around {data_in[0]} in the output?

Exercise 3. get_ports data_in[0] without braces gives invalid command name "0". Why?

Exercise 4. Braces fix that. Why do they not make data_in[*] match the bus?

Exercise 5. Which pattern reliably selects every bit of data_in, whatever the tool?

Exercise 6. get_ports clk returns size 0 and the script continues. What happens next, and how do you prevent it?

Exercise 7. You expected a port called reset_n and got nothing. What is the quickest way to find the real name?

Where this fits

Part of the Tcl curriculum.