Skip to content

Commit

Permalink
Add support for user-extending cpuif for PeakRDL command-line
Browse files Browse the repository at this point in the history
  • Loading branch information
amykyta3 committed Nov 9, 2022
1 parent 232faba commit 17afaf1
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
36 changes: 36 additions & 0 deletions docs/cpuif/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,39 @@ you can define your own.

3. Use your new CPUIF definition when exporting.
4. If you think the CPUIF protocol is something others might find useful, let me know and I can add it to PeakRDL!


Entry point for the PeakRDL command line tool
---------------------------------------------
To make your custom CPUIF class visible to the `PeakRDL command-line tool <https://peakrdl.readthedocs.io>`_,
provide an entry point linkage in your package's ``setup.py``. This advertises
your custom CPUIF class to the PeakRDL-regblock tool as a plugin that should be
loaded, and made available as a command-line option in PeakRDL.


.. code-block:: python
:emphasize-lines: 7-11
import setuptools
setuptools.setup(
name="my_package",
packages=["my_package"],
# ...
entry_points = {
"peakrdl_regblock.cpuif": [
'my-cpuif = my_package.__peakrdl_regblock__:MyCPUIF'
]
}
)
* ``my_package``: The name of your installable Python module
* ``peakrdl-regblock.cpuif``: This is the namespace that PeakRDL-regblock will
search. Any cpuif plugins you create must be enclosed in this namespace in
order to be discovered.
* ``my_package.__peakrdl_regblock__:MyCPUIF``: This is the import path that
points to your CPUIF class definition.
* ``my-cpuif``: The lefthand side of the assignment is your cpuif's name. This
text is what the end-user uses in the command line interface to select your
CPUIF implementation.
14 changes: 12 additions & 2 deletions src/peakrdl_regblock/__peakrdl__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import TYPE_CHECKING

from .exporter import RegblockExporter
from .cpuif import apb3, apb4, axi4lite, passthrough
from .cpuif import apb3, apb4, axi4lite, passthrough, CpuifBase
from .udps import ALL_UDPS
from . import entry_points

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,
Expand All @@ -20,6 +20,16 @@
"passthrough": passthrough.PassthroughCpuif
}

# Load any user-plugins
for ep in entry_points.get_entry_points("peakrdl_regblock.cpuif"): # type: ignore
name = ep.name
cpuif = ep.load()
if name in CPUIF_DICT:
raise RuntimeError(f"A plugin for 'peakrdl-regblock' tried to load cpuif '{name}' but it already exists")
if not issubclass(cpuif, CpuifBase):
raise RuntimeError(f"A plugin for 'peakrdl-regblock' tried to load cpuif '{name}' but it not a CpuifBase class")
CPUIF_DICT[name] = cpuif


class Exporter:
short_desc = "Generate a SystemVerilog control/status register (CSR) block"
Expand Down
19 changes: 19 additions & 0 deletions src/peakrdl_regblock/entry_points.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# type: ignore
import sys

if sys.version_info >= (3,10,0):
from importlib import metadata

def get_entry_points(group_name):
return metadata.entry_points().select(group=group_name)

elif sys.version_info >= (3,8,0):
from importlib import metadata

def get_entry_points(group_name):
return metadata.entry_points().get(group_name, tuple())

else:
import pkg_resources
def get_entry_points(group_name):
return pkg_resources.iter_entry_points(group_name)

0 comments on commit 17afaf1

Please sign in to comment.