Local-first RTL verification helper for UVM scaffolds, protocol checks, logs, and reports.
Project description
LazyUVM
LazyUVM is a local-first RTL verification helper that turns simple Verilog/SystemVerilog modules into starter testbenches, protocol guesses, UVM skeletons, and simulation-log triage reports.
It is intentionally small: one Python file, no required Python packages, and optional local AI through Ollama.
The LazyUVM checked badge means the repository's smoke checks pass on GitHub Actions. It is a quick project-health signal, not silicon sign-off.
What It Does Today
- Scans RTL files and reports modules, parameters, ports, widths, and directions.
- Generates starter SystemVerilog testbenches.
- Infers common bus protocols from port names:
- APB
- AHB
- AXI-Lite
- AXI-Stream
- Prints a simple multi-file hierarchy tree from module instances.
- Reads simulator-style filelists with source files, include dirs, defines, and nested
-fentries. - Emits copy/paste Verilator, VCS, and Questa command lines from a project filelist.
- Resolves simple parameterized port widths such as
[WIDTH-1:0]and[(DATA_WIDTH/8)-1:0]. - Runs lightweight static RTL checks for unresolved instances, unconnected ports, reset oddities, and obvious width mismatches.
- Cross-checks simple text spec rules against simulator log timelines.
- Generates UVM skeleton files:
- interface
- sequence item
- driver
- monitor
- sequencer
- sequence
- agent
- env
- smoke test
- top module
- filelist
- Emits APB-aware driver and monitor handshake timing.
- Emits AXI-Lite-aware driver and monitor handshake timing across write address, write data, write response, read address, and read data channels.
- Emits protocol-aware SVA and coverage starter files:
- APB setup/access/wait-state assertions
- AXI-Lite valid/ready hold assertions
- APB and AXI-Lite covergroup starter models
- Emits SystemVerilog
bindfiles that attach generated SVA and coverage sentinels to the DUT. - Runs a local auto-run loop that generates artifacts, lints with Verilator, compiles with
iverilog, runsvvp, triages logs, and writes a Markdown report. - Runs a seed-based local regression loop over selected modules and writes a PASS/FAIL case matrix.
- Runs a small
regress.yamltest plan so projects can keep repeatable smoke tests in source control. - Triages text coverage reports and suggests concrete next stimulus targets for low or missing coverage.
- Writes starter SystemVerilog directed-stimulus skeletons from coverage holes.
- Summarizes simulator logs with built-in rules, a time-ordered event timeline, and optional local Ollama AI.
- Stores and reuses explicit local-only log and coverage issue patterns when
--learn-cacheand--use-cacheare used.
Why This Exists
Research frameworks such as UVLLM and UVMarvel explore ambitious LLM-driven RTL verification flows. LazyUVM is deliberately narrower: a lightweight CLI that a student, junior engineer, or small team can clone and run locally in a few minutes.
| Area | Research Frameworks | LazyUVM |
|---|---|---|
| Goal | Broad automated verification research | Fast local UVM scaffold generation |
| Setup | Larger framework and experiment flow | Single Python script |
| AI | Often benchmarked with large LLM workflows | Optional local Ollama model |
| First use | Read paper, configure stack, run experiments | Run one command on an RTL file |
| Current strength | Full research pipeline | Protocol-aware starter files |
LazyUVM is not a replacement for a signoff verification flow. It is a bootstrap tool for getting from "I have RTL" to "I have a first UVM environment shape" quickly.
Installation
From a local checkout:
python3 -m pip install -e .
lazyuvm --version
lazyuvm --help
With pipx from GitHub:
pipx install git+https://github.com/jeonghunx/LazyUVM.git
After a PyPI release, the target install flow is:
pipx install lazyuvm
Contributors can still run python3 rtl_scout.py ... directly from the repository, but lazyuvm ... is the preferred CLI.
Release Status
Current package version: 0.1.0
- See
CHANGELOG.mdfor the release history. - See
docs/releases/v0.1.0.mdfor the first release note draft. - The GitHub Actions badge should be green before cutting a release tag.
- PyPI publishing is configured through
.github/workflows/release.ymland PyPI Trusted Publishing.
Quick Start
cd "/mnt/c/Users/jeonghun-dev/Documents/New project"
lazyuvm --version
lazyuvm --filelist examples/files.f --hierarchy
lazyuvm --filelist examples/files.f --checks
lazyuvm --filelist examples/files.f --auto-run --no-ai
lazyuvm --regress-file examples/regress.yaml --no-ai
lazyuvm --uvm-dir generated_uvm examples/apb_timer.sv
For focused examples, see the sections below for filelists, tool commands, regression, coverage triage, hierarchy, auto-run, log analysis, and reviewed pattern packs.
Generated files appear under:
generated_uvm/apb_timer/
The UVM generator now also writes assertion and coverage sentinels:
generated_uvm/apb_timer/lazyuvm_apb_timer_sva.sv
generated_uvm/apb_timer/lazyuvm_apb_timer_coverage.sv
generated_uvm/apb_timer/lazyuvm_apb_timer_bind.sv
generated_uvm/axi_lite_gpio/lazyuvm_axi_lite_gpio_sva.sv
generated_uvm/axi_lite_gpio/lazyuvm_axi_lite_gpio_coverage.sv
generated_uvm/axi_lite_gpio/lazyuvm_axi_lite_gpio_bind.sv
The bind files use SystemVerilog bind plus implicit port connections, so the generated sentinels can be attached to the DUT without editing the original RTL.
Generated outputs are ignored by Git because they can be recreated at any time.
Filelist Project Linker
Real RTL projects often compile from a files.f file instead of a single source path. LazyUVM can now use that same project entry point:
lazyuvm --filelist examples/files.f --hierarchy
lazyuvm --filelist examples/files.f --checks
lazyuvm --filelist examples/files.f --auto-run --no-ai
Supported filelist syntax:
+incdir+include
+define+SIMULATION
+define+WIDTH=32
-f nested_files.f
rtl/top.sv
rtl/block.sv
File paths and nested filelists are resolved relative to the filelist that mentions them. --auto-run passes include dirs and defines through to Verilator and Icarus Verilog, then records the exact reproduce commands in the Markdown report.
Tool Command Generator
LazyUVM can turn a project filelist into copy/paste commands for common RTL tools without launching licensed software:
lazyuvm --filelist examples/files.f --emit-tool verilator
lazyuvm --filelist examples/files.f --emit-tool vcs
lazyuvm --filelist examples/files.f --emit-tool questa
Example output:
verilator --lint-only --sv -f examples/files.f
vcs -sverilog -full64 -f examples/files.f
vlog -sv -f examples/files.f
When you pass --module, LazyUVM treats it as the top/module hint:
lazyuvm --filelist examples/files.f --emit-tool verilator --module chip_top
lazyuvm --filelist examples/files.f --emit-tool vcs --module chip_top
lazyuvm --filelist examples/files.f --emit-tool questa --module chip_top
Regression Runner
For a small local regression:
lazyuvm --filelist examples/files.f --regress --seeds 1,2,3 --no-ai
This writes:
LazyUVM_Regression.md
.lazyuvm_regress/
The regression runner:
- generates a smoke testbench for each selected module
- passes
+LAZYUVM_SEED=<seed>intovvp - repeats each module across the requested seed list
- keeps each case in its own workspace folder
- records lint, compile, simulation, and overall PASS/FAIL status in a Markdown matrix
Seed ranges are supported:
lazyuvm --filelist examples/files.f --regress --seeds 1-10 --module chip_top --no-ai
This is still an early screening loop, not signoff. Its job is to make local smoke regressions cheap enough to run constantly.
For a project-owned regression plan:
lazyuvm --regress-file examples/regress.yaml --no-ai
Example regress.yaml:
tests:
- name: apb_smoke
files: files.f
module: apb_timer
seeds: 1,2
- name: axi_smoke
files: files.f
module: axi_lite_gpio
seeds: 1,2
Paths in the YAML file are resolved relative to that YAML file, so a test plan under examples/ can simply use files: files.f.
Supported keys:
name: test name shown in reportsfilesorfilelist: one filelist path or a short listmoduleortop: module to runseeds: comma list or range such as1,2,3or1-10
Coverage Triage
For a text coverage report:
lazyuvm --analyze-coverage examples/coverage_report.txt --no-ai
LazyUVM extracts:
- coverage percentages such as line, branch, toggle, and functional coverage
- common vendor-style table rows with covered/total/percent columns
- ratio-only rows such as
0/1when the row looks like coverage data - low coverage metrics below a threshold
- explicit miss lines such as
0 hits,Hits: 0,Count = 0,uncovered,not covered, andnever hit - rule-based next stimulus ideas for APB, AXI-Lite, reset, FSM, and toggle holes
To change the low-coverage threshold:
lazyuvm --analyze-coverage examples/coverage_report.txt --coverage-threshold 80 --no-ai
To write the analysis to a file:
lazyuvm --analyze-coverage examples/coverage_report.txt --coverage-md LazyUVM_Coverage.md --no-ai
With Ollama available, omit --no-ai to add a local summary on top of the rule-based findings.
To generate starter SystemVerilog stimulus tasks from the same coverage holes:
lazyuvm --analyze-coverage examples/coverage_report.txt --coverage-stimulus-dir generated_stimulus --module apb_timer --no-ai
lazyuvm --analyze-coverage examples/vendor_coverage_report.txt --coverage-stimulus-dir generated_stimulus --module apb_timer --no-ai
This writes a skeleton such as:
generated_stimulus/lazyuvm_apb_timer_coverage_stimulus.sv
The generated file contains task stubs for holes such as APB wait states, AXI-Lite backpressure, reset edges, toggles, and generic directed bins. It also records parsed targets such as source locations, coverpoints, bins, branch conditions, and likely protocol signals. It intentionally leaves BFM/UVM calls as TODO comments because real projects name their sequence APIs differently.
Hierarchy Scan
For a folder with multiple RTL files:
lazyuvm --hierarchy examples
lazyuvm --hierarchy --module chip_top examples
This prints top-module candidates and a simple instance tree, for example:
chip_top [AXI-Lite 95%, APB 80%]
|-- apb_timer u_timer [APB 90%]
`-- axi_lite_gpio u_gpio [AXI-Lite 100%]
Width Solver
For parameterized designs:
lazyuvm --widths examples/axi_lite_gpio.sv
This resolves simple integer expressions in packed ranges:
axi_lite_gpio:
parameters:
ADDR_WIDTH = 12 => 12
DATA_WIDTH = 32 => 32
ports:
input awaddr: [ADDR_WIDTH-1:0] => 12 bits
input wstrb: [(DATA_WIDTH/8)-1:0] => 4 bits
Static Checks
For a quick local RTL review:
lazyuvm --checks examples
LazyUVM checks what it can prove from the local source:
- unresolved module instances
- unconnected named child ports
- obvious parent/child port width mismatches
- clock-like modules without reset-like inputs
- reset-like ports with suspicious directions
These checks are intentionally conservative: if LazyUVM cannot infer a width confidently, it avoids guessing a mismatch.
Auto-Run Report
For a one-command local triage loop:
lazyuvm --auto-run examples/apb_timer.sv
This writes:
LazyUVM_Report.md
.lazyuvm/
The auto-run loop:
- scans the RTL
- runs lightweight static RTL checks
- generates a starter testbench
- generates UVM skeleton files
- lints the RTL with Verilator when available
- compiles with
iverilog - runs with
vvp - triages lint/compile/simulation logs
- optionally asks local Ollama for an explanation
- writes patch suggestions under
.lazyuvm/patches/
If Verilator is not installed or you only want the simulator path:
lazyuvm --auto-run --no-lint examples/apb_timer.sv
Safety rule: LazyUVM does not modify your RTL source files during auto-run. Patch suggestions are isolated for manual review.
Local AI Log Analysis
AI is optional. The rule-based analyzer works without Ollama:
lazyuvm --analyze-log examples/sim_error.log --no-ai
lazyuvm --analyze-log examples/timing_trace.log --no-ai
The log analyzer extracts suspicious lines and a compact timeline before local AI is used:
Timeline:
100ns L3 [event] signals: psel=1, penable=0, pwrite=1
120ns L5 [error] signals: penable=1, penable=0, psel=1, pready=0
130ns L7 [fatal] signals: psel=1, penable=0, pready=0
With Ollama:
curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3.2:1b
lazyuvm --analyze-log examples/sim_error.log --ollama-model llama3.2:1b
Spec-Aware Log Cross-Check
For a small spec/log comparison:
lazyuvm --analyze-log examples/timing_trace.log --spec examples/spec.txt --no-ai
LazyUVM extracts simple requirement lines containing words such as must, shall, within N cycles, after reset, and remain high until, then compares the supported rules against the log timeline.
Example requirement:
PENABLE must assert one cycle after PSEL is asserted.
PSEL must remain high until PREADY.
The checker is intentionally conservative. It reports direct evidence from the timeline, for example:
Spec expects `penable` after `psel`, but timeline never shows `penable=1` before the failure evidence.
This is a fact cross-check, not a full natural-language spec verifier.
Local Pattern Cache
LazyUVM does not upload project data. By default, it only prints analysis results. If you explicitly add --learn-cache, it stores a small local pattern entry under .lazyuvm_cache/patterns.json.
lazyuvm --analyze-log examples/timing_trace.log --spec examples/spec.txt --learn-cache --no-ai
lazyuvm --analyze-coverage examples/coverage_report.txt --learn-cache --no-ai
lazyuvm --cache-report
After patterns are learned, use --use-cache to compare the current log or coverage report with the local project memory:
lazyuvm --analyze-log examples/timing_trace.log --spec examples/spec.txt --use-cache --no-ai
lazyuvm --analyze-coverage examples/coverage_report.txt --use-cache --no-ai
The cache keeps normalized fingerprints, categories, repeated-hit counts, signal names found in timelines, and short rule-based hints. Cache matching uses local fingerprints plus category, signal, and hint-token overlap. It is meant to become a private project memory, not hidden telemetry.
Use a custom cache folder when you want to keep experiments separate:
lazyuvm --analyze-log examples/timing_trace.log --learn-cache --cache-dir /tmp/lazyuvm_cache --no-ai
lazyuvm --analyze-log examples/timing_trace.log --use-cache --cache-dir /tmp/lazyuvm_cache --no-ai
For team sharing without a central server, export and import the cache as a plain JSON file:
lazyuvm --cache-export lazyuvm_patterns.json
lazyuvm --cache-import lazyuvm_patterns.json
lazyuvm --cache-report
Import merges by fingerprint. Re-importing the same file updates matching entries instead of duplicating them, so teams can pass around a reviewed pattern pack in source control, chat, or an internal artifact store.
For a reviewed team pattern pack, mark only trusted entries before exporting:
lazyuvm --cache-report
lazyuvm --cache-review b5064cf --review-note "APB setup/access timeout seen in smoke regressions"
lazyuvm --cache-export-reviewed lazyuvm_reviewed_patterns.json
lazyuvm --cache-import lazyuvm_reviewed_patterns.json
--cache-review and --cache-unreview accept unique fingerprint prefixes, so you do not need to type the full hash.
For a self-hosted team registry, publish reviewed packs into a shared folder:
lazyuvm --registry-dir /shared/lazyuvm_registry --registry-publish apb_smoke
lazyuvm --registry-dir /shared/lazyuvm_registry --registry-list
lazyuvm --registry-dir /shared/lazyuvm_registry --registry-pull apb_smoke
The registry is just files:
lazyuvm_registry.json
packs/apb_smoke.json
That makes it usable with an internal Git repo, shared drive, artifact store, or any company-controlled file server. No external service is required.
As the cache grows, inspect and prune it:
lazyuvm --cache-stats
lazyuvm --cache-prune 100
lazyuvm --cache-stats
Pruning keeps the highest-count and most recently seen entries first. Use export before pruning if you want a backup:
lazyuvm --cache-export lazyuvm_patterns_backup.json
lazyuvm --cache-prune 100
License
LazyUVM is released under GPLv3. Commercial licensing can be considered separately for companies that need different terms.
This is not legal advice; talk to a lawyer before using any open-source license strategy commercially.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lazyuvm-0.1.0.tar.gz.
File metadata
- Download URL: lazyuvm-0.1.0.tar.gz
- Upload date:
- Size: 70.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32c7444592d570a7721a42fdd117b20600d8915f682eadf59c8c01f4794d7c28
|
|
| MD5 |
0b69302e422bba7b86b6063b6023e45f
|
|
| BLAKE2b-256 |
68ac163f1c597ed76789e2607e25f66903c3c7d2a43e51316824c6015f22875f
|
Provenance
The following attestation bundles were made for lazyuvm-0.1.0.tar.gz:
Publisher:
release.yml on jeonghunx/LazyUVM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazyuvm-0.1.0.tar.gz -
Subject digest:
32c7444592d570a7721a42fdd117b20600d8915f682eadf59c8c01f4794d7c28 - Sigstore transparency entry: 1894278689
- Sigstore integration time:
-
Permalink:
jeonghunx/LazyUVM@76d7578c8ae9a56ae556f3434a846b4c8344522c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jeonghunx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@76d7578c8ae9a56ae556f3434a846b4c8344522c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file lazyuvm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lazyuvm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 71.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef8cb30c2815eb1f5f3fb5a5e21842652b4b422a699b775cd0eef61101254499
|
|
| MD5 |
9271f22cc1324004d6d59d8bc5f64553
|
|
| BLAKE2b-256 |
d8d6b2c4b31c21a17d59bacf9d48e0e064f22b65fd34e5816a83593df1c2ab31
|
Provenance
The following attestation bundles were made for lazyuvm-0.1.0-py3-none-any.whl:
Publisher:
release.yml on jeonghunx/LazyUVM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazyuvm-0.1.0-py3-none-any.whl -
Subject digest:
ef8cb30c2815eb1f5f3fb5a5e21842652b4b422a699b775cd0eef61101254499 - Sigstore transparency entry: 1894278925
- Sigstore integration time:
-
Permalink:
jeonghunx/LazyUVM@76d7578c8ae9a56ae556f3434a846b4c8344522c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jeonghunx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@76d7578c8ae9a56ae556f3434a846b4c8344522c -
Trigger Event:
workflow_dispatch
-
Statement type: