Skip to content
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 19 additions & 21 deletions src/finn/builder/build_dataflow_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
from enum import Enum
from typing import Any, List, Optional

from finn.transformation.fpgadataflow.vitis_build import VitisOptStrategy
from finn.util.basic import alveo_default_platform, alveo_part_map, pynq_part_map


Expand Down Expand Up @@ -65,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."""

Expand Down Expand Up @@ -304,7 +310,11 @@ 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
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.
Expand Down Expand Up @@ -388,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
Expand Down
3 changes: 2 additions & 1 deletion src/finn/builder/build_dataflow_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,10 +832,11 @@ 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,
fpga_memory_type=cfg.fpga_memory,
)
)
copy(model.get_metadata_prop("bitfile"), bitfile_dir + "/finn-accel.xclbin")
Expand Down
67 changes: 38 additions & 29 deletions src/finn/transformation/fpgadataflow/vitis_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,6 +39,7 @@
RemoveUnusedTensors,
)

from finn.builder.build_dataflow_config import FpgaMemoryType, VitisOptStrategy
from finn.transformation.fpgadataflow.create_dataflow_partition import (
CreateDataflowPartition,
)
Expand All @@ -64,17 +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 CreateVitisXO(Transformation):
"""Create a Vitis object file from a stitched FINN ip.

Expand Down Expand Up @@ -175,12 +164,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()
Expand Down Expand Up @@ -229,28 +220,42 @@ 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 == "":
# 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 == FpgaMemoryType.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 == FpgaMemoryType.HOST_MEM:
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
Expand Down Expand Up @@ -357,6 +362,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/HBM should be used
"""

def __init__(
Expand All @@ -369,6 +375,7 @@ def __init__(
floorplan_file=None,
enable_link=True,
partition_model_dir=None,
fpga_memory_type=FpgaMemoryType.DEFAULT,
):
super().__init__()
self.fpga_part = fpga_part
Expand All @@ -379,6 +386,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()
Expand Down Expand Up @@ -425,6 +433,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
Expand Down
Loading