Tcl in EDA tools

Learning objectives
  • Drive Yosys synthesis from a Tcl script with yosys -c and yosys -import
  • Write timing constraints as Tcl in SDC form with create_clock, set_input_delay and set_output_delay
  • Run static timing with an OpenSTA-style script
  • Make synthesis runs reproducible
  • Extract the numbers that matter from tool reports
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

One language, many tools

Open-source implementation tools share Tcl as their command language. Yosys accepts Tcl scripts; OpenSTA and OpenROAD are Tcl shells; and SDC constraint files are Tcl commands that every timing tool reads. The fundamentals from the previous lesson apply unchanged: variables, [command substitution], lists, proc, foreach and catch.

Tool How Tcl is used Typical command
Yosys Synthesis scripts yosys -c synth.tcl
OpenSTA Static timing analysis shell sta -exit sta.tcl
OpenROAD Floorplan to routing, plus STA openroad -exit flow.tcl
SDC file Clocks, I/O delays, exceptions read_sdc constraints.sdc

Yosys from Tcl

yosys -c synth.tcl runs a Tcl script inside Yosys. Each Yosys command is available through the yosys Tcl command, for example yosys read_verilog rtl/fifo.v. After yosys -import, most Yosys commands can be called directly as Tcl commands. Commands whose names clash with Tcl built-ins, notably proc, must still be called as yosys proc. A failing Yosys command stops the run with a non-zero exit status, which Make or a CI job sees.

Tcl adds what plain Yosys scripts lack: variables, loops over source files, and values from the environment.

set top    [expr {[info exists ::env(TOP)] ? $::env(TOP) : "fifo"}]
set srcs   [lsort [glob -nocomplain rtl/*.v]]
if {[llength $srcs] == 0} { error "no RTL found in rtl/" }

Constraints are Tcl

An SDC file is a Tcl script with a standard set of timing commands. Because it is Tcl, you can compute values rather than copy numbers by hand.

set clk_name   core_clk
set clk_port   [get_ports clk]
set clk_period 10.0
set io_delay   [expr {0.2 * $clk_period}]

create_clock -name $clk_name -period $clk_period $clk_port
set_clock_uncertainty 0.25 [get_clocks $clk_name]
set_input_delay  $io_delay -clock $clk_name [delete_from_list [all_inputs] $clk_port]
set_output_delay $io_delay -clock $clk_name [all_outputs]
Command Meaning
create_clock -period P port A clock of period P (ns) arrives on this port
set_clock_uncertainty Margin for jitter and skew before layout
set_input_delay D -clock C ports Inputs arrive D ns after the clock edge, from outside logic
set_output_delay D -clock C ports Outside logic needs outputs D ns before the next edge
get_ports, all_inputs, all_outputs Return collections of design objects

The clock port is removed from the input-delay list because a clock is not data. delete_from_list is an OpenSTA command; other tools offer similar helpers.

Reproducible runs

A synthesis result should be repeatable from the repository alone. Pin the tool version and record it, keep scripts and constraints under version control, list sources in a sorted order, and write every report to a named file under build/. Record the exact command line in the run log.

Reading reports

Reports are text, so the parsing techniques from earlier lessons apply. Report formats can change between tool releases: pin the version, test your regular expressions against a real report from that version, and make the script fail loudly when an expected line is missing rather than reporting zero.

Worked example

synth.tcl synthesises the top module to a standard-cell library from an open-source PDK and saves the statistics and netlist. The Liberty path comes from the environment so the script works on every machine.

yosys -import

set top  [expr {[info exists ::env(TOP)] ? $::env(TOP) : "fifo"}]
set lib  $::env(LIBERTY)
set srcs [lsort [glob -nocomplain rtl/*.v]]
if {[llength $srcs] == 0} { error "no RTL found in rtl/" }
file mkdir build

foreach src $srcs { read_verilog -defer $src }
hierarchy -check -top $top
synth -top $top
dfflibmap -liberty $lib
abc -liberty $lib
opt_clean
tee -o build/${top}_stat.txt stat -liberty $lib
write_verilog -noattr build/${top}_netlist.v

Run it, then check timing with OpenSTA:

export LIBERTY=$PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib
mkdir -p build
TOP=fifo yosys -c synth.tcl -l build/yosys.log
yosys -V >> build/yosys.log
# sta.tcl - run with: sta -exit sta.tcl
read_liberty $::env(LIBERTY)
read_verilog build/fifo_netlist.v
link_design fifo
read_sdc constraints.sdc
report_checks -path_delay max -digits 3 > build/fifo_timing.rpt
report_wns > build/fifo_wns.rpt
report_tns > build/fifo_tns.rpt

A short Tcl check then gates the flow on the result. It runs in plain tclsh because it only reads files:

set fh [open build/fifo_wns.rpt r]
set text [read $fh]
close $fh
if {![regexp {wns\s+(?:max\s+)?(-?[0-9.]+)} $text -> wns]} {
    puts stderr "no WNS value found in build/fifo_wns.rpt"
    exit 2
}
puts "worst negative slack: $wns ns"
exit [expr {$wns < 0}]

hierarchy -check fails early on a missing module. tee -o saves the stat output to a file while still printing it. The SDC file uses the Tcl shown earlier, so changing clk_period in one place updates every delay.

Check yourself

What is the difference between yosys read_verilog f.v and read_verilog f.v after yosys -import? Why must proc be called as yosys proc? Why is the clock port removed before set_input_delay? What makes a synthesis run reproducible? Why should a report-parsing script fail when it cannot find the expected line instead of assuming zero?

Engineering practice

Practice: Tcl in EDA tools

Task→Run / reason→Check result→Explain why

Wrap the flow in a Makefile with synth, sta and check targets so that editing an RTL file reruns synthesis but editing only constraints.sdc reruns only timing. Add a Tcl foreach over three clock periods (10, 8 and 6.5 ns) that writes one SDC file per period, runs STA for each, and prints a table of period against worst slack. Record the Yosys and OpenSTA versions in each report folder.

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