sed Part IV · Module 11 · Synthesis and STA Automation
Synthesis Tcl and Library-Path Updates
Module 10 covered simulation; this one covers implementation, and it starts with the edit every synthesis team makes on a schedule: a new standard-cell library release, and a setup script that has to point at it. The script looks like it contains one thing repeated — a path under a library root — and it does not. It contains a search path, a link library, a target library, a sourced setup file and a comment, all mentioning the same root for different reasons, and they do not all move at the same time. The chapter also introduces an oracle this track has not had since Module 9: a synthesis script is Tcl, and tclsh can tell you whether your edit broke it.
Intermediate19 min readsedPart IVSynthesisTclLibrary Paths
Part IV · Module 11 · Chapter 11.1 · Synthesis Tcl and Library-Path Updates
1. The Script
cat -n synth/dc.tcl 1 # Design Compiler setup
2 set search_path ". /libs/v1/db /libs/v1/mw"
3 set link_library "* /libs/v1/db/sc_tt_1v0_25c.db"
4 set target_library "/libs/v1/db/sc_tt_1v0_25c.db"
5 source /libs/v1/setup/common.tcl
6 # NOTE: /libs/v1 is the frozen release — see ECO-4471
7 read_verilog rtl/alu.v
8 compile_ultra/libs/v1 appears six times on five lines, and it means five different things: a search path (twice, on one line), a link library, a target library, a sourced setup file, and a sentence in a comment.
A library release bump is not "replace /libs/v1 with /libs/v2". It is a set of decisions about which of those five should move, and the chapter is about writing that set down.
2. The Procedure
1. AUDIT which settings exist, and what do they point at?
2. COUNT occurrences, not just lines — this decides /g
3. DECIDE which settings move, one substitution each
4. DRY RUN scoped, per setting
5. PARSE tclsh with the tool commands stubbed
6. VERIFY nothing stale, and the comment still tells the truth3. Step 1 — Audit, and the Difference Between Lines and Occurrences
The registered audit lists what is actually set:
sed -n -E '/^set (link|target)_library/p' synth/*.tclset link_library "* /libs/v1/db/sc_tt_1v0_25c.db"
set target_library "/libs/v1/db/sc_tt_1v0_25c.db"
set link_library "* /libs/v1/db/sc_ss_0p72v_125c.db"Three settings across two files — and note the third, in pt.tcl, names a different library. The glob found a file you might not have edited.
Now the root:
grep -oh '/libs/v[0-9]*' synth/*.tcl | sort | uniq -c 7 /libs/v1Seven occurrences, and only one version root, so this is a single migration rather than a tangle. Per file:
grep -c '/libs/v1' synth/*.tclsynth/dc.tcl:5
synth/pt.tcl:1Five plus one is six, not seven. That gap is the most useful thing in the audit: grep -c counts lines, grep -oh | wc counts occurrences, and the difference means some line contains the string twice. Here it is line 2, the search path.
When those two numbers differ, you need /g somewhere. Section 4 is what happens if you miss it.
4. Step 3 — One Substitution Per Setting
The registered commands scope each rewrite to the line that owns it.
The target library, which is a single path:
sed -n '/^set target_library/s|/libs/v1/|/libs/v2/|p' synth/dc.tclset target_library "/libs/v2/db/sc_tt_1v0_25c.db"One occurrence on the line, so no /g is needed and the command says so.
The search path, which is not:
sed -n '/search_path/s|/libs/v1|/libs/v2|gp' synth/dc.tclset search_path ". /libs/v2/db /libs/v2/mw"Both directories moved. Now the same command without /g:
sed -n '/search_path/s|/libs/v1|/libs/v2|p' synth/dc.tclset search_path ". /libs/v2/db /libs/v1/mw"5. What File-Wide Would Also Change
The tempting one-liner:
sed 's|/libs/v1|/libs/v2|g' synth/dc.tcl# Design Compiler setup
set search_path ". /libs/v2/db /libs/v2/mw"
set link_library "* /libs/v2/db/sc_tt_1v0_25c.db"
set target_library "/libs/v2/db/sc_tt_1v0_25c.db"
source /libs/v2/setup/common.tcl
# NOTE: /libs/v2 is the frozen release — see ECO-4471
read_verilog rtl/alu.v
compile_ultraThe three library settings are right. Two other lines changed, and both are decisions somebody should have made deliberately.
Line 5, the sourced setup file. source /libs/v2/setup/common.tcl assumes the new release ships a setup/common.tcl at the same path, with compatible contents. Often true; not automatic. If the new release reorganised its setup directory, this line now sources a file that does not exist, and the run fails at line 5 with an error about a missing file rather than anything to do with libraries.
Line 6, the comment. It now reads "/libs/v2 is the frozen release — see ECO-4471", which is false. v1 was the frozen release; that is why the note existed. Chapter 9.3 ranked a rewritten comment as the mildest silent boundary, and this is the case where that ranking is too generous: the sentence makes a factual claim, and the substitution inverted it while leaving the ECO reference pointing at a document that says the opposite.
The scoped alternative states the decision instead:
sed -e '/^set search_path/s|/libs/v1|/libs/v2|g' \
-e '/^set link_library/s|/libs/v1|/libs/v2|' \
-e '/^set target_library/s|/libs/v1|/libs/v2|' synth/dc.tclThree commands, three settings, and anything not named is left alone — including the comment, which a human should update by hand because only a human knows what it should now say.
6. Step 5 — Parse-Check With tclsh
A synthesis script is Tcl. That is not a metaphor: dc_shell embeds a Tcl interpreter, and the file follows Tcl's quoting and word-splitting rules. So a plain tclsh can answer one useful question — did my edit break the syntax? — provided the tool-specific commands are stubbed out.
cat stubs.tclforeach c {set_operating_conditions report_timing read_sdc read_verilog compile_ultra} {
proc $c args {}
}Each EDA command becomes a procedure that accepts anything and does nothing. Then source the real script:
echo 'source stubs.tcl; source sta/corners.tcl; puts PARSE-OK' | tclshPARSE-OKAnd the oracle has to be able to fail, or it is worthless. Here is a sed edit that damages the quoting — dropping the opening quote of a set value:
sed 's|"\* /libs/v1|* /libs/v1|' synth/pt.tcl | sed -n '1p'set link_library * /libs/v1/db/sc_ss_0p72v_125c.db"echo 'source stubs.tcl; source /tmp/m11bad.tcl; puts PARSE-OK' | tclshwrong # args: should be "set varName ?newValue?"No PARSE-OK. Tcl word-splitting now sees set with four arguments instead of two. The correct edit still passes:
sed 's|/libs/v1|/libs/v2|g' synth/pt.tcl | sed -n '1p'set link_library "* /libs/v2/db/sc_ss_0p72v_125c.db"PARSE-OK7. Step 6 — Verify
sed -e '/^set search_path/s|/libs/v1|/libs/v2|g' \
-e '/^set link_library/s|/libs/v1|/libs/v2|' \
-e '/^set target_library/s|/libs/v1|/libs/v2|' synth/dc.tcl | grep -n '/libs/v1'5:source /libs/v1/setup/common.tcl
6:# NOTE: /libs/v1 is the frozen release — see ECO-4471Two hits, and both are correct. The expected result of this verification is not "nothing".
Line 5 is a decision still to be made — does the new release ship setup/common.tcl at the same path? — and line 6 is a sentence only a human can rewrite. The scoped command left both precisely because neither is a path swap.
That is worth stating as a general point: the verification should encode what you intended, not what is convenient to check. "No occurrences remain" is the right assertion for Chapter 9.1's filelist and the wrong one here; here it is "two remain, and here is why each one does".
That is worth stating as a general point: the verification should encode what you intended, not what is convenient to check. "No occurrences remain" is the right assertion for Chapter 9.1's filelist and the wrong one here.
8. Think It Through
1. grep -c says 5 and grep -oh | wc -l says 6. What does that tell you?
That one line contains the string twice, so a substitution without /g will leave one behind. Section 4 measured exactly that: the search path came out as . /libs/v2/db /libs/v1/mw. Compare the two counts before writing the command.
2. Why is a half-updated search_path particularly dangerous?
Because it is valid. The tool starts, resolves most references against the new release and the rest against the old one, and completes successfully with a netlist built from two library versions. There is no error to find — only results that are subtly wrong in a way that surfaces much later.
3. The file-wide rewrite changed a comment. Why is this case worse than Chapter 9.3's?
Because the comment asserts a fact. "/libs/v1 is the frozen release — see ECO-4471" became "/libs/v2 is the frozen release", which is the opposite of the truth and now contradicts the ECO it cites. A rewritten comment that merely names a signal is stale; one that states a policy is misinformation.
4. What can tclsh tell you about an edited synthesis script, and what can it not?
It can tell you the file is still valid Tcl — balanced quotes and braces, commands with the right shape. It cannot tell you the paths exist, the libraries are compatible, or the result is correct. It is a syntax gate, not a correctness gate, and it is worth running because syntax damage is exactly what a bad substitution causes.
5. Why read PARSE-OK rather than $??
Because the check runs as a pipeline, and a pipeline's exit status is the last command's — Chapter 8.1 measured a failed stage reporting success. A marker printed only when the source completed is unambiguous. If you want a status instead, run tclsh script.tcl directly rather than piping into it.
6. After a correct scoped edit, grep -n '/libs/v1' returns two hits. Pass or fail?
Pass, if they are the two you deliberately left — the source line, which needs a decision about the new release's layout, and the comment, which needs a human sentence. The verification has to encode the intention: here the expected count is two, not zero. Writing the check as "expect nothing" makes a correct edit look broken and trains you to ignore the check.
9. Summary
- A synthesis script mentions one library root for several different reasons — search path, link library, target library, a sourced setup file, a comment — and they do not all move together.
- Audit with the registered command: three library settings across two files, including one in a file you might not have opened.
- Count occurrences, not lines. Five lines and six occurrences means one line has two, and that line needs
/g. - Without
/gthe search path came out half-updated —. /libs/v2/db /libs/v1/mw— which is valid, runs, and silently mixes two library releases. - One substitution per setting, each scoped to its own
setline. The file-wide version also rewrote asourceline and a comment. - The comment case is worse than usual here: it asserted which release was frozen, and the rewrite inverted the claim while leaving the ECO reference intact.
- tclsh is a real oracle for the syntax. With EDA commands stubbed, a correct edit prints
PARSE-OK; a broken quote giveswrong # args: should be "set varName ?newValue?"and no marker. - Read the marker, not
$?— a pipeline reports the last stage's status. - Verify what you intended. After the scoped edit, two hits remain — the
sourceline and the comment — and both are correct. "Expect nothing" is the wrong assertion here.
A library bump moves paths. The other recurring implementation migration moves a name — a timing corner, which appears in constraints, in report filenames, and, inconveniently, inside the filename of the library characterised at that corner. Chapter 11.2 — SDC and Timing-Corner Migrations is that, and it has a trap this chapter's paths do not.
Where this fits
Part of the sed curriculum.
