Tcl · Module 18
Querying Cells
Cells are the instances a design is built from. Selecting them is easy; selecting the right ones means knowing when to descend the hierarchy and when a name pattern is lying to you.
Intermediate16 min readtcledapart-iicellshierarchyattributescollections
Part II · Module 18 · Chapter 18.5 · Querying Cells
A cell is an instance — one use of a library component or a sub-block. A design is a hierarchy of them, and most analysis starts by selecting some.
Two decisions make a cell query right or wrong: how far down the hierarchy to look, and whether to select by name or by what the cell actually is.
1. The current level
get_cells * size 2 u_fifo u_aluTwo cells. This design has seven, and the other five are inside those two.
Without -hierarchical, a cell query returns the instances at the current level — the blocks the design is immediately made of. That is often exactly what you want: a report of the major blocks, or something applied per sub-block.
2. Descending the hierarchy
get_cells -hierarchical * size 7 u_fifo u_alu u_fifo/u_ctrl u_fifo/u_ram u_fifo/u_decode u_alu/u_add u_alu/u_acc_reg
get_cells -hierarchical *fifo* size 4 u_fifo u_fifo/u_ctrl u_fifo/u_ram u_fifo/u_decode-hierarchical searches the whole tree. Seven cells instead of two.
The second line is worth reading carefully. *fifo* matched four things: u_fifo itself, and its three children — because the children's full names all begin u_fifo/, so they contain fifo too.
Unlike pins (Chapter 18.4 §2), omitting -hierarchical here is a real choice rather than a mistake:
| You want | Use |
|---|---|
| the blocks this design is made of | get_cells * |
| every instance anywhere | get_cells -hierarchical * |
| one specific block | get_cells u_fifo |
| everything inside one block | get_cells -hierarchical u_fifo/* |
3. Cells have a reference and a type
Two attributes you will use constantly:
ref_name— which library cell or module this is an instance of. Many instances share oneref_name.is_sequential— whether it holds state.
The first is how you find every instance of a particular library cell; the second is §4.
4. Sequential or combinational: never by name
The registry's purpose asks you to distinguish sequential from combinational cells. Here is why that has to be done with an attribute.
show {by name -hierarchical *reg*} [get_cells -hierarchical *reg*]
show {by attribute is_sequential==true} [filter_collection [get_cells -hierarchical *] "is_sequential == true"] sequential cells by NAME vs by ATTRIBUTE:
by name -hierarchical *reg* size 1 u_alu/u_acc_reg
by attribute is_sequential==true size 4 u_fifo u_fifo/u_ctrl u_fifo/u_ram u_alu/u_acc_regThe correct form:
set all [get_cells -hierarchical *]
set seq [filter_collection $all "is_sequential == true"]
set comb [filter_collection $all "is_sequential != true"]
puts " [sizeof_collection $seq] sequential, [sizeof_collection $comb] combinational"Chapter 18.7 is about filter_collection properly.
5. When a name pattern is right
Not every name pattern is a mistake. Use one when the name genuinely is the thing you mean:
- A specific instance you know by name —
get_cells u_fifo. - Everything under one block —
get_cells -hierarchical u_fifo/*. The hierarchy path is structural, not a guess about function. - A generated naming scheme you control, where the convention is guaranteed because your own script or generator produced it.
The rule: a path is structure, a suffix is a convention. Trust structure; verify conventions.
6. Two reports you will write
Almost every cell query ends up inside one of these two shapes.
Per block — how big is each part of the design, and how much of it holds state:
foreach_in_collection blk [get_cells *] {
set inside [get_cells -hierarchical "$blk/*"]
set seq [filter_collection $inside "is_sequential == true"]
puts [format " %-10s %2d cells, %d sequential" \
$blk [sizeof_collection $inside] [sizeof_collection $seq]]
}=== a per-block report: the shape you will write most often ===
u_fifo 3 cells, 2 sequential
u_alu 2 cells, 1 sequentialNote the inner query: "$blk/*" builds the pattern from the block name, so the loop works for however many blocks the design has. It is quoted rather than braced because $blk must be substituted — the Chapter 2.9 rule.
Per library cell — which components is this design actually built from:
array set tally {}
foreach_in_collection c [get_cells -hierarchical *] {
set r [get_attribute $c ref_name]
incr tally($r)
}
foreach r [lsort [array names tally]] {
puts [format " %-8s %d" $r $tally($r)]
}=== counting instances per library cell (ref_name) ===
ADD16 1
ALU16 1
AND2 1
DFF 2
FIFO32 1
RAM8 1That second one is almost pure Part I — an array as a tally, incr on a missing key creating it, lsort on the key list, and format to line the columns up. The only tool commands are the query and get_attribute.
It is also the Chapter 16.4 §6 structure in miniature: gather at the edge, count in standard Tcl.
7. Checking the result
Every cell query deserves the same scepticism as every other:
set cells [get_cells -hierarchical u_fifo/*]
if {[sizeof_collection $cells] == 0} {
error "no cells under 'u_fifo' — check the instance name" {} {DESIGN NOCELLS}
}And when the count is surprising, two questions in order:
- Is
-hierarchicalright? Two instead of two thousand usually means it is missing. - Is the pattern matching the full path? Four instead of one usually means
*fifo*caught the children as well as the block.
Both are more likely than the design being wrong.
8. Exercises
Exercise 1. What does get_cells * return on a design whose top level has three blocks?
Exercise 2. get_cells -hierarchical *fifo* returned four cells for one block. Why?
Exercise 3. How do you select only the instances directly inside u_fifo?
Exercise 4. Why did *reg* find one sequential cell out of four?
Exercise 5. Give a case where a name pattern matches a cell that is not sequential.
Exercise 6. When is a name pattern a legitimate way to select cells?
Exercise 7. A cell query returns 2 and you expected thousands. What do you check first?
Where this fits
Part of the Tcl curriculum.
