From 12cf4a4cfb64069055cafde9eba939c7088b5319 Mon Sep 17 00:00:00 2001 From: Linus Jungemann <38974033+LinusJungemann@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:15:14 +0200 Subject: [PATCH 1/4] Add memory selector --- src/finn/builder/build_dataflow_config.py | 11 +++++ src/finn/builder/build_dataflow_steps.py | 1 + .../fpgadataflow/vitis_build.py | 44 ++++++++++++------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/finn/builder/build_dataflow_config.py b/src/finn/builder/build_dataflow_config.py index e35c1cd346..1092d54da3 100644 --- a/src/finn/builder/build_dataflow_config.py +++ b/src/finn/builder/build_dataflow_config.py @@ -63,6 +63,13 @@ class DataflowOutputType(str, Enum): BITFILE = "bitfile" PYNQ_DRIVER = "pynq_driver" DEPLOYMENT_PACKAGE = "deployment_package" + +class FpgaMemoryType(str, Enum): + "Memory Type used by the FPGA to store input/output data" + + DEFAULT = "default" + HOST_MEM = "host_memory" + class VitisOptStrategyCfg(str, Enum): @@ -303,6 +310,10 @@ class DataflowBuildConfig: #: Vitis optimization strategy #: Only relevant when `shell_flow_type = ShellFlowType.VITIS_ALVEO` vitis_opt_strategy: Optional[VitisOptStrategyCfg] = VitisOptStrategyCfg.DEFAULT + + #: FPGA memory type + #: Can be used to use host memory for input/output data instead of DDR or HBM memory + fpga_memory: Optional[FpgaMemoryType] = FpgaMemoryType.DEFAULT #: Whether intermediate ONNX files will be saved during the build process. #: These can be useful for debugging if the build fails. diff --git a/src/finn/builder/build_dataflow_steps.py b/src/finn/builder/build_dataflow_steps.py index ecc1d28c53..6124ba6dc6 100644 --- a/src/finn/builder/build_dataflow_steps.py +++ b/src/finn/builder/build_dataflow_steps.py @@ -829,6 +829,7 @@ def step_synthesize_bitfile(model: ModelWrapper, cfg: DataflowBuildConfig): enable_debug=cfg.enable_hw_debug, floorplan_file=cfg.vitis_floorplan_file, partition_model_dir=partition_model_dir, + fpga_memory_type=cfg.fpga_memory, ) ) copy(model.get_metadata_prop("bitfile"), bitfile_dir + "/finn-accel.xclbin") diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index 157d81cf35..a1d61e1fab 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -175,12 +175,14 @@ def __init__( f_mhz=200, strategy=VitisOptStrategy.PERFORMANCE, enable_debug=False, + fpga_memory_type = "default" ): super().__init__() self.platform = platform self.f_mhz = f_mhz self.strategy = strategy self.enable_debug = enable_debug + self.fpga_memory_type = fpga_memory_type def apply(self, model): _check_vitis_envvars() @@ -232,25 +234,31 @@ def apply(self, model): if producer is None or consumer is None: node_mem_port = sdp_node.get_nodeattr("mem_port") if node_mem_port == "": - # configure good defaults based on board - if "u50" in self.platform or "u280" in self.platform or "u55c" in self.platform: - # Use HBM where available (also U50 does not have DDR) - mem_type = "HBM" - mem_idx = 0 - elif "u200" in self.platform: - # Use DDR controller in static region of U200 - mem_type = "DDR" - mem_idx = 1 - elif "u250" in self.platform: - # Use DDR controller on the node's SLR if set, otherwise 0 - mem_type = "DDR" - if node_slr == -1: + if self.fpga_memory_type == "default": + # configure good defaults based on board + if "u50" in self.platform or "u280" in self.platform or "u55c" in self.platform: + # Use HBM where available (also U50 does not have DDR) + mem_type = "HBM" mem_idx = 0 + elif "u200" in self.platform: + # Use DDR controller in static region of U200 + mem_type = "DDR" + mem_idx = 1 + elif "u250" in self.platform: + # Use DDR controller on the node's SLR if set, otherwise 0 + mem_type = "DDR" + if node_slr == -1: + mem_idx = 0 + else: + mem_idx = node_slr else: - mem_idx = node_slr + mem_type = "DDR" + mem_idx = 1 + elif self.fpga_memory_type == "host_memory": + mem_type="HOST" + mem_idx=0 else: - mem_type = "DDR" - mem_idx = 1 + raise RuntimeError("Unknown fpga memory type: " + str(self.fpga_memory_type) + ". Aborting!") node_mem_port = "%s[%d]" % (mem_type, mem_idx) config.append("sp=%s.m_axi_gmem0:%s" % (instance_names[node.name], node_mem_port)) # connect streams @@ -357,6 +365,7 @@ class VitisBuild(Transformation): Must be parse-able by the ApplyConfig transform. :parameter enable_link: enable linking kernels (.xo files), otherwise just synthesize them independently. + :parameter fpga_memory_type: Specify whether Host or FPGA memory such as DDR or HBM should be used """ def __init__( @@ -369,6 +378,7 @@ def __init__( floorplan_file=None, enable_link=True, partition_model_dir=None, + fpga_memory_type="default" ): super().__init__() self.fpga_part = fpga_part @@ -379,6 +389,7 @@ def __init__( self.floorplan_file = floorplan_file self.enable_link = enable_link self.partition_model_dir = partition_model_dir + self.fpga_memory_type = fpga_memory_type def apply(self, model): _check_vitis_envvars() @@ -425,6 +436,7 @@ def apply(self, model): round(1000 / self.period_ns), strategy=self.strategy, enable_debug=self.enable_debug, + fpga_memory_type=self.fpga_memory_type ) ) # set platform attribute for correct remote execution From 7e0d6dd5cf74afd11f1a55ffacaf6d64a494536c Mon Sep 17 00:00:00 2001 From: Linus Jungemann <38974033+LinusJungemann@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:06:48 +0100 Subject: [PATCH 2/4] Change Host Mem implementation for better readability and fix small bug which causes odmas to not be generated on correct mem type --- .pre-commit-config.yaml | 2 +- .../fpgadataflow/vitis_build.py | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 72a9688505..6bb6b7d07d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ exclude: '^docs/conf.py' default_language_version: - python: python3.10 + python: python3 repos: - repo: https://github.com/pre-commit/pre-commit-hooks diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index a1d61e1fab..daa52d9f85 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -40,6 +40,8 @@ RemoveUnusedTensors, ) +# For better readability +from finn.builder.build_dataflow_config import FpgaMemoryType from finn.transformation.fpgadataflow.create_dataflow_partition import ( CreateDataflowPartition, ) @@ -175,7 +177,7 @@ def __init__( f_mhz=200, strategy=VitisOptStrategy.PERFORMANCE, enable_debug=False, - fpga_memory_type = "default" + fpga_memory_type="default", ): super().__init__() self.platform = platform @@ -231,12 +233,16 @@ def apply(self, model): if node_slr != -1: config.append("slr=%s:SLR%d" % (instance_names[node.name], node_slr)) # assign memory banks - if producer is None or consumer is None: + if producer is None or consumer is None or consumer == []: node_mem_port = sdp_node.get_nodeattr("mem_port") if node_mem_port == "": - if self.fpga_memory_type == "default": + if self.fpga_memory_type == FpgaMemoryType.DEFAULT: # configure good defaults based on board - if "u50" in self.platform or "u280" in self.platform or "u55c" in self.platform: + if ( + "u50" in self.platform + or "u280" in self.platform + or "u55c" in self.platform + ): # Use HBM where available (also U50 does not have DDR) mem_type = "HBM" mem_idx = 0 @@ -254,11 +260,15 @@ def apply(self, model): else: mem_type = "DDR" mem_idx = 1 - elif self.fpga_memory_type == "host_memory": - mem_type="HOST" - mem_idx=0 + elif self.fpga_memory_type == FpgaMemoryType.HOST_MEM: + mem_type = "HOST" + mem_idx = 0 else: - raise RuntimeError("Unknown fpga memory type: " + str(self.fpga_memory_type) + ". Aborting!") + raise RuntimeError( + "Unknown fpga memory type: " + + str(self.fpga_memory_type) + + ". Aborting!" + ) node_mem_port = "%s[%d]" % (mem_type, mem_idx) config.append("sp=%s.m_axi_gmem0:%s" % (instance_names[node.name], node_mem_port)) # connect streams @@ -365,7 +375,7 @@ class VitisBuild(Transformation): Must be parse-able by the ApplyConfig transform. :parameter enable_link: enable linking kernels (.xo files), otherwise just synthesize them independently. - :parameter fpga_memory_type: Specify whether Host or FPGA memory such as DDR or HBM should be used + :parameter fpga_memory_type: Specify whether Host or FPGA memory such as DDR/HBM should be used """ def __init__( @@ -378,7 +388,7 @@ def __init__( floorplan_file=None, enable_link=True, partition_model_dir=None, - fpga_memory_type="default" + fpga_memory_type=FpgaMemoryType.DEFAULT, ): super().__init__() self.fpga_part = fpga_part @@ -436,7 +446,7 @@ def apply(self, model): round(1000 / self.period_ns), strategy=self.strategy, enable_debug=self.enable_debug, - fpga_memory_type=self.fpga_memory_type + fpga_memory_type=self.fpga_memory_type, ) ) # set platform attribute for correct remote execution From 24f19342fc81953032161afbf91d96a898b2e468 Mon Sep 17 00:00:00 2001 From: Linus Jungemann <38974033+LinusJungemann@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:51:48 +0100 Subject: [PATCH 3/4] Solve circular import --- src/finn/builder/build_dataflow_config.py | 14 +++++--------- .../transformation/fpgadataflow/vitis_build.py | 8 +++++++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/finn/builder/build_dataflow_config.py b/src/finn/builder/build_dataflow_config.py index ad0ff74367..7eb21f9cee 100644 --- a/src/finn/builder/build_dataflow_config.py +++ b/src/finn/builder/build_dataflow_config.py @@ -34,7 +34,10 @@ from enum import Enum from typing import Any, List, Optional -from finn.transformation.fpgadataflow.vitis_build import VitisOptStrategy +from finn.transformation.fpgadataflow.vitis_build import ( + FpgaMemoryType, + VitisOptStrategy, +) from finn.util.basic import alveo_default_platform, alveo_part_map, pynq_part_map @@ -63,13 +66,6 @@ class DataflowOutputType(str, Enum): BITFILE = "bitfile" PYNQ_DRIVER = "pynq_driver" DEPLOYMENT_PACKAGE = "deployment_package" - -class FpgaMemoryType(str, Enum): - "Memory Type used by the FPGA to store input/output data" - - DEFAULT = "default" - HOST_MEM = "host_memory" - class VitisOptStrategyCfg(str, Enum): @@ -312,7 +308,7 @@ class DataflowBuildConfig: #: Vitis optimization strategy #: Only relevant when `shell_flow_type = ShellFlowType.VITIS_ALVEO` vitis_opt_strategy: Optional[VitisOptStrategyCfg] = VitisOptStrategyCfg.DEFAULT - + #: FPGA memory type #: Can be used to use host memory for input/output data instead of DDR or HBM memory fpga_memory: Optional[FpgaMemoryType] = FpgaMemoryType.DEFAULT diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index daa52d9f85..8fac76e98b 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -41,7 +41,6 @@ ) # For better readability -from finn.builder.build_dataflow_config import FpgaMemoryType from finn.transformation.fpgadataflow.create_dataflow_partition import ( CreateDataflowPartition, ) @@ -77,6 +76,13 @@ class VitisOptStrategy(Enum): BUILD_SPEED = "quick" +class FpgaMemoryType(str, Enum): + "Memory Type used by the FPGA to store input/output data" + + DEFAULT = "default" + HOST_MEM = "host_memory" + + class CreateVitisXO(Transformation): """Create a Vitis object file from a stitched FINN ip. From b6051eba1e4b0478f3239e4bf95f83bc378afc87 Mon Sep 17 00:00:00 2001 From: Linus Jungemann <38974033+LinusJungemann@users.noreply.github.com> Date: Tue, 14 Jan 2025 09:57:50 +0100 Subject: [PATCH 4/4] Refactor code for better readability --- src/finn/builder/build_dataflow_config.py | 39 +++++++------------ src/finn/builder/build_dataflow_steps.py | 2 +- .../fpgadataflow/vitis_build.py | 21 +--------- 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/src/finn/builder/build_dataflow_config.py b/src/finn/builder/build_dataflow_config.py index 7eb21f9cee..008eeec836 100644 --- a/src/finn/builder/build_dataflow_config.py +++ b/src/finn/builder/build_dataflow_config.py @@ -34,10 +34,6 @@ from enum import Enum from typing import Any, List, Optional -from finn.transformation.fpgadataflow.vitis_build import ( - FpgaMemoryType, - VitisOptStrategy, -) from finn.util.basic import alveo_default_platform, alveo_part_map, pynq_part_map @@ -68,17 +64,24 @@ class DataflowOutputType(str, Enum): DEPLOYMENT_PACKAGE = "deployment_package" -class VitisOptStrategyCfg(str, Enum): - """Vitis optimization strategy with serializable string enum values.""" +class VitisOptStrategy(Enum): + "Values applicable to VitisBuild optimization strategy." - DEFAULT = "default" - POWER = "power" - PERFORMANCE = "performance" - PERFORMANCE_BEST = "performance_best" - SIZE = "size" + DEFAULT = "0" + POWER = "1" + PERFORMANCE = "2" + PERFORMANCE_BEST = "3" + SIZE = "s" BUILD_SPEED = "quick" +class FpgaMemoryType(str, Enum): + "Memory Type used by the FPGA to store input/output data" + + DEFAULT = "default" + HOST_MEM = "host_memory" + + class LargeFIFOMemStyle(str, Enum): """Type of memory resource to use for large FIFOs.""" @@ -307,7 +310,7 @@ class DataflowBuildConfig: #: Vitis optimization strategy #: Only relevant when `shell_flow_type = ShellFlowType.VITIS_ALVEO` - vitis_opt_strategy: Optional[VitisOptStrategyCfg] = VitisOptStrategyCfg.DEFAULT + vitis_opt_strategy: Optional[VitisOptStrategy] = VitisOptStrategy.DEFAULT #: FPGA memory type #: Can be used to use host memory for input/output data instead of DDR or HBM memory @@ -395,18 +398,6 @@ def _resolve_cycles_per_frame(self): n_cycles_per_frame = n_clock_cycles_per_sec / self.target_fps return int(n_cycles_per_frame) - def _resolve_vitis_opt_strategy(self): - # convert human-readable enum to value expected by v++ - name_to_strategy = { - VitisOptStrategyCfg.DEFAULT: VitisOptStrategy.DEFAULT, - VitisOptStrategyCfg.POWER: VitisOptStrategy.POWER, - VitisOptStrategyCfg.PERFORMANCE: VitisOptStrategy.PERFORMANCE, - VitisOptStrategyCfg.PERFORMANCE_BEST: VitisOptStrategy.PERFORMANCE_BEST, - VitisOptStrategyCfg.SIZE: VitisOptStrategy.SIZE, - VitisOptStrategyCfg.BUILD_SPEED: VitisOptStrategy.BUILD_SPEED, - } - return name_to_strategy[self.vitis_opt_strategy] - def _resolve_vitis_platform(self): if self.vitis_platform is not None: return self.vitis_platform diff --git a/src/finn/builder/build_dataflow_steps.py b/src/finn/builder/build_dataflow_steps.py index e131af29aa..25ca01c48e 100644 --- a/src/finn/builder/build_dataflow_steps.py +++ b/src/finn/builder/build_dataflow_steps.py @@ -832,7 +832,7 @@ def step_synthesize_bitfile(model: ModelWrapper, cfg: DataflowBuildConfig): cfg._resolve_fpga_part(), cfg.synth_clk_period_ns, cfg._resolve_vitis_platform(), - strategy=cfg._resolve_vitis_opt_strategy(), + strategy=cfg.vitis_opt_strategy, enable_debug=cfg.enable_hw_debug, floorplan_file=cfg.vitis_floorplan_file, partition_model_dir=partition_model_dir, diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index 8fac76e98b..36a89696ae 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -30,7 +30,6 @@ import json import os import subprocess -from enum import Enum from qonnx.core.modelwrapper import ModelWrapper from qonnx.custom_op.registry import getCustomOp from qonnx.transformation.base import Transformation @@ -40,7 +39,7 @@ RemoveUnusedTensors, ) -# For better readability +from finn.builder.build_dataflow_config import FpgaMemoryType, VitisOptStrategy from finn.transformation.fpgadataflow.create_dataflow_partition import ( CreateDataflowPartition, ) @@ -65,24 +64,6 @@ def _check_vitis_envvars(): ), "XILINX_XRT must be set for Vitis, ensure the XRT env is sourced" -class VitisOptStrategy(Enum): - "Values applicable to VitisBuild optimization strategy." - - DEFAULT = "0" - POWER = "1" - PERFORMANCE = "2" - PERFORMANCE_BEST = "3" - SIZE = "s" - BUILD_SPEED = "quick" - - -class FpgaMemoryType(str, Enum): - "Memory Type used by the FPGA to store input/output data" - - DEFAULT = "default" - HOST_MEM = "host_memory" - - class CreateVitisXO(Transformation): """Create a Vitis object file from a stitched FINN ip.