diff --git a/setup.py b/setup.py index a290951..3dd9481 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,11 @@ setuptools.setup( "systemrdl-compiler>=1.22.0", "Jinja2>=2.11", ], + entry_points = { + "peakrdl.exporters": [ + 'regblock = peakrdl_regblock.__peakrdl__:Exporter' + ] + }, classifiers=( #"Development Status :: 5 - Production/Stable", "Development Status :: 3 - Alpha", diff --git a/src/peakrdl_regblock/__peakrdl__.py b/src/peakrdl_regblock/__peakrdl__.py new file mode 100644 index 0000000..f8380fa --- /dev/null +++ b/src/peakrdl_regblock/__peakrdl__.py @@ -0,0 +1,82 @@ +from typing import TYPE_CHECKING + +from .exporter import RegblockExporter +from .cpuif import apb3, axi4lite, passthrough + +if TYPE_CHECKING: + import argparse + from systemrdl.node import AddrmapNode + + +# TODO: make this user-extensible +CPUIF_DICT = { + "apb3": apb3.APB3_Cpuif, + "apb3-flat": apb3.APB3_Cpuif_flattened, + "axi4-lite": axi4lite.AXI4Lite_Cpuif, + "axi4-lite-flat": axi4lite.AXI4Lite_Cpuif_flattened, + "passthrough": passthrough.PassthroughCpuif +} + + +class Exporter: + short_desc = "Generate a SystemVerilog control/status register (CSR) block" + + def add_exporter_arguments(self, arg_group: 'argparse.ArgumentParser') -> None: + arg_group.add_argument( + "--cpuif", + choices=CPUIF_DICT.keys(), + default="apb3", + help="Select the CPU interface protocol to use [apb3]" + ) + + arg_group.add_argument( + "--module-name", + metavar="NAME", + default=None, + help="Override the SystemVerilog module name" + ) + + arg_group.add_argument( + "--package-name", + metavar="NAME", + default=None, + help="Override the SystemVerilog package name" + ) + + arg_group.add_argument( + "--rt-read-fanin", + action="store_true", + default=False, + help="Enable additional read path retiming. Good for register blocks with large readback fan-in" + ) + arg_group.add_argument( + "--rt-read-response", + action="store_true", + default=False, + help="Enable additional retiming stage between readback fan-in and cpu interface" + ) + arg_group.add_argument( + "--type-style", + dest="type_style", + choices=['lexical', 'hier'], + default="lexical", + help="""Choose how HWIF struct type names are generated. + The 'lexical' style will use RDL lexical scope & type names where + possible and attempt to re-use equivalent type definitions. + The 'hier' style uses component's hierarchy as the struct type name. [lexical] + """ + ) + + + def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> None: + x = RegblockExporter() + x.export( + top_node, + options.output, + cpuif_cls=CPUIF_DICT[options.cpuif], + module_name=options.module_name, + package_name=options.package_name, + reuse_hwif_typedefs=(options.type_style == "lexical"), + retime_read_fanin=options.rt_read_fanin, + retime_read_response=options.rt_read_response, + ) diff --git a/src/peakrdl_regblock/exporter.py b/src/peakrdl_regblock/exporter.py index 02f94bc..58546f3 100644 --- a/src/peakrdl_regblock/exporter.py +++ b/src/peakrdl_regblock/exporter.py @@ -99,9 +99,9 @@ class RegblockExporter: self.top_node = node - cpuif_cls = kwargs.pop("cpuif_cls", APB3_Cpuif) # type: Type[CpuifBase] - module_name = kwargs.pop("module_name", self.top_node.inst_name) # type: str - package_name = kwargs.pop("package_name", module_name + "_pkg") # type: str + cpuif_cls = kwargs.pop("cpuif_cls", None) or APB3_Cpuif # type: Type[CpuifBase] + module_name = kwargs.pop("module_name", None) or self.top_node.inst_name # type: str + package_name = kwargs.pop("package_name", None) or (module_name + "_pkg") # type: str reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool # Pipelining options