finn-plus-driver 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: finn-plus-driver
3
+ Version: 1.5.0
4
+ Summary: PYNQ runtime driver for FPGA accelerators generated by finn-plus
5
+ Maintainer: Felix Jentzsch
6
+ Maintainer-email: felix.jentzsch@upb.de
7
+ Requires-Python: >=3.10
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: bitstring (>=4.0)
15
+ Requires-Dist: click (>=8.0)
16
+ Requires-Dist: finn-dataset-loading (>=0.0.5)
17
+ Requires-Dist: grpcio (==1.64.0)
18
+ Requires-Dist: h5py (>=3.0)
19
+ Requires-Dist: matplotlib (>=3.4)
20
+ Requires-Dist: numpy (>=1.21,<2.0.0)
21
+ Requires-Dist: pillow (>=9.0)
22
+ Requires-Dist: qonnx (>=1.0.0)
23
+ Project-URL: EKI Project, https://www.eki-project.tech/
24
+ Project-URL: GitHub, https://github.com/eki-project/finn-plus
25
+ Description-Content-Type: text/markdown
26
+
27
+ # finn-plus-driver
28
+
29
+ Runtime driver for FPGA accelerators generated by
30
+ [finn-plus](https://github.com/eki-project/finn-plus) and deployed to ZYNQ/PYNQ boards.
31
+
32
+ This package contains everything needed to *run* a FINN-generated accelerator and nothing
33
+ of the compiler itself. It is installed on the board, while the accelerator-specific
34
+ artifacts (bitfile, `settings.json`, runtime weights) are produced by the finn-plus build
35
+ flow and copied to the board separately.
36
+
37
+ ## Installation
38
+
39
+ On a PYNQ board, inside the PYNQ virtual environment:
40
+
41
+ ```bash
42
+ sudo pip install finn-plus-driver
43
+ ```
44
+
45
+ `pynq` itself is not declared as a dependency: it is part of the board image.
46
+
47
+ To install the version matching a repository checkout (e.g. in CI):
48
+
49
+ ```bash
50
+ sudo pip install ./driver
51
+ ```
52
+
53
+ ## Usage
54
+
55
+ The driver is usually invoked through its CLI, which instantiates the driver class named in
56
+ `settings.json` and calls one of its member functions:
57
+
58
+ ```bash
59
+ finn-plus-driver -b bitfile/finn-accel.bit -s driver/settings.json -f throughput_test
60
+ ```
61
+
62
+ It can equally be used as a library:
63
+
64
+ ```python
65
+ from finn_plus_driver import FINNDMAOverlay
66
+
67
+ accel = FINNDMAOverlay("finn-accel.bit", io_shape_dict=io_shape_dict)
68
+ output = accel.execute(input_array)
69
+ ```
70
+
71
+ ## Contents
72
+
73
+ | Module | Purpose |
74
+ | --- | --- |
75
+ | `finn_plus_driver.overlays.dma` | `FINNDMAOverlay`, the standard DMA-based accelerator driver |
76
+ | `finn_plus_driver.overlays.instrumentation` | `FINNInstrumentationOverlay`, DMA-less instrumentation runs |
77
+ | `finn_plus_driver.overlays.live_fifo` | `FINNLiveFIFOOverlay`, live FIFO sizing experiments |
78
+ | `finn_plus_driver.overlays.dma_instrumentation` | `FINNDMAInstrumentationOverlay`, combined DMA + instrumentation |
79
+ | `finn_plus_driver.packing` | Data packing/unpacking between numpy and the accelerator's bit-level format |
80
+ | `finn_plus_driver.validate` | Dataset-specific accuracy validation (MNIST, CIFAR, ImageNet, RadioML, UNSW-NB15) |
81
+ | `finn_plus_driver.cli` | Command line interface |
82
+
@@ -0,0 +1,55 @@
1
+ # finn-plus-driver
2
+
3
+ Runtime driver for FPGA accelerators generated by
4
+ [finn-plus](https://github.com/eki-project/finn-plus) and deployed to ZYNQ/PYNQ boards.
5
+
6
+ This package contains everything needed to *run* a FINN-generated accelerator and nothing
7
+ of the compiler itself. It is installed on the board, while the accelerator-specific
8
+ artifacts (bitfile, `settings.json`, runtime weights) are produced by the finn-plus build
9
+ flow and copied to the board separately.
10
+
11
+ ## Installation
12
+
13
+ On a PYNQ board, inside the PYNQ virtual environment:
14
+
15
+ ```bash
16
+ sudo pip install finn-plus-driver
17
+ ```
18
+
19
+ `pynq` itself is not declared as a dependency: it is part of the board image.
20
+
21
+ To install the version matching a repository checkout (e.g. in CI):
22
+
23
+ ```bash
24
+ sudo pip install ./driver
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ The driver is usually invoked through its CLI, which instantiates the driver class named in
30
+ `settings.json` and calls one of its member functions:
31
+
32
+ ```bash
33
+ finn-plus-driver -b bitfile/finn-accel.bit -s driver/settings.json -f throughput_test
34
+ ```
35
+
36
+ It can equally be used as a library:
37
+
38
+ ```python
39
+ from finn_plus_driver import FINNDMAOverlay
40
+
41
+ accel = FINNDMAOverlay("finn-accel.bit", io_shape_dict=io_shape_dict)
42
+ output = accel.execute(input_array)
43
+ ```
44
+
45
+ ## Contents
46
+
47
+ | Module | Purpose |
48
+ | --- | --- |
49
+ | `finn_plus_driver.overlays.dma` | `FINNDMAOverlay`, the standard DMA-based accelerator driver |
50
+ | `finn_plus_driver.overlays.instrumentation` | `FINNInstrumentationOverlay`, DMA-less instrumentation runs |
51
+ | `finn_plus_driver.overlays.live_fifo` | `FINNLiveFIFOOverlay`, live FIFO sizing experiments |
52
+ | `finn_plus_driver.overlays.dma_instrumentation` | `FINNDMAInstrumentationOverlay`, combined DMA + instrumentation |
53
+ | `finn_plus_driver.packing` | Data packing/unpacking between numpy and the accelerator's bit-level format |
54
+ | `finn_plus_driver.validate` | Dataset-specific accuracy validation (MNIST, CIFAR, ImageNet, RadioML, UNSW-NB15) |
55
+ | `finn_plus_driver.cli` | Command line interface |
@@ -0,0 +1,48 @@
1
+ """Runtime driver for FPGA accelerators generated by finn-plus.
2
+
3
+ The overlay classes require ``pynq``, which is only available on a PYNQ board image. They
4
+ are therefore imported lazily, so that helper modules such as :mod:`finn_plus_driver.packing`
5
+ remain usable off-board (for example in tests or on a build host).
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ #: Maps the driver type names emitted into ``settings.json`` by the finn-plus build flow to
11
+ #: the module that implements them. Used instead of module introspection so the mapping is
12
+ #: explicit and does not depend on import side effects.
13
+ DRIVER_TYPES: dict[str, str] = {
14
+ "FINNDMAOverlay": "finn_plus_driver.overlays.dma",
15
+ "FINNInstrumentationOverlay": "finn_plus_driver.overlays.instrumentation",
16
+ "FINNLiveFIFOOverlay": "finn_plus_driver.overlays.live_fifo",
17
+ "FINNDMAInstrumentationOverlay": "finn_plus_driver.overlays.dma_instrumentation",
18
+ }
19
+
20
+ __all__ = [*DRIVER_TYPES, "DRIVER_TYPES", "get_driver_class"]
21
+
22
+
23
+ def get_driver_class(driver_type: str) -> type:
24
+ """Return the overlay class for the given driver type name.
25
+
26
+ Args:
27
+ driver_type: Name of the driver class, as stored in ``settings.json``.
28
+
29
+ Returns:
30
+ The overlay class matching ``driver_type``.
31
+
32
+ Raises:
33
+ ValueError: If ``driver_type`` is not a known driver type.
34
+ """
35
+ from importlib import import_module
36
+
37
+ if driver_type not in DRIVER_TYPES:
38
+ raise ValueError(
39
+ f"Unknown driver type '{driver_type}'. Known types: {sorted(DRIVER_TYPES)}"
40
+ )
41
+ return getattr(import_module(DRIVER_TYPES[driver_type]), driver_type)
42
+
43
+
44
+ def __getattr__(name: str) -> Any:
45
+ """Resolve overlay classes lazily so importing this package does not require pynq."""
46
+ if name in DRIVER_TYPES:
47
+ return get_driver_class(name)
48
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1,6 @@
1
+ """Allow running the driver CLI via ``python -m finn_plus_driver``."""
2
+
3
+ from finn_plus_driver.cli import driver_cli
4
+
5
+ if __name__ == "__main__":
6
+ driver_cli()
@@ -0,0 +1,97 @@
1
+ """Command line interface for the FINN PYNQ runtime driver."""
2
+
3
+ import click
4
+ import json
5
+
6
+ from finn_plus_driver import get_driver_class
7
+
8
+
9
+ def parse_kv(ctx, self, value):
10
+ """Parse key-value pairs from CLI arguments."""
11
+ result = {}
12
+ for item in value:
13
+ if len(item) != 2:
14
+ print(item)
15
+ raise click.UsageError(
16
+ "Items must be in form: key=val TYPE. "
17
+ 'With datatypes ["Str", "Int", "Bool", "Float"] being supported'
18
+ )
19
+ if item[0].count("=") != 1:
20
+ raise click.BadParameter("Items must be key=value")
21
+ k, v = item[0].split("=", 1)
22
+
23
+ data_type = item[1]
24
+ if data_type == "Str":
25
+ v = v
26
+ elif data_type == "Int":
27
+ v = int(v)
28
+ elif data_type == "Bool":
29
+ # Is always True except for v == False
30
+ v = not (v == "False")
31
+ elif data_type == "Float":
32
+ v = float(v)
33
+ else:
34
+ raise click.BadParameter(
35
+ f'Only datatypes ["Str", "Int", "Bool", "Float"] '
36
+ f"are supported. Used datatype: {data_type}"
37
+ )
38
+
39
+ result[k] = v
40
+ return result
41
+
42
+
43
+ @click.command(
44
+ "Example: finn-plus-driver -b ../bitfile/finn-accel.bit "
45
+ "-s ./settings.json -f experiment_instrumentation "
46
+ "-ck seed=42 Int -fk runtime=10 Int "
47
+ "-fk report_dir='./report_dir/' Str"
48
+ )
49
+ @click.option("--bitfile_name", "-b", help="Path to the Bitstream")
50
+ @click.option("--settings", "-s", help="Path to the settings.json")
51
+ @click.option("--function", "-f", help="Function to be executed")
52
+ @click.option(
53
+ "--ckwarg",
54
+ "-ck",
55
+ multiple=True,
56
+ callback=parse_kv,
57
+ nargs=2,
58
+ help=("Keyword argument for the class instance: ... -ck key1=val1 TYPE -ck key2=val2 TYPE"),
59
+ )
60
+ @click.option(
61
+ "--fkwarg",
62
+ "-fk",
63
+ multiple=True,
64
+ callback=parse_kv,
65
+ nargs=2,
66
+ help=("Keyword argument for the called function: ... -fk key1=val1 TYPE -fk key2=val2 TYPE"),
67
+ )
68
+ def driver_cli(bitfile_name, settings, function, ckwarg, fkwarg):
69
+ """CLI tool to instantiate driver and execute functions.
70
+
71
+ Instantiates a driver class and executes a member function.
72
+ The instantiation implicitly loads a bitstream to the FPGA.
73
+ Requires FINN generated bitstream file and settings.json.
74
+ Driver class is inferred from settings.json, while the called
75
+ member function must be chosen via the function option.
76
+ Kwargs for class instantiation or function call can be input
77
+ via --ckwarg or --fkwarg options respectively.
78
+ Class Kwargs take precedence over settings.json Kwargs.
79
+ """
80
+ with open(settings, encoding="utf-8") as f:
81
+ driver_settings = json.load(f)["driver_information"]
82
+
83
+ if ckwarg is None:
84
+ ckwarg = {}
85
+ if fkwarg is None:
86
+ fkwarg = {}
87
+
88
+ driver_type = driver_settings["driver_type"]
89
+ input_kwargs = {
90
+ **driver_settings,
91
+ **ckwarg,
92
+ } # ckwarg has precedence when a key conflict happens
93
+
94
+ cla = get_driver_class(driver_type)
95
+ inst = cla(bitfile_name, **input_kwargs)
96
+ func = getattr(inst, function)
97
+ print(func(**fkwarg))
@@ -0,0 +1,32 @@
1
+ """Helpers for reading metadata out of the HWH file accompanying a bitfile."""
2
+
3
+ import os
4
+ import xml.etree.ElementTree as ET
5
+
6
+
7
+ def get_clk_wiz_params_from_hwh(bitfile_name):
8
+ """Parse the HWH file to get clk_wiz_0 parameters.
9
+
10
+ PYNQ's ip_dict only contains IPs with an AXI-Lite slave interface, so the
11
+ Clocking Wizard (when configured without AXI-Lite) will not appear there.
12
+ This function reads the HWH XML directly to retrieve its parameters.
13
+
14
+ Returns a dict of parameter name -> value strings. The dict is empty when the HWH file
15
+ is missing, unparsable, or contains no Clocking Wizard, so that callers can fall back to
16
+ their configured frequency via ``dict.get(..., default)`` without a None check.
17
+ """
18
+ hwh_path = os.path.splitext(bitfile_name)[0] + ".hwh"
19
+ if not os.path.exists(hwh_path):
20
+ return {}
21
+ try:
22
+ tree = ET.parse(hwh_path)
23
+ root = tree.getroot()
24
+ for module in root.iter("MODULE"):
25
+ if module.get("INSTANCE") == "clk_wiz_0":
26
+ params = {}
27
+ for param in module.iter("PARAMETER"):
28
+ params[param.get("NAME")] = param.get("VALUE")
29
+ return params
30
+ except ET.ParseError:
31
+ return {}
32
+ return {}
@@ -0,0 +1,13 @@
1
+ """Overlay classes for FINN-generated accelerators."""
2
+
3
+ from finn_plus_driver.overlays.dma import FINNDMAOverlay
4
+ from finn_plus_driver.overlays.dma_instrumentation import FINNDMAInstrumentationOverlay
5
+ from finn_plus_driver.overlays.instrumentation import FINNInstrumentationOverlay
6
+ from finn_plus_driver.overlays.live_fifo import FINNLiveFIFOOverlay
7
+
8
+ __all__ = [
9
+ "FINNDMAInstrumentationOverlay",
10
+ "FINNDMAOverlay",
11
+ "FINNInstrumentationOverlay",
12
+ "FINNLiveFIFOOverlay",
13
+ ]