Files, processes, and the environment
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.
All 10 cards in this section, with answers
-
set def_file $::env(RESULTS_DIR)/6_final.defReads an environment variable exported by the flow's makefile.
Hint: Ask where a make-driven flow puts the values its scripts need.
envis an array holding the process environment, here the variables the makefile exported; and::names the global namespace explicitly so it works inside a procedure too. This is exactly how OpenROAD-flow-scripts passes itsconfig.mkvariables into every Tcl stage script. Tcl reference -
set fh [open $report w] puts $fh "slack $slack" close $fhOpens the file for writing, writes a line to it, and closes the handle.
Hint: Note the extra argument to puts, and what open returns.
putswrites to standard output unless given a channel first. The mode isrto read,wto truncate and write, andato append. Forgettingclosecan leave the last buffered lines unwritten if the script exits abruptly. Tcl reference -
if { [file exists $odb] } { set stem [file rootname [file tail $odb]] }Tests the path exists, then strips the directory and extension.
Hint: One command, several jobs, chosen by the word after it.
file existsis the test andtailwithrootnamedoes the stripping.fileis an ensemble:taildrops the directory,dirnamekeeps it,rootnamedrops the extension,extensionkeeps it, andjoinbuilds a path.file existsbefore reading is the usual guard in a flow script. Tcl reference -
set n [exec grep -c "VIOLATED" $report]Runs the program and returns what it printed, as the command's result.
Hint: Ask where the output of the program goes.
A non-zero exit status raises an error, so
execis usually wrapped incatchwhen the program's failure is expected, asgrepfinding nothing is. Redirections and pipes can be written in the arguments. Tcl reference -
source $::env(SCRIPTS_DIR)/load.tclRuns the file's commands in the current scope, as if typed there.
Hint: Ask what scope the sourced file's commands and variables end up in.
Everything the file sets is visible afterwards, and a second
sourceruns it again. This is how the flow shares a common setup across stage scripts; it is also why a sourced file that sets a variable can surprise the script that sourced it. Tcl reference -
set fh [open $report r] while { [gets $fh line] >= 0 } { ... } close $fhThe line's length, which is negative only at the end of the file.
Hint: Ask what the command returns, given what the test compares it with.
An empty line has length zero, so testing for greater than or equal to zero is right and testing for greater than zero silently stops at the first blank line. Reading a whole file with
readis simpler but loads all of it, which matters on a large report. Tcl reference -
if { [catch { exec grep -c VIOLATED $rpt } out] } { set out 0 }A non-zero exit status raises an error, so it has to be caught.
Hint: The command finds nothing. Ask what that does to the script.
Anything the command writes to its error stream, and any non-zero status, becomes a Tcl error. That is why counting matches is wrapped like this, and why
2>@1or a redirect to a file appears in scripts that expect warnings from the command they run. Tcl reference -
set out [file join $::env(RESULTS_DIR) reports timing.rpt] file mkdir [file dirname $out]Builds a path correctly and creates the directories leading to it.
Hint: Ask what this avoids, compared with building the path with slashes.
Joining handles a trailing separator and an absolute component correctly, which string concatenation does not. Making a directory creates every missing level and does not complain when it is already there, so no test is needed first. Tcl reference
-
set reports [glob $dir/*.rpt]Matching nothing is an error, which stops the script.
Hint: Ask what happens on the run where the stage produced nothing.
The command raises an error when no file matches, which is right for a required file and wrong for an optional one. Adding
-nocomplainreturns an empty list instead. Unlike a shell, nothing else expands the pattern: it is matched by this command alone. Tcl reference -
You want to walk a very large report one line at a time, without holding the whole file in memory, and without an extra empty pass at the end.while { [gets $fh line] >= 0 } { ... }
Hint: One of these tests the wrong thing, and runs the body once too often.
The end of a file is only known once a read has failed, so testing for it first runs the body one extra time with a stale line. Reading the whole file and splitting it is correct but loads everything, which matters on a report of millions of lines. Tcl reference