Skip to content

Latest commit

 

History

History
467 lines (359 loc) · 17.2 KB

File metadata and controls

467 lines (359 loc) · 17.2 KB

AGENTS.md - AI Assistant Notes

This document provides guidance for AI assistants working on the STG-Rust codebase.

Project Overview

STG (Structured Testbench Generation) is a Rust tool that automatically generates comprehensive testbenches for Verilog/SystemVerilog designs. It compares a Design Under Test (DUT) against a golden reference model.

Core Functionality

  • Parse Verilog/SystemVerilog modules and extract port information
  • Classify signals into control vs. data, and inputs vs. outputs
  • Generate semi-exhaustive test patterns with intelligent coverage
  • Support multiple testbench modes: SystemVerilog, C++, and SystemC
  • Compare DUT outputs against golden reference and report statistics

Key Design Principles

  1. Type Safety: Leverage Rust's type system to prevent entire classes of bugs
  2. Performance: Native binary with no runtime interpreter overhead
  3. Flexibility: Support multiple modes (SV, CC, SC) and design types
  4. Portability: Single binary that can be shipped anywhere

Architecture

Directory Structure

stg-rust/
├── src/
│   ├── main.rs              # Entry point, CLI parsing
│   ├── lib.rs               # Library exports
│   ├── cli.rs               # CLI argument definitions (using clap)
│   ├── python_runtime.rs    # Python environment management for LM features
│   ├── commands/            # Command implementations
│   │   ├── generate.rs      # Main testbench generation logic
│   │   ├── generate_fsm.rs  # FSM-based coverage-enhanced generation
│   │   ├── compile.rs       # Testbench compilation
│   │   ├── identify.rs      # Signal classification
│   │   └── parse.rs         # Module parsing and priority sorting
│   └── tools/               # Core functionality modules
│       ├── verilog_parser.rs      # Verilog parsing (sv-parser + iverilog)
│       ├── signal_classification.rs # Signal type identification
│       ├── generator.rs           # Testbench template generation
│       ├── compiler.rs            # iverilog/Verilator compilation
│       ├── emplace_verilog.rs     # Module emplacement (SV mode)
│       ├── fsm_extractor.rs       # FSM extraction for coverage
│       ├── fsm_analysis.rs        # FSM analysis and DFS engine
│       └── file_utils.rs          # File I/O utilities
├── examples/                # Test cases and examples
│   ├── ALU/                # Combinational logic example
│   ├── ALU_cc/             # C++ testbench example
│   ├── pingpong/           # Sequential clocked example
│   ├── seq_detector/       # FSM coverage example
│   └── traffic_light/      # Traffic light FSM example
├── tests/                  # Rust integration tests
└── docs/                   # Sphinx documentation

Key Components

1. Verilog Parser (verilog_parser.rs)

  • Hybrid approach: Uses sv-parser for Rust-based parsing, falls back to iverilog for port information
  • Module priority sorting: Analyzes instantiation hierarchy and submodule counts
  • Port extraction: Identifies inputs, outputs, widths, and signal types

2. Signal Classification (signal_classification.rs)

  • Identifies control signals (opcodes, enables, modes) vs. data signals (values, addresses)
  • Detects special signals: clock, reset, done/valid
  • Uses heuristics: signal width, naming patterns, module context

3. Generator (generator.rs)

  • Generates testbench templates from Tera templating engine
  • Three modes: SystemVerilog (SV), C++ (CC), SystemC (SC)
  • Test pattern generation strategy:
    • Control signals: Exhaustive enumeration (up to 2^26 combinations)
    • Data signals: Random sampling (default: 1024 samples per control vector)

4. Compiler (compiler.rs)

  • iverilog: Traditional SystemVerilog compilation
  • Verilator: High-performance C++ conversion with optional MPI support
  • Coverage analysis support (generates .dat files)
  • Multi-DUT support with unique prefixes (V0_, V1_, V2_...)

5. FSM Tools (fsm_extractor.rs, fsm_analysis.rs)

  • Extract FSM state machines from Verilog (deterministic or LM-assisted)
  • Generate state transition graphs
  • DFS-based test generation for complete state coverage
  • Hierarchical signal access for internal state monitoring

Design Types

STG supports three fundamental design types:

1. Combinational (combinational)

  • Pure combinational logic (no clock, no state)
  • Test approach: Enumerate control signals, random data signals
  • Examples: ALU, multiplexers, decoders
  • Golden model: Implements eval() function

2. Sequential Clocked (seq_clocked)

  • Clocked sequential design with continuous operation
  • Requires clock and usually reset signals
  • Test approach: Apply random control/data patterns over multiple clock cycles
  • Examples: Counters, shift registers, timers
  • Golden model: Implements posedge_clk() function

3. Sequential Done (seq_done)

  • Sequential design with transaction-based operation
  • Requires clock, reset, and done/valid signal
  • Test approach: Start transaction, wait for done signal, check results
  • Examples: GCD, dividers, state machines with completion signals
  • Golden model: Implements posedge_clk() and tracks completion

Testbench Modes

SystemVerilog Mode (SV)

  • Both DUT and golden are Verilog modules
  • Uses iverilog or Verilator for compilation
  • Single-stage workflow
  • Good for: Simple designs, standard workflow

C++ Mode (CC)

  • DUT is Verilog, golden is C++ header file
  • Two-stage workflow:
    1. Generate template with --out-header golden_model.h
    2. Implement golden model, then compile with --golden golden_model.h
  • Uses Verilator for DUT compilation
  • Good for: Complex golden models, custom logic, performance

SystemC Mode (SC)

  • Similar to CC but uses SystemC types (sc_uint<N>)
  • Two-stage workflow like CC
  • Good for: SystemC ecosystem integration, bit-accurate types

Multi-DUT Support

STG can test multiple DUT implementations simultaneously against one golden reference.

Key Features

  • Compare multiple implementations in one run
  • Individual statistics for each DUT in test_stats.json
  • Automatic unique prefixes (V0_, V1_, V2_...)
  • In SV mode: Use --emplace-module to avoid module name conflicts
  • In CC/SC mode: Verilator handles renaming automatically

Module Specification Methods

  1. Single name: --module alu (used for all DUTs)
  2. Comma-separated: --module alu1,alu2,alu3
  3. Interleaved: --verilog dut1.v --module alu1 --verilog dut2.v --module alu2

Important Conventions

Signal Naming

  • Clock signals: clk, clock
  • Reset signals: rst, rst_n, reset, reset_n
  • Done/Valid signals: done, valid, ready
  • Control signals: Usually narrow (1-4 bits), named like op, mode, cmd
  • Data signals: Usually wider (8+ bits), named like a, b, data, addr

Coding Patterns

  • Error handling: Use Result<T, String> for recoverable errors
  • File paths: Always use PathBuf and handle path operations carefully
  • Template rendering: Use Tera for all code generation
  • External tools: Shell out to iverilog, verilator using std::process::Command

Testing

  • Examples in examples/ serve as integration tests
  • Each example has a README.md and Makefile
  • Run cargo test for unit tests
  • Test examples with their Makefiles: make -C examples/ALU

Common Workflows

Adding a New Feature to Testbench Generation

  1. Update CLI (cli.rs):

    #[arg(long, help = "Your new feature")]
    pub new_feature: bool,
  2. Modify Generator (tools/generator.rs):

    • Add template variables in the generation context
    • Update Tera template rendering
  3. Update Templates (embedded in code or separate files):

    • Add new template sections
    • Use Tera syntax: {% if new_feature %}...{% endif %}
  4. Test:

    • Create example in examples/new_feature/
    • Add README.md and test files
    • Run and verify output

Adding Support for a New Signal Type

  1. Update Classification (tools/signal_classification.rs):

    • Add detection logic in signal classification algorithm
    • Update SignalInfo struct if needed
  2. Update Generator (tools/generator.rs):

    • Add handling for new signal type in testbench templates
    • Update test pattern generation
  3. Update Documentation:

    • Add to USAGE.md with examples
    • Update CLI help text

Debugging Verilog Parsing Issues

  1. Enable debug output: --debug flag
  2. Check parser fallback: sv-parser fails gracefully, iverilog provides backup
  3. Verify module names: Use stg parse to see what modules are detected
  4. Check port extraction: Use stg identify to see classified signals

FSM Coverage Enhancement

Overview

New feature for achieving higher coverage in sequential designs by extracting FSM structure.

Documentation: See docs/source/user_guide/fsm_coverage.md for the generate-fsm command guide.

Two Approaches

Option A: LM-Based Extraction

  • Uses language models (OpenAI, Gemini) to identify FSMs
  • Python-based, managed through python_runtime.rs
  • Environment setup with uv package manager
  • API keys from .env file (e.g., GOOGLE_API_KEY)

Option B: Deterministic Extraction

  • Parser/AST-based approach using iverilog or sv-parser
  • Extract state variables, state transitions
  • More reliable but less flexible than LM approach

DFS Test Generation

  • Uses extracted state transition graph
  • Performs depth-first search to cover all states
  • Generates targeted input sequences
  • Key advantage: Achieves states that random testing misses

Hierarchical Signal Access

  • Verilator supports accessing internal signals: dut->module->signal
  • Condition monitoring: Wait for internal states (e.g., counters reaching values)
  • Enables state-aware testing beyond just input/output

Examples

  • examples/seq_detector/: Sequence detector FSM
  • examples/traffic_light/: Traffic light controller FSM
  • Compare coverage: traditional vs. FSM-enhanced

Common Pitfalls and Warnings

1. Module Name Conflicts

Problem: Multiple Verilog files with same module names cause compilation errors Solution:

  • SV mode: Use --emplace-module to add prefixes
  • CC/SC mode: Verilator handles automatically with unique prefixes

2. Signal Classification Errors

Problem: Important control signals classified as data (or vice versa) Solution: Explicitly specify with --control-signals or --data-signals

3. Path Handling

Problem: Relative paths may break in different contexts Solution: Convert to absolute paths early using std::fs::canonicalize()

4. Golden Model Template

Problem: Users forget two-stage workflow in CC/SC mode Solution: Clear error messages mentioning stage 1 and stage 2

5. Verilator Version Compatibility

Problem: Older Verilator versions may not support required features Solution: Recommend Verilator v5.020+ in documentation and error messages

6. Coverage File Conflicts

Problem: MPI processes write to same coverage.dat file Solution: In CC/SC mode, use rank-specific filenames; SV mode doesn't support MPI coverage

7. Random Seed Consistency

Problem: Non-deterministic test results make debugging hard Solution: Use fixed seed for reproducibility (consider adding --seed flag)


Testing Strategy

Unit Tests

  • Located in tests/ directory
  • Test individual components: parser, classifier, generator
  • Run with cargo test

Integration Tests

  • Examples serve as integration tests
  • Each example has Makefile with test target
  • Verify generated testbench compiles and runs without errors

Regression Testing

  • Keep test_stats.json outputs for examples
  • Compare statistics after changes to detect regressions
  • Golden references should maintain 100% score

Coverage Testing

  • FSM examples test coverage enhancement features
  • Compare deterministic vs. LM-based vs. traditional coverage
  • Look for state coverage gaps in .dat files

Key Files Reference

File Purpose When to Modify
cli.rs Command-line interface Adding new flags/options
commands/generate.rs Main testbench generation Changing generation logic
tools/verilog_parser.rs Verilog parsing Parser improvements
tools/signal_classification.rs Signal type detection Classification algorithm changes
tools/generator.rs Template generation Testbench template updates
tools/compiler.rs Compilation backend Compiler flag changes
tools/fsm_analysis.rs FSM coverage DFS engine improvements
python_runtime.rs Python environment LM integration changes

External Dependencies

Required Tools

  • iverilog: SystemVerilog simulation (v11+ recommended)
  • Verilator: C++ conversion and high-performance simulation (v5.020+ required)
  • Python: For LM-based FSM extraction (managed through uv)

Rust Crates

  • clap: CLI parsing
  • serde: Serialization (YAML, JSON)
  • tera: Template engine
  • sv-parser: Verilog parsing
  • regex: Pattern matching

Development Guidelines

Before Committing

  1. Run cargo fmt to format code
  2. Run cargo clippy to check for warnings
  3. Run cargo test to verify unit tests
  4. Test relevant examples: make -C examples/ALU
  5. Update USAGE.md if adding user-facing features
  6. Update AGENTS.md if adding significant architectural changes

Adding Examples

  1. Create directory under examples/
  2. Add DUT Verilog file(s)
  3. Add golden reference (Verilog or C++ header)
  4. Create README.md explaining the example
  5. Add Makefile with targets: all, clean, test
  6. Document command-line usage in example README

Error Messages

  • Be specific: Include file names, line numbers, signal names
  • Be helpful: Suggest fixes or next steps
  • Be consistent: Follow existing error message patterns
  • Example: "Module 'alu' not found in dut.v. Available modules: [add, sub]. Use --module to specify."

Future Directions

Potential Improvements

  • Coverage analysis: Integrate Verilator coverage more deeply
  • Smart test generation: ML-guided test pattern selection
  • Assertion support: Generate SVA properties from golden model
  • Waveform comparison: VCD-based debugging for mismatches
  • Parallel DUT compilation: Speed up multi-DUT builds
  • Interactive mode: REPL for exploring designs

FSM Enhancement

  • Automatic state variable identification
  • Better LM prompt engineering for complex FSMs
  • Support for hierarchical/nested FSMs
  • Visualization of state transition graphs

Resources

Documentation

  • README.md: Quick start and installation
  • docs/source/getting_started.md: Installation and quick start guide
  • docs/source/user_guide/: Mode guides (SV, CC/SC), multi-DUT, FSM coverage, advanced features
  • docs/source/reference/cli.md: Complete CLI reference for all commands
  • docs/source/examples.md: Examples by design type
  • docs/source/troubleshooting.md: Common issues and solutions
  • examples/*/README.md: Specific example guides

External Links


Tips for AI Assistants

  1. Read before modifying: Always read relevant source files before suggesting changes
  2. Test your changes: Verify with examples before claiming success
  3. Follow Rust conventions: Use Result, Option, proper error handling
  4. Preserve existing behavior: Don't break working examples
  5. Document decisions: Update this file when architecture changes
  6. Be explicit: Don't guess module names or file paths - verify them
  7. Check dependencies: Ensure external tools (iverilog, verilator) are available
  8. Understand modes: SV vs. CC/SC have different workflows and constraints
  9. Multi-DUT awareness: Many features must handle multiple DUTs correctly
  10. FSM features are new: The FSM coverage enhancement is actively being developed

Quick Reference Commands

# Build and install
cargo build --release
cargo install --path .

# Run tests
cargo test
make -C examples/ALU test

# Generate testbench (SV mode)
stg generate --verilog dut.v --golden golden.v --type combinational --out tb.sv

# Generate testbench (CC mode, two-stage)
stg generate --verilog dut.v --type combinational --out tb.cpp --out-header golden.h --cc
# ... implement golden.h ...
stg generate --verilog dut.v --golden golden.h --type combinational --out tb.cpp --out-exe tb_exe --cc

# Multi-DUT
stg generate --verilog dut1.v --verilog dut2.v --golden golden.h --type combinational --out tb.cpp --out-exe tb_exe --cc

# Parse and identify
stg parse --verilog design.v --out modules.yaml
stg identify --verilog design.v --module top --type seq_clocked --out signals.yaml

# FSM-enhanced coverage (future)
stg generate --verilog dut.v --golden golden.v --type seq_clocked --out tb.cpp --fsm-coverage

Last updated: 2026-02-09 Maintained for AI assistants working on STG-Rust