Tcl · Module 23
Routing and DRC Reports
Everything so far in Part II has been a threshold. Design-rule checking is not a threshold domain: some categories must be empty, not small, and a total count hides which is which.
Advanced18 min readtcledapart-iiphysical-designroutingdrcsignoff
Part II · Module 23 · Chapter 23.5 · Routing and DRC Reports
Routing connects everything the netlist says is connected, on real metal, obeying the rules the foundry gave for that process. Then design-rule checking asks whether it actually did.
This chapter is about reading that answer, and it contains the one idea in Module 23 that does not reduce to a threshold.
1. Did routing finish?
The first question is not about quality. It is whether routing completed.
So a routing script asks for the count of unrouted nets explicitly, and treats a non-zero answer as fatal rather than as information.
2. DRC by category
foreach {cat n} [report_drc] {
puts [format " %-10s %3d" $cat $n]
} short 0
open 0
spacing 3
min_area 12
antenna 0Five categories, representative rather than exhaustive — real rule decks have hundreds, with foundry-specific names. What they mean:
- short — two different nets connected by metal. The design is wrong.
- open — a net that should be connected is not. The design is wrong.
- spacing — two shapes closer than the rule allows. Manufacturable yield risk.
- min_area — a piece of metal smaller than the minimum printable area. Manufacturing risk.
- antenna — a long conductor accumulating charge during fabrication, which can damage a gate. Process risk.
The loop is plain foreach over pairs. The classification that follows is the chapter.
3. The total is the one number you cannot act on
Add the five numbers above and you get 15.
Now consider a different run that also totals 15:
short 1
open 0
spacing 0
min_area 14
antenna 0Same total. The first run is a waiver conversation and a few fixes. The second run has a short — two nets electrically joined that the netlist says are separate. That chip does not work. No amount of "only 15 violations, down from 400 last week" changes that.
So the summary line everyone reaches for first — the total — is the summary that destroys the distinction that matters.
4. Must be empty, not small
# Categories that must be ZERO, versus those a project may carry with a waiver.
set MUST_BE_ZERO {short open antenna}
proc check_drc {must_be_zero} {
set fatal {} ; set other {}
foreach {cat n} [report_drc] {
if {$n == 0} { continue }
if {[lsearch -exact $must_be_zero $cat] >= 0} { lappend fatal [list $cat $n] } \
else { lappend other [list $cat $n] }
}
foreach f $fatal { puts stderr [format " ERROR %s: %d — this category must be empty" {*}$f] }
foreach o $other { puts stderr [format " WARNING %s: %d — needs a waiver or a fix" {*}$o] }
if {[llength $fatal] == 0 && [llength $other] == 0} { puts " ok DRC clean" }
return [llength $fatal]
}Run it on the two sets from §3, and on a clean one:
=== a run with spacing and min_area violations ===
WARNING spacing: 3 — needs a waiver or a fix
WARNING min_area: 12 — needs a waiver or a fix
fatal categories: 0
=== the same total count, but one short ===
ERROR short: 1 — this category must be empty
WARNING min_area: 14 — needs a waiver or a fix
fatal categories: 1
=== clean ===
ok DRC clean
fatal categories: 0Fifteen violations in both of the first two runs. fatal categories: 0 and fatal categories: 1. That is the chapter in two lines of output.
The procedure returns the fatal category count, not the violation count — because one short and nine shorts are the same decision. Chapter 22.7 made the matching argument about timing violations from the other side: there, the count mattered because every violation was the same kind. Here the kinds differ, so the kind is what you count.
Three Part I details worth noticing in that procedure:
lsearch -exact, not-glob. Category names could contain glob metacharacters in a real rule deck, and a-globsearch on untrusted names is a silent mismatch waiting to happen — the hazard Chapter 5.5 is about.{*}$fexpands the{category count}pair intoformat's two arguments. Without it,formatreceives one argument that happens to look like a list.- Errors on
stderr, the decision onstdout. A log and a gate are different audiences, which is Chapter 15.4's separation.
5. Which categories go in the list
The split above is a project decision, not a Tcl one, and it belongs in a variable so it is visible and reviewable:
set MUST_BE_ZERO {short open antenna}short and open are connectivity. A netlist that was signed off describes certain connections; metal that does not implement them means the thing being fabricated is not the thing that was verified. There is no trade here.
antenna is in the list because the failure mode is a damaged gate, discovered after fabrication, with no electrical symptom until then.
spacing and min_area are left out not because they are harmless but because they are yield statistics rather than functional failures, and projects legitimately carry a documented count of them into tape-out with the foundry's agreement.
6. The routing gate
route_design
set unrouted [count_unrouted_nets]
if {$unrouted > 0} {
puts stderr " routing did not complete: $unrouted net(s) unrouted"
exit 1
}
set fatal [check_drc $MUST_BE_ZERO]
if {$fatal > 0} {
puts stderr " $fatal fatal DRC categor(ies) — not signable"
exit 1
}
update_timing
report_constraint -all_violators > reports/post_route_violations.rptcount_unrouted_nets, check_drc and report_constraint stand in for whatever your tool calls them; the names here are not a vendor's. The order is the argument: completeness, then legality, then timing. A timing report on a partially routed design is a description of a circuit nobody is going to build, and a timing report on a design with a short describes a circuit that would not work even if the timing were perfect.
And update_timing again, for Chapter 22.5's reason — routing replaced every estimated wire with a real one, so every number in the graph is stale.
7. What else to capture after routing
- Wire length per layer, which is where power and the extraction runtime come from.
- Via count, a yield and resistance concern.
- Post-route timing with extracted parasitics — the first timing numbers in the entire flow that are not estimates. Chapter 22.3 §4 is about the difference, and this is where it stops applying.
- LVS, which asks the question DRC does not: does the layout implement this netlist. DRC checks the rules; LVS checks the identity.
That last pair is worth holding onto. A design can be perfectly rule-clean and implement the wrong circuit.
8. Exercises
Exercise 1. Why is "did route_design return" not the same question as "did routing complete"?
Exercise 2. Two runs each report 15 violations. Why can that number not be acted on?
Exercise 3. Which of short, spacing, min_area, antenna must be zero, and why those?
Exercise 4. Why does check_drc return a count of fatal categories rather than fatal violations?
Exercise 5. Why lsearch -exact rather than -glob?
Exercise 6. What does {*}$f do in the format call?
Exercise 7. Why does the gate check completeness before legality, and legality before timing?
Exercise 8. What question does LVS answer that DRC does not?
Where this fits
Part of the Tcl curriculum.
