| name | remote-innovus-pr |
| description | Use when running Cadence Innovus Place & Route on a remote Linux server. Covers project setup, floorplan, CTS, routing, and signoff for TSMC 65nm designs. First copy from example template, then modify per design. Use this skill whenever the user mentions Innovus, P&R, place and route, backend, physical design, GDS generation, or wants to run post-synthesis layout. |
Remote Innovus Place & Route
Overview
Run Cadence Innovus P&R flow on a remote Linux server via SSH/SCP. The server has Innovus v21.16 and TSMC 65nm libraries pre-installed. This skill covers: copying example template, modifying scripts for your design, running the full flow (init → floorplan → placement → CTS → routing → signoff), and downloading results.
When to Use
- After DC synthesis and FM formal verification are complete
- When you need to generate GDS, SDF, SPEF from a gate-level netlist
- When the user says "跑后端", "P&R", "Innovus", "layout", "GDS"
Prerequisites
Remote (Linux server)
- Server:
$SERVER, User: $USER
- Innovus:
/opt/cadence/installs/INNOVUS211/bin/innovus (NOT INNOVUSEXPORT21)
- TSMC 65nm libraries at
$STDCELL_PATH/
- Example template at
~/agent_digits/example/innovus_flow/
- DC outputs must exist:
../dc/gate/{top}_netlist.v, ../dc/sdc/{top}.sdc
Local (Windows/macOS)
- SSH/SCP access configured
- Disk space for GDS (~1-2MB per design)
CRITICAL: Always Copy from Example Template
The example template has all library paths, MMMC config, and layer maps pre-configured. Never write scripts from scratch. Copy the template, then modify only the design-specific parts.
WARNING: Innovus TCL scripts are extremely sensitive to missing options. Even a single omitted flag can cause the flow to silently produce wrong results or crash hours later. The example template has been verified through real tapeout runs — it contains hundreds of carefully tuned options for setNanoRouteMode, setSrouteMode, set_ccopt_property, setExtractRCMode, etc. that this skill only summarizes at a high level.
Therefore:
- Always
cp -r the example template as the starting point
- Only modify the design-specific lines listed in the "What to Modify" table below
- Do NOT rewrite scripts from scratch based on this skill alone — use it as a guide for WHAT to change, not as a complete reference for HOW each command works
- If unsure about a command's options, read the original template file first and preserve its options
ssh $USER@$SERVER \
"cp -r ~/agent_digits/example/innovus_flow/ \
~/agent_digits/{project}/innovus/"
ssh $USER@$SERVER \
"cd ~/agent_digits/{project}/innovus/ && \
rm -rf save/* output/* rpt/* extLogDir cdBfile *.rpt *.rpt.old logFile power.rpt \
rc_model.bin mp_data* HRAM_TOP timingReports .WeightWriting* .timing_file* *.swp .cadence/ \
innovus.cmd* innovus.log* innovus.logv* innovus_run.log model.asrt*"
Project Directory Structure
{project}/innovus/
├── lib/ # LEF, GDS map, layer map (from template, DO NOT MODIFY)
│ ├── tcbn65lp_9lmT2.lef # Standard cell LEF (9 metal layer)
│ ├── innovus_gds_out.map # GDS stream out map
│ ├── quantus_extract.layermap # RC extraction layer map
│ └── tQuantus_model.bin # Generated at runtime
├── scripts/ # TCL scripts (modify per design)
│ ├── all.tcl # Master script: sources 1-6 in order
│ ├── mmmc.tcl # MMMC view definition (WC/TC/BC corners)
│ ├── 1-init.tcl # Design import + MMMC setup
│ ├── 2-fp.tcl # Floorplan + power ring + stripes + sroute
│ ├── 3-place.tcl # Placement + optimization
│ ├── 4-cts.tcl # Clock tree synthesis + decap
│ ├── 5-route.tcl # Global/detail routing + post-route opt + filler
│ ├── 6-signoff.tcl # DRC/connectivity/timing + GDS/SDF/SPEF output
│ └── fix_pwr_signoff.tcl # (optional) Power fix + re-signoff
├── pre/ # Input files (copy from DC outputs)
│ ├── {top}_netlist.v # Gate-level netlist from DC
│ └── {top}.sdc # Timing constraints from DC
├── save/ # Checkpoint saves at each stage
├── output/ # Final outputs (GDS, SDF, SPEF, netlist)
└── rpt/ # Reports (timing, DRC, connectivity, power)
What to Modify Per Design
| File | What to change | Typical values |
|---|
scripts/1-init.tcl | init_top_cell, init_lef_file, init_verilog, init_pwr_net, remove win | top module name, power net names |
scripts/mmmc.tcl | SDC path in create_constraint_mode | ./pre/{top}.sdc |
scripts/2-fp.tcl | Rewrite entirely — floorplan size, power nets, ring/stripes | die size, VDD/VSS |
scripts/3-place.tcl | Usually no changes needed | — |
scripts/4-cts.tcl | Usually no changes needed | — |
scripts/5-route.tcl | Fix path bug: /rpt/ → ./rpt/ (template bug) | line ~72-73 |
scripts/6-signoff.tcl | Rewrite — GDS merge list, filler cells, remove IO references | stdcell GDS only |
Step-by-Step Workflow
Step 1: Copy template and prepare inputs
ssh $USER@$SERVER \
"cd ~/agent_digits/{project}/innovus/pre && \
rm -f *.v *.sdc *.io && \
cp ~/agent_digits/{project}/dc/gate/{top}_netlist.v ./ && \
cp ~/agent_digits/{project}/dc/sdc/{top}.sdc ./"
Step 2: Modify scripts
1-init.tcl — Key modifications
# Change these lines:
set init_lef_file {
./lib/tcbn65lp_9lmT2.lef # Only stdcell LEF, remove IO/analog LEFs
}
set init_top_cell {top} # Your top module name
set init_verilog ./pre/{top}_netlist.v
set init_gnd_net {VSS}
set init_pwr_net {VDD} # Single power domain, not AVDD/DVDD
# CRITICAL: Remove the "win" command — it crashes in -nowin mode
# Delete any line that is just "win"
2-fp.tcl — Rewrite for pure core design
The example template has IO pads, analog macros, multiple power domains — all of which must be removed for a pure digital core design.
Template for a simple core design:
##2-FLOORPLAN
# Die size: estimate from DC area. Target ~70% utilization.
# DC area / 0.70 = core area. Add margins (5um each side).
# Example: DC area 2200um² → core ~3140um² → side ~56 → die 66x66
floorPlan -site core -d 80 80 5.0 5.0 5.0 5.0
# Global nets — connect VDD/VSS to all std cells
clearGlobalNets
globalNetConnect VDD -type pgpin -pin VDD -inst * -all
globalNetConnect VSS -type pgpin -pin VSS -inst * -all
globalNetConnect VDD -type tiehi -inst * -all
globalNetConnect VSS -type tielo -inst * -all
# Power ring on M7 (horizontal) and M8 (vertical)
setAddRingMode -ring_target default -stacked_via_top_layer M8 -stacked_via_bottom_layer M1
addRing -nets {VDD VSS} -type core_rings -follow core \
-layer {top M7 bottom M7 left M8 right M8} \
-width {top 2 bottom 2 left 2 right 2} \
-spacing {top 1 bottom 1 left 1 right 1} \
-offset {top 0.5 bottom 0.5 left 0.5 right 0.5} -center 0
# Power stripes — MUST be added here (before routing!)
# These provide via stacks from M8 down to M1 followpins
setAddStripeMode -stacked_via_top_layer M8 -stacked_via_bottom_layer M1
addStripe -start_from left -start 20 -nets {VDD VSS} -layer M8 \
-direction vertical -width 2 -spacing 1 -number_of_sets 2 -create_pins 1
# Special route: connect followpins to ring and stripes
setSrouteMode -viaConnectToShape {ring stripe followpin}
sroute -connect {corePin floatingStripe} -nets {VDD VSS} \
-layerChangeRange {M1(1) M8(8)} \
-floatingStripeTarget {ring followpin stripe} \
-crossoverViaLayerRange {M1(1) M8(8)} \
-allowLayerChange 1 -targetViaLayerRange {M1(1) M8(8)}
fixVia -minCut
fixVia -minStep
fixVia -short
fixOpenFill -net {VDD VSS}
saveDesign ./save/fp.enc
mmmc.tcl — Only change SDC path
# Find this line and change the SDC path:
create_constraint_mode -name synth -sdc_files { ./pre/{top}.sdc}
Everything else (RC corners, library sets, delay corners, analysis views) stays the same — it's pre-configured for TSMC 65nm WC/TC/BC.
5-route.tcl — Fix template bug
The example template has absolute paths on lines ~72-73:
# WRONG (template bug):
verifyConnectivity -type all -report /rpt/postECO_v4.conn.rpt
reportGateCount -level 5 -stdCellOnly -outfile /rpt/postECO_v4.gateCount.rpt
# FIX: add "./" prefix
verifyConnectivity -type all -report ./rpt/postECO_v4.conn.rpt
reportGateCount -level 5 -stdCellOnly -outfile ./rpt/postECO_v4.gateCount.rpt
6-signoff.tcl — Rewrite for core design
##SIGNOFF — simplified for pure core design
# Reports
verify_drc -report ./rpt/signOff.drc.rpt -limit 10000
verifyConnectivity -type all -report ./rpt/signOff.conn.rpt
reportGateCount -level 5 -stdCellOnly -outfile ./rpt/signOff.gatecount.rpt
report_power -rail_analysis_format VS -outfile ./rpt/signOff.pwr.rpt
timeDesign -postRoute -outDir ./rpt/signOffTimingReports
timeDesign -postRoute -hold -outDir ./rpt/signOffTimingReports
# SPEF output (WC and BC corners)
set timing_enable_simultaneous_setup_hold_mode false
setAnalysisMode -checkType setup
set_analysis_view -setup setup -hold setup
rcOut -spef ./output/{top}_WC.spef -rc_corner rcWC
setAnalysisMode -checkType hold
set_analysis_view -setup hold -hold hold
rcOut -spef ./output/{top}_BC.spef -rc_corner rcBC
# SDF output
set_analysis_view -setup {setup typical} -hold {hold typical}
write_sdf -version 3.0 ./output/${init_top_cell}.sdf \
-process best:typical:worst -filter -nonegchecks -celltiming all \
-target_application verilog \
-temperature -40.0:25.0:125 -voltage 1.32:1.20:1.08 \
-typ_view hold -max_view setup -min_view hold
# Netlists
saveNetlist ./output/Calibre_${init_top_cell}_wo_filler.v \
-includePowerGround -phys \
-excludeCellInst {FILL1 FILL16 FILL2 FILL32 FILL4 FILL64 FILL8}
saveNetlist ./output/Calibre_${init_top_cell}_w_filler.v -includePowerGround -phys
saveNetlist ./output/EDI_to_VCS_${init_top_cell}.v \
-excludeCellInst {FILL1 FILL16 FILL2 FILL32 FILL4 FILL64 FILL8}
# GDS — merge with stdcell GDS only (no IO, no analog)
setStreamOutMode -SEvianames false -specifyViaName default \
-supportPathType4 true -virtualConnection false -textSize 1
streamOut ./output/${init_top_cell}.gds -dieAreaAsBoundary \
-libName DesignLib -mapFile ./lib/innovus_gds_out.map \
-mode ALL -stripes 1 -units 1000 -merge {\
$TSMC_HOME/digital/Back_End/gds/tcbn65lp_200a/tcbn65lp.gds}
saveDesign ./save/signoff.enc
Step 3: Run Innovus
ssh $USER@$SERVER \
"cd ~/agent_digits/{project}/innovus && \
nohup /opt/cadence/installs/INNOVUS211/bin/innovus -nowin \
-files scripts/all.tcl > innovus_run.log 2>&1 &"
Typical runtime: 15-20 minutes for a small design (~2000 gates).
Step 4: Monitor progress
ssh $USER@$SERVER \
"wc -l ~/agent_digits/{project}/innovus/innovus.log"
ssh $USER@$SERVER \
"tail -30 ~/agent_digits/{project}/innovus/innovus.log"
ssh $USER@$SERVER \
"ps aux | grep '$USER.*innovus' | grep -v grep | wc -l"
Log milestones by line count (approximate):
- ~160: Init complete, libraries loaded
- ~500-1000: Placement
- ~5000-10000: CTS + initial routing
- ~10000-15000: Post-route optimization + RC extraction
- ~16000+: Signoff complete
Step 5: Analyze results
ssh $USER@$SERVER \
"grep 'ERROR' innovus.log | grep -v 'Error Limit'"
ssh $USER@$SERVER \
"cat rpt/signOff.drc.rpt"
ssh $USER@$SERVER \
"tail -10 rpt/signOff.conn.rpt"
ssh $USER@$SERVER \
"zcat rpt/signOffTimingReports/{top}_postRoute.summary.gz | tail -20"
ssh $USER@$SERVER \
"zcat rpt/signOffTimingReports/{top}_postRoute_hold.summary.gz | tail -20"
ssh $USER@$SERVER \
"cat rpt/signOff.gatecount.rpt"
Step 6: Download outputs
mkdir -p {local_project}/innovus_output
scp $USER@$SERVER:\
~/agent_digits/{project}/innovus/output/{top}.gds \
{local_project}/innovus_output/
scp $USER@$SERVER:\
~/agent_digits/{project}/innovus/output/{top}.sdf \
{local_project}/innovus_output/
scp $USER@$SERVER:\
~/agent_digits/{project}/innovus/output/EDI_to_VCS_{top}.v \
{local_project}/innovus_output/
scp $USER@$SERVER:\
~/agent_digits/{project}/innovus/output/{top}_WC.spef \
{local_project}/innovus_output/
scp $USER@$SERVER:\
~/agent_digits/{project}/innovus/output/{top}_BC.spef \
{local_project}/innovus_output/
Reading Innovus Reports
Timing Summary
+--------------------+---------+
| Setup mode | all |
+--------------------+---------+
| WNS (ns):| 0.000 | ← Worst Negative Slack. 0 = MET, negative = VIOLATED
| TNS (ns):| 0.000 | ← Total Negative Slack. 0 = all paths meet timing
| Violating Paths:| 0 | ← Must be 0
+--------------------+---------+
- Setup (max delay): checks if data arrives before clock edge. WNS ≥ 0 = PASS
- Hold (min delay): checks if data stable after clock edge. WNS ≥ 0 = PASS
DRC Report
No DRC violations were found ← Must see this line
Connectivity Report
Begin Summary
0 Problem(s) ← Must be 0
End Summary
Common issue: "special routes with opens" on VDD/VSS means M1 followpins not fully connected to power ring. Add power stripes in floorplan to fix.
Gate Count
Level 0 Module {top} Gates=2032 Cells=599 Area=2194.9 um^2
Common Issues & Fixes
| Issue | Cause | Fix |
|---|
innovus fails with "build signature file" error | which innovus resolves to INNOVUSEXPORT21 | Use full path: /opt/cadence/installs/INNOVUS211/bin/innovus |
Script stops at win command in -nowin mode | win opens GUI, incompatible with -nowin | Remove win line from 1-init.tcl |
IMPCCOPT-2215: route graph for net 'clk' not fully connected | Clock gating cells split traversal graph | Harmless — timing still passes |
IMPOPT-310: Design density exceeds 95% | Floorplan too small | Increase die size in 2-fp.tcl |
| DRC violations after adding stripes post-route | Via stacks from stripes short signal wires | Add stripes in floorplan stage, BEFORE routing |
IMPSYT-7338: session directory not found | restoreDesign uses .enc file instead of .enc.dat directory | Use restoreDesign ./save/{name}.enc.dat {top} |
| VDD/VSS "special routes with opens" | M1 followpins not connected to power ring | Add power stripes + use setSrouteMode -viaConnectToShape {ring stripe followpin} |
/rpt/ path errors in signoff | Template bug: absolute path /rpt/ instead of ./rpt/ | Fix in 5-route.tcl lines ~72-73 |
| IMPCCOPT-2215 clock graph error | Clock gating cells in traversal path | Informational only, does not affect functionality |
Advanced: Partial Re-run with restoreDesign
If you need to fix something and re-run only part of the flow (e.g., redo routing after fixing floorplan):
# Correct syntax: use .enc.dat directory, not .enc file
restoreDesign ./save/{checkpoint}.enc.dat {top}
# Example: load from placement, add stripes, then re-run CTS+route+signoff
restoreDesign ./save/place.enc.dat aer_top
# ... modify floorplan, add stripes ...
saveDesign ./save/place_modified.enc
Important checkpoints:
place.enc — after placement, before CTS/routing (best for adding stripes)
cts.enc — after CTS, before routing
route4.enc — after all routing + optimization (for signoff tweaks only)
Tips
-
Always use the full Innovus path — nohup /opt/cadence/installs/INNOVUS211/bin/innovus — because nohup doesn't load shell aliases from .bashrc, and the default innovus binary is broken.
-
Floorplan sizing rule of thumb: DC area × 1.5 / 0.70 = core area. Then sqrt for side length. Add 10um for margins. It's better to be too large than too small — density under 85% is comfortable.
-
Power stripes must go in the floorplan — they create via stacks from M8 down to M1. If added after routing, these vias will short signal wires. Use addStripe in 2-fp.tcl before any routing happens.
-
Monitor memory usage — Innovus can use 10-12GB for small designs. The server has enough RAM but watch for OOM on larger designs.
-
The IMPCCOPT-2215 error is harmless — it appears when clock gating cells are present (DC inserts them automatically when set_clock_gating_style is used). The clock tree still works correctly.
-
MMMC config is pre-configured — the mmmc.tcl from the example template has WC/TC/BC corners, QRC tech files, SI-aware CDB files all pointing to the right paths. Only the SDC path needs changing.
Advanced: Analog Module + IO Pad Integration
The example template (~/agent_digits/example/innovus_flow/) was originally designed for a mixed-signal design with analog macros and IO pads. The pure-digital flow above stripped those parts out. If your design includes analog modules or needs IO pads, add back the following configurations.
IMPORTANT: Always start from the example template and KEEP the analog/IO sections, only modifying design-specific names and positions. Do not try to add these from memory — the template's exact options for setSrouteMode, addIoFiller, sroute for analog/IO are tuned and verified.
What changes at each stage
1-init.tcl — Additional LEF files
set init_lef_file {
./lib/tcbn65lp_9lmT2.lef # stdcell (always needed)
/path/to/analog_macro.lef # analog macro LEF (ADD)
/path/to/tpdn65lpnv2od3_9lm.lef # IO pad LEF (ADD if using IO pads)
}
# Multiple power domains
set init_gnd_net {VSS}
set init_pwr_net {AVDD DVDD} # AVDD for analog, DVDD for digital
2-fp.tcl — Major additions
The floorplan becomes significantly more complex. The example template's 2-fp.tcl is the reference — it handles all of the following:
a) IO pad placement:
# Load IO assignment file (defines signal-to-pad mapping and pad order)
loadIoFile ./pre/${init_top_cell}.io
# Fill gaps between IO pads with filler pads
addIoFiller -cell PFILLER20 PFILLER10 PFILLER5 PFILLER1 PFILLER05 -prefix IOFILLER
addIoFiller -cell PFILLER0005 -prefix IOFILLER -fillAnyGap
b) Analog macro placement:
# Fix analog macro at specific coordinates
placeInstance u_ANALOG_FIXLCS 390 390 -fixed
# Add halo (keep-out zone) around all macros
addHaloToBlock -allMacro 1 1 1 1
# Block routing over the analog macro
createRouteBlk -layer all -cover -inst u_ANALOG_FIXLCS
c) Multiple power domain connections:
clearGlobalNets
globalNetConnect AVDD -type pgpin -pin AVDD -inst * # analog power
globalNetConnect DVDD -type pgpin -pin DVDD -inst * # digital power
globalNetConnect VSS -type pgpin -pin VSS -inst * # common ground
globalNetConnect DVDD -type tiehi -inst * -all
globalNetConnect VSS -type tielo -inst * -all
d) Power ring for multiple nets:
addRing -nets {DVDD AVDD VSS} -type core_rings ... # 3 nets instead of 2
e) Special routing for analog and IO power:
# Standard cell power routing
sroute -connect {corePin floatingStripe} -nets {DVDD VSS} ...
# Analog cell power routing (connect macro pins to ring)
sroute -connect {blockPin floatingStripe} -nets {DVDD AVDD VSS} \
-layerChangeRange {M1(1) AP(10)} -blockPinTarget {nearestTarget} ...
# IO pad power routing
sroute -nets {AVDD VSS DVDD} -connect {padPin} \
-padPinPortConnect {allPort oneGeom} -padPinTarget {nearestTarget} ...
6-signoff.tcl — Multiple GDS merge
streamOut ./output/${init_top_cell}.gds ... -merge {\
/path/to/tcbn65lp.gds # stdcell
/path/to/analog_macro.gds # analog macro GDS (ADD)
/path/to/tpdn65lpnv2od3.gds # IO pad GDS (ADD)
/path/to/other_macro.gds # any additional macros (ADD)
}
Also exclude IO filler cells in netlist output:
saveNetlist ./output/Calibre_${init_top_cell}_wo_filler.v \
-excludeCellInst {FILL1 FILL16 FILL2 FILL32 FILL4 FILL64 FILL8 \
PFILLER0005 PFILLER05 PFILLER1 PFILLER10 PFILLER20 PFILLER5}
Typical analog+IO project layout
{project}/innovus/
├── lib/
│ ├── tcbn65lp_9lmT2.lef # stdcell LEF
│ ├── {analog}_edited.lef # analog macro LEF (copied from template or provided)
│ ├── tpdn65lpnv2od3_9lm.lef.edited # IO pad LEF (copied from template)
│ ├── innovus_gds_out.map
│ └── quantus_extract.layermap
├── pre/
│ ├── {top}_netlist.v
│ ├── {top}.sdc
│ └── {top}.io # IO assignment file (pin-to-pad mapping)
├── scripts/
│ ├── all.tcl
│ ├── mmmc.tcl
│ ├── 1-init.tcl # includes analog + IO LEFs
│ ├── 2-fp.tcl # includes IO + analog placement
│ ├── 3-place.tcl # same as digital
│ ├── 4-cts.tcl # same as digital
│ ├── 5-route.tcl # same as digital (routing blockage protects analog)
│ └── 6-signoff.tcl # multi-GDS merge + IO filler exclusion
IO assignment file (.io)
The .io file defines which signal maps to which IO pad and the pad order around the die perimeter. This is design-specific and must be created for each project. The example template has pre/MIX_TOP.io as a reference for the format. Key points:
- Pad order is clockwise or counter-clockwise around the die edge
- Each line:
pad_instance_name pad_cell_type signal_name side offset
- Power pads (VDD/VSS) are interleaved with signal pads
- The number and placement of power pads affects IR drop