Text processing and log checking

Learning objectives
  • Search simulator and synthesis logs with grep -E
  • Write extended regular expressions with anchors, classes and groups
  • Edit text streams with sed
  • Summarise fields with awk
  • Count PASS, FAIL and ERROR results across a regression
  • Fail a run when a log contains a warning that is not on an approved waiver list
1 Objective→ 2 Learn→ 3 Example→ 4 Practice→ 5 Verify→ 6 Continue
How to study this lessonUnderstand the idea first. Use the example to see the behaviour, practise where provided, then make sure you can explain the result before continuing.

Explanation

Logs are the evidence

Every EDA tool reports through text. A simulator exit status of 0 does not mean the test passed, and a synthesis run can finish while warning about inferred latches. Treat each log as data: extract what matters, count it, and decide automatically. Three classic tools cover most of this work.

Tool Best for Typical use
grep -E Selecting lines that match a pattern Find every ERROR or Warning line
sed Substituting or deleting text in a stream Strip timestamps before comparing logs
awk Splitting lines into fields and computing totals Count results per test, sum runtimes

Extended regular expressions

grep -E uses extended regular expressions (ERE). The same syntax works in sed -E and awk.

Pattern Matches
^ERROR ERROR at the start of a line
TEST (PASSED|FAILED)$ Either word at the end of a line
[0-9]+ One or more digits
seed=[0-9]+ A seed field such as seed=42
[Ww]arning Warning or warning
\.v:[0-9]+: A Verilog file and line number such as fifo.v:37:

Useful options: -c counts matching lines, -l lists matching files, -n adds line numbers, -v inverts the match, -i ignores case, and -q prints nothing and only sets the exit status. Quote patterns in single quotes so the shell does not expand |, $ or *.

sed for normalisation

sed applies an edit to every line. Common forms:

sed -E 's/[0-9]+ ns/<T> ns/g' sim.log      # hide simulation times
sed -E '/^#/d' filelist.f                  # drop comment lines
sed -n '/^Summary/,$p' synth.log           # print from "Summary" to end of file

Normalising logs before a diff stops harmless differences such as times or paths hiding the real change.

awk for fields and totals

awk splits each line into fields $1, $2, … on whitespace. A pattern selects lines and an action runs for each one. END runs after the last line.

awk '/^RESULT/ { n[$3]++ } END { for (k in n) print k, n[k] }' results.txt

For lines like RESULT fifo_basic PASS, this counts how many tests passed and failed.

Waivers instead of ignoring warnings

Some warnings are understood and accepted. Record them in a waiver file of regular expressions, one per line, and fail on anything else. grep -v -E -f waivers.txt removes waived lines, leaving only new warnings.

Worked example

A regression wrote one log per test to logs/. Each passing testbench prints TEST PASSED; a failure prints TEST FAILED or an ERROR line. Save this as check_logs.sh:

#!/usr/bin/env bash
set -euo pipefail

log_dir=${1:-logs}
waivers=${2:-waivers.txt}
shopt -s nullglob
logs=("$log_dir"/*.log)
(( ${#logs[@]} > 0 )) || { echo "no logs in $log_dir" >&2; exit 2; }

pass=0 fail=0
for log in "${logs[@]}"; do
    test=$(basename "$log" .log)
    if grep -q -E '^ERROR|TEST FAILED' "$log" || ! grep -q 'TEST PASSED' "$log"; then
        printf 'FAIL %s\n' "$test"
        grep -n -E '^ERROR' "$log" | head -n 3 | sed 's/^/    /'
        fail=$((fail + 1))
    else
        pass=$((pass + 1))
    fi
done

new_warnings=$(cat "${logs[@]}" | grep -i -E 'warning' \
    | { if [[ -f "$waivers" ]]; then grep -v -E -f "$waivers"; else cat; fi; } \
    | sort -u || true)

printf 'passed=%d failed=%d total=%d\n' "$pass" "$fail" "${#logs[@]}"
if [[ -n "$new_warnings" ]]; then
    printf 'unwaived warnings:\n%s\n' "$new_warnings"
    exit 1
fi
(( fail == 0 ))

A test with no TEST PASSED line counts as a failure: a simulation that crashed or hung before printing its verdict must not pass. The || true keeps pipefail from stopping the script when grep -v finds no remaining warnings, which is the good case. The final (( fail == 0 )) makes the script's own exit status 0 only when every test passed and no new warning appeared, so a CI job can call it directly.

An example waivers.txt:

timescale.*inherited from
Port .* of .*unused

Check yourself

Why is a missing TEST PASSED line treated as a failure? What is the difference between grep -c and grep -q, and which suits an if statement? Why should waivers be narrow regular expressions rather than broad words such as Warning? What does sed -n '/^Summary/,$p' print?

Engineering practice

Practice: Text processing and log checking

Task→Run / reason→Check result→Explain why

Extend check_logs.sh to print the slowest three tests. Assume each log ends with a line such as Runtime: 12.4 s; use awk to extract the number with the test name, then sort -k2 -n -r | head -n 3. Add a test log with an unwaived warning and confirm the script exits with status 1, then add a waiver for it and confirm the status becomes 0.

Practice work is non-certified and is not stored by ASIC Campus.