sed Part IV · Module 11 · Synthesis and STA Automation
SDC and Timing-Corner Migrations
Chapter 11.1 moved paths. This moves a name, and a name is the harder case — because once a string has been in a flow for a while, it stops being only a name. A timing corner called ss_0p72v_125c is a corner, and it is also part of the filename of every report generated at that corner, and it is also inside the filename of the vendor library characterised at that corner. Thirteen identical characters, three completely different kinds of thing, and a global rename changes all three. Two of those changes are what you wanted. The third points your flow at a library file that does not exist.
Advanced19 min readsedPart IVSTASDCTiming Corners
Part IV · Module 11 · Chapter 11.2 · SDC and Timing-Corner Migrations
1. The Migration
A corner changes: ss_0p72v_125c becomes ss_0p70v_125c. The voltage dropped; the temperature did not. Somebody has to update the signoff scripts.
cat -n sta/corners.tcl 1 read_sdc constraints/v1/top.sdc
2 read_sdc constraints/v1/scan.sdc
3 set_operating_conditions -analysis_type on_chip_variation ss_0p72v_125c
4 report_timing -corner ss_0p72v_125c -max_paths 10 > reports/ss_0p72v_125c.rpt
5 # ss_0p72v_125c is also referenced in the READMEcat -n synth/pt.tcl 1 set link_library "* /libs/v1/db/sc_ss_0p72v_125c.db"
2 read_sdc constraints/v1/top.sdc
3 set corner ss_0p72v_125c
4 report_timing -corner ss_0p72v_125c > reports/ss_0p72v_125c.rptTwo files, two migrations tangled together — the corner rename, and a constraints-directory bump from v1 to v2 that happens to live in the same lines. The chapter does them separately, because they are separate decisions.
2. The Procedure
1. LOCATE which files and lines mention the corner?
2. CENSUS what CONTEXTS does the string appear in? ← the step that matters
3. DECIDE which contexts should change
4. DRY RUN one substitution per decision
5. PARSE tclsh with the tool commands stubbed
6. VERIFY per context, not globallyStep 2 is the one this chapter exists for.
3. Step 2 — Census the Contexts, Not Just the Files
Finding the files is the obvious step and the easy one:
grep -rn 'ss_0p72v_125c' sta/ synth/sta/corners.tcl:3:set_operating_conditions -analysis_type on_chip_variation ss_0p72v_125c
sta/corners.tcl:4:report_timing -corner ss_0p72v_125c -max_paths 10 > reports/ss_0p72v_125c.rpt
sta/corners.tcl:5:# ss_0p72v_125c is also referenced in the README
synth/pt.tcl:1:set link_library "* /libs/v1/db/sc_ss_0p72v_125c.db"
synth/pt.tcl:3:set corner ss_0p72v_125c
synth/pt.tcl:4:report_timing -corner ss_0p72v_125c > reports/ss_0p72v_125c.rptSix lines, two files, eight occurrences. Now the step that is not obvious — ask what larger strings contain it:
grep -roh '[-_/a-z0-9.]*ss_0p72v_125c[-_/a-z0-9.]*' sta/ synth/ | sort | uniq -c 1 /libs/v1/db/sc_ss_0p72v_125c.db
2 reports/ss_0p72v_125c.rpt
5 ss_0p72v_125cThree different kinds of thing. The bracket expression grabs the surrounding path and filename characters, so each occurrence is reported with its context rather than bare.
- Five bare occurrences — the corner name itself, as an argument to
set_operating_conditions,report_timing -corner,set corner, and once in a comment. These are the migration. - Two report filenames —
reports/ss_0p72v_125c.rpt. Output files named after the corner. Renaming these is almost certainly right: reports from the new corner should not be written into the old corner's filename. - One library filename —
/libs/v1/db/sc_ss_0p72v_125c.db. This is not a name you control. It is a vendor file sitting on disk, characterised at 0.72 V, and it is still called that.
4. Step 3 and 4 — One Substitution Per Decision
Three contexts, three decisions, and the right command names each one.
The corner name itself, excluding the library line. The simplest scope is to leave set link_library alone:
sed '/^set link_library/!s/ss_0p72v_125c/ss_0p70v_125c/g' synth/pt.tclset link_library "* /libs/v1/db/sc_ss_0p72v_125c.db"
read_sdc constraints/v1/top.sdc
set corner ss_0p70v_125c
report_timing -corner ss_0p70v_125c > reports/ss_0p70v_125c.rptThe negated address from Chapter 4.4 — "on lines that are not the link library, rename". Line 1 is untouched and still names the file that exists.
On the STA script, where there is no library line, the global rename is right:
sed 's/ss_0p72v_125c/ss_0p70v_125c/g' sta/corners.tclread_sdc constraints/v1/top.sdc
read_sdc constraints/v1/scan.sdc
set_operating_conditions -analysis_type on_chip_variation ss_0p70v_125c
report_timing -corner ss_0p70v_125c -max_paths 10 > reports/ss_0p70v_125c.rpt
# ss_0p70v_125c is also referenced in the READMENote line 5. The comment now says the new corner is referenced in the README — which is true only once somebody updates the README. Unlike Chapter 11.1's comment, this one is not inverted into a falsehood; it has become a claim about work not yet done. Worth leaving as a reminder, or worth updating; either way it is a human's call, and the rename made it without asking.
5. The Other Migration in the Same Lines
The constraints directory bump is a separate change that happens to live in the same files:
sed -n '/read_sdc/s|constraints/v1/|constraints/v2/|p' sta/corners.tclread_sdc constraints/v2/top.sdc
read_sdc constraints/v2/scan.sdcTwo lines, scoped to read_sdc so a v1 appearing anywhere else — in the library path on pt.tcl line 1, for instance — is not caught.
Keeping it separate matters for a reason beyond tidiness: a corner change and a constraints-version change are approved by different people on different schedules. One command that does both produces a diff nobody can review for one of them, and cannot be reverted independently.
6. Step 6 — Verify Per Context
The registered verification expects the corner name to be gone:
grep -rn 'ss_0p72v_125c' sta/ || echo 'no stale corner references'Run against sta/ before any edit it finds the three lines, as it should. After the migration it should print the message.
But run the same check over synth/ and it will find the library filename — correctly, because you deliberately left it. Continuing Chapter 11.1's point: write the check per context.
grep -rn 'ss_0p72v_125c' sta/ expect NOTHING
grep -rn 'ss_0p72v_125c' synth/ expect exactly the .db line
grep -rn 'sc_ss_0p70v_125c' synth/ expect NOTHING — the wrong rename
ls /libs/v1/db/sc_ss_0p72v_125c.db expect the file to existThe third is the one worth adding to a script. It asserts the absence of the specific mistake this chapter is about, which is a stronger check than asserting the absence of the old name — and it costs nothing.
The fourth is the only one that leaves the text and asks the filesystem. A reference to a library is a claim that a file exists, and Chapter 9.1 made the same point about filelists: sed guarantees the text, never the filesystem.
7. Step 5 — Parse-Check
As in Chapter 11.1, a signoff script is Tcl, so the syntax is checkable even though the tool is not here:
echo 'source stubs.tcl; source sta/corners.tcl; puts PARSE-OK' | tclshPARSE-OKwith the tool commands stubbed:
cat stubs.tclforeach c {set_operating_conditions report_timing read_sdc read_verilog compile_ultra} {
proc $c args {}
}The same caveats apply and are worth repeating because they bound the claim: this proves the file is valid Tcl after the edit, not that the corner exists, the library loads, or the timing is signed off. Read the PARSE-OK marker rather than $?, because the pipeline's status is the last stage's.
8. Think It Through
1. What does the context census show that a file list does not?
What kind of thing each occurrence is. grep -rn found six lines in two files; the census showed those occurrences were three different things — a corner name, a report filename, and a vendor library filename — and that only two of them should change. The file list tells you where to look; the census tells you what you are looking at.
2. Why do word boundaries not solve this?
Because the problem is containment, not adjacency. [[:<:]]ss_0p72v_125c[[:>:]] still matches inside sc_ss_0p72v_125c.db, since the corner name sits between an underscore and a dot. Chapter 9.2's tool separates an identifier from a longer identifier; here the corner is genuinely part of a filename, and no pattern can know that the filename belongs to a vendor.
3. Your migration ran cleanly and the tool reports it cannot open a library. What happened?
The rename reached a .db filename. The library is named after the corner it was characterised at and still exists under the old name — section 3 measured the global rename producing sc_ss_0p70v_125c.db. Exclude the link_library line, then ls the path to confirm the file is really there.
4. Write a check that asserts the absence of this specific mistake.
grep -rn 'sc_ss_0p70v_125c' synth/ && echo 'ERROR: library filename was renamed' && exit 1. It looks for the wrong result rather than the absence of the old one, which is a sharper assertion — the old name is supposed to survive in that one place, so "no old name anywhere" would be the wrong test.
5. Why keep the corner rename and the constraints-version bump as separate commands?
Because they are separate decisions with separate approvals and separate revert paths. Combined, the diff cannot be reviewed for one of them independently, and backing out the constraints change means hand-editing around the corner change. The files overlapping is a coincidence of layout, not a reason to combine the edits.
6. The comment on line 5 now names the new corner. Is that right?
It is a claim about work that has not happened — the README still says the old name. That is different from Chapter 11.1's comment, which the rewrite made flatly false. Either update the README or revert the comment; what you should not do is leave it as an unnoticed side effect of a substitution.
9. Summary
- A long-lived name stops being only a name. One corner string was a corner, a report filename, and a vendor library filename.
- Census the contexts, not just the files:
grep -roh '[-_/a-z0-9.]*NAME[-_/a-z0-9.]*' … | sort | uniq -creturned three distinct contexts and their counts. - The library filename is the trap. A global rename produced
sc_ss_0p70v_125c.db, a file the vendor never shipped — textually uniform, and the flow cannot load its library. - Word boundaries do not help, because the corner is contained in a filename rather than adjacent to another identifier.
- Exclude the library line with a negated address:
/^set link_library/!s/old/new/g. - Keep the constraints-version bump separate — different decision, different approval, independent revert.
- Verify per context: nothing stale in
sta/, exactly the.dbline surviving insynth/, and — the sharpest check — nothing matching the wrongly-renamed library name. - Ask the filesystem too. A library reference is a claim that a file exists;
lsit. - tclsh gives
PARSE-OKfor syntax only, and the marker is the signal rather than$?.
Scripts tell the tools what to do. The last artifact in this module is what the tools hand back — a timing report, which is long, column-aligned for human eyes, and the input to every "did it meet timing" question anyone will ask. Chapter 11.3 — Timing Report Extraction and Cleanup pulls one section out of it and makes it machine-readable, then stops and hands the arithmetic to awk.
Where this fits
Part of the sed curriculum.
