From 0914d9e6b9e9a65144349a28e0dbb3ac524a5519 Mon Sep 17 00:00:00 2001 From: davideconficconi Date: Mon, 12 Sep 2022 15:11:47 +0200 Subject: [PATCH] [MK & co.] adding the remainder stuffs --- .gitignore | 67 +++++ Makefile | 345 +++++++++++++++++++++++ README.md | 212 ++++++++++++++- dse_scripts/dse_alveo_mi.sh | 53 ++++ dse_scripts/dse_alveo_waxmi.sh | 59 ++++ dse_scripts/dse_ultra96_cc.sh | 53 ++++ dse_scripts/dse_ultra96_wax.sh | 52 ++++ dse_scripts/dse_ultra96_waxcc.sh | 53 ++++ dse_scripts/dse_zcu104_mse.sh | 51 ++++ dse_scripts/dse_zcu104_waxmse.sh | 54 ++++ dse_scripts/dsesoa.sh | 41 +++ images/faber_abstract.png | Bin 0 -> 130991 bytes images/flt.png | Bin 0 -> 2064 bytes images/ref.png | Bin 0 -> 2193 bytes platforms/alveo_u200.mk | 65 +++++ platforms/alveo_u200_hw.mk | 2 + platforms/configuration_parameters.mk | 349 ++++++++++++++++++++++++ platforms/pynqz2.mk | 3 + platforms/ultra96_v2.mk | 3 + platforms/vitis_alveo.mk | 376 ++++++++++++++++++++++++++ platforms/vitis_alveo_host.mk | 48 ++++ platforms/zcu104.mk | 3 + platforms/zynq.mk | 122 +++++++++ platforms/zynq_mpsoc.mk | 21 ++ platforms/zynq_soc.mk | 21 ++ 25 files changed, 2052 insertions(+), 1 deletion(-) create mode 100755 .gitignore create mode 100644 Makefile create mode 100755 dse_scripts/dse_alveo_mi.sh create mode 100755 dse_scripts/dse_alveo_waxmi.sh create mode 100644 dse_scripts/dse_ultra96_cc.sh create mode 100755 dse_scripts/dse_ultra96_wax.sh create mode 100755 dse_scripts/dse_ultra96_waxcc.sh create mode 100755 dse_scripts/dse_zcu104_mse.sh create mode 100755 dse_scripts/dse_zcu104_waxmse.sh create mode 100755 dse_scripts/dsesoa.sh create mode 100644 images/faber_abstract.png create mode 100644 images/flt.png create mode 100644 images/ref.png create mode 100644 platforms/alveo_u200.mk create mode 100644 platforms/alveo_u200_hw.mk create mode 100644 platforms/configuration_parameters.mk create mode 100644 platforms/pynqz2.mk create mode 100644 platforms/ultra96_v2.mk create mode 100644 platforms/vitis_alveo.mk create mode 100644 platforms/vitis_alveo_host.mk create mode 100644 platforms/zcu104.mk create mode 100644 platforms/zynq.mk create mode 100644 platforms/zynq_mpsoc.mk create mode 100644 platforms/zynq_soc.mk diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..7500d47 --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +build +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# python +*.pyc + +# latex +*.aux +*.fdb_latexmk +*.fls +*.log +*.gz +*.toc +*.nav +*.snm +*.synctex.gz diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..acdf957 --- /dev/null +++ b/Makefile @@ -0,0 +1,345 @@ +#/****************************************** +#*MIT License +#* +#*Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +#* +#*Permission is hereby granted, free of charge, to any person obtaining a copy +#*of this software and associated documentation files (the "Software"), to deal +#*in the Software without restriction, including without limitation the rights +#*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#*copies of the Software, and to permit persons to whom the Software is +#*furnished to do so, subject to the following conditions: +#* +#*The above copyright notice and this permission notice shall be included in all +#*copies or substantial portions of the Software. +#* +#*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#*SOFTWARE. +#*/ +#/*************************************************************** +#* +#* Makefile +#* +#****************************************************************/ + +############################################################## +#directory stuffs +SHELL = /bin/bash +TOP := $(shell pwd) +MAIN_PRJ=faber + +PYTHON=python3 +############################################################## +#Directories stuff +SRC_DIR=$(TOP)/src +BUILD_DIR=$(TOP)/build +BUILD_PLAT_DIR ?= ${BUILD_DIR}/${TRGT_PLATFORM} +CURR_BUILD_DIR=$(BUILD_PLAT_DIR)/$(CURR_CONFIG) +HLS_CONFIG_DIR ?= $(CURR_BUILD_DIR)/src/hls +VTS_BUILD_DIR ?= $(CURR_BUILD_DIR) + + +HLS_DIR=$(SRC_DIR)/hls +HLS_INCLUDES= +HLS_DIR_VTS=$(HLS_DIR) +HLS_METRICS_DIR=$(HLS_DIR)/metrics +HLS_TX_DIR=$(HLS_DIR)/transform + +HLS_CURR_METRIC_DIR= +HLS_CURR_TX_DIR= +HLS_CURR_DIR= + +SCRIPT_DIR=$(SRC_DIR)/scripts +DRVR_DIR=$(SRC_DIR)/driver +DEPLOY_DIR=$(CURR_BUILD_DIR)/deploy +SW_DIR=$(SRC_DIR)/sw +HOSTS_DIR=$(SRC_DIR)/hosts +PRJ_NAME?=faber-hls + + +####################################################### +include platforms/configuration_parameters.mk +####################################################### +#HLS stuffs + +HLS_INCL ?= /xilinx/software/Vivado/2019.2/include +VIVADO_VERSION = $(shell vivado -version | grep Vivado) +VIVADO_SCRIPT_DIR ?= $(SCRIPT_DIR)/$(TRGT_PLATFORM) + +####################################################### + +HLS_CONF_LOGGER = hls_verification.csv + + +HLS_OPTS?=5 +# 0 for only project build; 1 for sim only; 2 synth; 3 cosim; 4 synth and ip downto impl; 5 synth and ip; 6 for ip export +####################################################### +#vivado stuffs +IP_REPO ?= $(CURR_BUILD_DIR)/$(PRJ_NAME)/solution1/impl/ip +VIVADO_MODE ?= batch # or gui +FREQ_MHZ ?= 150 + +KERNEL = faber +####################################################### + +LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):/usr/local/lib64 + +ACCEL_GENERATOR=generator.py +####################################################### + +#deploying parameters +BRD_IP?=192.168.3.1 +BRD_DIR?=/home/xilinx/faber/ +BRD_USR?=xilinx +####################################################### +DPLY_PY ?= $(BUILD_PLAT_DIR)/sw_py +APP_PY ?= $(BUILD_DIR)/app_py +PY_DIR = $(SW_DIR)/python +PY_MI ?= faber-single-mi.py +PY_PWL ?= faber-powell-blocked.py +PY_ONPL ?= faber-oneplusone-blocked.py +PY_WAXMI ?= faber-single-waxmi.py +PY_GENERIC = $(SW_DIR)/faberRegistratorsTorch.py +PY_GENERIC += $(PY_DIR)/faberImageRegistration.py +PY_OPTS ?= $(SW_DIR)/faberOptimizersTorch.py +PY_SW_PURE ?= $(SW_DIR)/fabersw-unique.py +###################################################### +.PHONY:help test_recipes print_config gen_hls_config gen_hls_config_vts + +help: + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo " Faber makefile helper " + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "" + @echo " [HELP] 'make' shows this helper" + @echo "" + @echo " [HELP] 'make print_config' print Faber current config generation" + @echo "" + @echo " [HELP] 'make curr_config' print Faber config generation parameters" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] 'make all' prepare everything, sw, hls, hw" + @echo "" + @echo "[INFO] 'make gen_hls_config' generate the HLS configuration " + @echo "[INFO] 'make gen_hls_config_vts' generate Vitis configuration" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] extract specific board results" + @echo " 'make resyn_extr_zynq_%' or 'make resyn_extr_vts_%'" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] 'make deploy' copy the deployable to the target dir" + @echo " default configuration: micro-usb addr 'BRD_URI?=192.168.3.1'" + @echo " default target directory on the board 'BRD_DIR?=/home/xilinx/Faber/'" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " Clean utilities " + @echo "" + @echo "*****************************************************************" + @echo "" + @echo "[INFO] 'make cleanhls' cleans hls project " + @echo "[INFO] 'make cleanvivado' cleans vivado project, only for Zynq" + @echo "[INFO] 'make cleanreport' cleans everything in the report folder" + @echo "[INFO] 'make cleanall' cleans everything in the build folder" + @echo "[INFO] 'make cleanplat' cleans everything in the plat folder" + @echo "" + @echo "" + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "" + @echo " End of general Faber makefile helper " + @echo "" + @echo "*****************************************************************" + @echo "*****************************************************************" + @echo "*****************************************************************" + @make helplat + @make helparam + @make helptargets + + + +####################################################### +# platform-specific Makefile include for bitfile synthesis +include platforms/$(TRGT_PLATFORM).mk + + +################################################################ +# HLS config stuffs +################################################################ + +print_config: + @echo $(CURR_CONFIG) + +copy_hls_code: check_accelerator + mkdir -p $(HLS_CONFIG_DIR) + cp -f $(hls_curr_code_filtered) $(HLS_CONFIG_DIR) + cp -f $(hls_curr_tb) $(HLS_CONFIG_DIR) + rm -f $(HLS_CONFIG_DIR)/*_testbench.cpp + +check_accelerator: +ifndef METRIC +ifndef TRANSFORM + $(error You must define either METRIC or TRANSFORM to generate an accelerator) +endif +endif + +default_ultra96: + make hw_gen D=${D} IB=${IB} OPTIMZER=plone TRGT_PLATFORM=ultra96_v2 \ + METRIC=cc TRANSFORM=wax PE=1 CORE_NR=2 FREQ_MHZ=200 HTYPS=float \ + CACHING=false URAM=false INTERP_TYPE=nearestn + make pysw + + +default_alveo_u200: + make hw_gen D=${D} IB=${IB} OPTIMZER=powell TRGT_PLATFORM=alveo_u200 \ + METRIC=mi PE=16 CORE_NR=1 PE_ENTROP=1 CACHING=false URAM=false\ + CLK_FRQ=300 TARGET=hw OPT_LVL=3 + make pysw + +pure_sw: + mkdir -p $(APP_PY) + cp $(PY_GENERIC) $(APP_PY)/ + cp $(PY_SW_PURE) $(APP_PY)/ + cp $(PY_OPTS) $(APP_PY)/ + +#TODO +#I have some doubts about the copy and remove of tb code. might fix this :D +gen_hls_config: copy_hls_code + $(PYTHON) $(SCRIPT_DIR)/generators/$(ACCEL_GENERATOR) -c -op $(HLS_CONFIG_DIR)/ $(GEN_CONFIG_DESIGN_OPTS) + + +gen_hls_config_vts:copy_hls_code + $(PYTHON) $(SCRIPT_DIR)/generators/$(ACCEL_GENERATOR) -c -op $(HLS_CONFIG_DIR)/ $(GEN_CONFIG_DESIGN_OPTS) -vts + +all: | sw hls hw + +all_config : | sw hw_gen + +resyn_extr_zynq_%: + $(SCRIPT_DIR)/extract_all_synt_res.sh $* false true ${FREQ_MHZ} + +resyn_extr_vts_%: + $(eval include platforms/$*_hw.mk) + echo $(TARGET_DEVICE) + $(SCRIPT_DIR)/extract_all_synt_res.sh $* true true ${FREQ_MHZ} $(TARGET_DEVICE) + +deploynewpy: + mkdir -p $(BUILD_DIR) + +deploy: deploypy + rsync -avz $(DEPLOY_DIR) $(BRD_USR)@$(BRD_IP):$(BRD_DIR) + +deploypy: pysw + rsync -avz $(DPLY_PY) $(BRD_USR)@$(BRD_IP):$(BRD_DIR) + +deploybitstr:deploypy + rsync -avz $(BUILD_DIR)/bitstream_$(TRGT_PLATFORM) $(BRD_USR)@$(BRD_IP):$(BRD_DIR) + +deployxclbin:deploypy + rsync -avz $(BUILD_DIR)/xclbin_$(TRGT_PLATFORM) $(BRD_USR)@$(BRD_IP):$(BRD_DIR) + +curr_config: print_config + @echo $(GEN_CONFIG_DESIGN_OPTS) + +## clean facilities +cleanconfig: + rm -rf $(CURR_BUILD_DIR) + +cleanvivado: + rm -rf $(PRJDIR) + +cleanhls: + rm -rf $(CURR_BUILD_DIR)/$(PRJ_NAME) + +cleanpysw: + rm -rf $(DPLY_PY) + +clean: cleanhls cleanvivado + rm -f $(CURR_BUILD_DIR)/*.log $(CURR_BUILD_DIR)/*.jou + + +cleanplat: + rm -rf $(BUILD_PLAT_DIR)/* + +cleanall: + rm -rf $(BUILD_DIR)/* + +helparam: + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " Makefile parameters helpers " + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] using shell=$(SHELL), top directory=$(TOP)" + @echo " [INFO] py version=$(PYTHON)" + @echo "" + @echo "" + @echo " [PARAM] Image dimension (D) = $(D)" + @echo " [PARAM] Image bit size (IB) = $(IB)" + @echo " [PARAM] Computation type (HT) = $(HT)" + @echo " [PARAM] Histogram PE (PE) = $(PE)" + @echo " [PARAM] Entropy PE (PE_ENTROP) = $(PE_ENTROP)" + @echo " [PARAM] Use caching (CACHING) = $(CACHING)" + @echo " [PARAM] Use URAM caching (URAM) = $(URAM)" + @echo " [PARAM] Core Number (CORE_NR) = $(CORE_NR)" + @echo "" + @echo " [PARAM] Similarity metric (METRIC) = $(METRIC)" + @echo " [PARAM] Supported METRIC: $(SUPPORTED_METRICS)" + @echo "" + @echo " [PARAM] Image Transforamtion (TRANSFORM) = $(TRANSFORM)" + @echo " [PARAM] Supported TRANSFORM: $(SUPPORTED_TX)" + @echo "" + @echo " [Help] Change those values for accelerator generation" + @echo "" + @echo "" + @echo " [PARAM] HLS_CLK=$(HLS_CLK) clock period for hls" + @echo " [PARAM] FREQ_MHZ=$(FREQ_MHZ) clock frequency for vivado bitstream" + @echo "" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " END of Makefile parameters helper " + @echo "" + @echo "*****************************************************************" + @echo "" + + +helptargets: + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " Target platforms helpers " + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [HELP] Currently using Vivado version $(VIVADO_VERSION)" + @echo "" + @echo " [HELP] Supported Zynq boards: $(SUPPORTED_ZYNQ)" + @echo "" + @echo " [HELP] Supported Alveo boards: $(SUPPORTED_ALVEO)" + @echo "" + @echo " [HELP] add TRGT_PLATFORM= to a command" + @echo " [HELP] For example 'make TRGT_PLATFORM=zcu104'" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " END of Target platforms helpers " + @echo "" + @echo "*****************************************************************" + @echo "" diff --git a/README.md b/README.md index b7226db..2ba56c7 100644 --- a/README.md +++ b/README.md @@ -1 +1,211 @@ -# faber_fpga \ No newline at end of file +# Faber: a Hardware/Software Toolchain for Image Registration + +This repository contains the source code of the Faber Toolchain. + +Faber Toolchain Grphical Abstract + + + + + +Faber is an open-source HW/SW CAD framework tailored to [image registration](https://en.wikipedia.org/wiki/Image_registration) that exploits FPGAs as accelerators. +The Faber toolchain comprises HW/SW highly-tunable registration components, supports users with different expertise in building custom pipelines, and automates the design process. + +The [Figure](#faber_abstract) showcases how Faber works. +Faber reads the various customization hyperparameters depending on the level of the user's knowledge and instantiates the optimization-based registration framework. +Based on the Entry, SW, or HW level, different degrees of customization are available within Faber. +Faber reads the input data, instantiates the transformation, the similarity metric, and the optimizer ([the main three components of Image Registration](https://doi.org/10.1145/3431920.3439291)). +Then, it executes the registration, providing the registered images as output. +Both the transformation and the metric can be instantiated in software or hardware and different algorithms are provided for the optimizer and the metrics. +In this way, the user can then deploy its FPGA-based pipeline and test on its device similarly to an off-the-shelf SW library. + + +## Quickstart for prepare and deploy a default Accelerated pipeline on Ultra96/Alveo u200 + +0. Prepare your environement for Vivado/Vitis 2019.2, i.e., `source /path/to/Vivado/2019.2/settings64.sh` and `source /opt/xilinx/xrt/setup.sh` for the building machine +1. `make default_ultra96` or `make default_alveo_u200` for default Faber accelerated registration pipelines. +2. wait the bitstream generation, then `make resyn_extr_zynq_ultra96_v2` or `make resyn_extr_vts_alveo_u200` +3. `make deploybitstr` or `make deployxclbin` to deploy your accelerated pipeline on the deployment machine (if different from the building one). Pay attention to other configuration parameters. The deployment is based on rsync transfer, we are assuming all the devices are reachable from the same network of the building machine. For configuration parameters deployment have a look to [this example deployment](#deploymentexample) + +For the pure sw just type `make pure_sw` and deploy on the target machine. + +## In-Depth Faber Toolchain Usage Guide + +### Table of contents +1. [Testing Environment](#testing_env) +2. [Code Organization](#code_org) +3. [Creating an HW-based Pipeline](#hw_design) +4. [Testing a HW Design](#testing_designs) +5. [Configuration Hyperparameters](#makefile) + * [Optimizer Hyperparameters](#sw_hyperparams) + * [General Makefile Hyperparameters (i.e, Entry and HW-based)](#general_params) + * [Zynq-Specific Hyperparams.](#zynq) + * [Alveo-Specific Hyperparams.](#alveo) +6. [Resource Results Extraction](#res_results) +7. [Estimating Resources and Latency of the Accelerators](#faber_model) +8. [Deployment Example and example of Dataset Structuring](#deploymentexample) +9. [External Components in Faber](#ext_comp) +10. [Credits and Contributors](#credits) + + + +### Testing Environment +1. We tested the hardware code generation on two different machines based on Ubuntu 18.04/20.4 and Centos OS 7.6 respectively. +2. We used Xilinx Vitis Unified Platform and Vivado HLx toolchains 2019.2. +3. We used Python 3 with `argparse` `numpy` `math` packets on the generation machine. +4. a) On the host machines, or hardware design machines, we used Pynq 2.5 on the Zynq based platforms (Pynq-Z2, Ultra96, Zcu104), where we employ `cv2`, `numpy`, `pandas`, `multiprocessing`, `statistics`, `argparse`, `pydicom`, and `scipy` packetes. For pure SW deployment the user will also need `torch` and `kornia` packets. +4. b) We tested the Alveo u200 on a machine with CentOS 7.6, i7-4770 CPU @ 3.40GHz, and 16 GB of RAM, and we installed Pynq 2.5.1 following the [instructions by the Pynq team](https://pynq.readthedocs.io/en/v2.5.1/getting_started/alveo_getting_started.html) with the same packets as point 4a. +5. [Optional] Possible issues with locale: export LANG="en_US.utf8". + +### Code Organization +* `Makefile` the primary interface of Faber with users willing to generate FPGA-based IR pipelines. +* `src/` source code for HLS based design, miscellaneous utilities, Python host and testing code, and various scripts. + * `hls/` HLS source code for both design and testbench of the Faber Library. + * `misc/` this folder contains only the board definition files (BDF), that are properties of the board producer, we report here just for the sake of the user. + * `model/` this folder contains the Python-based model code to get resource and latency estimations and to support expert users during the customization of the accelerators available within Faber. + * `scripts/` miscellaneous scripts for the design generation, from tcl for Vivado and Vivado HLS to design configurator, design results extractions. + * `scripts/generators` miscellaneous scripts for the design generation, from tcl for Vivado and Vivado HLS to design configurator and design results extractions, extensive testing campaign execution and results extraction. + * `sw/` contains the following folders, and Faber pure IR SW pipelines based on Torch, and a Python to extract the accuracy from a Gold stack and registred stack. + * `sw/python/` Python host source code for single accelerators test, whole accelerated application, IR library, abstraction layers of the accelerators, automatic hw mapper for different accelerators combos. + * `sw/example_measurements/` examples of scripts to perform measurements: e.g., perform power consumption measurement with PYNQ APIs, extract the accuracy; to extract with the `python_tester_extractor.sh` the power just decomment those lines with `power_` in it. +* `platforms/` makefile utilities and configuration parameters, specific platforms makefile for the current supported boards: Ultra96, Zcu104, Alveo u200. Pynq-Z2 supports for pure Similarity Metric Accelerator, **not tested** with warp transform as stand-alone accelerator, nor with W+Metric combos. +* `dse_scripts/` scripts to automatically explore the design reported in Faber paper. +* `images/` useful images for documentation purposes. + +### Creating an HW-based Pipeline: FPGA-based Accelerators generation flow + +1. Source the necessary scripts, for example: `source /settings64.sh`; for Alveo you will need to source xrt, e.g., `source /opt/xilinx/xrt/setup.sh`. +2. Install the board definition files (if needed) (misc folder contains them and a guide on how to install them). +3. Just do a `make`, or `make help` in the top folder for viewing an helper (other helpers `make helplat`, `make helparam`, `make helptargets` ). +4. use/modify the design space exploration script (e.g., `dsesoa.sh` or `dse_alveo_mi.sh`) or generate your designs or use single instance specific generation . + * 4a) `make hw_gen TRGT_PLATFORM=` for generating an instance of a Zynq-based design, where `trgt_zynq=zcu104|ultra96|pynqz2`. + * 4b) `make hw_gen TARGET=hw OPT_LVL=3 CLK_FRQ=$FREQZ TRGT_PLATFORM=alveo_u200` for generating an instance of the design on the Alveo u200 with target clock frequency `CLK_FRQ=$FREQZ`. +5. [Optional] Generate other instances changing the design parameters. Look at [Makefile parameters section ](#makefile) for details. + +A quick example: +`make hw_gen PE=1 CORE_NR=2 TARGET=hw CLK_FRQ=200 TRGT_PLATFORM=ultra96_v2 METRIC="mse" TRANSFORM="wax";` +it generates dual core W+MSE on an Ultra96 v2 with a single PE. + +### Testing a HW Design + +1. Complete at least one design in the previous section, and prepare the HW design for deployment (i.e., `make resyn_extr_zynq_ultra96_v2 ` or `make resyn_extr_vts_alveo_u200`). +2. `make pysw` creates a deploy folder for the Python code. +3. `make deploybitstr` or `make deployxclbin` `BRD_IP= BRD_USR= BRD_DIR=` copy onto the deploy folders the needed files. +4. connect to the remote device, i.e., via ssh `ssh @`. +5. [Optional] install all needed Python packages as above, or the pynq package on the Alveo host machine. +6. Navigate to the `/sw_py`. +7. + * 7a) Launch the script `python_tester_launcher.sh /bitstream_ultra96` (or where you transfered the folder of the .bit) for the Ultra96 testing. + * 7b) Modify the script with PLATFORM=Alveo, and launch the script `python_tester_launcher.sh /xclbn_alveo_u200` (or where you transfered the folder of the .xclbin) for the Alveo testing. + * 7c) the script will automatically detect the accelerator configuraiton (based on the folder name) and setup the testing of both, single accelerator, powell's, and 1+1 registrations, with a dataset structured as [descirbed here](#dataset_description). +8. `python_tester_extractor.sh /bitstream_ultra96 ` to automatically derive a .csv with most of the useful results of the experimental campaign. + +If you wish to have a **single test of the accelerator** for a single bitstream please follow these steps after previous step 6. +7. set `BITSTREAM=`, `CLK=200`, `CORE_NR=`, `PLATFORM=Alveo|Zynq`, `RES_PATH=path_results`, and source xrt on the Alveo host machine, e.g., `source /opt/xilinx/xrt/setup.sh`. +8. [Optional] `python3 test-single-mi.py --help` for a complete view of input parameters. +9. Execute the test `python3 test-single-mi.py -ol $BITSTREAM -clk $CLK -t $CORE_NR -p $PLATFORM -im 512 -rp $RES_PATH` (if on Zynq you will need `sudo`). + +To execute a **single registration**, follow similar steps such as the previous single accelerator test, or [have a look here](#deploymentexample). +`python3 faber-powell-blocked.py --help` will show a complete view of input parameters for powell HW-based registration procedure. + + +### Faber Configuration Hyperparameters +Faber offers different level of hyperparameters that are in-depth described as follows. + +#### Optimizer Hyperparameters + +Faber offers SW-like hyperaparameters for optimizer-specific ones as a Python class named `FaberHyperParams` in the `faberImageRegistration.py` file. + +Follows some makefile parameters (which are Entry-level, SW-level, HW-level Faber hyperparameters). + +#### General Makefile Parameters, and Design Configuration Parameters +* TRGT_PLATFORM=`ultra96_v2|zcu104|alveo_u200` (Entry-level) +* Image dimension D=`512|1024|2048` (Entry-level) +* Image bit size IB=`8|16` (Entry-level) +* Similarity metric METRIC=`mi|mse|cc|prz` +* Image Transforamtion TRANSFORM=`wax|empty` +* Histogram Computation type (for MI only) HT=`float|fixed` +* First Macrostage Map-Reduce PE Number PE=`1|2|4|8|16|32|64` +* Entropy PE Number (only for MI) PE_ENTROP=`1|2|4|8|16|32` +* Core Number CORE_NR=`1|2|3|4` +* Interpolation type (Warp Transform only) INTERP_TYPE=`nearestn|bilinear` +* Exploit URAM (Warp Transform only) WAX_URAM=`true|false`, not effective if no transformation kernel +* Cache dimension for the Warp Transform NUM_STORE_ROWS=`100|any number between 1 and max image size` +* Cache size befor beginning the Warp Transform kernel NUM_START_PROC=`50|any number >=1 Vivado and Zynq Specific Parameters Flow +* HLS_CLK=`default 10` clock period for hls synthesis +* FREQ_MHZ=`200` clock frequency for vivado block design and bitstream generation +* TOP_LVL_FN=`mutual_information_master` target top function for HLS, automatically configured by Faber +* HLS_OPTS=`5` HLS project flow. Supported options: 0 for only project build; 1 for sim only; 2 synth; 3 cosim; 4 synth and ip downto impl; 5 synth and ip export; 6 for ip export + +#### Alveo Specific Parameters Flow +* REPORT_FLAG=`R0|R1|R2` to report detail levels +* OPT_LVL=`0|1|2|3|s|quick` to optimization levels +* CLK_FRQ=`` to ClockID 0 (board) target frequency, should be PCIe clock +* JOBS=`8` by default, if you whish you could increase/decrease accordingly + +### Extracting Resources Results + +1. a) `make resyn_extr_zynq_` e.g., trgt_zynq=`zcu104|ultra96|pynqz2`, set FREQ_MHZ parameter if different from default. +1. b) `make resyn_extr_vts_` e.g., trgt_alveo=`alveo_u200`. +2. You will find in the `build/` folder a new folder with all the generated bitstreams, and in the `build//` directory you will find a .csv with all the synthesis results. + +### Estimating Resources and Latency of the Accelerators +Faber offers an empirical model that estimate accurately the latency and resource occupation of our Accelerators given a configuration. +For more information take a look to the corresponding [README](./src/model/README.md). + + +### Deployment Example on Ultra96/Alveo u200/ Pure SW +An example of deployment is `make deploybitstr TRGT_PLATFORM=ultra96_v2 BRD_USR=xilinx BRD_IP= BRD_DIR=/home/xilinx/faber` on the Ultra96. +For an Alveo u200 device `make deployxclbin TRGT_PLATFORM=alveo_u200 BRD_USR= BRD_IP= BRD_DIR=`. + +Connect to the host machine and go the target folder. + + + +We are assuming that the dataset is in a structure of folders such as `dataset_folder/patientname_number/Ref_folder` `dataset_folder/patientname_number/Flt_folder`, with the same amount of images for both the stacks. + +For instance consider the following structure: + * `Test/ST0/` + * `Test/ST0/SE0` the Reference stack 512x512x246 + * `Test/ST0/SE4` the Float stack 512x512x246 + +To register a stack of images on a machine that mounts an Alveo u200 (with the default accelerator configuration, i.e., Powell + MI16) with a folder structure like our example: +`python3 faber-powell-blocked.py -p Alveo -cp SE0 -pp SE4 -rp -ol -px /Test/ST -o 0 -pt 1 -exp -mtr mi -im 512` + +To register a stack of images on a machine that mounts an Alveo u200 (with the default accelerator configuration, i.e., 1+1 + WCC1) with a folder structure like our example: +`python3 faber-oneplusone-blocked.py -p Zynq -cp SE0 -pp SE4 -rp -ol -px /Test/ST -o 0 -pt 1 -mtr cc -tx wax -im 512` + +To register a stack of images on a machine with a SW application based on 1+1 and MSE with a folder structure like our example: +`python3 fabersw-unique.py -opt plone -cp SE0 -pp SE4 -rp -ol -px /Test/ST -o 0 -pt 1 -mtr mse -tx wax -im 512` + + +## External Components in Faber + +Faber Toolchain relies on the following external components: +* AMD-Xilinx Vivado Design Suite, Vivado HLS, Vitis Unified Software platform 2019.2. +* The [PYNQ framework](http://www.pynq.io/) and its drivers version 2.5.1 for the interfacing of Host-FPGA. +* The Warp transform Accelerator and all the necessary HLS-based parts comes from the [original repository of the Vitis Accelerated Libriaries for the Vision domain version 2019.2](https://github.com/Xilinx/Vitis_Libraries/tree/2019.2/vision). It is licensed under the [Apache License](http://www.apache.org/licenses/LICENSE-2.0). +* Several Python Packages among which: `argparse`, `numpy`, `math`, `cv2`, `numpy`, `pandas`, `multiprocessing`, `statistics`, `argparse`, `pydicom`, `os`, `glob`, `time`, `pynq`, `struct`, `scipy`, `torch`, `kornia`. +* The 1+1 code takes inspiration from [ITK code](https://github.com/InsightSoftwareConsortium/ITK). + +We are really grateful to the authors of these external components without which Faber will not be possible. + +## Credits and Contributors + +Contributors: D'Arnese Eleonora, Conficconi Davide, Del Sozzo Emanuele, Fusco Luigi, Sciuto Donatella, and Santambrogio Marco Domenico + +If you find this repository useful, please use the following citation(s): + +``` +@inproceedings{iron2021, +author = {Conficconi, Davide and D'Arnese, Eleonora and Del Sozzo, Emanuele and Sciuto, Donatella and Santambrogio, Marco D}, +title = {A Framework for Customizable FPGA-based Image Registration Accelerators}, +booktitle = {The 2021 ACM/SIGDA International Symposium on Field-Programmable Gate Arrays}, +pages={251--261}, +year = {2021} +} +``` diff --git a/dse_scripts/dse_alveo_mi.sh b/dse_scripts/dse_alveo_mi.sh new file mode 100755 index 0000000..4a7a041 --- /dev/null +++ b/dse_scripts/dse_alveo_mi.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(32 2 16 8 4 1) +CORE_NRS=(1) +HTYPS=('float') +PE_ENTROP=(1) +CACHING=(false) +URAM=(false) +FREQZ=200 +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for h in ${HTYPS[@]}; do + for pe in ${PE_ENTROP[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200 METRIC="mi"; + #make hw_gen PE=$p CORE_NR=$cn HT=$h FREQ_MHZ=$FREQZ PE_ENTROP=$pe \ + #CACHING=$c URAM=$u TRGT_PLATFORM=ultra96_v2 METRIC="mi"; + done; + done; + done; + done; + done; +done; diff --git a/dse_scripts/dse_alveo_waxmi.sh b/dse_scripts/dse_alveo_waxmi.sh new file mode 100755 index 0000000..5ce05f7 --- /dev/null +++ b/dse_scripts/dse_alveo_waxmi.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(32 16 8 4 2 1) +CORE_NRS=(1) +HTYPS=('float') +PE_ENTROP=(1) +CACHING=(false) +URAM=(false) +FREQZ=200 +INTERPOLATIONS=('nearestn') +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for h in ${HTYPS[@]}; do + for pe in ${PE_ENTROP[@]}; do + for it in ${INTERPOLATIONS[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + for wu in ${CACHING[@]}; do + make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200 \ + WAX_URAM=$wu METRIC="mi" INTERP_TYPE=$it TRANSFORM="wax"; + #make hw_gen PE=$p CORE_NR=$cn HT=$h FREQ_MHZ=$FREQZ WAX_URAM=$wu PE_ENTROP=$pe \ + #CACHING=$c URAM=$u TRGT_PLATFORM=ultra96_v2 METRIC="mi" INTERP_TYPE=$it TRANSFORM="wax"; + done; + done; + done; +done; +done; + done; + done; +done; diff --git a/dse_scripts/dse_ultra96_cc.sh b/dse_scripts/dse_ultra96_cc.sh new file mode 100644 index 0000000..86f9b0c --- /dev/null +++ b/dse_scripts/dse_ultra96_cc.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(2 8) +CORE_NRS=(2 1) +HTYPS=('float') +PE_ENTROP=(1) +CACHING=(false) +URAM=(false) +FREQZ=200 +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + # for h in ${HTYPS[@]}; do + # for pe in ${PE_ENTROP[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + #make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + #CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200; + make hw_gen PE=$p CORE_NR=$cn FREQ_MHZ=$FREQZ \ + CACHING=$c URAM=$u TRGT_PLATFORM=zcu104 METRIC="cc"; + done; + done; + done; + # done; + # done; +done; diff --git a/dse_scripts/dse_ultra96_wax.sh b/dse_scripts/dse_ultra96_wax.sh new file mode 100755 index 0000000..01951b5 --- /dev/null +++ b/dse_scripts/dse_ultra96_wax.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(2 8 ) +CORE_NRS=(2 1) +HTYPS=('float') +PE_ENTROP=(1) +CACHING=(false) +URAM=(false) +FREQZ=200 +INTERPOLATIONS=('nearestn' 'bilinear') +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for c in ${CACHING[@]}; do + for it in ${INTERPOLATIONS[@]}; do + for u in ${URAM[@]}; do + #make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + #CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200; + make hw_gen PE=$p CORE_NR=$cn FREQ_MHZ=$FREQZ \ + CACHING=$c WAX_URAM=$u INTERP_TYPE=$it TRGT_PLATFORM=ultra96_v2 TRANSFORM="wax"; + done; + done; + done; + done; +done; diff --git a/dse_scripts/dse_ultra96_waxcc.sh b/dse_scripts/dse_ultra96_waxcc.sh new file mode 100755 index 0000000..4f24ab7 --- /dev/null +++ b/dse_scripts/dse_ultra96_waxcc.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(1) +CORE_NRS=(2 1) +HTYPS=('float') +CACHING=(false) +URAM=(false) +FREQZ=200 +INTERPOLATIONS=('nearestn') +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for it in ${INTERPOLATIONS[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + for wu in ${CACHING[@]}; do + #make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + #CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200; + make hw_gen PE=$p CORE_NR=$cn FREQ_MHZ=$FREQZ WAX_URAM=$wu \ + CACHING=$c URAM=$u TRGT_PLATFORM=ultra96_v2 METRIC="cc" INTERP_TYPE=$it TRANSFORM="wax"; + done; + done; + done; + done; + done; +done; diff --git a/dse_scripts/dse_zcu104_mse.sh b/dse_scripts/dse_zcu104_mse.sh new file mode 100755 index 0000000..eba2054 --- /dev/null +++ b/dse_scripts/dse_zcu104_mse.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(32 8 16) +CORE_NRS=(3 2 1) +HTYPS=('float') +PE_ENTROP=(1) +CACHING=(false) +URAM=(false) +FREQZ=200 +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + #make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + #CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200; + make hw_gen PE=$p CORE_NR=$cn FREQ_MHZ=$FREQZ \ + CACHING=$c URAM=$u TRGT_PLATFORM=zcu104 METRIC="mse"; + done; + done; + done; + # done; + # done; +done; diff --git a/dse_scripts/dse_zcu104_waxmse.sh b/dse_scripts/dse_zcu104_waxmse.sh new file mode 100755 index 0000000..ca18c84 --- /dev/null +++ b/dse_scripts/dse_zcu104_waxmse.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +PES=(1) +CORE_NRS=(3 2 1) +HTYPS=('float') +CACHING=(false) +URAM=(false) +FREQZ=200 +INTERPOLATIONS=('nearestn') +#'bilinear') +#change this value if using a zynq-based, use 200MHz / 250 MHz + + +for p in ${PES[@]}; do + for cn in ${CORE_NRS[@]}; do + for it in ${INTERPOLATIONS[@]}; do + for c in ${CACHING[@]}; do + for u in ${URAM[@]}; do + for wu in ${CACHING[@]}; do + #make xclbin_config PE=$p CORE_NR=$cn HT=$h TARGET=hw OPT_LVL=3 \ + #CLK_FRQ=$FREQZ PE_ENTROP=$pe CACHING=$c URAM=$u TRGT_PLATFORM=alveo_u200; + make hw_gen PE=$p CORE_NR=$cn FREQ_MHZ=$FREQZ WAX_URAM=$wu \ + CACHING=$c URAM=$u TRGT_PLATFORM=zcu104 METRIC="mse" INTERP_TYPE=$it TRANSFORM="wax"; + done; + done; + done; + done; + done; +done; diff --git a/dse_scripts/dsesoa.sh b/dse_scripts/dsesoa.sh new file mode 100755 index 0000000..5a5476e --- /dev/null +++ b/dse_scripts/dsesoa.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# /****************************************** +# *MIT License +# * +# *Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +# * +# *Permission is hereby granted, free of charge, to any person obtaining a copy +# *of this software and associated documentation files (the "Software"), to deal +# *in the Software without restriction, including without limitation the rights +# *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# *copies of the Software, and to permit persons to whom the Software is +# *furnished to do so, subject to the following conditions: +# * +# *The above copyright notice and this permission notice shall be included in all +# *copies or substantial portions of the Software. +# * +# *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# *SOFTWARE. +# ******************************************/ + + +make default_ultra96 +make default_alveo_u200 + +make hw_gen PE=1 CORE_NR=2 TARGET=hw CLK_FRQ=200 TRGT_PLATFORM=ultra96_v2 METRIC="mse" TRANSFORM="wax"; +make hw_gen PE=1 CORE_NR=2 TARGET=hw CLK_FRQ=200 TRGT_PLATFORM=ultra96_v2 METRIC="mi" TRANSFORM="wax"; +make hw_gen PE=1 CORE_NR=2 TARGET=hw CLK_FRQ=200 TRGT_PLATFORM=ultra96_v2 METRIC="nmi" TRANSFORM="wax"; + +make hw_gen PE=1 CORE_NR=3 TARGET=hw CLK_FRQ=200 TRGT_PLATFORM=zcu104 METRIC="mse" TRANSFORM="wax"; + +echo "Hello moto" + +make hw_gen METRIC='cc' PE=32 CORE_NR=1 FREQ_MHZ=300 TRGT_PLATFORM=alveo_u200; +make hw_gen METRIC='mse' PE=32 CORE_NR=1 FREQ_MHZ=300 TRGT_PLATFORM=alveo_u200; +make hw_gen METRIC='prz' PE=16 CORE_NR=1 HT='float' FREQ_MHZ=300 TRGT_PLATFORM=alveo_u200; diff --git a/images/faber_abstract.png b/images/faber_abstract.png new file mode 100644 index 0000000000000000000000000000000000000000..29b291a2fa303601b2b41c11d723bca544ece7b1 GIT binary patch literal 130991 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 z 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≥3OGEA}$7@_U;lcA%bo4J;)_H3# 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 literal 0 HcmV?d00001 diff --git a/images/flt.png b/images/flt.png new file mode 100644 index 0000000000000000000000000000000000000000..d751da3dee093c564a00db34116a6d1a58512daa GIT binary patch literal 2064 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w3=!$sk4H3kOu>z*!-Ar*{o4{j6$3Nmio z{{KSGLlL3CguJO52HU+vW<;xUomnfy`Yf!Isd%+ZOEckT-G@yGywqU3QzX{ literal 0 HcmV?d00001 diff --git a/images/ref.png b/images/ref.png new file mode 100644 index 0000000000000000000000000000000000000000..64559b15587a2baac0649202ae852c3b062d01b7 GIT binary patch literal 2193 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w3=!$sk4H3kNb2u~NskP61P2RHIEFz_7O z@Z|sEm!cj#TX}0gg-QN;vexL!$>`J:|: +ifdef CLK_FRQ + ifdef KRNL_FRQ +KERNEL_LDCLFLAGS += --kernel_frequency "0:$(CLK_FRQ)|1:$(KRNL_FRQ)" #--optimize 3 + else +KERNEL_LDCLFLAGS += --kernel_frequency "0:$(CLK_FRQ)" #|1:350" +KRNL_LDCLFLAGS_MULTI_CORE += --kernel_frequency "0:$(CLK_FRQ)" + endif +else + ifdef KRNL_FRQ +KERNEL_LDCLFLAGS+= --kernel_frequency "1:$(KRNL_FRQ)" #--optimize 3 + else + #KERNEL_LDCLFLAGS+= --k ernel_frequency "200" + endif + +endif + + + + +#TARGET for compilation [sw_emu | hw_emu | hw] +TARGET=hw +REPORT_FLAG=n +REPORT= +ifeq (${TARGET}, sw_emu) +$(info software emulation) +TARGET=sw_emu +ifeq (${REPORT_FLAG}, y) +$(info creating REPORT for software emulation set to true. This is going to take longer at it will synthesize the kernel) +REPORT=-Restimate +else +$(info I am not creating a REPORT for software emulation, set REPORT_FLAG=y if you want it) +REPORT= +endif +else ifeq (${TARGET}, hw_emu) +$(info hardware emulation) +TARGET=hw_emu +REPORT= +else ifeq (${TARGET}, hw) +$(info system build) +TARGET=hw +REPORT= +else +$(info no TARGET selected) +endif + +####################################################### + +PERIOD:= : +UNDERSCORE:= _ +VTS_DST_DIR=$(VTS_BUILD_DIR)/$(TARGET)/$(subst $(PERIOD),$(UNDERSCORE),$(TARGET_DEVICE)) + +####################################################### + +ifndef XILINX_VITIS +$(error XILINX_VITIS is not set. Please source the Vitis settings64.{csh,sh} first) +endif + +ifndef XILINX_XRT +$(error XILINX_XRT is not set. Please source the XRT /opt/xilinx/xrt/setup.sh first) +endif + +check_TARGET: curr_status +ifeq (${TARGET}, none) + $(error Target can not be set to none) +endif + +xo: check_TARGET check_accelerator + mkdir -p $(VTS_DST_DIR) + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --jobs $(JOBS) --compile --include $(KERNEL_HDRS) $(REPORT) \ + --kernel $(KERNEL_NAME) $(KERNEL_FLAGS) \ + $(KERNEL_ADDITIONAL_FLAGS) -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xo' \ + $(KERNEL_SRC) + +hw: xclbin + +hw_gen: xclbin_config + +xclbin: check_TARGET xo check_accelerator + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --link --jobs $(JOBS) --include $(KERNEL_HDRS) $(REPORT) \ + --kernel $(KERNEL_NAME) $(VTS_DST_DIR)/$(KERNEL_EXE).xo $(KERNEL_LDCLFLAGS) \ + $(KERNEL_FLAGS) $(KERNEL_ADDITIONAL_FLAGS) \ + -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xclbin' + + +####################################################### + +ifeq ($(TARGET),sw_emu) +RUN_ENV += export XCL_EMULATION_MODE=sw_emu; +EMU_CONFIG = emconfig.json +else ifeq ($(TARGET),hw_emu) +RUN_ENV += export XCL_EMULATION_MODE=hw_emu; +EMU_CONFIG = emconfig.json +else ifeq ($(TARGET),hw) +RUN_ENV += echo "TARGET=hw"; +EMU_CONFIG = +endif + +emconfig.json : check_accelerator + emconfigutil --platform $(TARGET_DEVICE) --od $(VTS_DST_DIR) + +.PHONY: run run_sw_emu run_hw_emu run_hw check + +run_sw_emu: + make TARGET=sw_emu run + +run_hw_emu: + make TARGET=hw_emu run + +run_hw: + make TARGET=hw run + +run: host xclbin $(EMU_CONFIG) + $(RUN_ENV) \ + cd $(VTS_DST_DIR); ./$(HOST_EXE) $(HOST_ARGS); cd - + +run_config: host xclbin_config $(EMU_CONFIG) + $(RUN_ENV) \ + cd $(VTS_DST_DIR); ./$(HOST_EXE) $(HOST_ARGS) $(call RUN_TIME_INPUT_KERNEL_NAME,1); cd - + +.PHONY: host + +#sw:host + +host: check_TARGET $(HOST_SRC) $(HOST_HDRS) check_accelerator + mkdir -p $(VTS_DST_DIR) + $(XCC) $(HOST_SRC) $(HOST_HDRS) $(HOST_CFLAGS) $(HOST_LFLAGS) \ + -o $(VTS_DST_DIR)/$(HOST_EXE) + +$(HOST_SRC): + +run_only: $(EMU_CONFIG) + $(RUN_ENV) \ + cd $(VTS_DST_DIR); ./$(HOST_EXE) $(HOST_ARGS); cd - + +run_config_only: $(EMU_CONFIG) + $(RUN_ENV) \ + cd $(VTS_DST_DIR); ./$(HOST_EXE) $(HOST_ARGS) $(call RUN_TIME_INPUT_KERNEL_NAME,1); cd - + + + +build: host xclbin + + +run_system: build $(EMU_CONFIG) + $(RUN_ENV) \ + cd $(VTS_DST_DIR); ./$(HOST_EXE) $(HOST_ARGS); cd - +######################### + +xclbin_config_2: check_TARGET generate_vts_config_2 + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --link --jobs $(JOBS) $(REPORT) \ + $(VTS_DST_DIR)/$(KERNEL_NAME).xo $(KRNL_LDCLFLAGS_MULTI_CORE) \ + $(KERNEL_ADDITIONAL_FLAGS) \ + -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xclbin' + + +generate_vts_config_2: | gen_hls_config_vts xo_config_static check_accelerator + +$(VTS_DST_DIR)/$(KERNEL_NAME).xo: xo_config_static + +xo_config_static: check_TARGET check_accelerator + mkdir -p $(VTS_DST_DIR) + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --jobs $(JOBS) -c --include $(KERNEL_HDRS_CONFIG) \ + -k $(KERNEL_NAME) $(call XO_GEN_FLAGS_2,$*) \ + $(KERNEL_ADDITIONAL_FLAGS) -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xo' \ + $(KERNEL_SRC_CONFIG) + +generate_vts_config: gen_hls_config_vts $(XO_LIST) check_accelerator + for n in $(CORE_LIST_NR); do \ + make xo_config_$$n; \ + done; \ + +##CAREFUL +#This rule need to be called as separate make or with an eval function +xo_config_%: check_TARGET check_accelerator + mkdir -p $(VTS_DST_DIR) + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --jobs $(JOBS) -c --include $(KERNEL_HDRS_CONFIG) \ + -k $(KERNEL_NAME)_$* $(call XO_GEN_FLAGS,$*) \ + $(KERNEL_ADDITIONAL_FLAGS) -o '$(VTS_DST_DIR)/$(KERNEL_EXE)_$*.xo' \ + $(KERNEL_SRC_CONFIG) + +xclbin_config: check_TARGET generate_vts_config + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --link --jobs $(JOBS) $(REPORT) \ + $(XO_LIST) $(KRNL_LDCLFLAGS_MULTI_CORE) \ + $(KERNEL_ADDITIONAL_FLAGS) \ + -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xclbin' + +#rule for only xclbin +xclbin_only: check_TARGET check_accelerator + $(VPP) --platform $(TARGET_DEVICE) -t $(TARGET) \ + --link --jobs $(JOBS) $(REPORT) \ + $(XO_LIST) $(KRNL_LDCLFLAGS_MULTI_CORE) \ + $(KERNEL_ADDITIONAL_FLAGS) \ + -o '$(VTS_DST_DIR)/$(KERNEL_EXE).xclbin' + + +$(XO_LIST): + +test_config_%: + @echo "" + @echo "[INFO] printg some mapping functions" + @echo $(KRNL_LDCLFLAGS_MULTI_CORE) + @echo $(call XO_GEN_FLAGS,$*) + @echo "" + +############################################################################### + +hls: $(hls_curr_code) $(hls_tb_code) $(SCRIPT_DIR)/hls.tcl check_accelerator + mkdir -p $(CURR_BUILD_DIR) + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(hls_curr_code)" $(HLS_TB) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) "$(HLS_INCLUDES)" $(HLS_OPTS) $(HLS_INCL); cd ../ + +hls_config: gen_hls_config + mkdir -p $(CURR_BUILD_DIR) + $(eval HLS_GEN_CODE_RUN_WITH_TB := $(shell echo $(HLS_CONFIG_DIR)/*pp )) + $(eval HLS_GEN_CODE_RUN_WITH_TB += $(shell echo $(HLS_CONFIG_DIR)/*.h )) + $(eval HLS_GEN_CODE_RUN := $(filter-out $(hls_curr_tb_code_gen), $(HLS_GEN_CODE_RUN_WITH_TB))) + $(eval HLS_INCLUDES += "$(HLS_CONFIG_DIR)") + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(HLS_GEN_CODE_RUN)" $(hls_curr_tb) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) "$(HLS_INCLUDES)" $(HLS_OPTS) $(HLS_INCL); + +gen_hls_prj: check_accelerator + mkdir -p $(CURR_BUILD_DIR) + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(hls_curr_code)" $(HLS_TB) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) $(HLS_DIR)/ 0; cd ../ +############################################################################### +#pythonKRNL_LDCLFLAGS_MULTI_CORE +sw:pysw + +# rm -rf $(DPLY_PY) +# mkdir -p $(DPLY_PY) +# cp $(PY_DIR)/$(PY_MI) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_PWL) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_ONPL) $(DPLY_PY)/ +# cp $(SCRIPT_DIR)/python_tester_* $(DPLY_PY)/ + +pysw: + rm -rf $(DPLY_PY) + mkdir -p $(DPLY_PY) + cp $(PY_DIR)/*.py $(DPLY_PY)/ + cp $(SCRIPT_DIR)/python_tester_* $(DPLY_PY)/ + +curr_status: + @echo "" + @echo "*****************************************************************" + @echo " Alveo make status " + @echo "*****************************************************************" + @echo "" + @echo " [Help] curently using $(VPP), $(XCC), jobs=$(JOBS)" + @echo " [Help] Target platform/xsa/dsa= $(TARGET_DEVICE)" + @echo " Remember to change it accordingly to the proper version" + @echo "" + @echo " [Help] Target for build=$(TARGET)" + @echo " possible targets = sw_emu, hw_emu, hw" + @echo "" + @echo "" + @echo " [Help] Working with $(PORT_NR) memory port(s) and $(CORE_NR) core(s)" + @echo "" + @echo "*****************************************************************" + @echo " END of Alveo make status " + @echo "*****************************************************************" + @echo "" + +prepdeploy: + @echo "[INFO] placeholder REMEMBER!!!!" +######################## +helplat: curr_status + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " Alveo Specific helper " + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] 'make xo' generate the xo for the fixed code" + @echo " [INFO] 'make xclbin' generate the xclbin for the fixed code" + @echo "" + @echo "" + @echo " [INFO] 'make generate_vts_config' generate the xo for the target core number" + @echo "" + @echo "" + @echo " [INFO] 'make xclbin_config' generate the xclbin using config genrated xo files" + @echo "" + @echo "" + @echo " [INFO] 'make xclbin_only' create the xclbin only withou regenerating the xo, either config or not" + @echo "" + @echo "" + @echo " [INFO] 'make test_config_%' testing make recipe" + @echo "" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " END of Alveo Specific helper " + @echo "" + @echo "*****************************************************************" + @echo "" + @make helpparam_alveo +######################## + +helpparam_alveo: + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [Help] Follow some Makefile Parameter" + @echo "" + @echo " [Help] change REPORT_FLAG= to report detail levels" + @echo "" + @echo " [Help] change OPT_LVL=<0|1|2|3|s|quick> to optimization levels" + @echo "" + @echo " [Help] change CLK_FRQ= to ClockID 0 (board) target frequency" + @echo "" + @echo " [Help] change KRNL_FRQ= to ClockID 1 (kernel) target frequency" + @echo "" + @echo "*****************************************************************" + + +cleanvts: + rm -rf .Xil $(VTS_DST_DIR)/emconfig.json + +clean_sw_emu: cleanvts + rm -rf $(VTS_DST_DIR)/sw_emu +clean_hw_emu: cleanvts + rm -rf $(VTS_DST_DIR)/hw_emu +clean_hw: cleanvts + rm -rf $(VTS_DST_DIR)/hw + +cleanallvts: clean_sw_emu clean_hw_emu clean_hw + rm -rf _sdx_* xcl_design_wrapper_* _* sdx_* + rm -rf $(VTS_DST_DIR)/* + diff --git a/platforms/vitis_alveo_host.mk b/platforms/vitis_alveo_host.mk new file mode 100644 index 0000000..20b1156 --- /dev/null +++ b/platforms/vitis_alveo_host.mk @@ -0,0 +1,48 @@ +# #################TODO################## +# # #Host code +# HOST_SRC=$(HOSTCPP_DIR)/alveo/warptransform_host_alveo.cpp $(HOSTCPP_DIR)/alveo/xcl2/xcl2.cpp $(HLS_DIR)/$(TOP_FILE_NAME) +# HOST_HDRS= $(wildcard $(HOSTCPP_DIR)/alveo/*.hpp) + +# HOST_CFLAGS= -std=c++14 -fPIC +# HOST_CFLAGS += -g -D__SDSVHLS__ -DHLS_NO_XIL_FPO_LIB -DVIVADO_HLS_SIM -I${XILINX_XRT}/include/ \ +# -I $(HOSTCPP_DIR)/alveo/xcl2 \ +# -I ${HLS_DIR}/ \ +# -I ${HLS_DIR}/include \ +# -I$(XILINX_XRT)/include -I$(XILINX_VIVADO)/include +# #-O3 -I${XILINX_VITIS}/include/ --std=c++1y + + +# HOST_LFLAGS=-L${XILINX_XRT}/lib/ -lxilinxopencl -pthread \ +# -L/xilinx/software/Vivado/2019.2/lnx64/tools/opencv/opencv_gcc/ \ +# -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_calib3d \ +# -lopencv_features2d -lopencv_flann -L/xilinx/software/Vivado/2019.2/lnx64/tools/fpo_v7_0 \ +# -Wl,--as-needed -lgmp -lmpfr -lIp_floating_point_v7_0_bitacc_cmodel +# #-lopencv_core -lopencv_highgui -lopencv_imgproc \ +# # -L$(XILINX_VITIS)/lnx64/tools/opencv + + +# ifndef LD_LIBRARY_PATHVTS_DST_DIR +# LD_LIBRARY_PATH=$(XILINX_VITIS)/lnx64/tools/opencv:/usr/lib/:/usr/local/lib64/:$(XILINX_VIVADO)/lnx64/tools/opencv/opencv_gcc:/usr/lib64/ +# else +# LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(XILINX_VITIS)/lnx64/tools/opencv:/usr/lib:/usr/local/lib64/:/usr/lib64/ +# endif + +# ifeq (,$(LD_LIBRARY_PATH)) +# LD_LIBRARY_PATH = $(XILINX_XRT)/lib +# else +# LD_LIBRARY_PATH = $(XILINX_XRT)/lib:$(LD_LIBRARY_PATH) +# endif +# ifneq (,$(wildcard $(XILINX_VITIS)/bin/ldlibpath.sh)) +# export LD_LIBRARY_PATH = $(shell $(XILINX_VITIS)/bin/ldlibpath.sh $(XILINX_VITIS)/lib/lnx64.o):$(LD_LIBRARY_PATH) +# endif + +# #name of host executable +# HOST_EXE=$(KERNEL)_host_exe +# #argument passed to the execution of the kernel +# HOST_ARGS=$(KERNEL_EXE).xclbin ~/warpaffine/testdingo.png +# ################ENDTODO################ + +host: check_TARGET $(HOST_SRC) $(HOST_HDRS) + mkdir -p $(VTS_DST_DIR) + $(XCC) $(HOST_SRC) $(HOST_HDRS) $(HOST_CFLAGS) $(HOST_LFLAGS) \ + -o $(VTS_DST_DIR)/$(HOST_EXE) \ No newline at end of file diff --git a/platforms/zcu104.mk b/platforms/zcu104.mk new file mode 100644 index 0000000..fc9e0a8 --- /dev/null +++ b/platforms/zcu104.mk @@ -0,0 +1,3 @@ +BRD_PARTS= "xczu7ev-ffvc1156-2-e" +include platforms/zynq.mk +include platforms/zynq_mpsoc.mk \ No newline at end of file diff --git a/platforms/zynq.mk b/platforms/zynq.mk new file mode 100644 index 0000000..be4f6e3 --- /dev/null +++ b/platforms/zynq.mk @@ -0,0 +1,122 @@ +#/****************************************** +#*MIT License +#* +#*Copyright (c) [2022] [Eleonora D'Arnese, Davide Conficconi, Emanuele Del Sozzo, Luigi Fusco, Donatella Sciuto, Marco Domenico Santambrogio] +#* +#*Permission is hereby granted, free of charge, to any person obtaining a copy +#*of this software and associated documentation files (the "Software"), to deal +#*in the Software without restriction, including without limitation the rights +#*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#*copies of the Software, and to permit persons to whom the Software is +#*furnished to do so, subject to the following conditions: +#* +#*The above copyright notice and this permission notice shall be included in all +#*copies or substantial portions of the Software. +#* +#*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#*SOFTWARE. +#*/ +VIVADO_PRJNAME = ${KERNEL}-vivado +PRJDIR = $(CURR_BUILD_DIR)/$(VIVADO_PRJNAME) +BITSTREAM = $(PRJDIR)/$(VIVADO_PRJNAME).runs/impl_1/${KERNEL}_wrapper.bit +VVD_SCRIPT = $(VIVADO_SCRIPT_DIR)/create_vivado_project.tcl +VVD_SYNTH_SCRIPT = $(VIVADO_SCRIPT_DIR)/synth_vivado_project.tcl + +.PHONY: hls hw gen_vivado_prj bitfile launch_vivado_gui sw helplat +hls: $(hls_curr_code) $(hls_tb_code) $(SCRIPT_DIR)/hls.tcl check_accelerator + mkdir -p $(CURR_BUILD_DIR) + $(eval HLS_INCLUDES += "$(HLS_DIR)") + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(hls_curr_code)" $(HLS_TB) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) "$(HLS_INCLUDES)" $(HLS_OPTS) $(HLS_INCL); cd ../ + +hls_config: gen_hls_config + mkdir -p $(CURR_BUILD_DIR) + $(eval HLS_GEN_CODE_RUN_WITH_TB := $(shell echo $(HLS_CONFIG_DIR)/*pp )) + $(eval HLS_GEN_CODE_RUN_WITH_TB += $(shell echo $(HLS_CONFIG_DIR)/*.h )) + $(eval HLS_GEN_CODE_RUN := $(filter-out $(hls_curr_tb_code_gen), $(HLS_GEN_CODE_RUN_WITH_TB))) + $(eval HLS_INCLUDES += "$(HLS_CONFIG_DIR)") + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(HLS_GEN_CODE_RUN)" $(hls_curr_tb) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) "$(HLS_INCLUDES)" $(HLS_OPTS) $(HLS_INCL); cd ../ + +gen_hls_prj: check_accelerator + mkdir -p $(CURR_BUILD_DIR) + cd $(CURR_BUILD_DIR); vivado_hls -f $(SCRIPT_DIR)/hls.tcl -tclargs $(PRJ_NAME) "$(hls_curr_code)" $(HLS_TB) $(BRD_PARTS) $(HLS_CLK) $(TOP_LVL_FN) $(HLS_DIR)/ 0; cd ../ + +hw_gen: hls_config hw + +hw: $(BITSTREAM) + mkdir -p $(DEPLOY_DIR) + cp $(BITSTREAM) $(DEPLOY_DIR)/${KERNEL}_wrapper.bit; cp $(PRJDIR)/${KERNEL}_wrapper.tcl $(DEPLOY_DIR);\ + cp $(PRJDIR)/$(VIVADO_PRJNAME).srcs/sources_1/bd/$(KERNEL)/hw_handoff/$(KERNEL).hwh $(DEPLOY_DIR)/$(KERNEL)_wrapper.hwh + +hw_pre: + mkdir -p $(DEPLOY_DIR) + cp $(BITSTREAM) $(DEPLOY_DIR)/${KERNEL}_wrapper.bit; cp $(PRJDIR)/${KERNEL}_wrapper.tcl $(DEPLOY_DIR);\ + cp $(PRJDIR)/$(VIVADO_PRJNAME).srcs/sources_1/bd/$(KERNEL)/hw_handoff/$(KERNEL).hwh $(DEPLOY_DIR)/$(KERNEL)_wrapper.hwh + +# hw en +$(PRJDIR)/$(VIVADO_PRJNAME).xpr: $(IP_REPO) check_accelerator + vivado -mode $(VIVADO_MODE) -source $(VVD_SCRIPT) -tclargs $(TOP) $(VIVADO_PRJNAME) $(PRJDIR) $(IP_REPO) $(FREQ_MHZ) $(CORE_NR) $(CORE_NAME) $(KERNEL) + +gen_vivado_prj: $(IP_REPO) check_accelerator + vivado -mode $(VIVADO_MODE) -source $(VVD_SCRIPT) -tclargs $(TOP) $(VIVADO_PRJNAME) $(PRJDIR) $(IP_REPO) $(FREQ_MHZ) $(CORE_NR) $(CORE_NAME) $(KERNEL) + +bitfile: check_accelerator + vivado -mode $(VIVADO_MODE) -source $(VVD_SYNTH_SCRIPT) -tclargs $(PRJDIR)/$(VIVADO_PRJNAME).xpr $(PRJDIR) $(VIVADO_PRJNAME) ${KERNEL}_wrapper + +$(BITSTREAM): $(PRJDIR)/$(VIVADO_PRJNAME).xpr + vivado -mode $(VIVADO_MODE) -source $(VVD_SYNTH_SCRIPT) -tclargs $(PRJDIR)/$(VIVADO_PRJNAME).xpr $(PRJDIR) $(VIVADO_PRJNAME) ${KERNEL}_wrapper + +# launch Vivado in GUI mode with created project +launch_vivado_gui: $(PRJDIR)/$(VIVADO_PRJNAME).xpr + vivado -mode gui $(PRJDIR)/$(VIVADO_PRJNAME).xpr + +#python sw +pysw: + rm -rf $(DPLY_PY) + mkdir -p $(DPLY_PY) + cp $(PY_DIR)/*.py $(DPLY_PY)/ + cp $(SCRIPT_DIR)/python_tester_* $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_MI) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_PWL) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_ONPL) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_ACCEL) $(DPLY_PY)/ +# cp $(PY_DIR)/$(PY_WAXMI) $(DPLY_PY)/ +# cp $(SCRIPT_DIR)/python_tester_* $(DPLY_PY)/ +sw:pysw + +prepdeploy: + mkdir -p $(DEPLOY_DIR) + cp $(TOP)/platforms/$(GENERIC_TRGT_PLATFORM).mk $(DEPLOY_DIR)/Makefile +######################## +helplat: + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " Zynq Specific helper " + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " [INFO] 'make hls TOP_LVL_FN= ' builds hls project," + @echo " HLS_OPTS= 1-sim pre, 2-synth, 3-cosim, 4-ip, 5-synth & ip" + @echo " HLS_OPTS= 6-export ip, P&R, 7-sim & synth & cosim " + @echo " [INFO] 'make gen_hls_prj' generate hls project" + @echo "" + @echo "" + @echo " [INFO] 'make hw' create the bitstream, and copy it to be deployed" + @echo " [INFO] 'make bitfile' create the bitstream after project creation" + @echo " [INFO] 'make gen_vivado_prj' creation of the vivado project with all the sources" + @echo " [INFO] 'make launch_vivado_gui ' launch vivado in gui mode after creating the project" + @echo "" + @echo " [INFO] 'make sw' copy all the necessary stuffs on sw deployment side" + @echo "" + @echo "" + @echo "*****************************************************************" + @echo "" + @echo " END of Zynq Specific helper " + @echo "" + @echo "*****************************************************************" +######################## diff --git a/platforms/zynq_mpsoc.mk b/platforms/zynq_mpsoc.mk new file mode 100644 index 0000000..e7920d5 --- /dev/null +++ b/platforms/zynq_mpsoc.mk @@ -0,0 +1,21 @@ +ifndef KERNEL + KERNEL = faber +endif +BOARD_BITSTREAM=${KERNEL}_wrapper.bit +CLK_NAME=fclk0_mhz +CLK_FREQ?=100 +PREV_FREQ=sudo python3 -c "from pynq.ps import Clocks; import sys; sys.stdout.write(str(Clocks.$(CLK_NAME)))" + + +compile_host: + g++ -D"ULTRA" -std=c++11 -pthread *.cpp -lcma -o app + +load_bitfile: + @echo "Downloading bitstream named $(BOARD_BITSTREAM)" + sudo python3 -c "from pynq import Overlay; o = Overlay(' $(BOARD_BITSTREAM)'); o.download()" + +set_clk: + @echo "Prev frequency was $(PREV_FREQ)" + @echo "$(PREV_FREQ)" + @echo "Setting frequency to $(CLK_FREQ)" + sudo python3 -c "from pynq.ps import Clocks; Clocks.$(CLK_NAME) = $(CLK_FREQ); print(Clocks.$(CLK_NAME))" \ No newline at end of file diff --git a/platforms/zynq_soc.mk b/platforms/zynq_soc.mk new file mode 100644 index 0000000..f822cb1 --- /dev/null +++ b/platforms/zynq_soc.mk @@ -0,0 +1,21 @@ +ifndef KERNEL + KERNEL = faber +endif +BOARD_BITSTREAM=${KERNEL}_wrapper.bit +CLK_NAME=fclk0_mhz +CLK_FREQ?=100 +PREV_FREQ=sudo python3 -c "from pynq.ps import Clocks; import sys; sys.stdout.write(str(Clocks.$(CLK_NAME)))" + + +compile_host: + g++ -D"PYNQ" -std=c++11 -pthread *.cpp -lcma -o app + +load_bitfile: + @echo "Downloading bitstream named $(BOARD_BITSTREAM)" + sudo python3 -c "from pynq import Overlay; o = Overlay(' $(BOARD_BITSTREAM)'); o.download()" + +set_clk: + @echo "Prev frequency was $(PREV_FREQ)" + @echo "$(PREV_FREQ)" + @echo "Setting frequency to $(CLK_FREQ)" + sudo python3 -c "from pynq.ps import Clocks; Clocks.$(CLK_NAME) = $(CLK_FREQ); print(Clocks.$(CLK_NAME))" \ No newline at end of file