Procedures and scope

The cards come in more than one shape: a command to explain, a snippet with a fault to find, and a description whose command you name. A missed card returns later in the round and starts the schedule over. A card answered correctly moves up the schedule and next appears after 1, 3, 7, then 21 days. Keys 1 to 4 choose an option, h shows a hint, and Enter moves on. A hint keeps the card where it is on the schedule. An ordering card is answered by clicking its items in order, and one wrong click ends it. Time values are in nanoseconds. Progress is stored in this browser.

SourceTCL (Tool Command Language) is the scripting language every place-and-route and timing tool embeds, so the same skills carry between them. These cards follow the official Tcl manual pages, and each answer links to the page for that command. The examples are in the style the OpenROAD-flow-scripts scripts use, since that is Tcl written for a real flow. Reference: the Tcl manual (Tcl on GitHub).
All 8 cards in this section, with answers
  • proc report_stage {stage {verbose 0}} { puts "stage $stage" if { $verbose } { report_design_area } }
    Defines a command whose second argument is optional, defaulting to 0.

    Hint: Read the second parameter: it is written differently from the first.

    A parameter written as a two-element list gives a default. The special name args collects any remaining arguments into a list, which is how a wrapper passes options through to the command it wraps. Tcl reference

  • proc count_cell {} { global cell_count incr cell_count }
    Makes the global variable visible inside the procedure.

    Hint: Ask what a procedure can see by default.

    A procedure's variables are local unless declared otherwise, so a script that sets a variable at the top level and expects a procedure to see it is a common bug. upvar links to a caller's variable by name, which is how a procedure modifies a variable passed to it. Tcl reference

  • proc add_to {listVar item} { upvar 1 $listVar l lappend l $item }
    Links the caller's variable to a local name, so changes reach the caller.

    Hint: The procedure is given a variable's name rather than its value.

    Tcl passes arguments by value, so modifying a list means passing its name and linking to it. The 1 is how many levels up to look, almost always the immediate caller. uplevel is the same idea for running a script in the caller's scope. Tcl reference

  • proc report {stage args} { puts "$stage: $args" } report place -verbose -limit 10
    Whatever is left over arrives as a list in the final parameter.

    Hint: The last parameter has a name the language treats specially.

    This is how a wrapper passes options through to the command it calls, usually with {*}$args so the list is expanded back into separate arguments rather than passed as one. It is the standard way to wrap a tool command and add a default. Tcl reference

  • proc worst {slacks} { lindex [lsort -real $slacks] 0 }
    The value of the last command is returned.

    Hint: There is no return statement, and yet the procedure is useful.

    An explicit return is still clearer, and it is needed to leave early or to return something other than the last value. Its option form sets the code as well, so return -code error raises an error the caller can catch, exactly as error does. Tcl reference

  • namespace eval flow { variable count 0 proc reset {} { variable count; set count 0 } } flow::reset
    A named scope for procedures and variables.

    Hint: Ask what would happen if the procedure were called `reset` at the top level.

    A tool's interpreter already holds hundreds of commands, and a procedure named the same as one of them replaces it silently for the rest of the session. Namespacing a script's own procedures is the way to stay clear of that, and variable is how a procedure reaches the namespace's data. Tcl reference

  • set count 0 proc bump {} { incr count }
    The procedure has its own scope, so it does not see that variable.

    Hint: Ask which variable the procedure is reaching for.

    A procedure sees only its own variables and those it names with global, variable, or upvar. As written it fails, since there is no local variable to increment. The clearer fix in a tool script is often to pass the value in and return the new one. Tcl reference

  • Your procedure is given the name of a variable belonging to its caller, and it has to change that variable rather than a copy.
    upvar 1 $varName local

    Hint: The procedure needs a local name that stands for the caller's variable.

    Linking the names makes every later use of the local name act on the caller's variable. Declaring it global reaches the top level instead, which is wrong when the caller is another procedure, and assigning through the name only works if the variable happens to be visible. Tcl reference