awk Part I · Module 1 · Introduction to AWK
awk in Semiconductor Workflows
Chapter 1.1 showed what awk does to a line of text. This chapter shows where that gets used. A chip project runs tools that write text at every stage — a simulator leaves a log, a regression leaves a summary, timing and synthesis and coverage each leave a report — and awk is what turns that text into the few numbers a person acts on. The mechanics here stay deliberately small: a field comparison and a counter, both from 1.1. What is new is knowing what each kind of file represents, and therefore what the number you extracted actually licenses you to say. That second half is the part that separates a useful script from a confidently wrong one.
Foundation14 min readawkPart IFundamentalsLog AnalysisEDA Reports
Part I · Module 1 · Chapter 1.2 · awk in Semiconductor Workflows
1. Where awk Fits in a Semiconductor Project
A chip project is a sequence of tools, and almost every one of them writes text as a side effect of running. A simulator prints messages as the test proceeds. A synthesis tool writes a summary of what it built. A timing tool writes a report of the paths it analysed. None of that text is the tool's real output — the real output is a waveform database, a netlist, a timing model — but the text is the part a human reads to find out how it went.
That is the gap awk fills, and the flow is worth seeing as one picture before any commands.
Step 4 is the only place awk appears, and it is worth being blunt about the boundary. awk does not simulate the design, synthesise anything, analyse timing or measure coverage. It reads what the tool that did those things left behind. If the tool was configured wrongly, or never finished, awk will read the resulting text perfectly and tell you something untrue with complete confidence.
So the useful question for the rest of this chapter is not "how do I extract this value" — 1.1 already answered that — but "what does this file represent, and what does the value let me claim".
2. Simulation Logs
A simulation log is a running commentary. The simulator prints a line whenever something worth reporting happens, and in a UVM testbench those lines carry a severity — informational, a warning, an error, or a fatal that stops the run.
100 UVM_INFO Test started
250 UVM_WARNING Retry detected
420 UVM_ERROR Data mismatch
500 UVM_INFO Test finishedThree columns: a simulation time, a severity, and a message. The question an engineer asks first is whether anything went wrong, so print the error lines:
awk '/UVM_ERROR/ { print }' sim.log420 UVM_ERROR Data mismatchThat is the command from 1.1, and on this file it is correct. But now that we know the severity is always the second field, there is a more precise way to ask:
awk '$2 == "UVM_ERROR" { print }' sim.log420 UVM_ERROR Data mismatchSame answer. The two are not the same question, though, and it is worth seeing them disagree. Suppose a test prints an informational message that happens to mention the word:
100 UVM_INFO Test started
250 UVM_INFO Checking UVM_ERROR handling
420 UVM_ERROR Data mismatchawk '/UVM_ERROR/ { print }' tricky.log250 UVM_INFO Checking UVM_ERROR handling
420 UVM_ERROR Data mismatchawk '$2 == "UVM_ERROR" { print }' tricky.log420 UVM_ERROR Data mismatchThe first form asks "does this line contain the text anywhere", and a message body satisfies that. The second asks "is this line's severity exactly this", which is the question you meant. This is the first real payoff of fields over plain text matching: a field test can say where the text has to be.
3. Regression Results
A regression runs many tests and records how each one ended. The file below is a regression summary — something produced after the fact, either by the regression tool or by a script of your own, with one row per test.
test_a PASS
test_b FAIL
test_c PASS
test_d FAILThe two questions are which tests failed, and how many:
awk '$2 == "FAIL" { print $1 }' regression.txttest_b
test_dawk '$2 == "FAIL" { n++ } END { print n + 0 }' regression.txt2Both reuse exactly what 1.1 taught — a field comparison, and a counter printed after the last line. The + 0 matters on a clean run: if no test had failed, n would never have been created, and printing it alone gives an empty line rather than a zero.
The important thing about this file is what it is. This is not raw simulator output; it is a summary in a layout somebody chose. There is no universal regression-summary format, and asking awk to read one is only easy because a previous stage already reduced each run to one row.
4. Timing and STA Reports
Static timing analysis checks whether signals arrive in time, without simulating anything. It walks the paths through the design, adds up the delays, and compares when a signal actually arrives against when it was required to arrive.
Slack is that comparison expressed as one number: the difference between the required arrival time and the actual arrival time, under the particular timing check and analysis conditions that row represents. Positive slack means the signal arrived with time to spare. Negative slack means it arrived too late for that check — a violation.
path_a -0.12
path_b 0.08
path_c -0.05The violating rows are the negative ones:
awk '$2 < 0 { print }' timing.txtpath_a -0.12
path_c -0.05Two of the three paths fail their check. path_b has 0.08 ns of margin.
That is a genuinely useful thing to be able to do, and it needs three qualifications to stay true.
First, negative means a violation for the check that row represents — and only given that the row really is a slack figure and the analysis behind it was set up correctly. Slack is reported per check and per condition, so the same physical path appears more than once in a real report.
Second, not every negative number in a real timing report is slack. Reports carry delays, transition times, capacitances, required and actual arrival times, and skew. A command that prints every row with a negative second column against a real report will cheerfully print rows that are not slack at all.
Third, real timing reports are not two clean columns. The dominant layout is a block per path spanning many lines, with the startpoint, the endpoint, a delay table and the slack figure on separate lines. Splitting that on whitespace does not give you a row per path. Module 10 is about that structure, and it needs the execution model from Module 2 first.
None of that makes the two-column file artificial. A reduced table like this is a real and common intermediate artefact — often produced by the timing tool's own reporting commands rather than by text processing — so learning the filter against it is the right first move. The mistake to avoid is assuming a report arrives already in that shape.
5. Synthesis Reports
Synthesis turns RTL into a netlist of cells from a technology library. Its reports summarise what it built: how many cells, of which kinds, and various quality and resource figures.
DFF 120
AND 45
OR 30
MUX 18Pull out one category:
awk '$1 == "DFF" { print $2 }' cells.txt120Or total the counted column:
awk '{ total += $2 } END { print total }' cells.txt213213 is the sum of the numbers in the second column — a well-defined arithmetic result, and that is all it is.
6. Coverage Reports
Coverage answers a different kind of question: not "did it work" but "what did we actually exercise". A coverage tool instruments the design or the testbench, records which items were hit during simulation, and reports the result against the total it was tracking.
The column meanings matter more here than anywhere else in this chapter, so this file states them:
alu_decode 184 200
alu_flags 96 96
fifo_ctrl 41 75The useful beginner question is which scopes are not finished:
awk '$2 < $3 { print $1 }' coverage.txtalu_decode
fifo_ctrlThat compares two fields against each other rather than against a constant, which is the only new mechanical idea in this section. The complement — scopes where every tracked bin was hit — is the same test the other way round:
awk '$2 == $3 { print $1 }' coverage.txtalu_flags7. awk in Automation Pipelines
awk is rarely the whole of anything. It is one stage, and the stages around it have clearer owners.
Bash orchestrates. It decides which directories to walk, launches the tools, and passes files along. A loop over a run directory calling awk once per log is a Bash job with an awk stage inside it.
Tcl is the language EDA tools embed, so it usually runs inside the tool and is what produced the report in the first place. This matters practically: if you can ask the tool's own reporting commands for a tidy two-column file, you should, because the awk that reads it afterwards becomes trivial. A lot of awk complexity is paid for upstream by a report that was never asked to be machine-readable.
Python takes over when the job grows. Once you need structured data, several processing steps, real error handling, or a program other people maintain, Python is the better tool and awk becomes one stage feeding it — or disappears, because Python can read the file directly.
A conceptual shape, rather than a pipeline to copy:
Tcl inside the tool -> writes a tidy report
Bash -> finds the reports and runs the next stage on each
awk -> reduces each report to a few fields
Python -> combines, checks and presents the resultThe honest summary is that these are complementary, not competing. The question is never "awk or Python" in the abstract; it is which stage of a specific job you are standing in. Chapters 1.3 to 1.5 compare awk against grep, sed and Python one at a time, and Module 12 builds real pipelines once the language is in hand.
8. Engineering Limitations
Everything so far worked. This section is the other half, and it is measured rather than asserted — each trap below is a command run against a stated input with its real output.
A changed format silently returns nothing. Suppose the timing report gains a column naming the check:
path_a setup -0.12
path_b setup 0.08awk '$2 < 0 { print $1 }' timing_shift.txtNo output, no error, exit status 0. Slack is now $3, and the command that was right yesterday reports no violations today. This is the characteristic report-parsing failure: not a crash, but silence that reads like good news.
A non-numeric field changes the kind of comparison. awk compares numerically when both sides look like numbers, and as text otherwise. Add a unit suffix:
path_a +0.08ns
path_b -0.00ns
path_c 0.05nsawk '$2 < 0 { print $1, $2 }' timing_trap.txtpath_a +0.08ns
path_b -0.00nsBoth selected rows are wrong. Because +0.08ns is not a number, awk compared text, and + and - both sort before 0. Forcing arithmetic gives the right answer — none:
awk '$2 + 0 < 0 { print $1, $2 }' timing_trap.txtThe uncomfortable part is that on the original timing.txt the plain $2 < 0 was genuinely numeric and correct, and even on suffixed values like -0.12ns text ordering happens to agree. A trap that usually gives the right answer is harder to find than one that always fails.
A header is just another record. A report with a header row has one more line than it has data rows:
path slack
path_a -0.12
path_b 0.08awk 'END { print NR }' timing_hdr.txt3Three records, two paths. Any count that does not skip the header is one too high; NR > 1 is the guard.
A tool that died still parses cleanly. The strongest version of the section 2 warning:
Starting elaborationawk '$2 == "UVM_ERROR" { n++ } END { print "errors:", n + 0 }' died.logerrors: 0Zero errors, exit status 0, and nothing ran. Reporting that as a pass is the single most expensive mistake in this chapter.
Two more worth naming without a demonstration. Missing fields are the empty string, which counts as 0 in arithmetic, so a row short of a column quietly contributes nothing to a total rather than complaining. And awk implementations differ — the one used here is POSIX awk, while gawk adds features beyond it, so a command that works on your machine can fail on a compute farm running a different one. Chapter 8.6 covers that properly.
9. Exercises
Each exercise gives the exact input. Create the file, run your command, and compare. Nothing here needs anything beyond sections 2 to 4.
Exercise 1 — Extract the warnings
Using the sim.log from section 2:
100 UVM_INFO Test started
250 UVM_WARNING Retry detected
420 UVM_ERROR Data mismatch
500 UVM_INFO Test finishedPrint the warning lines. Use the field form rather than a text match.
awk '$2 == "UVM_WARNING" { print }' sim.log250 UVM_WARNING Retry detectedThe severity is always the second field, so testing $2 asks the precise question. A text match on UVM_WARNING gives the same answer on this file and would also match a message that merely mentioned the word.
Exercise 2 — Count the failing tests
Using the regression summary from section 3:
test_a PASS
test_b FAIL
test_c PASS
test_d FAILReport how many tests failed, as a number.
awk '$2 == "FAIL" { n++ } END { print n + 0 }' regression.txt2The pattern selects the failing rows, n++ counts them, and END prints once after the last line. Keep the + 0: on a clean regression n is never created, and print n alone would output an empty line where you wanted 0.
Exercise 3 — Name the violating paths
Using the reduced timing table from section 4:
path_a -0.12
path_b 0.08
path_c -0.05Print just the names of the paths with negative slack — the names only, not the slack values.
awk '$2 < 0 { print $1 }' timing.txtpath_a
path_cThe condition selects the row and print $1 chooses which part of it to show — the distinction 1.1 made between deciding which lines and deciding what of them. Given section 8, awk '$2 + 0 < 0 { print $1 }' is the form to prefer on any file whose numbers you have not inspected; on this clean column both give the same two names.
10. Summary
- awk reads what the tools write. It does not simulate, synthesise, analyse timing or measure coverage. It occupies one stage between a tool's text output and a human decision, which is why it works on all of these files and why it cannot tell whether the answer is sensible.
- Five kinds of file, five meanings. A simulation log is a running commentary; a regression summary is a prepared row per test; a timing report is a per-check margin; a synthesis report is a resource summary; a coverage report is a record of what was exercised against what was tracked.
- A field test can be more precise than a text match.
$2 == "UVM_ERROR"asks about the severity column;/UVM_ERROR/asks about the whole line, and a message body can satisfy it. - Extracting a value and validating a conclusion are different jobs. A matching line is not a distinct failure, no error lines is not a pass, a negative number is not automatically slack, a cell count is not an area, and averaged percentages are not coverage.
- The failure mode is silence, not a crash. A shifted column, a unit suffix, a header row and a tool that died all produce a plausible number and exit status 0. Check the result against the report.
- awk is one stage. Bash orchestrates, Tcl usually wrote the report inside the tool, Python takes over when the job outgrows a one-liner. A report that was asked to be machine-readable makes the awk trivial.
You can now say where in a flow a given awk command belongs, what the file it reads represents, and which claims the output does not support — which is the context the rest of Part I builds on.
The next step is to go back to the mechanics and sharpen the comparison this chapter leaned on twice. We used a text match and a field test almost interchangeably, and they are not the same tool. Chapter 1.3 — awk vs grep draws that line properly: grep decides which lines you keep, awk decides which part of a line you keep and what you compute from it.
Where this fits
Part of the awk curriculum.
