Synthesis and Power Analysis

September 3, 2026 · View on GitHub

This guide explains how to run synthesis, timing analysis, area analysis, and power analysis for Vortex across all supported back-ends: Xilinx (Vivado), Altera (Quartus), Yosys (open-source), and Synopsys Design Compiler.


Table of Contents


Design Configuration

All synthesis flows accept a CONFIGS variable to customize the hardware design at build time. CONFIGS is a string of preprocessor macro definitions (-D flags) that control core count, cache hierarchy, extensions, and other parameters.

Common configuration flags (all parameters live in the VX_CFG_* namespace; see VX_config.toml at the repo root for the full list):

FlagDescription
-DVX_CFG_NUM_CLUSTERS=NNumber of clusters
-DVX_CFG_NUM_CORES=NNumber of cores per cluster
-DVX_CFG_NUM_WARPS=NNumber of warps per core
-DVX_CFG_NUM_THREADS=NNumber of threads per warp
-DVX_CFG_L2_ENABLEEnable shared L2 cache
-DVX_CFG_L3_ENABLEEnable shared L3 cache
-DVX_CFG_EXT_TCU_ENABLEEnable Tensor Core Unit
-DVX_CFG_EXT_DXA_ENABLEEnable DXA extension
-DVX_CFG_DCACHE_SIZE=NSet data cache size in bytes

Example:

CONFIGS="-DVX_CFG_NUM_CLUSTERS=1 -DVX_CFG_NUM_CORES=4 -DVX_CFG_L2_ENABLE -DVX_CFG_EXT_TCU_ENABLE"

Overriding top-module parameters (-G)

CONFIGS may also carry Verilog parameter overrides as -G<NAME>=<value> alongside the -D macros. gen_sources.sh forwards these to repl_params.py, which rewrites the parameter's default in the top module's per-build copy (the source tree is untouched, so concurrent builds with different overrides stay isolated). gen_config ignores -G tokens, so no separate Makefile variable is needed.

This is mainly for the DUT unittest wrappers, whose knobs are Verilog parameters rather than VX_CFG_* macros — e.g. the cache wrapper's AMO_ENABLE and IS_LLC:

# LLC cache DUT, AMO disabled vs enabled (NT=NW=32)
CONFIGS="-DVX_CFG_NUM_THREADS=32 -DVX_CFG_NUM_WARPS=32 -GAMO_ENABLE=0 -GIS_LLC=1" PREFIX=amo0 make cache
CONFIGS="-DVX_CFG_NUM_THREADS=32 -DVX_CFG_NUM_WARPS=32 -GAMO_ENABLE=1 -GIS_LLC=1" PREFIX=amo1 make cache

All flows also support the NUM_CORES Makefile shorthand which auto-selects a pre-defined cluster/core/L2 configuration:

NUM_CORES=4   # equivalent to -DVX_CFG_NUM_CLUSTERS=1 -DVX_CFG_NUM_CORES=4 -DVX_CFG_L2_ENABLE
NUM_CORES=16  # equivalent to -DVX_CFG_NUM_CLUSTERS=1 -DVX_CFG_NUM_CORES=16 -DVX_CFG_L2_ENABLE
NUM_CORES=32  # equivalent to -DVX_CFG_NUM_CLUSTERS=2 -DVX_CFG_NUM_CORES=16 -DVX_CFG_L2_ENABLE

Using PREFIX for Isolated Builds

Use PREFIX=<unique_build_dir> to keep builds separate. Each flow creates a build directory derived from PREFIX so that multiple configurations can coexist without overwriting each other:

# Xilinx XRT: creates build_4c_<platform>_<target>/
PREFIX=build_4c NUM_CORES=4 make -C hw/syn/xilinx/xrt

# Synopsys: creates my_test_Vortex/
PREFIX=my_test make -C hw/syn/synopsys synthesis

The tinygpu Configuration for Fast Turnaround

When the component under investigation is outside the GPU core — the AFU shell, the command processor, the runtime, or the FPGA driver — a full-size Vortex build is wasted synthesis time. Most of the hours go into cores and caches that the bug does not live in, and every debug iteration pays for them again.

For those cases, use a deliberately minimal GPU: one core, two warps of two threads, all L1 caches off, and shared memory off.

CONFIGS="-DVX_CFG_NUM_CLUSTERS=1 -DVX_CFG_NUM_CORES=1 \
         -DVX_CFG_NUM_WARPS=2 -DVX_CFG_NUM_THREADS=2 \
         -DVX_CFG_ICACHE_DISABLE -DVX_CFG_DCACHE_DISABLE -DVX_CFG_LMEM_DISABLE"

Note the _DISABLE spelling: knobs that default to true in VX_config.toml are turned off by defining their _DISABLE guard, not by assigning =0.

This strips the design down to a single pipeline talking straight to the memory interface. Synthesis and place-and-route finish in a small fraction of the time a production configuration takes, and the resulting bitstream still exercises the complete external path: host to driver, driver to shell, shell to command processor, command processor to core, and the memory traffic back out. Timing closure is generally uneventful at this size, so a failure to close is itself a signal that the problem is in the surrounding logic rather than in core density.

Pair it with the sgemm benchmark. sgemm is well understood, self-checking, and touches every part of the external path — kernel launch, argument passing, bulk DMA in both directions, and completion signalling — while staying small enough to run quickly. A sgemm failure on tinygpu isolates the defect to the surrounding infrastructure, because the core configuration is too small to be hiding a microarchitectural corner case. Conversely, sgemm passing on tinygpu but failing at full size points back at the core, cache hierarchy, or a concurrency effect that only appears with more warps in flight.

Treat this as the first move when debugging external components, not a fallback after a long build fails. Once tinygpu is green, scale back up to the target configuration to confirm the fix under real conditions.


Generating SAIF Files

SAIF (Switching Activity Interchange Format) files capture signal toggle rates during simulation and are used to produce accurate power estimates. Vortex supports SAIF generation through its RTL simulators: rtlsim, opaesim, and xrtsim.

Method 1: Build the Simulator Directly

Build the simulator with SAIF tracing enabled, then run a workload:

# Build rtlsim with SAIF support
make -C sim/rtlsim SAIF=1

# Run a test application
make -C tests/regression/sgemm run-rtlsim

The SAIF file is written to trace.saif in the application directory.

Method 2: Use the Blackbox Test Driver

The ci/blackbox.sh script provides a convenient wrapper:

./ci/blackbox.sh --driver=rtlsim --app=sgemm --cores=4 --l2cache --saif

When --saif is passed, blackbox.sh:

  1. Builds the simulator with SAIF=1
  2. Runs the application
  3. Copies the resulting trace.saif to the current directory

--saif composes with --debug on every RTL driver, so a run can emit both the run.log trace and the SAIF. It cannot be combined with --vcd: a model emits one waveform format or the other.

Available drivers for SAIF generation:

DriverSimulatorUse Case
rtlsimVerilator RTL simGeneral-purpose RTL power analysis
opaesimOPAE AFU simulatorIntel/Altera platform-specific analysis
xrtsimXRT simulatorXilinx platform-specific analysis

Specifying SAIF_INST

When reading a SAIF file, the tool must strip the testbench hierarchy prefix from signal names so they align with the synthesized netlist. SAIF_INST specifies this prefix.

Typical values:

FlowSAIF_INST
Xilinx DUTTOP.rtlsim_shim.vortex
Xilinx XRTTOP.vortex_afu_shim.vortex_afu
Synopsys / YosysInstance path matching your simulation hierarchy

The path does not have to be absolute. A module instance name works if the tool can resolve it unambiguously (find-first semantics).

If the SAIF root scope already matches the top module, leave SAIF_INST empty.


DUT Sub-Component Evaluation

Both Xilinx and Altera provide DUT (Device Under Test) flows for synthesizing and analyzing sub-components in isolation, without the full platform wrapper. This is useful for evaluating individual units such as the TCU, FPU, cache, or a single core.

Xilinx DUT Targets

Located in hw/syn/xilinx/dut/. Available sub-component targets:

TargetModuleDescription
unittestUnit testsBasic block tests
scopeScope analyzerDebug scope
mem_unitMemory unitMemory subsystem
lmemLocal memoryLocal/shared memory
cacheCacheCache subsystem
fpuFPUFloating-point unit
tcuTCUTensor Core Unit
dxaDXADXA extension
coreCoreSingle core
issueIssue unitInstruction issue
vortexVortexFull processor (no AFU wrapper)
topTopFull design with AFU
cd hw/syn/xilinx/dut

# Synthesize the TCU in isolation
CONFIGS="-DVX_CFG_EXT_TCU_ENABLE" make tcu

# Synthesize a 4-core Vortex without the platform wrapper
CONFIGS="-DVX_CFG_NUM_CORES=4 -DVX_CFG_L2_ENABLE" make vortex

# Run power analysis on an existing tcu
make tcu-power SAIF_FILE=/path/to/trace.saif SAIF_INST=*.tensor_unit

Each target creates its build under <target>/<BUILD_DIR>/ (e.g., tcu/build/).

Altera DUT Targets

Located in hw/syn/altera/dut/. Same set of sub-component targets as Xilinx. Requires the DEVICE_FAMILY variable and IP cache generation:

cd hw/syn/altera/dut

# Generate IP cache first (required for fpu, vortex, top)
make ip-gen

# Synthesize TCU for Arria 10
DEVICE_FAMILY=arria10 CONFIGS="-DVX_CFG_EXT_TCU_ENABLE" make tcu

# Synthesize a single core for Stratix 10
DEVICE_FAMILY=stratix10 make core

Build directories include the device family: <target>/build_<device_family>/.


Xilinx (Vivado)

XRT Full-Platform Flow

Located in hw/syn/xilinx/xrt/. Builds a complete Vitis xclbin for deployment on Xilinx FPGAs.

Supported platforms: Alveo U50, U55C, U200, U250, U280, Versal VCK5000.

Running Synthesis

cd hw/syn/xilinx/xrt

# Build a 4-core design for U280
PREFIX=build_4c NUM_CORES=4 TARGET=hw \
  PLATFORM=xilinx_u280_gen3x16_xdma_1_202310_1 \
  CONFIGS="-DVX_CFG_L2_ENABLE -DVX_CFG_DCACHE_SIZE=8192" \
  make > build.log 2>&1 &

Key variables:

VariableDefaultDescription
PREFIXbuild$(XLEN)Build directory prefix
TARGEThwhw for hardware, hw_emu for emulation
PLATFORM(required)Xilinx platform identifier
NUM_CORES-Shorthand for core configuration
CONFIGS-Additional design macros
MAX_JOBS8Parallel Vivado jobs

Power Analysis

make power SAIF_FILE=/path/to/trace.saif SAIF_INST=TOP.vortex_afu_shim.vortex_afu BUILD_DIR=<build_dir>

The script (hw/scripts/xilinx_power_analysis.tcl) resolves the post-implementation checkpoint from BUILD_DIR automatically.

Where to Find Reports

XRT flow (under <BUILD_DIR>/):

ReportLocationContent
Utilization<BUILD_DIR>/bin/utilization.rptLUTs, FFs, BRAM, DSP
Timing<BUILD_DIR>/bin/timing.rptWorst setup paths
Power (vectorless)power_vectorless.rptBaseline power estimate
Power (SAIF)power_saif.rptActivity-annotated power

DUT flow (under <target>/<BUILD_DIR>/):

ReportLocationContent
Post-synth utilizationpost_synth_util.rptHierarchical resource usage
Post-impl utilizationpost_impl_util.rptHierarchical resource usage after P&R
Timingtiming.rpt100 worst setup paths
Methodologymethodology.rptDesign rule checks
Clock utilizationclock_utilization.rptClock tree and register usage
RAM utilizationram_utilization.rptDetailed RAM/BRAM usage
Power (vectorless)power_vectorless.rptBaseline power
Power (VCD)power_vcd.rptVCD-annotated power (if VCD_FILE set)
Power (SAIF)power_saif.rptSAIF-annotated power (via make power)
DRCdrc.rptDesign rule violations
High fanout netshigh_fanout_nets.rptNets with >100 fanout

Finding Key Metrics

  • Fmax: Look in timing.rpt for the worst negative slack (WNS). Fmax = 1 / (clock_period - WNS).
  • Total LUTs: In post_impl_util.rpt, find the row for CLB LUTs or Slice LUTs.
  • Total DSPs: In post_impl_util.rpt, find the row for DSPs or DSP48E2.
  • Total BRAM: In post_impl_util.rpt, find the row for Block RAM Tile or RAMB36/RAMB18.

Altera (Quartus)

OPAE Full-Platform Flow

Located in hw/syn/altera/opae/. Builds AFU images for Intel OPAE platforms (Arria 10, Stratix 10).

Running Synthesis

cd hw/syn/altera/opae

# Full build: IP generation, setup, and synthesis
DEVICE_FAMILY=arria10 PREFIX=build_4c NUM_CORES=4 TARGET=fpga make

# For ASE simulation build
DEVICE_FAMILY=stratix10 TARGET=asesim make

Key variables:

VariableDefaultDescription
DEVICE_FAMILYarria10arria10 or stratix10
PREFIXbuild$(XLEN)Build directory prefix
TARGETfpgafpga, asesim, or ase
NUM_CORES-Shorthand for core configuration
CONFIGS-Additional design macros

Build directory: <PREFIX>_<device_family>_<target>_<num_cores>c/.

Power Analysis

Altera power analysis uses Quartus PowerPlay with VCD-based toggle annotation:

# Located in hw/syn/altera/power_play.sh
quartus_pow --input_vcd=trace.vcd \
  --vcd_filter_glitches=on \
  --default_input_io_toggle_rate=10000transitions/s \
  $ProjectName

Where to Find Reports

Reports are generated in the synthesis build directory by the Quartus report scripts.

Area reports (from report_area.tcl):

ReportContent
*.syn.area.resource_summary.csvSynthesis resource summary
*.syn.area.resource_breakdown.csvResource breakdown by entity
*.syn.area.ram_summary.csvSynthesis RAM summary
*.syn.area.stats.csvPost-synthesis netlist statistics
*.fit.area.resource_summary.csvFitter resource summary (post-P&R)
*.fit.area.resource_breakdown.csvFitter resource breakdown by entity
*.fit.area.ram_summary.csvFitter RAM summary
*.fit.area.routing_summary.csvRouting utilization
*.fit.area.routing_global.csvGlobal signal routing
*.fit.area.routing_high_fanout.csvHigh fanout signal routing

Timing reports (from analyze_timing.tcl):

ReportContent
*.fit.timing.summary.txtSummary with Fmax, setup/hold, clock summary
*.fit.timing.setup.htmlTop 200 setup violation paths (with routing)
*.fit.timing.hold.htmlTop 200 hold violation paths
*.fit.timing.recovery.htmlRecovery timing paths
*.fit.timing.removal.htmlRemoval timing paths
*.fit.timing.check_errors.htmlTiming DRC (no clock, multiple clock, loops)
*.fit.timing.check_metastability.htmlMetastability report
*.fit.timing_histogram.*.setup.htmlPer-clock setup slack histograms
*.fit.timing.setup.bottlenecks.txtBottleneck analysis (TNS, fanout, fanin)
*.fit.timing.summary.fmax.csvFmax summary (CSV)
*.fit.timing.summary.setup.csvSetup summary (CSV)
*.fit.timing.summary.hold.csvHold summary (CSV)
*.fit.timing.summary.multicorner.csvMulti-corner timing summary

Finding Key Metrics

  • Fmax: Open *.fit.timing.summary.txt or *.fit.timing.summary.fmax.csv. The Fmax summary reports the restricted Fmax for each clock domain.
  • Total ALMs/LUTs: In *.fit.area.resource_summary.csv, look for ALMs needed (Stratix 10) or Logic utilization (Arria 10).
  • Total DSPs: In *.fit.area.resource_summary.csv, look for the DSP row.
  • Total BRAM (M20K/M10K): In *.fit.area.resource_summary.csv, look for M20K blocks or M10K blocks. Also see *.fit.area.ram_summary.csv for detailed RAM usage by entity.

Yosys (Open-Source)

Located in hw/syn/yosys/. Uses Yosys/ABC for technology mapping and OpenSTA for pre-layout timing and power analysis. ASAP7 7.5-track v28 is the default PDK; NanGate45 remains available as a legacy option.

Running Synthesis

# First use installs the selected, pinned ASAP7 Liberty files automatically.
# Synthesis only (generic gates)
make -C build/hw/syn/yosys PREFIX=test NUM_CORES=1 synthesis

# Explicit legacy library selection
make -C build/hw/syn/yosys PREFIX=test NUM_CORES=1 PDK=nangate45 timing

# Synthesis + technology mapping
make -C build/hw/syn/yosys PREFIX=test NUM_CORES=1 techmap

# Full flow: synthesis + mapping + STA + power
make -C build/hw/syn/yosys PREFIX=test NUM_CORES=1 SAIF_FILE=/path/to/trace.saif SAIF_INST=<inst> timing

Key variables:

VariableDefaultDescription
PREFIXbuildBuild directory prefix
TOP_LEVEL_ENTITYVortexTop module name
NUM_CORES-Shorthand for core configuration
CONFIGS-Additional design macros
CLOCK_FREQ800Target clock frequency in MHz
DELAY_UNC0.02Clock uncertainty (fraction of period)
DELAY_IO0.05I/O delay (fraction of period)
ABC_DRIVER_CELLASAP7 RVT: BUFx4_ASAP7_75t_RInput driver cell used by ABC for buffering and sizing
ABC_LOADASAP7: 5.0ABC primary-output load in fF
YOSYS_FLATTEN1Flatten hierarchy before technology mapping for better cross-module optimization
YOSYS_SHARE1Enable Yosys resource sharing before mapping; set to 0 to disable
PDKasap7asap7 or the legacy nangate45 library
ASAP7_VTrvtASAP7 threshold-voltage library: rvt or lvt
CORNERttASAP7 tt, ss, or ff NLDM corner
LIB_TGTselected by PDKExplicit custom Liberty override
SAIF_FILE-SAIF file for power annotation
SAIF_INSTtop moduleOpenSTA SAIF scope override
DUT_FILELIST-VCS-style filelist for an arbitrary DUT
SDC_FILEproject.sdcClock, reset, and I/O constraints

Example synthesizing a TFR FEDP unit with FP8 and MX enabled with ASAP7 RVT at the default 800 MHz:

make -C build/hw/syn/yosys timing TOP_LEVEL_ENTITY=VX_tcu_fedp_tfr PREFIX=tfr_fedp CORNER=tt EXTRA_CONFIGS='-DVX_CFG_EXT_TCU_ENABLE -DVX_CFG_TCU_TYPE_TFR -DVX_CFG_NUM_THREADS=32 -DVX_CFG_TCU_FEDP_FP8_ENABLE -DVX_CFG_TCU_MX_ENABLE'

Output reports are written to build/hw/syn/yosys/tfr_fedp_VX_tcu_fedp_tfr/reports/

Build directory: <PREFIX>_<TOP_LEVEL_ENTITY>/ (e.g., test_Vortex/).

The flow uses sv2v to convert SystemVerilog sources to Verilog before feeding them to Yosys.

Per-DUT synthesis

The DUTs above are declared once, in hw/syn/yosys/dut/catalog.mk — a top module, an include path and a define set each — and driven through one dispatcher, so a hand run and the asic_gate (below) build the same thing:

make -C build/hw/syn/yosys/dut list                 # what is available
make -C build/hw/syn/yosys/dut om                   # synthesis + STA (TARGET=timing)
make -C build/hw/syn/yosys/dut tcu TARGET=synthesis # synthesis only
make -C build/hw/syn/yosys/dut om CLOCK_FREQ=500    # override the target clock

PREFIX defaults to the DUT name, so each DUT gets its own tree. That is not cosmetic: the flow caches $(BUILD_DIR)/src and does not regenerate it when EXTRA_INCLUDE changes, so two DUTs sharing one tree silently synthesize the first one's sources. Override PREFIX to keep an automated sweep away from a hand-run build of the same DUT.

Synthesis-regression gate (asic_gate)

ci/asic_gate.py runs that catalog against checked-in goldens in ci/baselines/synthesis/yosys/ and fails on a Fmax or cell-area move beyond ±5%. It is the ASIC sibling of ci/fpga_gate.py and shares its implementation (ci/synth_gate.py).

ci/asic_gate.py --list             # builds and their recorded baselines
ci/asic_gate.py -b om -b tex       # gate two builds
ci/asic_gate.py --update-baseline  # re-record (human-reviewed, never in CI)

Two things about Fmax on this flow are worth knowing before reading a number. ABC maps to the target period and stops, so a design that closes does so with picoseconds of margin and its Fmax sits just above CLOCK_FREQ by construction — cell area is the sensitive metric, and Fmax is mostly a met/missed signal. And report_wns is worst negative slack, clamped at zero: run_sta.tcl uses report_worst_slack (signed) for exactly this reason, which is what worst_slack.rpt holds.

See docs/designs/continuous_integration.md §3.5 and §4.5.

The first ASAP7 invocation runs the generated build/hw/syn/libs/asap7/install.sh installer. It downloads and SHA-256 verifies only the selected VT's five logical groups (INVBUF, SIMPLE, AO, OA, and SEQ) at TT, SS, and FF, then writes the merged Liberty files to build/hw/syn/libs/asap7/lib/. Gate-level simulation additionally installs the selected functional Verilog models in build/hw/syn/libs/asap7/verilog/. Later invocations verify the installed files and skip the download and preparation. The pin manifest, installer, preparation script, and upstream license are versioned in hw/syn/libs/asap7/, alongside the other standard-cell collateral; configure instantiates only install.sh.in into the build tree, and it reads the manifest and preparation script from the source tree in place. No ASAP7 collateral is kept under third_party/, and the flow requires no OpenROAD executable or physical collateral.

Threshold-Voltage Selection

RVT is the default because it is the appropriate general-purpose implementation library. Use LVT to establish a timing-focused bound or when a design does not meet its target with RVT:

make -C build/hw/syn/yosys timing ASAP7_VT=lvt CLOCK_FREQ=1000

Arbitrary DUT and Gate-Level SAIF

An arbitrary Verilog DUT can bypass Vortex source generation with its own top, filelist, and SDC. Filelists may contain RTL files, -f, +incdir+, and +define+ entries.

make -C build/hw/syn/yosys timing TOP_LEVEL_ENTITY=my_dut \
  DUT_FILELIST=/absolute/path/to/dut.f \
  SDC_FILE=/absolute/path/to/dut.sdc PREFIX=my_dut

For gate-level simulation, provide a Verilator-compatible testbench filelist. The testbench must instantiate the mapped DUT (the default instance name is dut) and call $dumpfile("gate_raw.saif") plus $dumpvars. SIM_ARGS, GATE_SIM_FLAGS, TB_TOP, and GATE_DUT_INSTANCE are available for testbench-specific needs.

make -C build/hw/syn/yosys gate-saif TOP_LEVEL_ENTITY=my_dut \
  DUT_FILELIST=/absolute/path/to/dut.f \
  SDC_FILE=/absolute/path/to/dut.sdc \
  TB_FILELIST=/absolute/path/to/tb.f SIM_ARGS="+seed=1"

make -C build/hw/syn/yosys timing TOP_LEVEL_ENTITY=my_dut \
  DUT_FILELIST=/absolute/path/to/dut.f \
  SDC_FILE=/absolute/path/to/dut.sdc \
  SAIF_FILE=$PWD/build_my_dut/gate.saif

The gate simulation traces Yosys-generated underscore nets and retains the complete mapped-cell hierarchy before re-rooting the DUT SAIF scope. OpenSTA writes annotated and unannotated pin reports and treats a requested SAIF with zero coverage as an error.

SRAM Area Estimation

Yosys uses blackbox modules (VX_dp_ram_asic, VX_sp_ram_asic) for SRAM. The sram_cost.py script estimates SRAM area from the Yosys JSON netlist by inferring width and depth from port connectivity:

Area = (width x depth x SRAM_BIT_AREA) + SRAM_OVERHEAD

Defaults: SRAM_BIT_AREA=0.1 um^2/bit, SRAM_OVERHEAD=100.0 um^2. These can be overridden via environment variables.

Where to Find Reports

All reports are under <BUILD_DIR>/reports/:

ReportContent
yosys.logFull Yosys synthesis log
stat_lib.rptCell count and area (post-mapping, by liberty cell type)
sram_area.rptEstimated SRAM area breakdown
sta.logOpenSTA timing log
setup.rpt / hold.rptDetailed setup and hold paths
wns.rpt / tns.rptWorst and total negative slack (clamped at 0 when timing closes)
worst_slack.rptWorst slack, signed — positive when the design closes with margin
synth_summary.csvOne-row machine-readable summary of all of the above (synth_summary.py)
power.rptPower estimate (vectorless or SAIF-annotated)
power_hier.rptHierarchical power breakdown
saif_annotated.rptPins covered by SAIF
saif_unannotated.rptSignals not covered by SAIF

Netlists are written to <BUILD_DIR>/out/:

FileContent
<TOP>_syn.vPost-synthesis generic netlist
<TOP>_mapped.vPost-mapping technology netlist
<TOP>.jsonYosys JSON netlist (used by sram_cost.py)

Finding Key Metrics

  • Total area: In stat_lib.rpt, look for Chip area for top module. Add the estimated SRAM area from sram_area.rpt for the total.
  • Cell count: In stat_lib.rpt, the per-cell-type breakdown shows gate counts.
  • Timing (WNS/TNS): In sta.log, look for the report_wns and report_tns outputs. Fmax = 1 / (target_period - WNS).
  • Power: In power.rpt, look for total power. power_hier.rpt breaks it down by hierarchy.

Synopsys Design Compiler

Located in hw/syn/synopsys/. Uses Synopsys DC for ASIC synthesis with support for multiple technology libraries.

Supported Libraries

LIB_TYPETechnologyPath
DEFAULTNanGate 15nm OCLBundled in hw/syn/libs/
ASAP7ASAP7 7nm/mnt/nas0/eda.libs/asap7/asap7sc7p5t_28/LIB/NLDM
SAED14SAED 14nm SLVT/mnt/nas0/eda.libs/saed14/EDK_03_2025

Running Synthesis

cd hw/syn/synopsys

# Default library, 1 core
PREFIX=test make synthesis

# ASAP7 library, 4 cores, with SAIF power
PREFIX=test NUM_CORES=4 LIB_TYPE=ASAP7 \
  SAIF_FILE=/path/to/trace.saif SAIF_INST=<inst> \
  make synthesis

# Synthesis without SRAM macros (blackbox)
PREFIX=test make synthesis-nosram

# Synthesis with estimated SRAM area
PREFIX=test make synthesis-estsram

Key variables:

VariableDefaultDescription
PREFIXbuildBuild directory prefix
TOP_LEVEL_ENTITYVortexTop module name
NUM_CORES-Shorthand for core configuration
CONFIGS-Additional design macros
CLOCK_FREQ800Target frequency in MHz
DELAY_UNC0.02Clock uncertainty (fraction of period)
DELAY_IO0.05I/O delay (fraction of period)
LIB_TYPEDEFAULTTechnology library selection
SAIF_FILE-SAIF file for power annotation
SAIF_INST-Instance path prefix in SAIF

Build directory: <PREFIX>_<TOP_LEVEL_ENTITY>/ (e.g., test_Vortex/).

Synthesis Variants

  • synthesis: Full synthesis with generated SRAM wrappers from the technology library's SRAM .db files. Requires the library to provide SRAM models.
  • synthesis-nosram: Synthesis without any SRAM logic. RAM modules are inferred by DC.
  • synthesis-estsram: Blackboxes VX_dp_ram_asic and VX_sp_ram_asic, then estimates their area from port dimensions (same approach as Yosys).

Where to Find Reports

All reports are under <BUILD_DIR>/reports/:

ReportContent
area.rptHierarchical area breakdown
qor.rptQuality of Results summary (area, timing, utilization)
timing_max.rptSetup timing (50 worst paths, with nets/transitions/capacitance)
timing_min.rptHold timing (50 worst paths)
clock_skew.rptClock skew analysis
constraints_violators.rptAll constraint violations
check_design.rptPre-synthesis design checks
power_active.rptSAIF-annotated hierarchical power (if SAIF_FILE provided)
power_vectorless.rptVectorless power estimate (if no SAIF_FILE)
saif_annotation_coverage.rptSAIF annotation coverage statistics

Outputs are under <BUILD_DIR>/out/:

FileContent
<TOP>.mapped.ddcSynopsys binary netlist
<TOP>.mapped.vMapped gate-level Verilog
<TOP>.mapped.sdfStandard Delay Format for back-annotation
<TOP>.post_compile.sdcPost-compile timing constraints

Finding Key Metrics

  • Total area: In area.rpt, look for the top-level Total cell area. The SRAM estimated area (if using synthesis-estsram) is printed in the build log as Total Estimated SRAM Area.
  • Timing / Fmax: In timing_max.rpt, the slack of the first path gives the worst negative slack (WNS). Fmax = 1 / (target_period - WNS). Also check qor.rpt for a summary.
  • Power: In power_active.rpt (with SAIF) or power_vectorless.rpt (without), the hierarchical breakdown shows internal, switching, and leakage power per module.
  • Gate count: In qor.rpt, look for Design Area and Number of cells.

Understanding Power Reports

Power reports across all flows break down total power into similar categories. Understanding these helps identify optimization targets.

Power Components

ComponentDescription
Dynamic powerPower consumed by signal switching activity
  InternalShort-circuit current during output transitions within cells
  SwitchingCharging/discharging of interconnect and load capacitances
Static (leakage) powerPower consumed even when signals are not switching; due to sub-threshold and gate leakage currents

Total Power = Dynamic (Internal + Switching) + Static (Leakage)

Vectorless vs. Activity-Annotated

  • Vectorless: The tool assumes a default toggle rate (typically 12.5%) and static probability (0.5) for all signals. Provides a rough baseline but can significantly over- or under-estimate actual power.
  • SAIF/VCD-annotated: Uses real switching activity captured during simulation. Much more accurate for the specific workload simulated. Signals not covered by the SAIF/VCD fall back to the default toggle rate.

Always compare the vectorless and annotated reports to understand which modules differ most from the default assumption.

Tips

  • Run a representative workload when generating SAIF files. Short or trivial tests will underestimate steady-state power.
  • Check SAIF annotation coverage reports (saif_annotation_coverage.rpt in Synopsys, saif_unannotated.rpt in Yosys) to ensure good signal coverage.
  • For Xilinx, the power report includes device-specific contributions (clocking, I/O, BRAM, DSP power) that are not present in ASIC flows.
  • For hierarchical analysis, look at per-module power breakdowns to identify the most power-hungry blocks (e.g., caches, FPU, TCU).