diff --git a/rdl2ot/README.md b/rdl2ot/README.md index 7f82002..96b71c8 100644 --- a/rdl2ot/README.md +++ b/rdl2ot/README.md @@ -1,7 +1,8 @@ # rdl2ot cli tool A PeakRDL extension to generate Opentitan style source files from SystemRDL files. -## How to generate the Opentitan register interfaces from a RDL file +## Using as a standalone tool +### How to generate the Opentitan register interfaces from a RDL file ```sh rdl2ot export-rtl ``` @@ -12,6 +13,17 @@ mkdir -p /tmp/lc_ctrl rdl2ot export-rtl tests/snapshots/lc_ctrl.rdl /tmp/lc_ctrl/ ``` +## Using as a Peakrdl pluggin +### Installing +```sh +pip install peakrdl rdl2ot +``` +### Running +```sh +mkdir -p /tmp/lc_ctrl +peakrdl rdl2ot tests/snapshots/lc_ctrl.rdl -o /tmp/lc_ctrl/ +``` + ## Contributing ### How to run tests ```sh diff --git a/rdl2ot/pyproject.toml b/rdl2ot/pyproject.toml index fbf78cd..4055406 100644 --- a/rdl2ot/pyproject.toml +++ b/rdl2ot/pyproject.toml @@ -23,6 +23,9 @@ Homepage = "https://github.com/lowrisc/benevisrdl" Issues = "https://github.com/lowrisc/benevisrdl/issues" Documentation = "https://github.com/lowrisc/benevisrdl" +[project.entry-points."peakrdl.exporters"] +rdl2ot = "rdl2ot.__peakrdl__:Exporter" + [build-system] requires = ["hatchling"] build-backend = "hatchling.build" @@ -38,3 +41,4 @@ executionEnvironments = [ [tool.hatch.build.targets.wheel] packages = ["src/rdl2ot", "src/templates"] + diff --git a/rdl2ot/src/rdl2ot/__peakrdl__.py b/rdl2ot/src/rdl2ot/__peakrdl__.py new file mode 100644 index 0000000..2a2b5e4 --- /dev/null +++ b/rdl2ot/src/rdl2ot/__peakrdl__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +"""Generates Opentitan regblock RTL.""" + +from pathlib import Path +from typing import TYPE_CHECKING + +from peakrdl.plugins.exporter import ExporterSubcommandPlugin # pylint: disable=import-error + +from rdl2ot import rtl_exporter + +if TYPE_CHECKING: + import argparse + + from systemrdl.node import AddrmapNode + + +class Exporter(ExporterSubcommandPlugin): + """Generates Opentitan regblock RTL.""" + + short_desc = "Generates Opentitan register block RTL." + + def add_exporter_arguments(self, arg_group: "argparse.ArgumentParser") -> None: + """No extra arguments.""" + + def do_export(self, top_node: "AddrmapNode", options: "argparse.Namespace") -> None: + """Plugin entry function.""" + rtl_exporter.run(top_node, Path(options.output)) diff --git a/rdl2ot/src/rdl2ot/cli.py b/rdl2ot/src/rdl2ot/cli.py index 34f2b56..e776bf8 100644 --- a/rdl2ot/src/rdl2ot/cli.py +++ b/rdl2ot/src/rdl2ot/cli.py @@ -41,6 +41,6 @@ def export_rtl(input_file: str, out_dir: str) -> None: rdlc.compile_file(input_file) root = rdlc.elaborate() - rtl_exporter.run(rdlc, root, Path(out_dir)) + rtl_exporter.run(root.top, Path(out_dir)) print("Successfully finished!\n") diff --git a/rdl2ot/src/rdl2ot/rtl_exporter.py b/rdl2ot/src/rdl2ot/rtl_exporter.py index deac8eb..21e41af 100644 --- a/rdl2ot/src/rdl2ot/rtl_exporter.py +++ b/rdl2ot/src/rdl2ot/rtl_exporter.py @@ -8,7 +8,7 @@ from pathlib import Path from jinja2 import Environment, FileSystemLoader -from systemrdl import RDLCompiler, node +from systemrdl import node from systemrdl.rdltypes import OnReadType from rdl2ot import opentitan @@ -17,10 +17,10 @@ DEFAULT_INTERFACE_NAME = "regs" -def run(rdlc: RDLCompiler, obj: node.RootNode, out_dir: Path) -> None: +def run(root_node: node.AddrmapNode, out_dir: Path) -> None: """Export RDL to opentitan RTL.""" - factory = OtInterfaceBuilder(rdlc) - data = factory.parse_root(obj.top) + factory = OtInterfaceBuilder() + data = factory.parse_root(root_node) Path(out_dir / "rdl.json").write_text(json.dumps(data, indent=2), encoding="utf-8") @@ -54,11 +54,6 @@ class OtInterfaceBuilder: async_registers: list = [(int, str)] # List of all the (index, register) with async clock any_shadowed_reg: bool = False reg_index: int = 0 - rdlc: RDLCompiler - - def __init__(self, rdlc: RDLCompiler) -> None: - """Constructor.""" - self.rdlc = rdlc def get_field(self, field: node.FieldNode) -> dict: """Parse a field and return a dictionary.""" diff --git a/rdl2ot/tests/test_rdl2ot.py b/rdl2ot/tests/test_rdl2ot.py index 11f496e..961b23a 100644 --- a/rdl2ot/tests/test_rdl2ot.py +++ b/rdl2ot/tests/test_rdl2ot.py @@ -24,7 +24,10 @@ def _run_cli_tool(input_file_path: Path, output_dir_path: Path) -> subprocess.Co ] return subprocess.run(command, capture_output=True, text=True, check=False) # noqa: S603 + test_ips = ["lc_ctrl", "uart"] + + @pytest.mark.parametrize("ip_block", test_ips) def test_export_ip(tmp_path: Path, ip_block: str) -> None: """Test an given ip block."""