Add support for user-extending cpuif for PeakRDL command-line
This commit is contained in:
@@ -76,3 +76,39 @@ you can define your own.
|
|||||||
|
|
||||||
3. Use your new CPUIF definition when exporting.
|
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!
|
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.
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from .exporter import RegblockExporter
|
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 .udps import ALL_UDPS
|
||||||
|
from . import entry_points
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import argparse
|
import argparse
|
||||||
from systemrdl.node import AddrmapNode
|
from systemrdl.node import AddrmapNode
|
||||||
|
|
||||||
|
|
||||||
# TODO: make this user-extensible
|
|
||||||
CPUIF_DICT = {
|
CPUIF_DICT = {
|
||||||
"apb3": apb3.APB3_Cpuif,
|
"apb3": apb3.APB3_Cpuif,
|
||||||
"apb3-flat": apb3.APB3_Cpuif_flattened,
|
"apb3-flat": apb3.APB3_Cpuif_flattened,
|
||||||
@@ -20,6 +20,16 @@ CPUIF_DICT = {
|
|||||||
"passthrough": passthrough.PassthroughCpuif
|
"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:
|
class Exporter:
|
||||||
short_desc = "Generate a SystemVerilog control/status register (CSR) block"
|
short_desc = "Generate a SystemVerilog control/status register (CSR) block"
|
||||||
|
|||||||
19
src/peakrdl_regblock/entry_points.py
Normal file
19
src/peakrdl_regblock/entry_points.py
Normal file
@@ -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)
|
||||||
Reference in New Issue
Block a user