- name
- eda-sim
- description
- Offline EDA simulation workflow for ASIC DV projects using Synopsys VCS/Verdi. Use this skill whenever the user asks to run simulation, compile RTL, run regression, debug waveforms, read FSDB/waveform files, check coverage, or any task involving VCS/Verdi/UVM simulation. Also trigger when encountering compile errors, sim failures, needing to analyze sim.log results, or reading signal values from FSDB waveform dumps. This skill ensures correct offline tool invocation and includes an FSDB reader script using Synopsys NPI.
# Offline EDA Simulation Workflow
This skill defines the mandatory procedure for running Synopsys VCS simulations in an offline (no-network) environment. The EDA tools are installed locally but their default wrappers try to phone home for license validation, which fails without network access. The workaround is to invoke binaries directly and point to a local license server.
## Why This Matters
Synopsys tool wrappers (e.g., `vcs`, `verdi`) use `snpslmd` license checkout that may route through network namespaces. In offline setups, this fails silently or hangs. By calling the binary directly via `$VCS_BIN` (set in `.envrc`) and ensuring `SNPSLMD_LICENSE_FILE=27000@localhost.localdomain`, we bypass network dependencies entirely.
## Step 0: Environment Setup (MANDATORY, every session)
Before ANY EDA operation, source the project environment:
```bash
source <project_root>/.envrc
```
This sets all required variables. Verify with:
```bash
echo "VCS_BIN=$VCS_BIN"
echo "VERDI_HOME=$VERDI_HOME"
echo "LM_LICENSE_FILE=$LM_LICENSE_FILE"
```
If `.envrc` doesn't exist, create one following this template:
```bash
#!/bin/bash
export PROJECT_HOME="<absolute_path>"
export DV_ROOT="$PROJECT_HOME/dv"
export DIG_ROOT="$PROJECT_HOME/rtl"
export VCS_HOME="<path_to_vcs_installation>"
export VERDI_HOME="<path_to_verdi_installation>"
export SNPSLMD_LICENSE_FILE="27000@localhost.localdomain"
export LM_LICENSE_FILE="$SNPSLMD_LICENSE_FILE"
export VCS_BIN="$VCS_HOME/bin/vcs"
export VERDI_PLI_TAB="$VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab"
export VERDI_PLI_A="$VERDI_HOME/share/PLI/VCS/LINUX64/pli.a"
export PATH="$DV_ROOT/sim:$PATH"
```
## Step 1: Running a Single Test
Use the project Makefile when available:
```bash
cd $DV_ROOT/sim
make all CASE_NAME=<category/test_name>
```
If no Makefile or it doesn't work, use direct VCS invocation:
```bash
$VCS_BIN -full64 -top test_bench -sverilog -lca -kdb \
-f $DV_ROOT/sim/flist \
-timescale=1ns/1ps \
+notimingcheck +nospecify \
-debug_access+all \
+define+DUMPOFF \
+warn=noIPC +lint=TFIPC-L \
+error+20 \
-P $VERDI_PLI_TAB $VERDI_PLI_A \
-l compile.log
./simv +UVM_TESTNAME=base_test -l sim.log
```
Key points:
- Always use `$VCS_BIN` (the direct binary path), NEVER bare `vcs`
- `-timescale=1ns/1ps` sets default for modules without explicit timescale
- Do NOT use `-unit_timescale` — it overrides ALL modules including vendor IPs with different timescales, causing timing behavior changes
- Do NOT use `+memcbk` on VCS 2023.12+ — it's deprecated, use `-debug_access+all` instead
## Step 2: Running Regression
Use the project regression script:
```bash
cd $DV_ROOT/sim
./run_regr.sh [regr_list_name] # Default: regr_list
MAX_PARALLEL=8 ./run_regr.sh regr_list # Override parallel count
```
If writing a custom regression script, key patterns:
- Use `$VCS_BIN` not `vcs` for compilation
- Each test needs its own working directory with `current_case/` symlinks
- Create empty `define.sv` if the test case doesn't provide one (flist requires it)
- Check `sim.log` for `$finish` AND filter error/warning lines using `exclude.txt`
- Use `timeout` command to prevent hung simulations
## Step 3: Post-Processing Results
Check simulation pass/fail:
```bash
# 1. Verify simulation completed
grep -q '$finish' sim.log && echo "SIM FINISHED" || echo "SIM INCOMPLETE"
# 2. Check for errors (filter known benign patterns via exclude.txt)
grep -iE 'error|warning' sim.log \
| grep -v 'Warning-\[' \
| grep -v 'UVM_WARNING *:' \
| grep -v 'UVM_ERROR *:' \
| grep -v 'UVM_FATAL *:' \
| grep -v -f exclude.txt
```
Common false positive patterns to add to `exclude.txt`:
- `error_type.*v_error_type_e` — UVM transaction field prints
- `^UVM_INFO` — info messages containing "error" substring
- `error_en 0 rand_num` — error-enable field in protocol logs
- `Command:.*simv` — VCS command line echoes containing "error" in paths
- `illegal seting of role control` — analog model transient states
- `MEM_Error` — SRAM model clock glitch in functional sim (no SDF)
## Step 4: Waveform Debug (if needed)
```bash
# Recompile with waveform dump enabled
make all CASE_NAME=<name> FSDB=1
# Launch Verdi
$VERDI_HOME/bin/verdi -elab simv.daidir/kdb.elab++ -ssf test.fsdb
```
## Step 5: Coverage
```bash
# After regression, merge coverage databases
urg -full64 -dir $(find . -name "*.vdb") -dbname merge.vdb
# View in Verdi
$VERDI_HOME/bin/verdi -cov -covdir merge.vdb
```
## Step 6: FSDB Waveform Reading (without Verdi GUI)
FSDB is a Synopsys proprietary binary format. Use the bundled `scripts/fsdb_reader.py` to read signals programmatically. The script uses **Synopsys NPI (primary)** or CLI tools (fallback), no GUI needed.
**IMPORTANT**: NPI requires Verdi's bundled Python 3.6 (`$VERDI_HOME/platform/linux64/Python/bin/python3.6`). The script auto-detects this. System Python (3.7+) will cause segfault with NPI `.so` files — the script handles this transparently by invoking Verdi's Python as a subprocess.
### Read a signal's value changes
```bash
python3 <skill_dir>/scripts/fsdb_reader.py <file.fsdb> --signal <path> [--start <time>] [--end <time>] [--format h]
```
Signal paths use `.` as hierarchy separator (NPI native format):
```bash
python3 scripts/fsdb_reader.py test.fsdb --signal test_bench.u_chip.clk --end 100ns
```
Format options: `b` (binary), `o` (octal), `d` (decimal), `u` (unsigned), `h` (hex, default).
### List signals in an FSDB
```bash
python3 scripts/fsdb_reader.py test.fsdb --list-signals --depth 2
```
### Convert FSDB to VCD
```bash
python3 scripts/fsdb_reader.py test.fsdb --to-vcd --output out.vcd [--end 1us]
```
VCD is a text format readable by any tool. Use `--end` to limit file size for large FSDBs.
### Force CLI fallback mode
```bash
python3 scripts/fsdb_reader.py test.fsdb --signal test_bench.clk --cli
```
### Direct CLI (alternative)
If the script isn't available, use Verdi tools directly:
```bash
# Read signal values (fsdbreport uses / separator, writes report.txt to CWD)
$VERDI_HOME/bin/fsdbreport file.fsdb -s "test_bench/signal_name" -of h -et 1us
# Convert to VCD
$VERDI_HOME/bin/fsdb2vcd file.fsdb -o output.vcd -et 1us
```
### Generating FSDB from simulation
To enable FSDB dump, run with `FSDB=1`:
```bash
make all CASE_NAME=<name> FSDB=1
```
If the testbench `$fsdbDumpvars` is commented out, use UCLI at runtime:
```bash
echo 'call {$fsdbDumpfile("test.fsdb")}
call {$fsdbDumpvars(0, test_bench)}
run
quit' > dump.tcl
./simv +UVM_TESTNAME=base_test -ucli -i dump.tcl -l sim.log
```
## Compilation Troubleshooting
| Error | Cause | Fix |
|-------|-------|-----|
| `Error-[DEBUG_DEP_ERROR] +memcbk deprecated` | VCS 2023.12+ removed `+memcbk` | Use `-debug_access+all` instead |
| `Error-[XMRE] Cross-module reference` | Test references instances not in current TB | Check if the model/module exists in the testbench |
| `Error-[UM] Undefined macro` | Missing `+define+` or define file not compiled before RTL | Ensure `define.sv` is listed BEFORE RTL in flist |
| `Error-[SFCOR] Source file cannot be opened` | Generated file (e.g., from TCL script) not created | Run the generation script (e.g., `tclsh gen_regs.tcl > test_cmd.sv`) |
| `Error-[SE] Syntax error: parameter in begin block` | `parameter`/`localparam` not allowed in procedural blocks | Inline the constant value or move declarations before assignments |
| License checkout failure / tool hangs | Network wrapper can't reach license server | Use `$VCS_BIN` directly instead of `vcs` wrapper |
## Regression Analysis Checklist
When analyzing regression failures:
1. Classify failures: COMPILE FAIL vs SIM FAIL vs TIMEOUT
2. For SIM FAIL, check `check_log_failed.log` — if it only contains `V_NO_ERROR` or `error_type` lines, it's a false positive
3. Group failures by error pattern (ADC value mismatch, CC timing, MEM_Error, etc.)
4. Fix the highest-impact issues first (false positive filtering fixes the most tests)
5. Re-process existing sim.log files when only the pass/fail checker changed (no need to re-simulate)
Auf GitHub ansehen