VC SpyGlass Lint Tutorial: Complete Setup Guide with I2C Example and Waiver File
A hands-on VC SpyGlass Lint walkthrough for RTL signoff: analyze/elaborate/check_lint flow, SGDC constraints, waive_lint waiver files, configure_lint_tag enable/disable, and fault-finding for InferredLatch W164a, MultiDriven W415, UndrivenSignal, and WidthMismatch on a real I2C Master IP.
1. What is VC SpyGlass Lint?
VC SpyGlass Lint is Synopsys' next-generation static analysis platform for RTL lint and ASIC/VLSI signoff. It catches structural RTL bugs before simulation: inferred latches, multiple drivers, undriven signals, width mismatches, tristate misuse, and hundreds of methodology rules across the STARC and OpenMORE rule decks.
The key shift from classic SpyGlass is that the VC SpyGlass flow is driven entirely by Tcl (analyze, elaborate, check_lint) instead of a .prj project file, and exceptions are controlled through tags and waiver files rather than inline RTL pragmas.
Never modify RTL source to suppress a lint violation. Use waiver files. RTL pragmas get lost in merges and silently hide real bugs. Waivers are auditable, ticketed, and survive code churn.
2. The Core Flow (analyze, elaborate, check_lint)
Every VC SpyGlass lint run follows the same five steps. This is the canonical Tcl flow you will reuse in every project:
| Step | Command | Purpose |
|---|---|---|
| 1. Analyze | analyze -format verilog -f filelist.f | Parse all RTL files. |
| 2. Elaborate | elaborate <top> | Build the netlist from the top module. |
| 3. Configure | configure_lint_tag -enable/-disable | Turn checks on or off by tag. |
| 4. Check | check_lint | Run the enabled rules for the lint_rtl goal. |
| 5. Report | report_lint -file report.rpt | Produce a violations report. |
3. Building the Environment (I2C Example)
We will use a simplified I2C Master IP. The top module is i2c_master_top,
and it consists of a bit controller, byte controller, register file, and clock divider.
The full RTL is available in the
I2C IP repo (placeholder).
Directory layout
i2c_ip/
rtl/
i2c_master_top.v
i2c_bit_ctrl.v
i2c_byte_ctrl.v
i2c_regs.v
i2c_clk_div.v
i2c.f # filelist
i2c_constraints.sgdc # SGDC constraints
i2c_waiver.tcl # waive_lint file
run_i2c_lint.tcl # SpyGlass Tcl run script
Filelist
i2c.f./rtl/i2c_master_top.v
./rtl/i2c_byte_ctrl.v
./rtl/i2c_bit_ctrl.v
./rtl/i2c_regs.v
./rtl/i2c_clk_div.v
SGDC constraint file
For an I2C master, the important SGDC constraints are the clocks and any black-boxed
PAD cells. If the SDA tristate buffer lives in a PAD macro, tell the tool to propagate through it with
assume_path. The official SGDC syntax reference is at the
SGDC constraint syntax page (placeholder).
// i2c_constraints.sgdc
current_design i2c_master_top
// I2C has a system clock and a generated SCL domain
clock -name "clk_i" -domain clk_domain
clock -name "scl_i" -domain scl_domain
// Propagate SDA direction through the PAD blackbox
assume_path -name I2C_PAD -input sda_dir -output sda_out sda_in
SpyGlass waiver file (waive_lint)
Every waiver is a legal record. It must name the exact design unit and carry a bug ticket or engineering justification in the comment. Unjustified waivers are rejected at signoff.
i2c_waiver.tcl# i2c_waiver.tcl
# Intentional latch in the register file, documented in BUG-1234
waive_lint -tag W164a \
-du i2c_regs \
-comment "BUG-1234: Intentional latch in register file" \
-owner "designer_a"
# Top-level test port tied off in synthesis
waive_lint -tag UnusedPort \
-du i2c_master_top \
-port "test_mode_i" \
-comment "BUG-5678: Test port tied off in synthesis"
4. The SpyGlass Tcl Run Script
This is the master SpyGlass Tcl script. It follows the standard flow, loads GuideWare methodology rules (without them most rules never fire), then reports and saves a session for interactive debugging.
run_i2c_lint.tcl# run_i2c_lint.tcl
# --- 1. Environment ---
set search_path [list . ./rtl]
set link_library "*"
set_app_var enable_lint true
# --- 2. Analyze and elaborate ---
analyze -format verilog -vcs {-f i2c.f}
elaborate i2c_master_top
# --- 3. SGDC constraints and waiver file ---
read_file -type sgdc i2c_constraints.sgdc
source i2c_waiver.tcl
# --- 4. configure_lint_tag enable / disable ---
configure_lint_tag -enable \
-tag {UseMuxBusses InferLatch MultiDriven UndrivenSignal} \
-goal lint_rtl
configure_lint_tag -disable \
-tag {STARC05-2.5.1.2} \
-goal lint_rtl
# --- 5. Run checks ---
configure_lint_setup -goal lint_rtl
check_lint
# --- 6. Report (include waived for audit) ---
report_lint -limit 0 -verbose -include_waived -file i2c_lint_report.rpt
# --- 7. Save session for GUI debug ---
checkpoint_session -session i2c_lint_session
The default rule deck is tiny. Loading the GuideWare methodology file is what activates the STARC, RMM, and structural rule sets that catch real bugs. See the GuideWare methodology reference (placeholder).
source $::env(VC_STATIC_HOME)/auxx/monet/tcl/GuideWare/block/rtl_handoff/lint/lint_rtl.tcl
5. Executing and Debugging
Batch run
vc_static_shell -f run_i2c_lint.tcl -batch -output_log_file i2c_run.log
Interactive debug with checkpoint_session and view_activity
Restore the saved session without re-running the entire analysis:
vc_static_shell -restore -session i2c_lint_session
# then inside the shell:
view_activity
configure_lint_tag: live enable and disable
You can also toggle tags without editing the script. Useful when investigating a noisy rule:
configure_lint_tag -disable -tag {TagName}
configure_lint_tag -enable -tag {TagName}
6. What to Look For (Fault Patterns)
After the run, do not drown in violation counts. Sort by severity, then weight. The following five patterns are where real I2C silicon bugs hide.
InferredLatch (W164a) Error
Classic in the register file. A case statement has a branch that does not assign every output.
This is the number one silent RTL killer. An inferred latch breaks timing and is invisible in simulation.
- Debug: click the violation, press
Ito open the schematic. Look for a feedback loop or an unassigned mux path. - Fix: add
default: data_out = 8'h00;or complete theelsebranch.
MultiDriven (W415) Error
Two always blocks or a continuous assignment plus an output pin driving the same net.
- Debug: open the schematic and inspect the driver end of the signal.
- Fix: consolidate into one
alwaysblock, or find the bad port connection.
UndrivenSignal Error
Signal is read but never assigned. In I2C this often means an empty port map entry.
- Debug: check instantiation for
.data()left empty. - Fix: drive it, tie it off, or waive it if it is a top-level input driven by the PAD.
WidthMismatch Warning
I2C is 8-bit wide. Watch for 32-bit constants or 10-bit addresses silently truncated.
- Fix: explicit slice (
[7:0]) or resize before assignment.
UseMuxBusses (tristate on SDA) Warning
RTL like assign sda = sda_dir ? sda_out : 1'bz; should normally live inside the PAD cell,
not in the core. Inside the core it breaks synthesis and layout.
- Fix: move the tristate to the top-level I/O ring. The core should only expose
sda_outandsda_dir. - Or waive it if it is intentional for simulation, with a comment referencing the PAD integration plan. See the PAD library datasheet (placeholder).
7. Waivers: The Rules
Waivers are how you keep the report clean without hiding real bugs. Treat them like a code review. The full waiver policy template is at the team signoff wiki (placeholder).
| Do | Do not |
|---|---|
| Include a bug ticket or ticket reference in the comment | Write "looks fine" or "noisy" |
Scope to a specific design unit (-du) | Waive a rule globally |
| Assign an owner | Leave it anonymous |
Review waivers with -include_waived in the report | Forget they exist |
| Remove dead waivers that no longer match a violation | Let dead waivers accumulate |
You cannot tape out with unresolved Errors. Warnings are acceptable only when they have an approved waiver with a ticket.
In the GUI data view, filter violations by module. Clear all Latches and MultiDriven in one module before moving to the next. This prevents the "1000 warnings" paralysis and surfaces systemic issues, like a whole bus left unconnected.
8. Related Resources
Placeholder cards. Swap the href and text for your real links when you publish.
This article is a VC SpyGlass Lint tutorial covering RTL lint, ASIC lint, and VLSI lint flows for RTL signoff. It demonstrates a SpyGlass Tcl script example, SGDC constraints, a SpyGlass waiver file with waive_lint, configure_lint_tag enable/disable, GuideWare methodology setup, and how to debug InferredLatch W164a, MultiDriven W415, UndrivenSignal, WidthMismatch, and UseMuxBusses violations on an I2C Master IP.