peakrdl-pybind11


Namepeakrdl-pybind11 JSON
Version 0.4.3 PyPI version JSON
download
home_pageNone
SummaryExport SystemRDL to PyBind11 modules for Python-based hardware testing
upload_time2025-10-31 05:03:05
maintainerNone
docs_urlNone
authorArnav Sacheti
requires_python>=3.10
licenseGPL-3.0-only
keywords systemrdl pybind11 register hardware testing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PeakRDL-pybind11

[![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://github.com/arnavsacheti/PeakRDL-pybind11/blob/main/LICENSE)
[![Documentation Status](https://readthedocs.org/projects/peakrdl-pybind11/badge/?version=latest)](https://peakrdl-pybind11.readthedocs.io/en/latest/?badge=latest)

PeakRDL-pybind11 is an exporter for the PeakRDL toolchain that generates PyBind11 modules from SystemRDL register descriptions. This enables Python-based hardware testing and interaction with register maps through a clean, type-safe Python API.

## Features

- **PyBind11 Module Generation**: Automatically generates C++ descriptors and Python bindings from SystemRDL
- **SoC Hierarchy Exposure**: Import generated modules to access the complete SoC register hierarchy
- **Pluggable Master Backends**: Support for multiple communication backends:
  - Mock Master (for testing without hardware)
  - OpenOCD Master (for JTAG/SWD debugging)
  - SSH Master (for remote access)
  - Custom Master backends (extensible interface)
- **Comprehensive API**: 
  - `attach_master()`: Connect to hardware or simulator
  - `read()`: Read register values
  - `write()`: Write register values
  - `modify()`: Read-modify-write operations
  - **Context Manager Support**: Batch field modifications for efficient register updates
- **Type Safety**: Generated `.pyi` stub files for full IDE support and type checking
- **Python-Based Testing**: Enable hardware testing with callbacks and custom logic

## Context Manager Support

The context manager feature allows you to batch multiple field modifications into a single bus transaction, significantly improving performance when updating multiple fields in the same register:

```python
# Traditional approach: Each field write is a separate read-modify-write cycle (6 bus transactions)
soc.uart.control.enable.write(1)      # Read + Write
soc.uart.control.baudrate.write(2)    # Read + Write
soc.uart.control.parity.write(1)      # Read + Write

# Context manager approach: All modifications batched into one transaction (2 bus transactions)
with soc.uart.control as reg:
    reg.enable.write(1)       # Cached
    reg.baudrate.write(2)     # Cached
    reg.parity.write(1)       # Cached
    # All changes written atomically when exiting context

# You can also read and manipulate field values within the context
with soc.uart.control as reg:
    current_mode = reg.mode.read()
    reg.enable.write(current_mode & 0x1)
    reg.baudrate.write(2)
```

Benefits:
- **Performance**: Reduces bus transactions from N read + N write to 1 read + 1 write
- **Atomicity**: All field changes are committed together
- **Readability**: Cleaner code for complex field manipulations

## Installation

```bash
pip install peakrdl-pybind11
```

## Usage

### Command Line

```bash
peakrdl pybind11 input.rdl -o output_dir --soc-name MySoC --top top_addrmap --gen-pyi
```

#### CLI Options

- `--soc-name`: Name of the generated SoC module (default: derived from input file)
- `--top`: Top-level address map node to export (default: top-level node)
- `--gen-pyi`: Generate `.pyi` stub files for type hints (enabled by default)
- `--split-bindings COUNT`: Split bindings into multiple files for parallel compilation when register count exceeds COUNT. This significantly speeds up compilation for large register maps (default: 100, set to 0 to disable). Ignored when `--split-by-hierarchy` is used.
- `--split-by-hierarchy`: Split bindings by addrmap/regfile hierarchy instead of by register count. This keeps related registers together and provides more logical grouping. Recommended for designs with clear hierarchical structure.

#### Compilation Performance Optimization

For large register maps, compilation can be very slow. PeakRDL-pybind11 includes several optimizations:

1. **Hierarchical binding splitting** (recommended): Use `--split-by-hierarchy` to split bindings by addrmap/regfile boundaries. This keeps related registers together in the same compilation unit, providing better organization and cache locality.
2. **Register count binding splitting**: When register count exceeds `--split-bindings` threshold (default: 100), bindings are automatically split into multiple `.cpp` files that can be compiled in parallel
3. **Optimized compiler flags**: The generated CMakeLists.txt uses `-O1` optimization even for debug builds, which significantly reduces compilation time for template-heavy code
4. **Parallel compilation**: CMake will automatically compile split files in parallel when using `make -j` or `ninja`

Examples for large register maps:
```bash
# Split by hierarchy (recommended for well-structured designs)
peakrdl pybind11 large_design.rdl -o output --split-by-hierarchy

# Split bindings every 50 registers for faster compilation
peakrdl pybind11 large_design.rdl -o output --split-bindings 50

# Build with parallel compilation (4 cores)
cd output
pip install . -- -DCMAKE_BUILD_PARALLEL_LEVEL=4
```

### Python API

```python
from peakrdl_pybind11 import Pybind11Exporter
from systemrdl import RDLCompiler

# Compile SystemRDL
rdl = RDLCompiler()
rdl.compile_file("input.rdl")
root = rdl.elaborate()

# Export to PyBind11
exporter = Pybind11Exporter()
exporter.export(root, "output_dir", soc_name="MySoC")

# For large designs, enable binding splitting by hierarchy (recommended)
exporter.export(root, "output_dir", soc_name="MySoC", split_by_hierarchy=True)

# Or split by register count
exporter.export(root, "output_dir", soc_name="MySoC", split_bindings=50)
```

### Using Generated Modules

```python
import MySoC
from peakrdl_pybind11.masters import MockMaster

# Create and attach a master
soc = MySoC.create()
mock = MockMaster()
master = MySoC.wrap_master(mock)
soc.attach_master(master)

# Read/write registers
value = soc.peripherals.uart.control.read()
soc.peripherals.uart.control.write(0x1234)

# Access individual fields
soc.peripherals.uart.control.enable.write(1)
enable_value = soc.peripherals.uart.control.enable.read()

# Modify specific fields (traditional approach - each field modification is a separate bus transaction)
soc.peripherals.uart.control.enable.write(1)
soc.peripherals.uart.control.baudrate.write(2)
soc.peripherals.uart.control.parity.write(1)

# Use context manager for batched field modifications (recommended)
# Only 1 read + 1 write transaction to the bus
with soc.peripherals.uart.control as reg:
    reg.enable.write(1)
    reg.baudrate.write(2)
    reg.parity.write(1)
    # All changes are cached and written atomically when exiting the context

# Copy and modify field values within a context
with soc.peripherals.uart.control as reg:
    current_baudrate = reg.baudrate.read()
    reg.enable.write(current_baudrate & 0x1)  # Use one field value to set another
```

## Requirements

- Python >= 3.10
- systemrdl-compiler >= 1.30.1
- jinja2
- CMake >= 3.15 (for building generated modules)
- C++11 compatible compiler (for building generated modules)
- pybind11 (runtime dependency for generated code)

## Benchmarks

Performance benchmarks are available to measure export and build times:

```bash
# Run fast export benchmarks
python benchmarks/run_benchmarks.py fast

# Run all benchmarks
pytest benchmarks/ --benchmark-only

# See all benchmark options
python benchmarks/run_benchmarks.py
```

See [benchmarks/README.md](benchmarks/README.md) for detailed documentation.
## Documentation

Full documentation is available at [ReadTheDocs](https://peakrdl-pybind11.readthedocs.io/).

To build the documentation locally:

```bash
pip install -e .[docs]
cd docs
make html
```

The built documentation will be in `docs/_build/html/`.

## License

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

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "peakrdl-pybind11",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "SystemRDL, PyBind11, register, hardware, testing",
    "author": "Arnav Sacheti",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/e7/73/42a53af5990e50952848fcec210bf240259f9518f021f40533e370a2a497/peakrdl_pybind11-0.4.3.tar.gz",
    "platform": null,
    "description": "# PeakRDL-pybind11\n\n[![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://github.com/arnavsacheti/PeakRDL-pybind11/blob/main/LICENSE)\n[![Documentation Status](https://readthedocs.org/projects/peakrdl-pybind11/badge/?version=latest)](https://peakrdl-pybind11.readthedocs.io/en/latest/?badge=latest)\n\nPeakRDL-pybind11 is an exporter for the PeakRDL toolchain that generates PyBind11 modules from SystemRDL register descriptions. This enables Python-based hardware testing and interaction with register maps through a clean, type-safe Python API.\n\n## Features\n\n- **PyBind11 Module Generation**: Automatically generates C++ descriptors and Python bindings from SystemRDL\n- **SoC Hierarchy Exposure**: Import generated modules to access the complete SoC register hierarchy\n- **Pluggable Master Backends**: Support for multiple communication backends:\n  - Mock Master (for testing without hardware)\n  - OpenOCD Master (for JTAG/SWD debugging)\n  - SSH Master (for remote access)\n  - Custom Master backends (extensible interface)\n- **Comprehensive API**: \n  - `attach_master()`: Connect to hardware or simulator\n  - `read()`: Read register values\n  - `write()`: Write register values\n  - `modify()`: Read-modify-write operations\n  - **Context Manager Support**: Batch field modifications for efficient register updates\n- **Type Safety**: Generated `.pyi` stub files for full IDE support and type checking\n- **Python-Based Testing**: Enable hardware testing with callbacks and custom logic\n\n## Context Manager Support\n\nThe context manager feature allows you to batch multiple field modifications into a single bus transaction, significantly improving performance when updating multiple fields in the same register:\n\n```python\n# Traditional approach: Each field write is a separate read-modify-write cycle (6 bus transactions)\nsoc.uart.control.enable.write(1)      # Read + Write\nsoc.uart.control.baudrate.write(2)    # Read + Write\nsoc.uart.control.parity.write(1)      # Read + Write\n\n# Context manager approach: All modifications batched into one transaction (2 bus transactions)\nwith soc.uart.control as reg:\n    reg.enable.write(1)       # Cached\n    reg.baudrate.write(2)     # Cached\n    reg.parity.write(1)       # Cached\n    # All changes written atomically when exiting context\n\n# You can also read and manipulate field values within the context\nwith soc.uart.control as reg:\n    current_mode = reg.mode.read()\n    reg.enable.write(current_mode & 0x1)\n    reg.baudrate.write(2)\n```\n\nBenefits:\n- **Performance**: Reduces bus transactions from N read + N write to 1 read + 1 write\n- **Atomicity**: All field changes are committed together\n- **Readability**: Cleaner code for complex field manipulations\n\n## Installation\n\n```bash\npip install peakrdl-pybind11\n```\n\n## Usage\n\n### Command Line\n\n```bash\npeakrdl pybind11 input.rdl -o output_dir --soc-name MySoC --top top_addrmap --gen-pyi\n```\n\n#### CLI Options\n\n- `--soc-name`: Name of the generated SoC module (default: derived from input file)\n- `--top`: Top-level address map node to export (default: top-level node)\n- `--gen-pyi`: Generate `.pyi` stub files for type hints (enabled by default)\n- `--split-bindings COUNT`: Split bindings into multiple files for parallel compilation when register count exceeds COUNT. This significantly speeds up compilation for large register maps (default: 100, set to 0 to disable). Ignored when `--split-by-hierarchy` is used.\n- `--split-by-hierarchy`: Split bindings by addrmap/regfile hierarchy instead of by register count. This keeps related registers together and provides more logical grouping. Recommended for designs with clear hierarchical structure.\n\n#### Compilation Performance Optimization\n\nFor large register maps, compilation can be very slow. PeakRDL-pybind11 includes several optimizations:\n\n1. **Hierarchical binding splitting** (recommended): Use `--split-by-hierarchy` to split bindings by addrmap/regfile boundaries. This keeps related registers together in the same compilation unit, providing better organization and cache locality.\n2. **Register count binding splitting**: When register count exceeds `--split-bindings` threshold (default: 100), bindings are automatically split into multiple `.cpp` files that can be compiled in parallel\n3. **Optimized compiler flags**: The generated CMakeLists.txt uses `-O1` optimization even for debug builds, which significantly reduces compilation time for template-heavy code\n4. **Parallel compilation**: CMake will automatically compile split files in parallel when using `make -j` or `ninja`\n\nExamples for large register maps:\n```bash\n# Split by hierarchy (recommended for well-structured designs)\npeakrdl pybind11 large_design.rdl -o output --split-by-hierarchy\n\n# Split bindings every 50 registers for faster compilation\npeakrdl pybind11 large_design.rdl -o output --split-bindings 50\n\n# Build with parallel compilation (4 cores)\ncd output\npip install . -- -DCMAKE_BUILD_PARALLEL_LEVEL=4\n```\n\n### Python API\n\n```python\nfrom peakrdl_pybind11 import Pybind11Exporter\nfrom systemrdl import RDLCompiler\n\n# Compile SystemRDL\nrdl = RDLCompiler()\nrdl.compile_file(\"input.rdl\")\nroot = rdl.elaborate()\n\n# Export to PyBind11\nexporter = Pybind11Exporter()\nexporter.export(root, \"output_dir\", soc_name=\"MySoC\")\n\n# For large designs, enable binding splitting by hierarchy (recommended)\nexporter.export(root, \"output_dir\", soc_name=\"MySoC\", split_by_hierarchy=True)\n\n# Or split by register count\nexporter.export(root, \"output_dir\", soc_name=\"MySoC\", split_bindings=50)\n```\n\n### Using Generated Modules\n\n```python\nimport MySoC\nfrom peakrdl_pybind11.masters import MockMaster\n\n# Create and attach a master\nsoc = MySoC.create()\nmock = MockMaster()\nmaster = MySoC.wrap_master(mock)\nsoc.attach_master(master)\n\n# Read/write registers\nvalue = soc.peripherals.uart.control.read()\nsoc.peripherals.uart.control.write(0x1234)\n\n# Access individual fields\nsoc.peripherals.uart.control.enable.write(1)\nenable_value = soc.peripherals.uart.control.enable.read()\n\n# Modify specific fields (traditional approach - each field modification is a separate bus transaction)\nsoc.peripherals.uart.control.enable.write(1)\nsoc.peripherals.uart.control.baudrate.write(2)\nsoc.peripherals.uart.control.parity.write(1)\n\n# Use context manager for batched field modifications (recommended)\n# Only 1 read + 1 write transaction to the bus\nwith soc.peripherals.uart.control as reg:\n    reg.enable.write(1)\n    reg.baudrate.write(2)\n    reg.parity.write(1)\n    # All changes are cached and written atomically when exiting the context\n\n# Copy and modify field values within a context\nwith soc.peripherals.uart.control as reg:\n    current_baudrate = reg.baudrate.read()\n    reg.enable.write(current_baudrate & 0x1)  # Use one field value to set another\n```\n\n## Requirements\n\n- Python >= 3.10\n- systemrdl-compiler >= 1.30.1\n- jinja2\n- CMake >= 3.15 (for building generated modules)\n- C++11 compatible compiler (for building generated modules)\n- pybind11 (runtime dependency for generated code)\n\n## Benchmarks\n\nPerformance benchmarks are available to measure export and build times:\n\n```bash\n# Run fast export benchmarks\npython benchmarks/run_benchmarks.py fast\n\n# Run all benchmarks\npytest benchmarks/ --benchmark-only\n\n# See all benchmark options\npython benchmarks/run_benchmarks.py\n```\n\nSee [benchmarks/README.md](benchmarks/README.md) for detailed documentation.\n## Documentation\n\nFull documentation is available at [ReadTheDocs](https://peakrdl-pybind11.readthedocs.io/).\n\nTo build the documentation locally:\n\n```bash\npip install -e .[docs]\ncd docs\nmake html\n```\n\nThe built documentation will be in `docs/_build/html/`.\n\n## License\n\nThis project is licensed under the GPL-3.0 License - see the [LICENSE](LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": "GPL-3.0-only",
    "summary": "Export SystemRDL to PyBind11 modules for Python-based hardware testing",
    "version": "0.4.3",
    "project_urls": {
        "Homepage": "https://github.com/arnavsacheti/PeakRDL-pybind11",
        "Issues": "https://github.com/arnavsacheti/PeakRDL-pybind11/issues",
        "Repository": "https://github.com/arnavsacheti/PeakRDL-pybind11"
    },
    "split_keywords": [
        "systemrdl",
        " pybind11",
        " register",
        " hardware",
        " testing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0de8c48e320a17323212603c859b4156b65efcafbe7b6b6302d96d12341962b4",
                "md5": "1fc59c6e60d2824a3915642eb7fc78be",
                "sha256": "7de70086193319c159d263ca5787d5833bea42503fd8050d08e21efcf2ac65f2"
            },
            "downloads": -1,
            "filename": "peakrdl_pybind11-0.4.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1fc59c6e60d2824a3915642eb7fc78be",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 42377,
            "upload_time": "2025-10-31T05:03:04",
            "upload_time_iso_8601": "2025-10-31T05:03:04.282381Z",
            "url": "https://files.pythonhosted.org/packages/0d/e8/c48e320a17323212603c859b4156b65efcafbe7b6b6302d96d12341962b4/peakrdl_pybind11-0.4.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e77342a53af5990e50952848fcec210bf240259f9518f021f40533e370a2a497",
                "md5": "29225fa2179afc4be83224ef79aa3b42",
                "sha256": "62c5081baaae5576b90547a26f1ea1059be1615c893a4171afe745111cbedd5d"
            },
            "downloads": -1,
            "filename": "peakrdl_pybind11-0.4.3.tar.gz",
            "has_sig": false,
            "md5_digest": "29225fa2179afc4be83224ef79aa3b42",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 49446,
            "upload_time": "2025-10-31T05:03:05",
            "upload_time_iso_8601": "2025-10-31T05:03:05.698345Z",
            "url": "https://files.pythonhosted.org/packages/e7/73/42a53af5990e50952848fcec210bf240259f9518f021f40533e370a2a497/peakrdl_pybind11-0.4.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-31 05:03:05",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "arnavsacheti",
    "github_project": "PeakRDL-pybind11",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "peakrdl-pybind11"
}
        
Elapsed time: 0.87560s