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.
- finn_plus_driver-1.5.0/PKG-INFO +82 -0
- finn_plus_driver-1.5.0/README.md +55 -0
- finn_plus_driver-1.5.0/finn_plus_driver/__init__.py +48 -0
- finn_plus_driver-1.5.0/finn_plus_driver/__main__.py +6 -0
- finn_plus_driver-1.5.0/finn_plus_driver/cli.py +97 -0
- finn_plus_driver-1.5.0/finn_plus_driver/hwh.py +32 -0
- finn_plus_driver-1.5.0/finn_plus_driver/overlays/__init__.py +13 -0
- finn_plus_driver-1.5.0/finn_plus_driver/overlays/dma.py +540 -0
- finn_plus_driver-1.5.0/finn_plus_driver/overlays/dma_instrumentation.py +555 -0
- finn_plus_driver-1.5.0/finn_plus_driver/overlays/instrumentation.py +209 -0
- finn_plus_driver-1.5.0/finn_plus_driver/overlays/live_fifo.py +664 -0
- finn_plus_driver-1.5.0/finn_plus_driver/packing.py +400 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/__init__.py +37 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/cifar.py +54 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/imagenet.py +90 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/mnist.py +53 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/radioml.py +80 -0
- finn_plus_driver-1.5.0/finn_plus_driver/validate/unswnb15.py +49 -0
- finn_plus_driver-1.5.0/pyproject.toml +56 -0
|
@@ -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,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
|
+
]
|