Metadata-Version: 2.4
Name: excel2pyral
Version: 1.2.3
Summary: Convert Excel register specifications to PyUVM RAL models via SystemRDL
Home-page: https://github.com/SanCodex/excel2pyral
Author: Sanjay Singh
Author-email: Sanjay Singh <your.email@example.com>
License: MIT
Project-URL: Homepage, https://github.com/SanCodex/excel2pyral
Project-URL: Repository, https://github.com/SanCodex/excel2pyral
Project-URL: Issues, https://github.com/SanCodex/excel2pyral/issues
Keywords: SystemRDL,PyUVM,RAL,Register,Excel,UVM
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: systemrdl-compiler>=1.27.0
Requires-Dist: pyuvm>=2.8.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: openpyxl>=3.0.0
Requires-Dist: tksheet>=7.5.16
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# excel2pyral Converter

A comprehensive tool for converting Excel register specifications into Python PyUVM Register Abstraction Layer (RAL) models via SystemRDL intermediate representation.

⚠️ **Note:**  
excel2pyral is currently **under active development**. Features and interfaces may change, and some functionalities might be incomplete or unstable.  
Please use it **carefully** and report any issues or feedback to help improve the project. 🙏


[![Python Version](https://img.shields.io/badge/python-3.7+-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Status](https://img.shields.io/badge/status-stable-brightgreen.svg)](https://github.com)

## 🚀 Features

- **Excel to PyUVM RAL**: Convert Excel register specs directly to Python PyUVM RAL models
- **SystemRDL Generation**: Generate standalone SystemRDL files from Excel specifications
- **Built-in GUI Editor**: Interactive Excel editor for viewing and modifying register specifications
- **Selective Submodule Processing**: Choose specific submodules to process with `-s/--submodules` flag
- **Flexible Top-Level Naming**: Automatic or custom naming with priority-based logic
- **Comprehensive Validation**: Early error detection with hierarchy and sheet consistency checks
- **Proper UVM Structure**: Generates hierarchical RAL models matching industry standards  
- **SystemRDL Integration**: Uses SystemRDL as intermediate representation for accuracy
- **Built-in Validation**: Automatic validation through SystemRDL compiler ensures correctness of register descriptions
- **Submodule Support**: Handles complex hierarchical designs with multiple IP blocks
- **Field-Level Detail**: Supports register fields with access types, reset values, descriptions
- **Debug Support**: Comprehensive logging and intermediate file preservation options
- **Flexible Output**: Choose between PyUVM RAL generation or standalone SystemRDL output

## 📁 Project Structure

```
excel2pyral/                      # Root project directory
├── README.md                     # This file
├── requirements.txt              # required python package list
├── pyproject.toml                # Build system and configuration for your Python project
├── excel2pyral/                  # Main Python package
│   ├── __init__.py               # Package initialization
│   ├── excel_importer.py         # Excel to SystemRDL converter
│   ├── systemrdl_compiler.py     # SystemRDL compiler wrapper
│   ├── pyuvm_generator.py        # PyUVM RAL generator
│   └── main.py                   # Main converter logic
├── docs/                         # Documentation
|   └── README_api.md             # README file for API
├── examples/                     # Example files
|   ├── mychip.xlsx               # Simple example input Excel file
|   ├── mychip.rdl                # Generated SystemRDL file for mychip
|   ├── mychip_ral.py             # Generated PyUVM RAL model for mychip
|   ├── PROJECT_TEST.xlsx         # Complex example with multiple modules
|   ├── PROJECT_TEST.rdl          # Generated SystemRDL for complex example
|   └── PROJECT_TEST_ral.py       # Generated PyUVM RAL for complex example
└── setup.py                      # Package installation
```

## 📋 Table of Contents

- [Features](#-features)
- [Project Structure](#-project-structure)
- [Available Commands](#-available-commands)
  - [pyral Command](#1-pyral-command)
  - [genrdl Command](#2-genrdl-command)
- [Installation](#-installation)
  - [Prerequisites](#prerequisites)
  - [Install Package](#install-package)
- [Command Line Options](#-command-line-options)
  - [Common Options](#common-options-for-both-commands)
  - [Additional Options for pyral](#additional-options-for-pyral-command)
- [Excel File Format](#-excel-file-format)
  - [Required Sheets](#required-sheets)
  - [Column Descriptions](#column-descriptions)
  - [Field Bits Format](#field-bits-format-support)
  - [Access Permission Values](#access-permission-values)
- [Quick Start](#-quick-start)
  - [Prepare Excel File](#1-prepare-your-excel-file)
  - [Automatic SystemRDL Validation](#2-automatic-systemrdl-validation)
  - [Run Conversion](#3-run-conversion)
  - [Use Generated PyUVM RAL](#4-use-generated-pyuvm-ral)
- [Python API](#-python-api)
  - [ExcelToPyRALConverter Class](#exceltopyralconverter-class)
  - [Individual Components](#individual-components)
- [Generated PyUVM Structure](#-generated-pyuvm-structure)
  - [Register Classes](#type-based-register-classes)
  - [Block Classes](#type-based-block-classes)

- [Best Practices](#best-practices)
  - [Excel Organization](#excel-file-organization)
  - [Module Design](#module-design)
  - [PyUVM Integration](#pyuvm-integration)
  - [Development Workflow](#development-workflow)
- [Troubleshooting](#-troubleshooting)
  - [Common Issues](#common-issues)
  - [Debug Mode](#debug-mode)
  - [Validation](#validation)
- [Contributing](#-contributing)
- [License](#-license)
- [Acknowledgments](#-acknowledgments)

## � Available Commands

The package provides two main commands:

### 1. `pyral` Command
Converts Excel register specifications to PyUVM RAL models with optional SystemRDL generation.

```bash
# Basic conversion to PyUVM RAL
pyral registers.xlsx

# Edit Excel file in GUI editor
pyral registers.xlsx --edit
pyral registers.xlsx -e

# Keep intermediate SystemRDL file
pyral registers.xlsx --keep-rdl

# Process only specific submodules
pyral registers.xlsx -s CPU_Core Memory_Ctrl

# Specify custom names
pyral registers.xlsx --top-name chip_top --package-name chip_ral_pkg

# Custom output directory and keep SystemRDL
pyral chip_spec.xlsx --output results/ --keep-rdl

# Custom sheet names (updated parameter)
pyral design.xlsx --hierarchy-sheet "Hierarchy" --default-sheet "Properties"

# Process selective submodules with custom top name
pyral my_chip.xlsx -s GPIO UART -t custom_chip_top --package-name custom_ral
```

### 2. `genrdl` Command
Generates only the SystemRDL file from Excel specifications.

```bash
# Basic SystemRDL generation
genrdl registers.xlsx

# Edit Excel file in GUI editor
genrdl registers.xlsx --edit
genrdl registers.xlsx -e

# Custom output directory
genrdl registers.xlsx -o output/

# Custom top-level name
genrdl registers.xlsx --top-name chip_top

# Process only specific submodules  
genrdl registers.xlsx -s CPU_Core UART_Module

# Custom top name with selective processing
genrdl registers.xlsx -s Memory_Ctrl --top-name memory_subsystem

# Verbose output
genrdl registers.xlsx -v
```

## �🔧 Installation

### Prerequisites

```bash
# Required dependencies
pip install systemrdl-compiler
pip install pyuvm
pip install pandas
pip install openpyxl
```

### Install Package

```bash
# Clone the repository
git clone https://github.com/SanCodex/excel2pyral.git
cd excel2pyral

# Install in development mode
pip install -e .
```

## 🎯 Command Line Options

### pyral Command
```
usage: pyral [-h] [--version] [-o OUTPUT] [-r] [-t TOP_NAME] [--package-name PACKAGE_NAME]
            [--hierarchy-sheet HIERARCHY_SHEET] [--default-sheet DEFAULT_SHEET] 
            [-s SUBMODULES [SUBMODULES ...]] [-e] [-v] [-q]
            excel_file

Convert Excel register specifications to PyUVM RAL models
```

### genrdl Command
```
usage: genrdl [-h] [--version] [-o OUTPUT] [-t TOP_NAME] 
             [--hierarchy-sheet HIERARCHY_SHEET] [--default-sheet DEFAULT_SHEET]
             [-s SUBMODULES [SUBMODULES ...]] [-e] [-v] [-q]
             excel_file

Convert Excel register specifications to SystemRDL
```

### Common Options for Both Commands

| Option | Description | Default |
|--------|-------------|---------|
| `-e, --edit` | Open Excel file in GUI editor before conversion | `False` |
| `-o, --output` | Output directory | `output` |
| `-t, --top-name` | Override top-level addrmap name (Priority 1) | See Top Name Logic |
| `--hierarchy-sheet` | Name of submodule hierarchy sheet | `Hierarchy` |
| `--default-sheet` | Name of default properties sheet | `default` |
| `-s, --submodules` | Specific submodule sheets to process (enables selective processing) | All sheets |
| `-v, --verbose` | Enable verbose output | `False` |
| `-q, --quiet` | Suppress all output except errors | `False` |

### Top Name Logic (Priority Order)
The top-level addrmap name is determined using the following priority order:
1. **If `-t/--top-name` is specified**: Use the provided name
2. **If `-s/--submodules` is used**: Use `{submodule_names}_top` format
3. **If neither**: Use Excel filename (without extension)

Examples:
- `pyral chip.xlsx -t CustomChip` → `CustomChip.rdl`
- `pyral chip.xlsx -s CPU GPIO` → `CPU_GPIO_top.rdl`  
- `pyral chip.xlsx` → `chip.rdl`

### Additional Options for pyral Command

| Option | Description | Default |
|--------|-------------|---------|
| `-r, --keep-rdl` | Keep intermediate SystemRDL file | `False` |
| `--package-name` | Name for UVM package | `{top_name}_ral` |

## ⚡ Quick Start

### Excel GUI Editor

Both `pyral` and `genrdl` commands include a built-in GUI editor for Excel files. This feature allows you to:
- View and edit Excel register specifications in a user-friendly interface
- Quickly modify register definitions, offsets, and field properties
- Validate your changes before conversion
- Save changes directly to the Excel file

**Using the Excel Editor:**

```bash
# Edit Excel file in GUI editor
pyral registers.xlsx --edit

# Edit Excel file in GUI editor
genrdl registers.xlsx -e

# Short form works with both commands
pyral chip_spec.xlsx -e
genrdl design.xlsx -e
```

**Features:**
- Browse all sheets in your Excel file
- Select and view register definitions
- Edit cell values directly in the GUI
- Save changes and close to proceed with conversion
- Cancel to abort without conversion

**Note:** The editor opens in a Tkinter GUI window, so ensure you have a display available. After closing the editor:
- If you saved changes, conversion proceeds with the updated file
- If you cancelled or closed without saving, the conversion is aborted

## 📊 Excel File Format

### Required Sheets

#### 1. **"Hierarchy" Sheet** (Required for hierarchical designs)
Defines the top-level module hierarchy:

| Column | Description | Example |
|--------|-------------|---------|
| Submodule Name | Name of the module type/class | GPIO, UART, SPI |
| Instances | Unique instance name | gpio0, uart_primary |
| Base Addresses | Hexadecimal base address | 0x1000, 0x2000 |

**Note**: The hierarchy sheet name can be customized using `--hierarchy-sheet` parameter.

#### 2. **Module Type Sheets** (One per module type)
Define registers and fields for each module type:

| Column | Description | Example |
|--------|-------------|---------|
| Register Name | Name of the register | CONTROL_REG |
| Offset | Offset within module | 0x0, 0x4 |
| Width | Register Width | 32, 64 |
| Reset Value | Reset value (hex/decimal) | 0, 0x5A |
| Field Name | Name of the register field | ENABLE, MODE |
| Field Bits | Field bit positions | [0:0], [7:4] |
| Field Descripton | Description of field bits | Start txn UART |
| SW Access | Access type | rw |
| HW Access | Hardware access | r |
| Behaviour | SystemRDL field property | onwrite=woclr, onwrite=woset |

#### 3. **"default" Sheet** (Optional)
Global default properties:

| Property | Value | Description |
|----------|-------|-------------|
| regwidth | 32 | Default register width |
| accesswidth | 32 | Default access width |
| addressing | regalign | Address alignment |

### Column Value Inheritance

When a register has multiple fields, you can leave certain column values empty and they will be inherited from the previous row. This applies to:
- Register Name
- Offset
- Width
- Reset Value

For example, in the UART sheet below, the second field 'START' of RESET_REG inherits the register properties from the first row. This reduces redundancy and makes the spreadsheet more maintainable.

### Column Descriptions

#### Required Columns:
- `Register Name`: Name of the register
- `Offset`: Register offset address (hex format: 0x...)
- `Field Name`: Name of the register field
- `Field Bits`: Bit range in format [msb:lsb], [bit], or width number

#### Optional Columns:
- `Field Description`: Description of the field's functionality
- `SW Access`: Software access permissions (e.g., rw, r, w, rw1c)
- `HW Access`: Hardware access permissions (e.g., r, w, rw)
- `Reset Value`: Field reset value (hex format)
- `Behaviour`: Additional field behaviors using SystemRDL property assignments. Examples:
  - `onwrite=woclr` - Write one to clear behavior
  - `onwrite=woset` - Write one to set behavior

### Field Bits Format Support:
- Range format: `[7:0]` - 8-bit field from bit 7 to 0
- Single bit: `[3]` - Single bit field at position 3
- Width only: `8` - 8-bit field (position auto-assigned)

### Access Permission Values:
- Software (SW) Access:
  - `rw`: Read-Write
  - `r`: Read-only
  - `w`: Write-only
  - `rw1c`: Read-Write 1 to Clear
  - Other standard SystemRDL access types

- Hardware (HW) Access:
  - `r`: Read-only
  - `w`: Write-only
  - `rw`: Read-Write
  - Other standard SystemRDL access types

### Selective Submodule Processing

You can process only specific submodules instead of all sheets using the `-s/--submodules` flag:

```bash
# Process only GPIO and UART submodules
pyral registers.xlsx -s GPIO UART

# Process single submodule with custom top name  
pyral chip.xlsx -s Memory_Controller -t memory_top

# Generate SystemRDL for specific submodules
genrdl design.xlsx -s CPU_Core ALU_Unit
```

**Benefits of Selective Processing:**
- ✅ Faster generation for large designs
- ✅ Focus on specific subsystems during development
- ✅ Reduced output complexity for testing
- ✅ Automatic top name generation (`{submodule}_top`)

**Validation**: The tool validates that:
- All specified submodules exist in the hierarchy sheet
- All specified submodule sheets exist in the Excel file
- Consistent processing between hierarchy and register definitions

### 1. Prepare Your Excel File

Create an Excel file with register specifications:

**Sheet: "Hierarchy"**
| Submodule Name |  Instances  | Base Addresses |
|----------------|-------------|----------------|
| GPIO           | gpio0,gpio1 | 0x1000,0x1100  | 
| UART           | uart0,uart1 | 0x2000,0x3000  |

**Sheet: "default" (Optional)**
| SW Access | HW Access | Access Width | Reg Width |
|-----------|-----------|--------------|-----------|
| rw        | r         | 32          | 32        |

The default sheet provides global default values that apply to all registers unless overridden.

**Sheet: "GPIO"**
| Register Name | Offset | Width | Reset Value | Field Name | Field Bits | Field Description | SW Access | HW Access | Behaviour |
|--------------|--------|-------|-------------|------------|------------|------------------|-----------|-----------|-----------|
| CTRL_REG     | 0x0    | 32    | 0x0        | ENABLE    | [0:0]     | Enable GPIO      | rw        | r         | onwrite=woclr |
|      |     |     |         | MODE      | [3:1]     | Mode Select     | rw        | r         | onwrite=woclr|
| STATUS_REG   | 0x4    | 32    | 0x0        | INT_STATUS| [0:0]     | Interrupt Status| rw1c      | r         | onwrite=woclr|

**Sheet: "UART"**
| Register Name | Offset | Width | Reset Value | Field Name | Field Bits | Field Description | SW Access | HW Access | Behaviour |
|--------------|--------|-------|-------------|------------|------------|------------------|-----------|-----------|-----------|
| RESET_REG    | 0x8    | 32    | 0x0        | PAUSE     | [0:0]     | Pause txn UART   | rw        | r         | onwrite=woclr |
|     |     |     |         | START     | [3:1]     | Start txn UART   | rw        | r         |  |
| STOP_REG     | 0x16   | 32    | 0x0        | END       | [0:0]     | Stop txn UART    | rw        | r         | onwrite=woclr |

### 2. Automatic SystemRDL Validation

One of the key features of excel2pyral is its built-in validation through the SystemRDL compiler. Both `pyral` and `genrdl` commands perform this validation automatically. During conversion, your register descriptions go through rigorous validation:

For `pyral` command:
```
Excel File → SystemRDL Generation → SystemRDL Compiler Validation → PyUVM RAL
```

For `genrdl` command:
```
Excel File → SystemRDL Generation → SystemRDL Compiler Validation → Final SystemRDL
```

The SystemRDL compiler validates:
- ✓ Register and field bit ranges
- ✓ Access permission combinations
- ✓ Address overlaps and conflicts
- ✓ Field property assignments
- ✓ Structural relationships
- ✓ SystemRDL syntax compliance

When the SystemRDL compiler finds issues:
- Compilation stops immediately
- Detailed error messages are provided to help fix your Excel file
- For `pyral` command:
  - With `--keep-rdl`, the intermediate SystemRDL file is preserved in the output directory for debugging
  - No PyUVM RAL model is generated until all validation errors are fixed
- For `genrdl` command:
  - The SystemRDL file is written to the output directory (e.g., `mychip.rdl`)
  - If validation fails, this file is preserved with the invalid content for debugging
  - You can fix the Excel file and run the command again to generate a correct SystemRDL file

To debug validation issues:
```bash
# Using pyral command with verbose output
pyral registers.xlsx --keep-rdl --verbose

# Using genrdl command with verbose output
genrdl registers.xlsx --verbose

# If compilation fails, examine the generated SystemRDL:
cat output/registers.rdl  # Look for where compilation stopped
```

### 3. Run Conversion

#### Using pyral (Generate PyUVM RAL)
```bash
# Generate PyUVM RAL model (all submodules)
pyral mychip.xlsx --keep-rdl

# Process only specific submodules
pyral mychip.xlsx -s GPIO UART --keep-rdl

# With custom top name and selective processing
pyral mychip.xlsx -s Memory_Controller -t mem_subsystem --output custom_output/
```

#### Using genrdl (Generate SystemRDL Only)
```bash
# Generate SystemRDL file (all submodules)
genrdl mychip.xlsx

# Process only specific submodules
genrdl mychip.xlsx -s GPIO UART

# With custom top name and selective processing
genrdl mychip.xlsx -s CPU_Core -t processor_top --verbose
```



### 4. Use Generated PyUVM RAL

```python
# Import the generated RAL model
from output.mychip_ral import build_ral_model

# Build the RAL model in your test class
class MyTest(uvm_test):
    def __init__(self, name, parent):
        super().__init__(name, parent)
        self.ral = build_ral_model()
    
    async def run_phase(self, phase):
        # Access registers through proper hierarchy
        await self.ral.gpio0.CRTL_REG.write(0x5)
        data = await self.ral.uart0.RESET_REG.read()
        
        # Access individual fields
        await self.ral.gpio0.CRTL_REG.ENABLE.write(1)
        enable_val = await self.ral.gpio0.CRTL_REG.ENABLE.read()
        
        # Use with sequences
        reg_seq = uvm_reg_sequence.type_id.create("reg_seq")
        reg_seq.model = self.ral
        await reg_seq.start(None)
```

## 🎯 Advanced Features

### Selective Submodule Processing

Process only specific submodules from your Excel file instead of all available sheets:

```bash
# Process only CPU and Memory submodules
pyral chip_design.xlsx -s CPU_Core Memory_Controller

# Generate SystemRDL for specific subsystem
genrdl full_chip.xlsx -s UART_Module SPI_Controller

# Combine with custom top name
pyral soc_design.xlsx -s ARM_Core L2_Cache -t processor_subsystem
```

**Use Cases:**
- **Incremental Development**: Test individual IP blocks during development
- **Subsystem Testing**: Generate RAL models for specific subsystems only
- **Performance**: Faster generation for large designs by processing subset
- **CI/CD**: Generate different RAL variants for different test scenarios

### Smart Top-Level Naming

The tool automatically determines the top-level addrmap name using intelligent priority logic:

**Priority Order:**
1. **Explicit Name** (`-t/--top-name`): User-specified name takes highest priority
2. **Selective Mode** (`-s/--submodules`): Auto-generates `{submodule_names}_top`
3. **Full Processing**: Uses Excel filename (without extension)

**Examples:**
```bash
# Explicit naming (Priority 1)
pyral chip.xlsx -t MyCustomChip
# Result: MyCustomChip.rdl, MyCustomChip_ral.py

# Selective processing auto-naming (Priority 2)  
pyral chip.xlsx -s GPIO UART Timer
# Result: GPIO_UART_Timer_top.rdl, GPIO_UART_Timer_top_ral.py

# Default filename-based naming (Priority 3)
pyral my_processor.xlsx  
# Result: my_processor.rdl, my_processor_ral.py
```

### Comprehensive Error Validation

The tool provides comprehensive validation with clear error messages:

**Hierarchy Validation:**
- Ensures all specified submodules exist in hierarchy sheet
- Validates consistency between register sheets and hierarchy definitions
- Provides clear error messages with available options

**Excel Structure Validation:**
- Verifies all specified sheets exist in Excel file
- Checks for required columns in register definitions
- Validates proper hierarchy sheet structure

**SystemRDL Validation:**
- Automatic compilation and validation of generated SystemRDL
- Catches register definition errors early
- Provides detailed error messages for quick debugging

### Flexible Sheet Configuration

Customize sheet names to match your Excel file organization:

```bash
# Custom hierarchy sheet name
pyral design.xlsx --hierarchy-sheet "Module_Hierarchy"

# Custom default properties sheet
pyral design.xlsx --default-sheet "Global_Defaults"

# Both custom sheets with selective processing
pyral design.xlsx --hierarchy-sheet "Blocks" --default-sheet "Props" -s CPU GPU
```

## 🐍 Python API

### ExcelToPyRALConverter Class
Main class that orchestrates the Excel → SystemRDL → PyUVM pipeline:

```python
from excel2pyral import ExcelToPyRALConverter

# Initialize converter
converter = ExcelToPyRALConverter()

# Convert with all options
result = converter.convert(
    excel_file="registers.xlsx",      # Input Excel file
    output="output",                  # Output directory
    top_name="my_chip",               # Top-level module name (Priority 1)
    package_name="my_chip_ral",       # Generated package name
    hierarchy_sheet="Hierarchy",      # Name of submodule hierarchy sheet
    default_sheet="default",          # Name of default properties sheet
    submodule_sheets=["GPIO", "UART"], # Specific submodules to process (optional)
    keep_rdl=True,                    # Keep intermediate SystemRDL
)

# Returns a dictionary with file paths
print(f"Generated PyUVM RAL: {result['pyuvm_file']}")
print(f"Generated SystemRDL: {result['systemrdl_file']}")  # If keep_rdl=True
```

### ExcelToSystemRDLImporter Class
For generating SystemRDL files only:

```python
from excel2pyral import ExcelToSystemRDLImporter

# Initialize importer
importer = ExcelToSystemRDLImporter()

# Generate SystemRDL content
systemrdl_content = importer.excel_to_systemrdl(
    excel_file="mychip.xlsx",
    top_name="chip_top",               # Custom top name (optional)
    hierarchy_sheet="Hierarchy",       # Custom hierarchy sheet name (optional)
    default_sheet="default",           # Custom default sheet name (optional)
    submodule_sheets=["GPIO", "UART"]  # Process specific submodules (optional)
)

# Write to file
with open("output/chip.rdl", "w") as f:
    f.write(systemrdl_content)
```

### Individual Components

```python
# Use individual components
from excel2pyral import (
    ExcelToSystemRDLImporter,
    SystemRDLCompiler, 
    PyUVMRALGenerator
)

# Step 1: Excel to SystemRDL
excel_importer = ExcelToSystemRDLImporter()
systemrdl_content = excel_importer.excel_to_systemrdl(
    excel_file="registers.xlsx",
    top_name="my_chip"
)

# Step 2: Compile SystemRDL
rdl_compiler = SystemRDLCompiler()
compiled_root = rdl_compiler.compile_string(systemrdl_content)

# Step 3: Generate PyUVM RAL
ral_generator = PyUVMRALGenerator()
ral_generator.generate(
    root_node=compiled_root,
    output_file="my_chip_ral.py"
)
```

## 🏗️ Generated PyUVM Structure

The generated PyUVM RAL follows a clean Python-native structure with three layers:

### Register Classes
Each register is a `uvm_reg` subclass. Fields are declared in `__init__` and configured in `build()`:
```python
class CrtlReg(uvm_reg):
    """CRTL_REG"""

    def __init__(self, name="CRTL_REG", reg_width=32):
        super().__init__(name, reg_width)
        self.ENABLE = uvm_reg_field("ENABLE")
        self.MODE   = uvm_reg_field("MODE")

    def build(self):
        self.ENABLE.configure(self, size=1, lsb_pos=0, access="RW", is_volatile=False, reset=0x0)
        self.MODE.configure(  self, size=3, lsb_pos=1, access="RO", is_volatile=False, reset=0x0)
        self._set_lock()
```

> `is_volatile=True` is set automatically when the `hw` access type in SystemRDL is `w`, `rw`, or `rw1` — i.e. hardware can write the field (status/monitor registers).

### Register Block Classes
Each regfile becomes a `uvm_reg_block` subclass. `build()` accepts a `base_address` parameter so the same class can be instantiated at different addresses:
```python
class Gpio(uvm_reg_block):
    """GPIO — register block (default base 0x1000)."""

    def __init__(self, name="GPIO"):
        super().__init__(name)
        self.def_map = None

    def build(self, base_address=0x1000):
        self.def_map = uvm_reg_map("def_map")
        self.def_map.configure(self, base_address)
        self.default_map = self.def_map

        self.def_map.crtl_reg_reg = CrtlReg("crtl_reg_reg")
        self.def_map.crtl_reg_reg.configure(self, hex(base_address + 0x0), "", False, False)
        self.def_map.add_reg(self.def_map.crtl_reg_reg, "0", "RW")

        self.def_map.status_reg_reg = StatusReg("status_reg_reg")
        self.def_map.status_reg_reg.configure(self, hex(base_address + 0x4), "", False, False)
        self.def_map.add_reg(self.def_map.status_reg_reg, "0", "RW")
```

> If the same regfile type is instantiated multiple times (e.g. `gpio0`, `gpio1`), only **one** class is generated and each instance is built with its own `base_address`.

### Top-Level Container Class
The top addrmap becomes a plain Python class (not `uvm_reg_block`) that owns all block instances and wires them to the sequencer/adapter:
```python
class MychipTop:
    """
    Top-level RAL container — holds one uvm_reg_block per hardware module.
    get_all_maps() and set_sequencer_adapter() discover sub-blocks automatically
    via Python introspection; no changes needed elsewhere when a new block is added.
    """

    def __init__(self, name="mychip_top"):
        self.name  = name
        self.gpio0 = Gpio("gpio0")
        self.gpio1 = Gpio("gpio1")
        self.uart0 = Uart("uart0")
        self.uart1 = Uart("uart1")

    def build(self):
        self.gpio0.build(base_address=0x1000)
        self.gpio1.build(base_address=0x1100)
        self.uart0.build(base_address=0x2000)
        self.uart1.build(base_address=0x3000)

    def get_all_maps(self):
        """Return default_map of every uvm_reg_block attribute."""
        return [
            getattr(self, attr).default_map
            for attr in vars(self)
            if isinstance(getattr(self, attr), uvm_reg_block)
        ]

    def set_sequencer_adapter(self, seqr, adp):
        """Wire adapter+sequencer on every sub-block map — call once from connect_phase."""
        for m in self.get_all_maps():
            m.set_sequencer(seqr)
            m.set_adapter(adp)
```

## Best Practices

### Excel File Organization

1. **Use consistent naming:** Keep module, register, and field names consistent
2. **Group related functionality:** Put similar registers together  
3. **Document thoroughly:** Use description fields extensively
4. **Validate addresses:** Ensure no overlapping address ranges
5. **Standard bit ranges:** Use standard field sizes where possible

### Module Design

1. **Logical grouping:** Group related registers in the same module
2. **Address alignment:** Align register addresses to natural boundaries
3. **Reserved fields:** Include reserved fields for future expansion

### PyUVM Integration

1. **Register model early:** Create RAL model during build phase
2. **Use callbacks:** Implement register callbacks for monitoring
3. **Enable coverage:** Turn on register coverage for verification
4. **Sequence integration:** Use with standard UVM register sequences

### Development Workflow

1. **Start simple:** Begin with basic register definitions
2. **Test incrementally:** Test after each module addition
3. **Use version control:** Track changes to Excel files
4. **Keep intermediate files:** Use `--keep-rdl` for debugging
5. **Validate generated code:** Review generated PyUVM RAL model


## 🐛 Troubleshooting

### Common Issues

#### "Walker did not find any top-level addrmap block"
**Cause:** Missing or incorrectly formatted Hierarchy sheet
**Solution:** 
- Ensure Hierarchy sheet exists (or use `--hierarchy-sheet` for custom name)
- Check column names match exactly: "Submodule Name", "Instances", "Base Addresses"
- Verify sheet name matches the `--hierarchy-sheet` parameter (default: "Hierarchy")

#### "Requested submodules not found in hierarchy sheet"
**Cause:** Using `-s/--submodules` with submodule names that don't exist in the hierarchy sheet
**Solution:**
- Check spelling of submodule names in the `-s` argument
- Verify the submodule names exist in the "Submodule Name" column of hierarchy sheet
- The error message shows available submodules for reference

#### "Found register sheets without corresponding entries in hierarchy sheet"
**Cause:** Excel contains register sheets that are not listed in the hierarchy (when not using `-s`)
**Solution:**
- Add missing submodules to the hierarchy sheet, OR
- Use `-s` to process only specific submodules, OR
- Remove unused register sheets from the Excel file

#### "Specified submodule sheets not found in Excel file"
**Cause:** Using `-s` with sheet names that don't exist in the Excel file
**Solution:**
- Check spelling of sheet names in the `-s` argument
- Verify the sheets exist in the Excel file
- Ensure sheet names match exactly (case-sensitive)

#### "SystemRDL compilation failed"
**Cause:** Invalid register/field definitions caught by SystemRDL compiler validation
**Solution:**
The SystemRDL compiler automatically validates your register descriptions and will catch issues such as:
- Invalid bit ranges: Ensures `[MSB:LSB]` format is correct and MSB >= LSB
- Unsupported access types: Validates that access types (RW, RO, WO, etc.) are legal
- Address conflicts: Detects overlapping register addresses
- Invalid field properties: Validates SystemRDL property assignments
- Structural issues: Checks for proper register and field relationships

To debug:
1. Use `--keep-rdl --verbose` to inspect the generated SystemRDL file
2. Review the SystemRDL compiler error messages for specific validation issues
3. Fix the corresponding entries in your Excel file

#### "No registers found in design"
**Cause:** Module type sheets missing or incorrectly named
**Solution:**
- Ensure each Submodule Name in hierarchy sheet has corresponding sheet
- Check sheet names match Submodule Name exactly (case-sensitive)
- Verify register definitions have all required columns
- When using `-s`, ensure specified submodule sheets exist

#### Import errors in generated PyUVM
**Cause:** PyUVM not installed or wrong version
**Solution:**
- Install PyUVM: `pip install pyuvm`
- Check Python environment is correct
- Verify all dependencies are installed

### Debug Mode

Enable detailed debugging:

```bash
# For pyral command
pyral registers.xlsx --keep-rdl --verbose

# For genrdl command  
genrdl registers.xlsx --verbose

# With selective processing
pyral registers.xlsx -s GPIO UART --keep-rdl --verbose
```

This provides:
- Step-by-step conversion progress
- Intermediate SystemRDL file for inspection
- Detailed error messages with context
- Generated file locations and sizes


### Validation Checklist

Before conversion, verify your Excel file:

- [ ] Hierarchy sheet exists with correct column names (or custom sheet name set with `--hierarchy-sheet`)
- [ ] All submodule types have corresponding sheets
- [ ] If using `-s/--submodules`, verify specified submodules exist in hierarchy sheet
- [ ] If using `-s/--submodules`, verify specified sheets exist in Excel file
- [ ] Register definitions have all required columns
- [ ] Bit ranges are in correct format `[MSB:LSB]`
- [ ] Access types are valid (RW, RO, WO, etc.)
- [ ] Addresses are in hexadecimal format
- [ ] No overlapping address ranges
- [ ] Field names are valid identifiers
- [ ] Reset values are properly formatted


### Pre-Conversion Validation

Before running the conversion, manually verify your Excel file structure and content using the [Validation Checklist](#validation-checklist) above.
## 🤝 Contributing

### Development Setup

```bash
git clone https://github.com/SanCodex/excel2pyral.git
cd excel2pyral

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\\Scripts\\activate  # Windows

# Install development dependencies
pip install -r requirements-dev.txt
pip install -e .
```

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

- [SystemRDL Compiler](https://github.com/SystemRDL/systemrdl-compiler) for SystemRDL support
- [PyUVM](https://github.com/pyuvm/pyuvm) for Python UVM framework
- [PeakRDL](https://github.com/SystemRDL/PeakRDL) ecosystem for inspiration

---

**⭐ If this project helped you, please consider giving it a star on GitHub!**
