excel2pyral 1.2.2
Convert Excel register specifications to PyUVM RAL models via SystemRDL
License: MIT
Requires Python: >=3.6
Keywords: SystemRDL, PyUVM, RAL, Register, Excel, UVM

# 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
- **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)
  - [Enhanced Classes](#enhanced-pyuvm-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

# 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
pyral design.xlsx --submodule-sheet "Modules" --default-sheet "Properties"

# Use enhanced classes with custom package name
pyral my_chip.xlsx --package-name custom_ral --enhanced-classes
```

### 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

# 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]
            [--submodule-sheet SUBMODULE_SHEET] [--default-sheet DEFAULT_SHEET] [-e] [-v] [-q]
            excel_file

Convert Excel register specifications to PyUVM RAL models
```

### genrdl Command
```
usage: genrdl [-h] [--version] [-o OUTPUT] [-t TOP_NAME] [--submodule-sheet SUBMODULE_SHEET]
             [--default-sheet DEFAULT_SHEET] [-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 | From filename |
| `--submodule-sheet` | Name of submodule hierarchy sheet | `Submodules` |
| `--default-sheet` | Name of default properties sheet | `default` |
| `-v, --verbose` | Enable verbose output | `False` |
| `-q, --quiet` | Suppress all output except errors | `False` |

### 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` |
| `--enhanced-classes` | Use enhanced PyUVM classes | `True` |

## ⚡ 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. **"Submodules" 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 |

#### 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

### 1. Prepare Your Excel File

Create an Excel file with register specifications:

**Sheet: "Submodules"**
| 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
pyral mychip.xlsx --keep-rdl

# With custom options
pyral mychip.xlsx --output custom_output/ --top-name chip_top --package-name chip_pkg
```

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

# With custom options
genrdl mychip.xlsx -o rdl_output/ --top-name chip_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)
```

## 🐍 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
    package_name="my_chip_ral",    # Generated package name
    submodule_sheet="Submodules",  # Name of submodule hierarchy sheet
    default_sheet="default",       # Name of default properties sheet
    keep_rdl=True,                 # Keep intermediate SystemRDL
    use_enhanced_classes=True      # Enable enhanced features
)

# 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",
    submodule_sheet="Submodules",  # Optional
    default_sheet="default"        # 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 proper UVM hierarchical structure:

### Type-Based Register Classes
```python
class GpioCrtlReg(uvm_reg):
    """Register: GPIO::CRTL_REG"""
    def __init__(self, name="CRTL_REG"):
        super().__init__(name, 32, has_coverage=uvm_cvr_t.UVM_CVR_ALL)
        
        # Fields
        self.ENABLE = uvm_reg_field.type_id.create("ENABLE")
        self.MODE = uvm_reg_field.type_id.create("MODE")
```

### Type-Based Block Classes  
```python
class GPIO(uvm_reg_block):
    """Register Block: GPIO"""
    def __init__(self, name="GPIO"):
        super().__init__(name, has_coverage=uvm_cvr_t.UVM_CVR_ALL)
        
        # Register instances
        self.CRTL_REG = GpioCrtlReg.type_id.create("CRTL_REG")
        self.STATUS_REG = GpioStatusReg.type_id.create("STATUS_REG")
    
    def build_phase(self, phase):
        # Create register map and add registers
        self.default_map = uvm_reg_map.type_id.create("default_map")
        self.default_map.add_reg(self.CRTL_REG, 0x0, "RW")
        self.default_map.add_reg(self.STATUS_REG, 0x4, "RW")
```

### Top-Level Class with Sub-Block Instances
```python
class Mychip(uvm_reg_block):
    """Top-level register block: mychip"""
    def __init__(self, name="mychip"):
        super().__init__(name, has_coverage=uvm_cvr_t.UVM_CVR_ALL)
        
        # Sub-block instances (like SystemVerilog UVM)
        self.gpio0 = GPIO.type_id.create("gpio0")
        self.gpio1 = GPIO.type_id.create("gpio1") 
        self.uart0 = UART.type_id.create("uart0")
        self.uart1 = UART.type_id.create("uart1")
    
    def build_phase(self, phase):
        # Add submaps at proper addresses (like add_submap)
        self.default_map.add_submap(self.gpio0.default_map, 0x1000)
        self.default_map.add_submap(self.gpio1.default_map, 0x1100)
        self.default_map.add_submap(self.uart0.default_map, 0x2000) 
        self.default_map.add_submap(self.uart1.default_map, 0x3000)
```

### Enhanced PyUVM Classes

Enable enhanced PyUVM classes for additional features:

```python
converter.convert(
    excel_file="registers.xlsx",
    use_enhanced_classes=True  # Enables coverage, callbacks, etc.
)
```

## 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 Submodules sheet
**Solution:** 
- Ensure Submodules sheet exists
- Check column names match exactly: "Module Type", "Instance Name", "Base Address", "Description"
- Verify sheet name is exactly "Submodules"

#### "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 Module Type in Submodules sheet has corresponding sheet
- Check sheet names match Module Type exactly (case-sensitive)
- Verify register definitions have all required columns

#### 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
pyral registers.xlsx --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:

- [ ] Submodules sheet exists with correct column names
- [ ] All module types have corresponding sheets
- [ ] 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!**