Skip to content
VLSI Mentor

Tcl · Module 21

The Phases of a Synthesis Script

Synthesis scripts differ enormously in detail and almost not at all in shape. Learn the six phases once and every later chapter is a phase of a script you can already picture.

Intermediate16 min readtcledapart-iisynthesisflowscripts

Part II · Module 21 · Chapter 21.1 · The Phases of a Synthesis Script

A synthesis script turns RTL into a gate-level netlist. They vary a great deal between projects and tools, and almost not at all in shape.

Six phases, always in this order. Learn them once and the rest of this module is a chapter per phase.

1. The six phases

Six phases in order. First, read the RTL sources and the technology libraries. Second, elaborate and link so the design and its references are resolved. Third, apply the timing constraints. Fourth, compile, which is the optimisation step. Fifth, generate the report set. Sixth, write the netlist and record what produced it.A synthesis run, in order01READRTL sources and technology libraries02ELABORATE AND LINKresolve the design and its references03CONSTRAINapply the SDC04COMPILEthe optimisation step05REPORTtiming, area, power, quality06WRITEthe netlist, and what produced it
Figure 1 — the canonical order of a synthesis run. Each phase depends on the one before it having actually worked, which is why a phase that silently did nothing lets the next one proceed on an empty design.
PhaseWhat happensChapter
Readsources and libraries enter the tool21.2, 21.4
Elaboratethe hierarchy is built and references resolved21.5
Constrainthe SDC is applied21.6
Compilelogic is optimised and mapped to library cells21.7
Reporttiming, area, power and quality are captured21.8
Writethe netlist leaves the tool21.9

2. Why the order is fixed

It is not convention. Each phase needs the previous one's result:

  • You cannot elaborate a design whose sources have not been read.
  • You cannot constrain a port that does not exist until elaboration created it.
  • Compile has nothing to optimise toward without constraints — it would produce a netlist optimised against no requirement, which is Chapter 20.1 §1's empty-report problem in a more expensive form.
  • Reports describe the compiled result, so they come after it.
  • Writing the netlist is last because that is the artefact everything else was for.

The one that trips people is constrain before compile. Applying constraints to an already-compiled design does not retroactively change how it was optimised.

3. Every phase can fail quietly

This is the thread running through the module, and it is why it ends with a review chapter rather than a summary.

A tool command applied to nothing succeeds (Chapter 18.8). So:

  • A file list that silently lost a file elaborates a partial design — 21.2.
  • An unresolved reference leaves a black box the tool happily optimises around — 21.5.
  • A constraint file that was sourced but applied nothing leaves the design unconstrained — 21.6.
  • A report that was never written leaves a directory somebody assumes is complete — 21.8.

Each failure lets the next phase proceed. A run can pass through all six and exit successfully having produced a netlist nobody should use — which is the module blurb's "run which finished but produced nothing you can sign off", and Chapter 21.10 is the check for it.

4. The scaffolding

Because every phase can fail, the script needs a shape that notices. This is ordinary Tcl and it is the frame every later chapter plugs into:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
proc run_phase {name body} {
    puts "  --- $name"
    if {[catch {uplevel 1 $body} err]} {
        puts stderr "  FAILED  $name: $err"
        return 1
    }
    puts "  ok      $name"
    return 0
}

set failures 0
incr failures [run_phase "read"      { read_sources   $files }]
incr failures [run_phase "elaborate" { elaborate_top  $top }]
incr failures [run_phase "constrain" { apply_sdc      $sdc }]
incr failures [run_phase "compile"   { compile_design }]
incr failures [run_phase "report"    { write_reports  $rundir }]
incr failures [run_phase "write"     { write_netlist  $rundir }]

exit [expr {$failures > 0 ? 1 : 0}]

With one phase failing, the shape is visible:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  --- read
  ok      read
  --- elaborate
  FAILED  elaborate: cannot resolve reference to 'missing_mod'
  --- constrain
  ok      constrain
  ---
  1 phase(s) failed

Five Part I decisions, each from Chapter 15.9:

  • A catch per phase, so a failure is attributed to the phase that caused it rather than appearing as a trace from somewhere deep inside.
  • Failures counted, not fatal immediately — though §5 qualifies that.
  • Diagnostics on stderr, progress on stdout (Chapter 14.9 §2).
  • An honest exit status so the surrounding automation stops.
  • uplevel 1 so each phase body runs in the caller's scope and can see $files, $top and the rest (Chapter 11.5).

5. Continue or stop?

Chapter 15.9 §4 argued that a batch loop should continue past one bad input. Synthesis is the opposite case, and it is worth being clear why.

The inputs there were independent — one malformed file says nothing about the next. Here the phases are dependent: if elaboration failed, compiling is not merely pointless, it burns an hour and produces a misleading artefact.

So the right structure is to stop at the first failure:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
foreach {name body} $phases {
    if {[run_phase $name $body]} {
        puts stderr "  stopping: '$name' failed"
        exit 1
    }
}

The rule generalises: continue when the items are independent, stop when each depends on the last.

6. What varies and what does not

Between tools, the command names change completely — read_verilog versus something else, and the compile command especially. Chapter 17.5's adapter idea applies if you need more than one tool.

Between projects, the options change — which libraries, which effort level, which reports.

What does not change is the order, the fact that each phase can fail quietly, and the scaffolding around them. That is why learning the shape once is worth more than learning any particular tool's commands.

7. What a run must leave behind

Stated here because it shapes every later chapter: a synthesis run is not finished when the tool exits. It is finished when it has left

  • a netlist,
  • a report set somebody can read,
  • a record of what produced them — 21.9 §4,
  • and an exit status that tells the truth.

A run missing any of those is one somebody will have to repeat, usually when they are short of time.

8. Exercises

Exercise 1. Name the six phases in order.

Exercise 2. Why must constraints be applied before compile rather than after?

Exercise 3. Give two examples of a phase failing quietly.

Exercise 4. Why does run_phase use uplevel 1?

Exercise 5. Why stop at the first failed phase, when 15.9's batch loop continued past a bad input?

Exercise 6. What changes between tools, and what does not?

Exercise 7. Name the four things a finished run must leave behind.

Where this fits

Part of the Tcl curriculum.