# SAMO: Streaming Architecture Mapping Optimiser

The SAMO framework provides a method of optimising the mapping of a Convolutional Neural Network model onto an FPGA platform for Streaming Architecture frameworks. Both a Simulated Annealing and Brute Force optimiser are implemented. We currently support the following frameworks:

- [FINN](https://github.com/Xilinx/finn)
- [HLS4ML](https://github.com/fastmachinelearning/hls4ml)
- [fpgaConvNet](https://github.com/AlexMontgomerie/fpgaconvnet-optimiser)


## Installation

You can install this package using:

```
python -m pip install samo
```

## Usage

The general usage of the SAMO tool can be seen by running `python -m samo --help`.

Example platform configurations are given in the `platforms` directory and example CNN models can be generated by running `python scripts/generate_networks.py`.

### FINN

> TODO

### HLS4ML

This tool can be used to generate optimised designs for the [HLS4ML](https://github.com/fastmachinelearning/hls4ml) framework. SAMO tunes the `reuse-factor` for layers of the CNN model, and generates a `Resource` driven design.

To optimise a keras model for a given platform, run the following:

```
python -m samo --optimiser annealing --model models/model.keras \
    --backend hls4ml --platform platforms/zedboard.json \
    --output-path outputs/model_hls4ml.json
```

The previous command generates a configuration file (`outputs/model_hls4ml.json`), which can be used by the HLS4ML to generate hardware. To do this, you will need to use the HLS4ML API to convert this configuration file into a HLS project.

```python
import hls4ml
from tensorflow import keras

# load the configuration
with open("outputs/model_hls4ml.json", "r") as f:
    config = json.load(f)

# load the platform
with open("platforms/zedboard.json", "r") as f:
    platform = json.load(f)

# load the keras model
model = keras.models.load_model("models/model.keras")

# create the hls model
hls_model = hls4ml.converters.convert_from_keras_model(model, hls_config=config,
        output_dir="outputs/hls4ml_prj",  io_type="io_stream", fpga_part=platform["part"])

# build the HLS project
hls_model.build(csim=True, cosim=True)
```

---

Feel free to post an issue if you have any questions or problems!
