From Ad-Hoc Commands to Production Flows

You've learned the individual synthesis commands—read_verilog, hierarchy, proc, abc—and run them interactively to understand what each does. But real projects demand repeatability, consistency, and efficiency. You can't manually type dozens of commands every time you modify a single line of RTL. This is where synthesis scripts transform your workflow from exploratory to professional.

Synthesis scripts capture your entire synthesis strategy in a reusable, version-controlled, and shareable format. They document your optimization decisions, encode your constraints, and enable push-button synthesis that produces consistent results. Whether you're synthesizing for multiple process corners, experimenting with different optimization strategies, or coordinating work across a team, well-crafted synthesis scripts are essential.

This module teaches you to create robust, maintainable synthesis scripts that scale from small experiments to production designs.

Understanding Yosys Script Files

What Are .ys Files?

A Yosys script file (.ys extension by convention) is a text file containing a sequence of Yosys commands, executed in order:

Basic Script Structure

# synthesis.ys
# Comments start with '#'

# Read design files
read_verilog design.v

# Synthesis flow
hierarchy -check -top my_module
proc
fsm
memory
opt

# Technology mapping
read_liberty -lib cells.lib
abc -liberty cells.lib

# Output
write_verilog design_synth.v

Execution

$ yosys -s synthesis.ys

Or from within Yosys:

yosys> script synthesis.ys

Script File Advantages

Repeatability
Every synthesis run executes the same commands in the same order, producing consistent results.

Documentation
The script documents your synthesis strategy. Six months later, you'll know exactly what optimization passes ran and why.

Version Control
Scripts are text files—perfect for Git. Track changes, review diffs, and collaborate effectively.

Parameterization
Scripts can be parameterized for different designs, corners, or optimization goals.

Automation
Integrate scripts into makefiles, continuous integration, or regression testing.

Creating Reusable Synthesis Scripts

Basic Script Template

Minimal Working Script

# minimal_synth.ys
# Minimal synthesis script template

# Source files
read_verilog rtl/design.v

# Synthesis
hierarchy -check -auto-top
proc
opt

# Technology mapping
read_liberty -lib lib/cells.lib
abc -liberty lib/cells.lib

# Output
write_verilog output/design_synth.v
stat

This handles simple single-file designs with automatic top detection.

Intermediate Script Template

Multi-File Design with Options

# synth_design.ys
# Synthesis script for multi-file design

# Configuration
set TOP_MODULE counter_top

# Read all RTL files
read_verilog rtl/counter.v
read_verilog rtl/adder.v
read_verilog rtl/mux.v
read_verilog rtl/top.v

# Establish design hierarchy
hierarchy -check -top $TOP_MODULE

# High-level synthesis
proc
fsm
memory

# Generic optimization (run multiple times)
opt
opt

# Clean up
clean

# Load technology library
read_liberty -lib lib/stdcells_typ.lib

# Technology mapping with timing focus
abc -liberty lib/stdcells_typ.lib -D 2000

# Post-mapping optimization
opt
clean

# Generate outputs
write_verilog -noattr output/${TOP_MODULE}_mapped.v
write_json output/${TOP_MODULE}.json

# Statistics and reporting
stat -liberty
tee -o output/synthesis_report.txt stat -top $TOP_MODULE

# Visualization
show -prefix output/${TOP_MODULE}_netlist -format svg

Key Features:

  • Variables for easy parameterization
  • Multiple input files
  • Comprehensive optimization
  • Multiple output formats
  • Automated reporting

Advanced Script Template

Production-Quality Script

# production_synth.ys
# Production synthesis script with error checking and logging

# ============================================================
# Configuration Section
# ============================================================
set TOP_MODULE processor_core
set RTL_DIR rtl
set LIB_DIR lib
set OUT_DIR output/${TOP_MODULE}
set CORNER typical

# Target frequency (in ns)
set CLK_PERIOD 2.0

# ============================================================
# Setup and Validation
# ============================================================

# Create output directory structure
tee -q mkdir -p ${OUT_DIR}

# Start logging
tee -o ${OUT_DIR}/synthesis_full.log echo "=== Synthesis Started ==="
tee -a ${OUT_DIR}/synthesis_full.log echo "Top Module: ${TOP_MODULE}"
tee -a ${OUT_DIR}/synthesis_full.log echo "Corner: ${CORNER}"
tee -a ${OUT_DIR}/synthesis_full.log echo "Clock Period: ${CLK_PERIOD} ns"

# ============================================================
# Read RTL
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Reading RTL ==="

read_verilog -sv ${RTL_DIR}/alu.sv
read_verilog -sv ${RTL_DIR}/register_file.sv
read_verilog -sv ${RTL_DIR}/control_unit.sv
read_verilog -sv ${RTL_DIR}/datapath.sv
read_verilog -sv ${RTL_DIR}/${TOP_MODULE}.sv

# Check for read errors
check

# ============================================================
# Hierarchy and Elaboration
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Elaborating Design ==="

hierarchy -check -top ${TOP_MODULE}

# Generate hierarchy report
tee -o ${OUT_DIR}/hierarchy.txt hierarchy -check

# ============================================================
# Generic Synthesis
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Generic Synthesis ==="

# Convert behavioral to structural
proc

# FSM optimization
fsm

# Memory inference
memory

# Initial optimization
opt

# Statistics after generic synthesis
tee -o ${OUT_DIR}/stats_generic.txt stat

# ============================================================
# Technology Library Setup
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Loading Technology Library ==="

read_liberty -lib ${LIB_DIR}/stdcells_${CORNER}.lib

# Verify library loaded
stat -liberty

# ============================================================
# Technology Mapping
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Technology Mapping ==="

# Calculate target delay in picoseconds
set TARGET_DELAY [expr {int($CLK_PERIOD * 1000 * 0.8)}]

# Map with timing constraints
abc -liberty ${LIB_DIR}/stdcells_${CORNER}.lib -D ${TARGET_DELAY}

# Post-mapping optimization
opt
clean

# ============================================================
# Quality Checks
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Quality Checks ==="

# Check for design errors
check -assert

# Ensure all cells are mapped
select -assert-none t:$*

# ============================================================
# Reporting
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Generating Reports ==="

# Detailed statistics
tee -o ${OUT_DIR}/stats_final.txt stat -liberty
tee -o ${OUT_DIR}/stats_detailed.txt stat -top ${TOP_MODULE}

# Cell count by type
tee -o ${OUT_DIR}/cell_report.txt stat -liberty -width

# ============================================================
# Output Generation
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Writing Outputs ==="

# Verilog netlist (clean, no attributes)
write_verilog -noattr -noexpr ${OUT_DIR}/${TOP_MODULE}_mapped.v

# JSON for other tools
write_json ${OUT_DIR}/${TOP_MODULE}.json

# Graphical representation
show -prefix ${OUT_DIR}/${TOP_MODULE}_schematic -format svg -width

# ============================================================
# Completion
# ============================================================
tee -a ${OUT_DIR}/synthesis_full.log echo "\n=== Synthesis Complete ==="
tee -a ${OUT_DIR}/synthesis_full.log echo "Outputs written to: ${OUT_DIR}"

Production Features:

  • Comprehensive logging
  • Error checking at every stage
  • Organized output directory structure
  • Detailed reporting
  • Quality assertions
  • Parameterized for different corners
  • Self-documenting with comments

Constraint Specification

Why Constraints Matter

Constraints tell the synthesis tool what your design requirements are:

  • Timing constraints: How fast must the circuit run?
  • Area constraints: How large can it be?
  • Power constraints: How much power is acceptable?

Without constraints, synthesis optimizes blindly—you might get a small, slow design when you needed fast performance.

SDC (Synopsys Design Constraints)

While Yosys has limited native SDC support, you can pass constraints to ABC:

Basic SDC File

# constraints.sdc

# Define clock
create_clock -period 5.0 -name clk [get_ports clk]

# Input delays (relative to clock)
set_input_delay -clock clk -max 0.5 [all_inputs]
set_input_delay -clock clk -min 0.1 [all_inputs]

# Output delays
set_output_delay -clock clk -max 0.5 [all_outputs]
set_output_delay -clock clk -min 0.1 [all_outputs]

# Load capacitance on outputs
set_load 0.05 [all_outputs]

# Drive strength on inputs
set_driving_cell -lib_cell BUF_X1 [all_inputs]

Using SDC with Yosys

# In synthesis script
abc -liberty cells.lib -constr constraints.sdc

ABC reads the SDC and uses it to guide optimization.

Inline Constraints in Yosys Scripts

For simpler cases, embed constraints directly:

Timing Constraints via ABC Options

# Target delay: 2ns = 2000ps
abc -liberty cells.lib -D 2000

Area Constraints

# Maximum area
abc -liberty cells.lib -A 50000

Combined Constraints

# Delay and area
abc -liberty cells.lib -D 2000 -A 50000

Constraint-Driven Optimization Strategy

Practical Workflow:

  1. Initial synthesis without strict constraints

    abc -liberty cells.lib -fast
    stat
    # Baseline: 1500 cells, 3.2ns critical path
    
  2. Add timing constraint

    abc -liberty cells.lib -D 2500
    stat
    # Result: 1650 cells, 2.4ns critical path
    # Area increased to meet timing
    
  3. Balance with area constraint

    abc -liberty cells.lib -D 2500 -A 55000
    stat
    # Result: 1600 cells, 2.5ns critical path
    # Balanced solution
    

Clock Definition

Defining Clocks in Synthesis

Clocks are the heartbeat of synchronous designs. Proper clock definition ensures:

  • Correct register inference
  • Accurate timing analysis
  • Proper clock tree synthesis (in later stages)

Clock Definition Methods

Method 1: SDC File

# clocks.sdc
create_clock -period 10.0 -name sys_clk [get_ports clk]
create_clock -period 20.0 -name slow_clk [get_ports clk2]

# Clock uncertainty (jitter, skew)
set_clock_uncertainty -setup 0.5 [get_clocks sys_clk]
set_clock_uncertainty -hold 0.2 [get_clocks sys_clk]

Method 2: ABC Command-Line

# Specify clock period directly
abc -liberty cells.lib -D [expr {10.0 * 1000 * 0.9}]
# 10ns clock, 90% of period available for logic

Method 3: Scripted Clock Calculation

# Define clock parameters
set CLK_FREQ 100.0 ;# MHz
set CLK_PERIOD [expr {1000.0 / $CLK_FREQ}] ;# ns
set LOGIC_BUDGET [expr {$CLK_PERIOD * 0.85}] ;# 85% for logic
set TARGET_DELAY [expr {int($LOGIC_BUDGET * 1000)}] ;# ps

# Use in ABC
abc -liberty cells.lib -D ${TARGET_DELAY}

# Log the constraints
tee -a synthesis.log echo "Clock Frequency: ${CLK_FREQ} MHz"
tee -a synthesis.log echo "Clock Period: ${CLK_PERIOD} ns"
tee -a synthesis.log echo "Logic Budget: ${LOGIC_BUDGET} ns"
tee -a synthesis.log echo "Target Delay: ${TARGET_DELAY} ps"

Multi-Clock Designs

For designs with multiple clock domains:

Define All Clocks in SDC

create_clock -period 5.0 -name fast_clk [get_ports clk_fast]
create_clock -period 20.0 -name slow_clk [get_ports clk_slow]

# Define clock relationships (if related)
set_clock_groups -asynchronous -group {fast_clk} -group {slow_clk}

Synthesis Strategy

# Optimize for the fastest clock
set CRITICAL_CLK_PERIOD 5.0
set TARGET_DELAY [expr {int($CRITICAL_CLK_PERIOD * 1000 * 0.85)}]

abc -liberty cells.lib -constr clocks.sdc -D ${TARGET_DELAY}

The synthesis tool will ensure all clock domains meet their respective constraints.

Synthesis for Different Corners

Why Multiple Corners?

As you learned in Module 6.2, designs must work across process, voltage, and temperature (PVT) variations. Synthesizing for multiple corners ensures robustness.

Typical Corner Set:

  • SS (Slow-Slow): Worst-case timing (setup checks)
  • TT (Typical-Typical): Nominal operation
  • FF (Fast-Fast): Worst-case hold timing

Multi-Corner Synthesis Strategy

Option 1: Separate Synthesis Per Corner

Create a synthesis script for each corner:

synthesis_ss.ys

# SS corner synthesis
set CORNER ss
set LIB_FILE lib/stdcells_ss_1p62v_125c.lib
set CLK_PERIOD 2.2  ;# Longer period for slow corner

read_verilog design.v
hierarchy -check -top my_design
proc; fsm; memory; opt

read_liberty -lib ${LIB_FILE}
abc -liberty ${LIB_FILE} -D [expr {int($CLK_PERIOD * 1000 * 0.9)}]

write_verilog output/design_${CORNER}.v
stat -liberty

synthesis_tt.ys

# TT corner synthesis
set CORNER tt
set LIB_FILE lib/stdcells_tt_1p80v_25c.lib
set CLK_PERIOD 2.0  ;# Nominal period

read_verilog design.v
hierarchy -check -top my_design
proc; fsm; memory; opt

read_liberty -lib ${LIB_FILE}
abc -liberty ${LIB_FILE} -D [expr {int($CLK_PERIOD * 1000 * 0.9)}]

write_verilog output/design_${CORNER}.v
stat -liberty

synthesis_ff.ys

# FF corner synthesis
set CORNER ff
set LIB_FILE lib/stdcells_ff_1p98v_n40c.lib
set CLK_PERIOD 1.8  ;# Shorter period for fast corner

read_verilog design.v
hierarchy -check -top my_design
proc; fsm; memory; opt

read_liberty -lib ${LIB_FILE}
abc -liberty ${LIB_FILE} -D [expr {int($CLK_PERIOD * 1000 * 0.9)}]

write_verilog output/design_${CORNER}.v
stat -liberty

Option 2: Parameterized Master Script

Create one script that handles all corners:

synthesis_multi_corner.ys

# Multi-corner synthesis script
# Usage: yosys -s synthesis_multi_corner.ys

# ============================================================
# Configuration
# ============================================================
set TOP_MODULE my_design
set BASE_CLK_PERIOD 2.0  ;# TT corner target

# Corner definitions
array set corners {
    ss {lib/stdcells_ss.lib 2.2}
    tt {lib/stdcells_tt.lib 2.0}
    ff {lib/stdcells_ff.lib 1.8}
}

# ============================================================
# Read RTL (once, shared across all corners)
# ============================================================
read_verilog design.v

# Save the design state
write_ilang design_rtl.il

# ============================================================
# Synthesize Each Corner
# ============================================================
foreach corner {ss tt ff} {
    echo "=========================================="
    echo "Synthesizing for corner: $corner"
    echo "=========================================="
    
    # Restore RTL state
    design -reset
    read_ilang design_rtl.il
    
    # Get corner-specific parameters
    set lib_file [lindex $corners($corner) 0]
    set clk_period [lindex $corners($corner) 1]
    set target_delay [expr {int($clk_period * 1000 * 0.85)}]
    
    echo "Library: $lib_file"
    echo "Clock Period: $clk_period ns"
    echo "Target Delay: $target_delay ps"
    
    # Generic synthesis
    hierarchy -check -top ${TOP_MODULE}
    proc
    fsm
    memory
    opt
    
    # Technology mapping for this corner
    read_liberty -lib $lib_file
    abc -liberty $lib_file -D $target_delay
    
    opt
    clean
    
    # Output corner-specific netlist
    write_verilog -noattr output/${TOP_MODULE}_${corner}.v
    
    # Generate corner-specific report
    tee -o output/stats_${corner}.txt stat -liberty
}

echo "=========================================="
echo "Multi-corner synthesis complete"
echo "=========================================="

Running Multi-Corner Synthesis

$ yosys -s synthesis_multi_corner.ys

This produces three netlists:

  • my_design_ss.v - Optimized for slow corner
  • my_design_tt.v - Optimized for typical corner
  • my_design_ff.v - Optimized for fast corner

Corner-Specific Considerations

SS Corner (Slow-Slow)

  • Longest delays → Focus on meeting timing
  • Higher threshold voltage → Lower leakage
  • Use higher drive strengths to compensate for slow transistors

TT Corner (Typical-Typical)

  • Balanced optimization
  • Primary synthesis target
  • Used for area and power estimates

FF Corner (Fast-Fast)

  • Shortest delays → Focus on hold timing
  • Lower threshold voltage → Higher leakage
  • Need to ensure minimum delays are adequate

Using Different Libraries Per Corner

Library Organization

lib/
├── stdcells_ss_1p62v_125c.lib  # SS: 1.62V, 125°C
├── stdcells_tt_1p80v_25c.lib   # TT: 1.80V, 25°C
└── stdcells_ff_1p98v_n40c.lib  # FF: 1.98V, -40°C

Each library contains the same cells with corner-specific characterization data.

Corner Selection in Scripts

# Environment variable approach
set CORNER $env(SYNTH_CORNER)
set LIB_FILE lib/stdcells_${CORNER}.lib

read_liberty -lib ${LIB_FILE}
abc -liberty ${LIB_FILE}

Running

$ SYNTH_CORNER=ss yosys -s synthesis.ys
$ SYNTH_CORNER=tt yosys -s synthesis.ys
$ SYNTH_CORNER=ff yosys -s synthesis.ys

Script Organization Best Practices

Modular Script Design

Separate Configuration from Flow

config.ys (Configuration)

# Design configuration
set TOP_MODULE processor
set RTL_FILES "cpu.v alu.v mem.v"
set CLK_PERIOD 2.0
set CORNER tt

flow.ys (Synthesis flow)

# Load configuration
source config.ys

# Execute synthesis
read_verilog $RTL_FILES
hierarchy -check -top $TOP_MODULE
# ... rest of flow

This allows changing configuration without modifying the flow.

Directory Structure

Organized Project Layout

project/
├── rtl/
│   ├── top.v
│   ├── module1.v
│   └── module2.v
├── lib/
│   ├── stdcells_ss.lib
│   ├── stdcells_tt.lib
│   └── stdcells_ff.lib
├── constraints/
│   ├── timing.sdc
│   └── clocks.sdc
├── scripts/
│   ├── synthesis.ys
│   ├── synthesis_ss.ys
│   ├── synthesis_tt.ys
│   └── synthesis_ff.ys
└── output/
    ├── ss/
    ├── tt/
    └── ff/

Version Control Integration

.gitignore

# Ignore synthesis outputs
output/
*.log
*.dot
*.svg

# Keep scripts and sources
!scripts/
!rtl/
!lib/
!constraints/

Commit scripts, RTL, and constraints. Exclude generated outputs.

Makefile Integration

Makefile

# Synthesis Makefile

.PHONY: all synth_ss synth_tt synth_ff clean

all: synth_ss synth_tt synth_ff

synth_ss:
	yosys -s scripts/synthesis_ss.ys

synth_tt:
	yosys -s scripts/synthesis_tt.ys

synth_ff:
	yosys -s scripts/synthesis_ff.ys

clean:
	rm -rf output/*

stats:
	@echo "=== SS Corner ==="
	@cat output/ss/stats.txt
	@echo "\n=== TT Corner ==="
	@cat output/tt/stats.txt
	@echo "\n=== FF Corner ==="
	@cat output/ff/stats.txt

Usage

$ make synth_tt      # Synthesize TT corner only
$ make all           # Synthesize all corners
$ make stats         # Display statistics
$ make clean         # Remove outputs

Advanced Scripting Techniques

Conditional Synthesis

Debug vs. Release Modes

set DEBUG 1

if {$DEBUG} {
    # Debug mode: preserve hierarchy, add assertions
    hierarchy -check -top $TOP_MODULE
    # Don't flatten
} else {
    # Release mode: aggressive optimization
    hierarchy -check -top $TOP_MODULE
    flatten  # Flatten hierarchy for better optimization
}

Iterative Optimization

Progressive Synthesis

# First pass: Quick synthesis
abc -liberty cells.lib -fast
stat
write_verilog output/design_v1.v

# Analyze results
set initial_area [stat -area]

# Second pass: Better timing
design -reset
read_ilang checkpoint.il
abc -liberty cells.lib -D 2000
stat
write_verilog output/design_v2.v

# Compare
set optimized_area [stat -area]
echo "Area reduction: [expr {($initial_area - $optimized_area) / $initial_area * 100}]%"

Error Recovery

Robust Scripts with Error Handling

# Check hierarchy
hierarchy -check -top $TOP_MODULE
if {[catch {check}]} {
    echo "ERROR: Design check failed"
    exit 1
}

# Verify mapping
abc -liberty cells.lib
if {[catch {select -assert-none t:$*}]} {
    echo "ERROR: Unmapped cells remain"
    exit 1
}

Summary

Synthesis scripts transform your workflow into a professional, maintainable process:

  • Reusable .ys files capture synthesis strategy and ensure repeatability
  • Constraints guide optimization toward your timing, area, and power goals
  • Clock definitions specify operating frequency and timing budgets
  • Multi-corner synthesis ensures designs work across PVT variations
  • Best practices include modular design, version control, and automation

Key skills you've developed:

  • Creating comprehensive synthesis scripts from templates
  • Specifying and using constraints effectively
  • Defining clocks and calculating timing budgets
  • Synthesizing for multiple process corners
  • Organizing scripts for team collaboration and CI/CD integration

With robust synthesis scripts, you can confidently iterate on designs, experiment with optimizations, and produce consistent, high-quality results. Your synthesis flow is now automated, documented, and ready for production use—whether you're building a hobby project or a commercial ASIC.

In the next modules, we'll analyze the synthesized designs, interpret reports, and perform timing analysis to verify that our constraints are met.

Did you find what you were looking for?

Quiz

No quiz questions available for this article.