Tcl · Module 28
Partitioning the Flow
Four languages, one flow. The boundaries are decidable on criteria you can check rather than taste — and they are usually drawn wrongly in one of two specific directions.
Intermediate22 min readtcledapart-iiarchitecturepythonbash
Part II · Module 28 · Chapter 28.4 · Partitioning the Flow
Three chapters have each claimed a piece: the shell launches, Make decides what is stale, Python works over the results. This one is about why those are the right pieces, and what it looks like when they are not.
1. The partition
| Part of the flow | Language | Because |
|---|---|---|
| CI's entry point | shell | it sets the environment of a child process (28.1) |
| What is out of date | Make | it is a dependency graph over files (28.2) |
| Everything inside the tool session | Tcl | it is the only language in there (17.1) |
| Comparison across runs, aggregation, rendering | Python | the question is about several runs (28.3) |
The third row is not a preference and deserves saying plainly: inside a tool session there is no choice. The session's interpreter is Tcl, the design database is reachable only from it, and anything else has to generate Tcl and feed it in. That one constraint fixes the middle of the partition and leaves the edges to be argued about.
2. The criteria
Four questions, each with an answer you can check rather than debate.
Does it need the design database? If yes, it is Tcl, inside the session. There is no second option.
Does it span more than one run? If yes, it is outside — a session knows about one run (Chapter 28.3 §1).
Is it a dependency question over files? If yes, Make. "Is the netlist older than the SDC" is what Make exists for, and reimplementing it with [ a -nt b ] is a worse Make.
Does it need arithmetic on the flow's numbers? If yes, it is not the shell — and §3 is why that is a wall rather than a preference.
3. The shell cannot do the flow's arithmetic
=== can each language do the flow's arithmetic? ===
bash integer : 16388
bash float : bin/limits.sh: line 3: 1.5 + 2.5 : syntax error: invalid arithmetic operator (error token is ".5 + 2.5 ")
bash float : bin/limits.sh: line 4: 159268.01 - 158940.33 : syntax error: invalid arithmetic operator (error token is ".01 - 158940.33 ")
via bc : 327.68
tclsh : 327.6800000000221
python3 : 327.68000000002214. And the three languages disagree on one subtraction
Look again at the last three lines:
via bc : 327.68
tclsh : 327.6800000000221
python3 : 327.6800000000221Same subtraction, two different answers. And the one that looks wrong is the right one.
=== why bc's answer looks different ===
bc default scale : 327.68
bc scale=20 : 327.68
bc 1/3 (scale 0) : 0
bc 1/3 scale=10 : .3333333333
tcl 1.0/3.0 : 0.3333333333333333
python 1/3 : 0.3333333333333333
=== so the three disagree in different ways ===
bc : arbitrary-precision DECIMAL, truncated at 'scale'
tcl : IEEE 754 double
py : IEEE 754 double — identical to tcl, bit for bit
do tcl and python agree exactly? : yes (0.3333333333333333)5. Wrong direction one: too far right
The boundary pushed too far into the tool session. The symptom is a dashboard, a cross-run database, or an HTML generator living in Tcl.
It happens for a good reason: the data is right there, in a dict, already parsed. Adding thirty lines to format it as a table is obviously easier than writing a file and a second program.
What it costs, and the first three are from Chapter 28.3 §1:
- A sign-off licence is held while formatting a table.
- It cannot be tested without the tool, so it never is.
- It cannot answer a question about more than one run, which is most of the questions worth asking.
- And it grows. A table becomes a trend becomes a comparison becomes a page, each step a small addition to a file nobody meant to own, in a language with no library for any of it.
The tell is easy to check: does this code touch the design database? A procedure that only reads a dict the flow built is not doing tool work, and it is in the wrong place.
6. Wrong direction two: too far left
The boundary pushed out of the session, into the shell or Make. The symptom is awk parsing a report, grep | sed extracting a slack, a for loop over corners in bash, or arithmetic in bc.
This one also happens for a reason: the shell is where the person already is.
What it costs:
- No floating-point arithmetic (§3), so a third language arrives.
- No data structures. A list of scenarios with reasons attached (Chapter 26.4) is a dict in Tcl and a set of parallel arrays in bash 3.2 — which has no associative arrays at all.
- It throws away structure that already existed. The tool session had the slack as a number, in a dict, keyed by endpoint. Printing it to a report and extracting it with
awkis a round trip through text that loses the typing, the structure and the error handling, and gains Module 24's entire set of parsing hazards.
7. What belongs nowhere
Three things that look like they need a home and should not have one.
A second copy of the configuration. The shell wrapper knowing the library path and setup.tcl knowing it is Chapter 27.3 §1's copy-that-drifts. One owner, and the others receive it — via the environment, or an argument, or by reading the same file.
A language chosen for familiarity against a criterion. "I know Python better" is a real consideration for the parts §2 leaves open, and not for the parts it does not: no amount of Python fluency gets you inside a tool session, and no amount of shell fluency gets you floating-point arithmetic.
Glue between two glues. A shell script that calls Make which calls a shell script which calls Tcl has one layer too many, and the symptom is that nobody can say what runs when a stage fails. Four languages is already the maximum a flow can carry; the goal is a short path from CI to the tool, not a complete separation of concerns.
8. The partition as a review
- Does every piece of code touching the design database live in Tcl? It has to.
- Does anything outside the session do arithmetic on flow numbers? If it is the shell, it cannot; if it is
bc, check itsscale. - Is any number computed twice, in two languages? Compute once, pass the result.
- Does anything parse a report the same flow produced as data? That is pure loss.
- Does any Tcl in the session format output for humans? That belongs outside.
- Does the dependency logic live in Make, rather than in a shell
-nttest? - Is the configuration owned in one place, with the others receiving it?
- Can somebody say what runs when a stage fails, in one sentence? If not, there is a layer too many.
That last question closes Module 28 and, with it, the practical half of Part II. Everything from Module 21 onward has been one argument in different clothes: a flow is only as trustworthy as its ability to tell you what it actually did — which is why so much of it has been about exit statuses, provenance, denominators and second independent measurements rather than about the Tcl.
9. Exercises
Exercise 1. Which part of the partition is not a choice, and why?
Exercise 2. State the four criteria.
Exercise 3. What does 1.5 + 2.5 do in bash, and why does the error message mislead?
Exercise 4. Why is "no float arithmetic" a wall rather than a preference for an EDA flow?
Exercise 5. bc says 327.68 and Tcl says 327.6800000000221. Which is right, and why?
Exercise 6. Why does bc scale=20 give the same answer as the default?
Exercise 7. What does bc do with 1/3, and why is that a trap?
Exercise 8. Why do Tcl and Python agree bit for bit?
Exercise 9. State the rule about computing a quantity once.
Exercise 10. Give the tell for "too far right" — one question you can ask of a procedure.
Exercise 11. State the sharpest rule about the "too far left" direction, and the one legitimate exception.
Exercise 12. What is wrong with a shell script calling Make calling a shell script calling Tcl?
Where this fits
Part of the Tcl curriculum.
