| name | t28-ioring-simulator |
| description | Build and run simulation testbenches for T28 IO ring or mixed-signal Cadence Virtuoso cells. Use when the user asks to create a testbench, export/redistribute a symbol, classify IO pins, place sources or loads, generate sim_config.json, run Spectre, sync Maestro setup, inspect simulation measurements, or continue a prior simulator run. |
T28 IO Ring Simulator
Build a simulation testbench around an existing Virtuoso DUT cell and optionally run direct Spectre simulation with Maestro setup sync.
This skill is the simulation sibling of t28-ioring-generator. Use the generator to create the IO ring schematic/layout; use this simulator on the generated or any existing schematic cell.
Output Contract
Use one shared output root:
AMS_OUTPUT_ROOT="${AMS_OUTPUT_ROOT:-<repo-root>/output}"
Simulator artifacts must go under:
${AMS_OUTPUT_ROOT}/simulation/<YYYYMMDD_HHMMSS>/
${AMS_OUTPUT_ROOT}/simulation/.latest_run
Do not create new runs under the old SIM-IO/output/ path.
Entry Points
| Situation | Start here |
|---|
Fresh run with lib and cell | Step 0 then Step 1 |
pin_info.json exists but classifications are missing | Step 2 |
pin_classifications.json and sim_config.json exist | Step 3 |
| Testbench exists and user only wants simulation | Step 4 |
Step 0: Environment Setup
Auto-detect paths from this skill root. Do not hard-code an absolute install path.
SKILL_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
SCRIPTS_PATH="${SKILL_ROOT}/scripts"
export PYTHONPATH="${SKILL_ROOT}:${PYTHONPATH:-}"
REPO_ROOT="$(cd "${SKILL_ROOT}" && while [ ! -f tools/t28_config_export.py ] && [ "$(pwd)" != "/" ]; do cd ..; done; pwd)"
VENV_ROOT="$(cd "${SKILL_ROOT}" && while [ ! -d .venv ] && [ "$(pwd)" != "/" ]; do cd ..; done; pwd)"
if [ -f "${VENV_ROOT}/.venv/Scripts/python.exe" ]; then export AMS_PYTHON="${VENV_ROOT}/.venv/Scripts/python.exe"
elif [ -f "${VENV_ROOT}/.venv/bin/python" ]; then export AMS_PYTHON="${VENV_ROOT}/.venv/bin/python"
elif command -v python3 >/dev/null 2>&1; then export AMS_PYTHON="python3"
elif command -v python >/dev/null 2>&1; then export AMS_PYTHON="python"
else echo "ERROR: No Python found."; return 1; fi
if [ -f "${REPO_ROOT}/tools/t28_config_export.py" ]; then
eval "$("$AMS_PYTHON" "${REPO_ROOT}/tools/t28_config_export.py" --shell sh)"
fi
export VB_DISABLE_CONTROL_MASTER="${VB_DISABLE_CONTROL_MASTER:-1}"
All subsequent commands use $AMS_PYTHON.
Required simulator configuration:
_local/site.yaml at the repository root.
~/.virtuoso-bridge/.env, created by virtuoso-bridge init, for bridge connection values.
Optional:
VB_DISABLE_CONTROL_MASTER (recommended 1 on Windows/OpenSSH jump-host setups)
Step 1: Symbol Export
Run when the user provides a Virtuoso library and cell with an existing schematic view.
$AMS_PYTHON "$SCRIPTS_PATH/symbol_export.py" <lib> <cell> [--vdd <vdd_value>]
What it does:
- Exports or regenerates
{lib}/{cell}/symbol from the schematic.
- Redistributes pins to a left/right testbench-friendly symbol layout.
- Extracts pin names, directions, positions, and sides.
- Writes
pin_info.json and dut_context.json.
- Writes
${AMS_OUTPUT_ROOT}/simulation/.latest_run.
Outputs:
output/simulation/<timestamp>/pin_info.json
output/simulation/<timestamp>/dut_context.json
output/simulation/<timestamp>/build/
Exit code 0 means proceed to Step 2. Exit code 1 means read stderr and fix environment, bridge, lib/cell, or schematic availability before continuing.
Step 2: Pin Intent Authoring
This is the deliberate LLM step between symbol export and testbench build.
Find the run directory from the path printed by Step 1, or read:
${AMS_OUTPUT_ROOT}/simulation/.latest_run
Then write two files into that run directory.
File 1: pin_classifications.json
- Read
references/pin_classification.md.
- Read
<run_dir>/pin_info.json.
- Classify every pin, including
_CORE pins and duplicated supply pins.
- Write
<run_dir>/pin_classifications.json.
Validate against:
scripts/pin_classify_schema.json
Key rules:
- Use
device_class to drive source/load topology.
- Assign analog local ground zones.
- Assign digital supply pairs.
- Use non-round stimulus values, for example
1.72, 2.7m, 137n.
File 2: sim_config.json
- Read
references/sim_config_rules.md.
- Collect every
vpulse period from pin_classifications.json.
- Set
tstop = 10 * max(per), clamped to [100n, 10u].
- Declare per-pin measurement intent in
pin_measurements.
- Write
<run_dir>/sim_config.json.
Validate against:
scripts/sim_config_schema.json
Do not write raw OCEAN expressions in outputs; use pin_measurements.
Step 3: Build Testbench
$AMS_PYTHON "$SCRIPTS_PATH/tb_builder.py" [--run-dir <run_dir>]
If --run-dir is omitted, the script reads ${AMS_OUTPUT_ROOT}/simulation/.latest_run.
What it does:
- Creates
{lib}/{cell}_tb/schematic.
- Places the DUT instance.
- Labels DUT terminals using label-based wiring.
- Places sources, loads, PVSS references, digital supply currents, and inner devices from
pin_classifications.json.
- Writes
result.json.
Output:
<run_dir>/result.json
If pin_classifications.json is missing, the script can fall back to heuristic classification, but for real T28 IO ring work you should write the classification file first.
Step 4: Direct Spectre Simulation with Maestro Sync
$AMS_PYTHON "$SCRIPTS_PATH/spectre_runner.py" [--run-dir <run_dir>] [--intent "<description>"]
What it does:
- Exports a fresh Spectre netlist from
{cell}_tb.
- Builds
deck.scs from sim_config.json plus model includes from _local/site.yaml.
- Runs Spectre directly.
- Parses PSF results locally.
- Writes measurements and SVG plots.
- Syncs the resolved setup into Maestro without running Maestro simulation.
Primary outputs:
<run_dir>/spectre/netlist.scs
<run_dir>/spectre/deck.scs
<run_dir>/spectre/spectre.out
<run_dir>/measurements.json
<run_dir>/sim_run_result.json
<run_dir>/plots/
Do not use Maestro results as the verification source for this route. Use sim_run_result.json, measurements.json, and plots/.
Optional: Maestro Runner
Use only for legacy/debug workflows:
$AMS_PYTHON "$SCRIPTS_PATH/maestro_runner.py" [--run-dir <run_dir>] [--run-sim]
Prefer spectre_runner.py for normal simulator validation.
Troubleshooting
| Problem | Action |
|---|
| Virtuoso connection fails | Check virtuoso-bridge status, local port, and daemon .il loaded in CIW |
lib/cell not found | Verify SIM_CDS_LIB or CDS_LIB_PATH_28 points to the right remote cds.lib |
| No schematic view | Open/create {lib}/{cell}/schematic before Step 1 |
| Wrong source/load placement | Re-read pin_classification.md and fix pin_classifications.json |
| Spectre model missing | Check spectre.io_model_include and spectre.core_model_include in _local/site.yaml |
| Spectre license error | Set spectre.lm_license_file and spectre.cds_lic_file in _local/site.yaml |
si netlist export hangs | Dismiss Virtuoso confirmation dialogs or check templates/si_spectre.env |
Completion Checklist