Skip to content
VLSI Mentor

Tcl · Module 26

The Driver Loop

Walking the scenario list is a nested foreach. Making one scenario's failure harmless to the rest is the part that takes thought — and the obvious fix produces a confident wrong number.

Advanced22 min readtcledapart-iimcmmautomationerror-handling

Part II · Module 26 · Chapter 26.5 · The Driver Loop

Chapter 26.4 produced a list of scenarios. Walking it is three lines of Part I:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach s $scenarios {
    apply_mode   [dict get $s mode]
    apply_corner [dict get $s corner]
    report_timing [dict get $s check]
}

That loop is correct for a plan with no mistakes in it, and plans have mistakes in them. The rest of this chapter is about what the loop does when one scenario fails, which is the only interesting question it raises.

1. The plan with one typo

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
set PLAN {
    {functional ss_0p72v_125c}
    {functional tt_0p80v_25C}
    {functional ff_0p88v_m40c}
}

The middle entry ends in 25C rather than 25c. That is not a contrived defect — it is what a hand-maintained list acquires, and Chapter 26.3 argued that corner names are identifiers rather than data precisely so that a typo in one is a lookup failure rather than a silently different corner.

So the lookup fails. The question is what the loop does about it.

2. Shape A: no isolation at all

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach s $PLAN {
    apply_mode   [lindex $s 0]
    apply_corner [lindex $s 1]
    puts [format "%s %s worst setup %.4f" ... [worst_slack setup]]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== the same plan, but the failure is not caught at all ===
    functional    ss_0p72v_125c  worst setup -0.4800
    loop aborted: 1 / no such corner: tt_0p80v_25C
    scenarios completed: 1 of 3

One of three. The error propagates out of the foreach, the loop stops, and the two remaining scenarios — including ff_0p88v_m40c, which is a required hold-sign-off corner — never run.

This is bad, and it is the good failure mode. It is loud, it names the cause, it reports 1 of 3, and nobody can mistake the run for complete. In a nightly flow it costs a night. It does not cost correctness.

3. Shape B: catch, and carry on

The obvious fix is to catch the error so the loop survives:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach s $PLAN {
    set mode [lindex $s 0] ; set corner [lindex $s 1]
    catch { apply_mode $mode ; apply_corner $corner }
    puts [format "%-13s %-14s %9.4f" $mode $corner [worst_slack setup]]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== catching the error but reporting anyway ===
    MODE          CORNER             SLACK  NOTE
    functional    ss_0p72v_125c    -0.4800  session actually holds: functional ss_0p72v_125c
    functional    tt_0p80v_25C     -0.4800  session actually holds: functional ss_0p72v_125c
    functional    ff_0p88v_m40c     1.8980  session actually holds: functional ff_0p88v_m40c

This is the same shape as every central finding in Part II — Chapter 24.1 §7's truncated slack, Chapter 25.4 §2's failing test exiting 0, Chapter 25.5 §3's PASSED row pointing at a FAILED log. A correct mechanism, applied to state it did not establish, producing a confident number.

Note also what made the lie visible here: the loop printed session_state beside each row. A driver that reports what the session actually holds, rather than what the plan said it should hold, turns this defect from invisible into obvious — which is the cheapest possible instrumentation.

4. Shape C: reset first, then apply

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach s $PLAN {
    set mode [lindex $s 0] ; set corner [lindex $s 1]
    reset_session
    if {[catch { apply_mode $mode ; apply_corner $corner } e]} {
        puts [format "    %-13s %-14s %9s  SKIPPED: %s" $mode $corner "-" $e]
        continue
    }
    puts [format "    %-13s %-14s %9.4f" $mode $corner [worst_slack setup]]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== with reset_session first, the failure cannot produce a number ===
    MODE          CORNER             SLACK  NOTE
    functional    ss_0p72v_125c    -0.4800
    functional    tt_0p80v_25C           -  SKIPPED: no such corner: tt_0p80v_25C
    functional    ff_0p88v_m40c     1.8980

Two scenarios ran, one was skipped by name with its reason, and nothing produced a number it was not entitled to.

5. The production loop

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
proc run_scenarios {scenarios} {
    set results {} ; set failures 0
    foreach s $scenarios {
        set mode   [dict get $s mode]
        set corner [dict get $s corner]
        set check  [dict get $s check]

        reset_session
        if {[catch { apply_mode $mode ; apply_corner $corner } e]} {
            incr failures
            lappend results [dict merge $s [dict create status SETUP-FAILED reason $e worst ""]]
            puts stderr "  $mode / $corner / $check — setup failed: $e"
            continue
        }
        if {[catch { worst_slack $check } w]} {
            incr failures
            lappend results [dict merge $s [dict create status ANALYSIS-FAILED reason $w worst ""]]
            puts stderr "  $mode / $corner / $check — analysis failed: $w"
            continue
        }
        lappend results [dict merge $s [dict create status OK reason "" worst $w]]
    }
    return [list $results $failures]
}

Five decisions, each one a lesson from an earlier module.

reset_session first, per §4.

Setup failure and analysis failure are separate statuses. SETUP-FAILED means the scenario could not be established — a typo, a missing library, a mode that does not exist. ANALYSIS-FAILED means it was established and the analysis broke. Those go to different people, which is Chapter 25.4 §7's argument about distinct exit statuses applied to a results table.

Every scenario produces a row, including the failed ones. A results list with the failures missing is a list whose length no longer matches the plan — and Chapter 26.6 depends on being able to compare those two numbers.

dict merge $s ... keeps the scenario's own identity in the result rather than rebuilding it. The row is the scenario plus what happened to it, so nothing downstream has to re-derive which mode a number came from.

Errors go to stderr, results to the returned list. A log and a data structure are different audiences, per Chapter 15.4.

6. What catch does not isolate

Being honest, because §4 reads like a solution and in a real tool it is a partial one.

The mock's reset_session clears two variables. A real tool session accumulates far more, and the things that leak between scenarios are:

  • Constraints. set_false_path and set_multicycle_path from the previous mode do not vanish because you sourced a different SDC. Most tools need an explicit reset_design or equivalent, and some exceptions survive even that.
  • Derates and operating conditions. A set_timing_derate applied for one corner stays applied. This one is particularly nasty because it changes numbers without changing anything a report prints about the configuration.
  • The timing graph. Even with constraints replaced, the previously computed graph may be reused unless invalidated — Chapter 22.5's entire subject, arriving as a cross-scenario hazard rather than a within-scenario one.
  • The design database itself. If a scenario modified the netlist — an ECO, a sizing experiment — nothing in a constraint reset undoes that.

7. Exercises

Exercise 1. Why is a typo'd corner name a lookup failure rather than a different corner?

Exercise 2. Shape A aborts after 1 of 3. Why is that the good failure mode?

Exercise 3. Shape B reported −0.4800 for the typical corner. Trace exactly how.

Exercise 4. Why is shape B worse than shape A?

Exercise 5. Why is the mislabelled row particularly unlikely to be questioned?

Exercise 6. What made the lie visible in the §3 output?

Exercise 7. Why does the reset belong at the top of the iteration rather than after the failure?

Exercise 8. Why continue rather than letting a skipped scenario fall through?

Exercise 9. Why are SETUP-FAILED and ANALYSIS-FAILED separate statuses?

Exercise 10. Why does every scenario produce a row, including the failures?

Exercise 11. Name three things that leak between scenarios in one tool session.

Exercise 12. What is the only complete isolation, what does it cost, and what is the usual compromise?

Where this fits

Part of the Tcl curriculum.