# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**sv2svg** converts structural SystemVerilog modules into readable logic-diagram SVGs using Schemdraw. It parses HDL, assigns gates to levels via topological sorting, and renders them left-to-right (or top-to-bottom) with automatic routing and collision avoidance.

## Key Development Commands

### Environment Setup
```bash
# Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate  # macOS/Linux
# .venv\Scripts\activate   # Windows

# Install in editable mode
pip install --upgrade pip
pip install -e .
```

### Running the CLI
```bash
# Basic usage
sv2svg input.sv -o output.svg

# Test against your own modules
python -m sv2svg.cli input.sv --style blueprint --orientation vertical -o output.svg

# Check version
python -m sv2svg.cli --version
```

### Testing
The CI workflow (`.github/workflows/ci.yml`) performs an import smoke test:
```bash
python -c "import sv2svg; print('Imported sv2svg OK')"
```

There are currently no formal unit tests. When adding tests, integrate them into the CI workflow.

### Release Process
- **Commits**: Follow [Conventional Commits](https://www.conventionalcommits.org) (e.g., `feat:`, `fix:`, `docs:`) for semantic versioning
- **Versioning**: Managed by `hatch-vcs` from git tags (dev builds show `0.x.x.dev0+g<hash>`)
- **Automation**: Merge to `main` triggers semantic-release, which updates `CHANGELOG.md`, tags releases, and publishes to PyPI via trusted publishing

## Architecture

### Core Components

**`src/sv2svg/core.py`** — Main logic engine:
- **`SVCircuit`**: Parses SystemVerilog, builds connectivity graph, assigns gate levels, generates Schemdraw drawing
- **Parser**: Regex-based extraction of module ports, gate instantiations, and simple `assign` statements
- **Level Assignment**: Topological sort to place gates in left-to-right layers
- **Layout Algorithm**:
  - Barycenter-based gate ordering within each level (reduces wire crossings)
  - Optional symmetry mode: mirrors sibling gates around shared driver centerlines
  - Grid snapping for alignment
- **Routing**: Wire routing with bounding-box collision avoidance (detours around gates)
- **Vertical Orientation**: SVG post-processing rotates horizontal layout 90° clockwise

**`src/sv2svg/cli.py`** — Command-line interface:
- Argument parsing via `argparse`
- Delegates to `SVCircuit.parse_file()` and `SVCircuit.generate_diagram()`
- Stdout support for pipeline integration (`-o -`)

**`src/sv2svg/__init__.py`** — Package entry point exposing `__version__` and public API

**`src/sv2svg/_version.py`** — Auto-generated by `hatch-vcs` during build (git-based version)

### Data Flow
1. **Parse** SystemVerilog → extract module name, ports, gates, internal signals
2. **Build Connectivity** → map signal drivers/sinks, construct dependency graph
3. **Assign Levels** → topological sort for left-to-right placement
4. **Reorder by Barycenter** → minimize crossings via iterative weighted positioning
5. **Generate Schemdraw Drawing** → place gates, route wires with collision avoidance
6. **Rotate (optional)** → apply SVG transformation for vertical orientation
7. **Output** → write SVG file or stdout

### Parser Limitations

The parser supports **structural SystemVerilog** (explicit gate instantiations) with limited `assign` statement support:

#### ✅ Fully Supported
- Gate instantiations: `AND u1(a, b, y);`
- All common logic gates: AND, OR, NAND, NOR, XOR, XNOR, NOT/INV, BUF/BUFFER

#### ⚠️ Limited Support
- **Simple two-input assign patterns only**:
  - `assign y = a & b;` → AND
  - `assign y = a | b;` → OR
  - `assign y = ~(a & b);` → NAND
  - `assign y = ~a;` → NOT
  - (See `core.py:161-206` for full list)

#### ❌ Not Supported
- Mixed operators: `assign y = a & b | c;`
- Multi-input operations: `assign y = a & b & c;`
- Nested expressions: `assign y = (a & b) | (c ^ d);`
- **For complex logic, use explicit gate instantiations**

### Routing and Collision Avoidance

The routing algorithm (`core.py:450-613`) uses two key strategies:

1. **Horizontal line avoidance** (`hline_avoid`): Detours around gate bounding boxes
2. **Vertical trunk allocation** (`used_verticals`): Tracks occupied vertical bus lines to prevent overlap

When modifying routing logic:
- **Primary inputs** use a vertical "trunk" that branches to multiple gates
- **Internal signals** use a midpoint vertical with horizontal branches
- **Commutative gates** (AND, OR, XOR, etc.) have their inputs auto-sorted by Y-coordinate to minimize crossings
- Grid snapping (`--grid-x`, `--grid-y`) happens **after** coordinate calculation

### Style System

`STYLE_PRESETS` in `core.py:22-39` defines color schemes:
- `classic` — Dark blue-gray
- `blueprint` — NASA blue
- `midnight` — Cyan on dark
- `mono` — Grayscale

Each preset configures `schemdraw.Drawing.config()` parameters (`color`, `lw`, `fontsize`) and module label color.

## Common Development Patterns

### Adding a New Gate Type
1. Update `_add_gate()` in `core.py:636-659` to handle the new gate type string
2. Map to appropriate Schemdraw `logic.*` class or fallback to `elm.Box`
3. If adding assign statement support, add regex pattern in `parse_file()` (lines 161-206)

### Modifying Layout Algorithm
- **Level assignment**: See `_assign_levels()` (lines 223-248)
- **Barycenter ordering**: See `_reorder_levels_by_barycenter()` (lines 250-290)
- **Symmetry logic**: See `generate_diagram()` symmetry block (lines 373-405)

### Debugging Routing Issues
- Inspect `bboxes` list (generated at line 432) for gate collision regions
- Add temporary `print()` statements in `hline_avoid()` or `vline_avoid()`
- Use `--grid-x 0 --grid-y 0` to disable snapping and see raw coordinates

### Extending CLI Options
1. Add argument to `cli.py` parser (lines 8-22)
2. Pass through to `SVCircuit.generate_diagram()` call (lines 34-43)
3. Update `SVCircuit.generate_diagram()` signature in `core.py` (line 292)

## Project Constraints

- **Python 3.9+** required (`pyproject.toml:14`)
- **Single dependency**: `schemdraw>=0.16` (no additional test frameworks yet)
- **No linting/formatting tools configured** — maintain existing code style (4-space indents, snake_case)
- **Regex-based parser** — not a full HDL parser; only handles simple structural constructs
- **CI is minimal** — only import smoke test; expand as project grows

## Version Management

- **Source of truth**: Git tags via `hatch-vcs`
- **Fallback version**: `0.0.0` (when `.git` not present)
- **Dev builds**: Auto-suffixed with `.dev0+g<hash>.d<date>`
- **Version file**: Auto-generated at `src/sv2svg/_version.py` during build (gitignored)

Do not manually edit `_version.py` or hardcode versions elsewhere.