Convert Excel register specifications to PyUVM RAL models via SystemRDL
Project description
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. ๐
๐ Features
- Excel to PyUVM RAL: Convert Excel register specs directly to Python PyUVM RAL models
- SystemRDL Generation: Generate standalone SystemRDL files from Excel specifications
- SV Register Interface Generation: Auto-generate
{addrmap}_csr_pkg.sv(typedef structs) and{addrmap}_csr_bridge.sv(glue module) from Excel or RDL โ triggered automatically bygenrdlandpyral --keep-rdl, or standalone viagenregif - Configurable Reset Style: Control the reset port name in the generated SV bridge with
--default-rst(rst,rst_n,arst,arst_n; defaultrst) - Individual Mode: Generate separate per-submodule files with
-i/--individual, each with its own SystemRDL, SV package, and SV bridge โ ideal for IP-level integration - Built-in GUI Editor: Interactive Excel editor for viewing and modifying register specifications
- Selective Submodule Processing: Choose specific submodules to process with
-s/--submodulesflag - 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
- CSV Directory Support: Pass a directory of
.csvfiles instead of an.xlsxfile โ each CSV file corresponds to one sheet (stem = sheet name); handles all Excel CSV encoding variants automatically
๐ 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
โ โโโ sv_regif_generator.py # SV register interface generator (regif_pkg + top)
โ โโโ main.py # Main converter logic
โโโ docs/ # Documentation
| โโโ README_api.md # README file for API
| โโโ genregif_README.md # README for genregif SV interface generator
โโโ 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
๏ฟฝ Available Commands
The package provides two main commands:
1. pyral Command
Converts Excel register specifications to PyUVM RAL models with optional SystemRDL generation.
# Basic conversion to PyUVM RAL
pyral registers.xlsx
# Input can also be a directory of CSV files (one file per sheet)
pyral registers/ # Hierarchy.csv, default.csv, GPIO.csv, UART.csv โฆ
pyral registers/ --keep-rdl
pyral registers/ -i --keep-rdl
# Edit Excel file in GUI editor (not available for CSV directories)
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 a custom addrmap name
pyral registers.xlsx --top-name chip_top --package-name chip_ral_pkg
# Custom output directory and keep SystemRDL + SV files
pyral chip_spec.xlsx --output results/ --keep-rdl
# Individual mode โ separate file per submodule (auto-discovers from Hierarchy sheet)
pyral design.xlsx -i --keep-rdl
# Individual mode with explicit submodule list
pyral design.xlsx -i -s GPIO UART --keep-rdl
# Individual mode with per-submodule addrmap name overrides
# (one value per -s submodule; use '_' to keep the default for that slot)
pyral design.xlsx -i -s GPIO UART --keep-rdl --top-name gpio_regs _
# Individual mode with per-submodule SV name overrides
pyral design.xlsx -i -s GPIO UART --keep-rdl \
--regif-pkg-name my_gpio_pkg _ \
--regif-module-name my_gpio_bridge _
# Override peakrdl module/package names used inside the bridge (all submodules)
pyral design.xlsx -i --keep-rdl --rdl-module my_rdl_top --rdl-pkg my_rdl_top_pkg
# Per-submodule peakrdl name overrides in individual mode
pyral design.xlsx -i -s GPIO UART --keep-rdl \
--rdl-module gpio_rdl_mod uart_rdl_mod \
--rdl-pkg gpio_rdl_pkg uart_rdl_pkg
# Override SV names in standard (combined) mode
pyral chip_spec.xlsx --keep-rdl --regif-pkg-name chip_csr_pkg --regif-module-name chip_csr_bridge
# Control reset port name in generated SV bridge (rst | rst_n | arst | arst_n)
pyral design.xlsx --keep-rdl --default-rst rst_n
pyral design.xlsx -i --keep-rdl --default-rst arst_n
# Custom sheet names
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.
# Basic SystemRDL generation
genrdl registers.xlsx
# Input can also be a directory of CSV files (one file per sheet)
genrdl registers/ # Hierarchy.csv, default.csv, GPIO.csv, UART.csv โฆ
genrdl registers/ -i # individual mode
genrdl registers/ -s GPIO UART # selective submodules
# Edit Excel file in GUI editor (not available for CSV directories)
genrdl registers.xlsx --edit
genrdl registers.xlsx -e
# Custom output directory
genrdl registers.xlsx -o output/
# Custom top-level addrmap name
genrdl registers.xlsx --top-name chip_top
# Process only specific submodules
genrdl registers.xlsx -s CPU_Core UART_Module
# Individual mode โ separate .rdl + SV files per submodule (auto-discovers from Hierarchy sheet)
genrdl registers.xlsx -i
# Individual mode with explicit submodule list
genrdl registers.xlsx -i -s CPU_Core UART_Module
# Individual mode with per-submodule addrmap name overrides
# (one value per -s submodule; '_' keeps the default for that slot)
genrdl registers.xlsx -i -s CPU_Core UART_Module --top-name cpu_regs _
# Individual mode with per-submodule SV name overrides
genrdl registers.xlsx -i -s CPU_Core UART_Module \
--regif-pkg-name my_cpu_pkg _ \
--regif-module-name my_cpu_bridge _
# Override peakrdl module/package names used inside the bridge (broadcast to all)
genrdl registers.xlsx --rdl-module chip_rdl --rdl-pkg chip_rdl_pkg
# Per-submodule peakrdl name overrides in individual mode
genrdl registers.xlsx -i -s CPU_Core UART_Module \
--rdl-module cpu_rdl_mod uart_rdl_mod \
--rdl-pkg cpu_rdl_pkg uart_rdl_pkg
# Override SV names in standard (combined) mode
genrdl registers.xlsx --regif-pkg-name chip_csr_pkg --regif-module-name chip_csr_bridge
# Control reset port name in generated SV bridge (rst | rst_n | arst | arst_n)
genrdl registers.xlsx --default-rst rst_n
genrdl registers.xlsx -i -s CPU_Core UART_Module --default-rst arst_n
# Verbose output
genrdl registers.xlsx -v
Note:
genrdlalways generates{addrmap}_csr_pkg.svand{addrmap}_csr_bridge.svalongside the SystemRDL file. In-iindividual mode each submodule produces its own pair of SV files.
3. genregif Command
Generates SystemVerilog register interface files directly from an existing .rdl file.
Use this when you already have a compiled SystemRDL file and need to (re)generate the SV interface.
# Basic SV register interface generation
genregif rdl_datacap.rdl
# Custom output directory
genregif rdl_datacap.rdl -o rtl/
# Override struct/module prefix
genregif rdl_datacap.rdl --prefix dc
# Override SV package name
genregif rdl_datacap.rdl --regif-pkg-name snap_csr_pkg
# Override top module name
genregif rdl_datacap.rdl --regif-module-name dc_csr_bridge
# Override peakrdl module name used in instantiation (default: addrmap name, e.g. rdl_datacap)
genregif rdl_datacap.rdl --rdl-module my_rdl_module
# Override peakrdl package name used in imports (default: {addrmap}_pkg)
genregif rdl_datacap.rdl --rdl-pkg my_rdl_module_pkg
# Override register data width (if not declared in RDL)
genregif rdl_datacap.rdl --data-width 64
# Control reset port name in generated SV bridge (rst | rst_n | arst | arst_n; default: rst)
genregif rdl_datacap.rdl --default-rst rst_n
genregif rdl_datacap.rdl --default-rst arst_n
# Verbose output
genregif rdl_datacap.rdl -v
๏ฟฝ๐ง Installation
Prerequisites
# Required dependencies
pip install systemrdl-compiler
pip install pyuvm
pip install pandas
pip install openpyxl
Install Package
# 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 NAME [NAME ...]] [--package-name PACKAGE_NAME]
[--regif-pkg-name NAME [NAME ...]] [--regif-module-name NAME [NAME ...]]
[--rdl-module NAME [NAME ...]] [--rdl-pkg NAME [NAME ...]]
[--default-rst {rst,rst_n,arst,arst_n}]
[--hierarchy-sheet HIERARCHY_SHEET] [--default-sheet DEFAULT_SHEET]
[-s SUBMODULES [SUBMODULES ...]] [-i] [-e] [-v] [-q]
excel_file
Convert Excel register specifications to PyUVM RAL models
(excel_file may be an .xlsx/.xls file OR a directory of .csv files)
genrdl Command
usage: genrdl [-h] [--version] [-o OUTPUT] [-t NAME [NAME ...]]
[--regif-pkg-name NAME [NAME ...]] [--regif-module-name NAME [NAME ...]]
[--rdl-module NAME [NAME ...]] [--rdl-pkg NAME [NAME ...]]
[--default-rst {rst,rst_n,arst,arst_n}]
[--hierarchy-sheet HIERARCHY_SHEET] [--default-sheet DEFAULT_SHEET]
[-s SUBMODULES [SUBMODULES ...]] [-i] [-e] [-v] [-q]
excel_file
Convert Excel register specifications to SystemRDL
(excel_file may be an .xlsx/.xls file OR a directory of .csv files)
Common Options for Both Commands
| Option | Description | Default |
|---|---|---|
-e, --edit |
Open Excel file in GUI editor before conversion (โ not available for CSV directories) | 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 |
--default-rst |
Reset port name in generated SV bridge (rst, rst_n, arst, arst_n) |
rst |
-v, --verbose |
Enable verbose output | False |
-q, --quiet |
Suppress all output except errors | False |
Top Name Logic
Standard mode (no -i) โ single addrmap name, priority order:
-t/--top-name single_valueโ use the provided name-s/--submodulespresent โ use{submodule_names}_top- Neither โ use input filename stem (Excel) or directory name (CSV directory)
Individual mode (-i) โ each submodule gets its own addrmap:
-t/--top-name A B Cโ per-submodule names matching the-slist-t/--top-name single_valueโ broadcasts to all submodules- Use
_as a placeholder to keep the auto-derived name for a specific slot - Omitted โ each submodule uses its sheet name (e.g.
GPIO,UART)
Examples:
# Standard mode (Excel)
pyral chip.xlsx -t CustomChip # โ CustomChip.rdl
pyral chip.xlsx -s CPU GPIO # โ CPU_GPIO_top.rdl
pyral chip.xlsx # โ chip.rdl
# Standard mode (CSV directory)
pyral chip/ -t CustomChip # โ CustomChip.rdl
pyral chip/ # โ chip.rdl (dir name = "chip")
# Individual mode
genrdl chip.xlsx -i -s GPIO UART # โ GPIO.rdl, UART.rdl
genrdl chip/ -i -s GPIO UART # same โ CSV directory input
genrdl chip.xlsx -i -s GPIO UART \
--top-name gpio_regs _ # โ gpio_regs addrmap, UART addrmap
Additional Options for pyral Command
| Option | Description | Default |
|---|---|---|
-r, --keep-rdl |
Keep intermediate SystemRDL file (also triggers SV regif generation) | False |
--package-name |
Name for UVM package | {top_name}_ral |
genregif Command Options
usage: genregif [-h] [--version] [-o OUTPUT] [--prefix PREFIX]
[--regif-module-name NAME] [--regif-pkg-name NAME]
[--rdl-module NAME] [--rdl-pkg NAME]
[--data-width DATA_WIDTH] [--default-rst {rst,rst_n,arst,arst_n}]
[-v] [-q]
rdl_file
| Option | Default | Description |
|---|---|---|
rdl_file |
(required) | Path to the SystemRDL (.rdl) input file |
-o, --output |
output |
Output directory for generated .sv files |
--prefix |
auto (from addrmap name) | Struct/module name prefix (e.g. datacap) |
--regif-module-name |
{prefix}_csr_bridge |
Override generated SV top module name |
--regif-pkg-name |
{prefix}_csr_pkg |
Override generated SV package name |
--rdl-module |
addrmap name (e.g. rdl_datacap) |
Override peakrdl instantiation name inside bridge |
--rdl-pkg |
{addrmap}_pkg |
Override peakrdl package name used in import statements |
--data-width |
auto (from RDL regwidth) |
Register data width in bits |
--default-rst |
rst |
Reset port name in module instantiation (rst, rst_n, arst, arst_n) |
-v, --verbose |
โ | Enable verbose output |
-q, --quiet |
โ | Suppress all output except errors |
Prefix auto-detection strips common RDL prefixes from the addrmap name:
| Addrmap name | Auto prefix |
|---|---|
rdl_datacap |
datacap |
reg_uart |
uart |
my_module |
my_module (no strip) |
โก 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:
# 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
๐ Input File Format
Excel File vs CSV Directory
All three commands (pyral, genrdl, genregif) accept either:
| Input type | Example | Notes |
|---|---|---|
| Excel workbook | registers.xlsx |
All sheets in one file; GUI --edit available |
| CSV directory | registers/ |
One .csv file per sheet; stem = sheet name |
CSV Directory Layout
Split each sheet from the Excel file into its own CSV and place them all in one directory:
registers/
โโโ Hierarchy.csv # Required โ submodule hierarchy
โโโ default.csv # Optional โ default SW/HW access, widths
โโโ GPIO.csv # One per submodule type
โโโ UART.csv
The CSV file stem must exactly match the sheet name (case-sensitive).
Encoding support: All four encoding variants that Excel can produce when saving as CSV are handled automatically โ UTF-8 with BOM, plain UTF-8, Windows-1252 (CP1252), Mac Roman, MS-DOS CP437, and Latin-1 (last-resort fallback). You do not need to manually specify an encoding.
Performance note: Excel saves all 1,048,576 rows to CSV even for small sheets, producing multi-megabyte files with blank trailing lines. The importer uses a fast binary scan to skip blank rows, so loading a
Hierarchy.csvwith only 2 data rows takes ~18 ms regardless of file size.
--editflag: The built-in GUI editor works only with.xlsx/.xlsfiles. When the input is a CSV directory,--editprints a warning and exits โ edit the.csvfiles directly with any text editor or spreadsheet application.
Required Sheets
1. "Hierarchy" Sheet / Hierarchy.csv (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 registerOffset: Register offset address (hex format: 0x...)Field Name: Name of the register fieldField Bits: Bit range in format [msb:lsb], [bit], or width number
Optional Columns:
Field Description: Description of the field's functionalitySW 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 behavioronwrite=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-Writer: Read-onlyw: Write-onlyrw1c: Read-Write 1 to Clear- Other standard SystemRDL access types
-
Hardware (HW) Access:
r: Read-onlyw: Write-onlyrw: 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:
# 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 Input (Excel or CSV Directory)
Create an Excel file or a CSV directory with register specifications:
Option A โ Excel file (chip.xlsx)
Sheet: "Hierarchy"
| Submodule Name | Instances | Base Addresses |
|---|---|---|
| GPIO | gpio0,gpio1 | 0x1000,0x1100 |
| UART | uart0,uart1 | 0x2000,0x3000 |
Option B โ CSV directory (chip/)
Export each sheet separately as CSV (or create them from scratch):
chip/Hierarchy.csv:
Submodule Name,Instances,Base Addresses
GPIO,"gpio0,gpio1","0x1000,0x1100"
UART,"uart0,uart1","0x2000,0x3000"
chip/default.csv:
SW Access,HW Access,Access Width,Reg Width
rw,r,32,32
chip/GPIO.csv (and chip/UART.csv etc.):
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
Cells left blank in a register's field rows inherit the value from the first row of that register (Register Name, Offset, Width, Reset Value).
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
With --keep-rdl:
Excel File โ SystemRDL Generation โ SystemRDL Compiler Validation โ PyUVM RAL
โ {addrmap}_csr_pkg.sv
โ {addrmap}_csr_bridge.sv
With --keep-rdl -i (individual mode):
Excel File โ (per submodule) โ submodule.rdl โ submodule_ral.py
โ {submodule}_csr_pkg.sv
โ {submodule}_csr_bridge.sv
For genrdl command:
Excel File โ SystemRDL Generation โ SystemRDL Compiler Validation โ {addrmap}.rdl
โ {addrmap}_csr_pkg.sv
โ {addrmap}_csr_bridge.sv
For genrdl -i (individual mode):
Excel File โ (per submodule) โ submodule.rdl
โ {submodule}_csr_pkg.sv
โ {submodule}_csr_bridge.sv
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
pyralcommand:- 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
- With
- For
genrdlcommand:- 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
- The SystemRDL file is written to the output directory (e.g.,
To debug validation issues:
# 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)
# Excel input
pyral mychip.xlsx --keep-rdl
# CSV directory input โ identical flags, just pass the directory
pyral mychip/ --keep-rdl
pyral mychip/ -i --keep-rdl
pyral mychip/ -s GPIO UART --keep-rdl
# Process only specific submodules
pyral mychip.xlsx -s GPIO UART --keep-rdl
# Individual mode โ separate files per submodule
pyral mychip.xlsx -i --keep-rdl
# Individual mode with custom per-submodule SV names
pyral mychip.xlsx -i -s GPIO UART --keep-rdl \
--top-name gpio_regs _ \
--regif-pkg-name my_gpio_pkg _ \
--regif-module-name my_gpio_bridge _
# With custom top name and selective processing
pyral mychip.xlsx -s Memory_Controller -t mem_subsystem --output custom_output/
Using genrdl (Generate SystemRDL + SV)
# Excel or CSV directory โ same flags for both
genrdl mychip.xlsx
genrdl mychip/ # CSV directory โ identical output
# Generate SystemRDL + SV files (all submodules combined)
genrdl mychip.xlsx
# Process only specific submodules
genrdl mychip.xlsx -s GPIO UART
# Individual mode โ separate file set per submodule
genrdl mychip.xlsx -i
# Individual mode with custom per-submodule addrmap and SV names
genrdl mychip.xlsx -i -s GPIO UART \
--top-name gpio_regs _ \
--regif-pkg-name my_gpio_pkg _ \
--regif-module-name my_gpio_bridge _
# With custom top name and selective processing
genrdl mychip.xlsx -s CPU_Core -t processor_top --verbose
4. Use Generated PyUVM RAL
# 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:
# 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:
Standard mode priority:
- Explicit Name (
-t/--top-name): User-specified name takes highest priority - Selective Mode (
-s/--submodules): Auto-generates{submodule_names}_top - Full Processing: Uses Excel filename (without extension)
Individual mode (-i) โ each submodule gets its own file set:
- Addrmap defaults to the sheet name (e.g.
GPIO,UART) - Override with
--top-name NAME1 NAME2 ...(one per submodule;_keeps default) - Same pattern for
--regif-pkg-nameand--regif-module-name
Examples:
# Explicit naming
pyral chip.xlsx -t MyCustomChip
# Result: MyCustomChip.rdl, MyCustomChip_ral.py
# Selective processing auto-naming
pyral chip.xlsx -s GPIO UART Timer
# Result: GPIO_UART_Timer_top.rdl, GPIO_UART_Timer_top_ral.py
# Default filename-based naming
pyral my_processor.xlsx
# Result: my_processor.rdl, my_processor_ral.py
# Individual mode โ one file set per submodule
genrdl chip.xlsx -i -s GPIO UART
# Result: GPIO.rdl + GPIO_csr_pkg.sv + GPIO_csr_bridge.sv
# UART.rdl + UART_csr_pkg.sv + UART_csr_bridge.sv
# Individual mode with selective renaming
genrdl chip.xlsx -i -s GPIO UART --top-name gpio_regs _
# Result: gpio_regs addrmap for GPIO; UART keeps default
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:
# 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:
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:
from excel2pyral import ExcelToSystemRDLImporter
# Initialize importer
importer = ExcelToSystemRDLImporter()
# Generate SystemRDL content
systemrdl_content = importer.excel_to_systemrdl(
excel_file="mychip.xlsx", # Can also be a CSV directory: "mychip/"
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
# Use individual components
from excel2pyral import (
ExcelToSystemRDLImporter,
SystemRDLCompiler,
PyUVMRALGenerator,
SVRegifGenerator,
)
# 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"
)
SVRegifGenerator Class
Generates SystemVerilog register interface files directly from a .rdl file:
from excel2pyral import SVRegifGenerator
gen = SVRegifGenerator()
result = gen.generate(
rdl_file="rdl_datacap.rdl", # Input .rdl file
output_dir="rtl/", # Output directory
pkg_name=None, # SV package name (optional โ default: {prefix}_csr_pkg)
struct_prefix="datacap", # Struct prefix (optional โ auto-detected from addrmap name)
top_module_name=None, # Module name (optional โ default: {prefix}_csr_bridge)
reg_data_width=None, # Data width (optional โ auto-detected from RDL regwidth)
rdl_module_name=None, # peakrdl instantiation name (optional โ default: addrmap name)
rdl_pkg_name=None, # peakrdl package name in imports (optional โ default: {addrmap}_pkg)
default_rst="rst_n", # Reset port name (optional โ default: "rst"; choices: rst, rst_n, arst, arst_n)
)
print(result["pkg_file"]) # โ rtl/datacap_csr_pkg.sv
print(result["top_file"]) # โ rtl/datacap_csr_bridge.sv
What it generates:
| Output file | Contents |
|---|---|
{prefix}_csr_pkg.sv |
SV package with {prefix}_reg_in_t and {prefix}_reg_out_t typedef structs |
{prefix}_csr_bridge.sv |
Glue module bridging peakrdl block to HW signal struct ports |
Classification logic โ fields classified by the hw access property:
RDL hw |
Direction | Struct | Assignment |
|---|---|---|---|
hw = w |
HW writes (status) | {prefix}_reg_in_t |
hwif_in.inst.REG.field.next = reg_in.REG[hi:lo] |
hw = r |
SW writes (control) | {prefix}_reg_out_t |
reg_out.REG[hi:lo] = hwif_out.inst.REG.field.value |
hw = rw |
Both | both structs | appears in both always_comb blocks |
REG_DATA_WIDTH is auto-detected from default regwidth in the RDL โ no manual parameter needed.
peakrdl name separation โ
--rdl-module/rdl_module_nameoverrides the instantiation name (my_mod my_mod_i (...)) and the comment header inside the bridge. The__in_t/__out_tsignal type names are always derived from the addrmap name (e.g.rdl_datacap__in_t) because those types are generated by peakrdl and cannot be renamed at this layer.
๐๏ธ 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():
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=Trueis set automatically when thehwaccess type in SystemRDL isw,rw, orrw1โ 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:
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 ownbase_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:
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
- Use consistent naming: Keep module, register, and field names consistent
- Group related functionality: Put similar registers together
- Document thoroughly: Use description fields extensively
- Validate addresses: Ensure no overlapping address ranges
- Standard bit ranges: Use standard field sizes where possible
Module Design
- Logical grouping: Group related registers in the same module
- Address alignment: Align register addresses to natural boundaries
- Reserved fields: Include reserved fields for future expansion
PyUVM Integration
- Register model early: Create RAL model during build phase
- Use callbacks: Implement register callbacks for monitoring
- Enable coverage: Turn on register coverage for verification
- Sequence integration: Use with standard UVM register sequences
Development Workflow
- Start simple: Begin with basic register definitions
- Test incrementally: Test after each module addition
- Use version control: Track changes to Excel files
- Keep intermediate files: Use
--keep-rdlfor debugging - 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-sheetfor custom name) - Check column names match exactly: "Submodule Name", "Instances", "Base Addresses"
- Verify sheet name matches the
--hierarchy-sheetparameter (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
-sargument - 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
-sto 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
-sargument - Verify the sheets exist in the Excel file
- Ensure sheet names match exactly (case-sensitive)
"No .csv files found in directory: โฆ"
Cause: The specified directory is empty (no .csv files)
Solution:
- Ensure the directory contains at least one
.csvfile - Check the path is correct and the directory is not empty
- Each expected sheet must have a corresponding
.csvfile
"Input must have a 'Hierarchy' sheet/file for hierarchy"
Cause (CSV input): Hierarchy.csv is missing from the CSV directory
Solution:
- Add a
Hierarchy.csvfile to the directory with columns:Submodule Name,Instances,Base Addresses - Or use
--hierarchy-sheetto specify a different sheet name โ the corresponding{name}.csvmust exist
"Excel editor is not available for CSV directories"
Cause: --edit / -e flag used with a CSV directory input
Solution:
- Edit
.csvfiles directly using any text editor or spreadsheet application - The
--editGUI is only available for.xlsx/.xlsfiles
"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:
- Use
--keep-rdl --verboseto inspect the generated SystemRDL file - Review the SystemRDL compiler error messages for specific validation issues
- 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:
# 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 above.
๐ค Contributing
Development Setup
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 file for details.
๐ Acknowledgments
- SystemRDL Compiler for SystemRDL support
- PyUVM for Python UVM framework
- PeakRDL ecosystem for inspiration
โญ If this project helped you, please consider giving it a star on GitHub!
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 excel2pyral-1.3.0.tar.gz.
File metadata
- Download URL: excel2pyral-1.3.0.tar.gz
- Upload date:
- Size: 183.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55bdd09ea0ba17ba0167c61d91ca47f4931c47d24d84dbc7a50408784457517d
|
|
| MD5 |
7f5b7d4056fe6090980f87ed6b5d8357
|
|
| BLAKE2b-256 |
d2a2561a68f1a3adbff09f20e3b41993611085ea15d69767d1c9c82f6483f225
|
File details
Details for the file excel2pyral-1.3.0-py3-none-any.whl.
File metadata
- Download URL: excel2pyral-1.3.0-py3-none-any.whl
- Upload date:
- Size: 161.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9e3b381b576e32e76ab8ec440d4d3b70bd911d0c1e353ec2f092d3d0241a851
|
|
| MD5 |
751215314853499aacc47a7de847b1f4
|
|
| BLAKE2b-256 |
265ca747aa96b2e46d37a423bd6bf86f94bc18020aea77f96c5ddb3f57d393ca
|