Skip to content
VLSI Mentor

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

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach {cat n} [report_drc] {
    puts [format "    %-10s %3d" $cat $n]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    short        0
    open         0
    spacing      3
    min_area    12
    antenna      0

Five 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    short        1
    open         0
    spacing      0
    min_area    14
    antenna      0

Same 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

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== 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: 0

Fifteen 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 -glob search on untrusted names is a silent mismatch waiting to happen — the hazard Chapter 5.5 is about.
  • {*}$f expands the {category count} pair into format's two arguments. Without it, format receives one argument that happens to look like a list.
  • Errors on stderr, the decision on stdout. 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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.rpt

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