diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index cb9182c23cf3532a33c6716a5a6bc7dda996c902..c37d753f6070fb3f2dc82c22ecd6be4a20bcb5a2 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -51,6 +51,7 @@ from finn.transformation.fpgadataflow.make_pynq_driver import MakePYNQDriver from finn.transformation.general import GiveReadableTensorNames, GiveUniqueNodeNames from finn.util.basic import make_build_dir from finn.transformation.infer_data_layouts import InferDataLayouts +from enum import Enum def _check_vitis_envvars(): @@ -63,6 +64,17 @@ 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. @@ -164,10 +176,11 @@ class VitisLink(Transformation): ModelProto's metadata_props field with the XCLBIN full path as value. """ - def __init__(self, platform, f_mhz=200): + def __init__(self, platform, f_mhz=200, strategy=VitisOptStrategy.PERFORMANCE): super().__init__() self.platform = platform self.f_mhz = f_mhz + self.strategy = strategy def apply(self, model): _check_vitis_envvars() @@ -246,9 +259,14 @@ class VitisLink(Transformation): f.write("cd {}\n".format(link_dir)) f.write( "v++ -t hw --platform %s --link %s" - " --kernel_frequency %d --config config.txt --optimize 2" + " --kernel_frequency %d --config config.txt --optimize %s" " --save-temps -R2\n" - % (self.platform, " ".join(object_files), self.f_mhz) + % ( + self.platform, + " ".join(object_files), + self.f_mhz, + self.strategy.value, + ) ) f.write("cd {}\n".format(working_dir)) bash_command = ["bash", script] @@ -266,11 +284,14 @@ class VitisLink(Transformation): class VitisBuild(Transformation): """Best-effort attempt at building the accelerator with Vitis.""" - def __init__(self, fpga_part, period_ns, platform): + def __init__( + self, fpga_part, period_ns, platform, strategy=VitisOptStrategy.PERFORMANCE + ): super().__init__() self.fpga_part = fpga_part self.period_ns = period_ns self.platform = platform + self.strategy = strategy def apply(self, model): _check_vitis_envvars() @@ -315,7 +336,11 @@ class VitisBuild(Transformation): ) kernel_model.save(dataflow_model_filename) # Assemble design from kernels - model = model.transform(VitisLink(self.platform, round(1000 / self.period_ns))) + model = model.transform( + VitisLink( + self.platform, round(1000 / self.period_ns), strategy=self.strategy + ) + ) # set platform attribute for correct remote execution model.set_metadata_prop("platform", "alveo") diff --git a/tests/end2end/test_vitis_end2end_cnv_w1a1.py b/tests/end2end/test_vitis_end2end_cnv_w1a1.py index e1df93c5750db049b02fa073486de99d5b9a51fa..3f8799c04e0f0e13969291722999334fcaa2afc5 100644 --- a/tests/end2end/test_vitis_end2end_cnv_w1a1.py +++ b/tests/end2end/test_vitis_end2end_cnv_w1a1.py @@ -55,7 +55,7 @@ from finn.transformation.streamline import Streamline from finn.util.basic import alveo_part_map, alveo_default_platform from finn.util.test import get_test_model_trained, load_test_checkpoint_or_skip from finn.transformation.fpgadataflow.annotate_resources import AnnotateResources -from finn.transformation.fpgadataflow.vitis_build import VitisBuild +from finn.transformation.fpgadataflow.vitis_build import VitisBuild, VitisOptStrategy import pkg_resources as pk from finn.transformation.double_to_single_float import DoubleToSingleFloat from finn.transformation.move_reshape import RemoveCNVtoFCFlatten @@ -176,7 +176,14 @@ def test_end2end_vitis_cnv_w1a1_build(): model = load_test_checkpoint_or_skip( build_dir + "/end2end_vitis_cnv_w1a1_folded.onnx" ) - model = model.transform(VitisBuild(test_fpga_part, target_clk_ns, test_platform)) + model = model.transform( + VitisBuild( + test_fpga_part, + target_clk_ns, + test_platform, + strategy=VitisOptStrategy.BUILD_SPEED, + ) + ) model.save(build_dir + "/end2end_vitis_cnv_w1a1_build.onnx") diff --git a/tests/end2end/test_vitis_end2end_tfc_w1a1.py b/tests/end2end/test_vitis_end2end_tfc_w1a1.py index 085c63acece06db06a0b09929c66699e17a9a1db..c5057f25353c30ed4e680b8989bdf96abaa1a28a 100644 --- a/tests/end2end/test_vitis_end2end_tfc_w1a1.py +++ b/tests/end2end/test_vitis_end2end_tfc_w1a1.py @@ -60,7 +60,7 @@ from finn.transformation.streamline import Streamline from finn.transformation.streamline.round_thresholds import RoundAndClipThresholds from finn.util.basic import alveo_part_map, alveo_default_platform from finn.util.test import get_test_model_trained, load_test_checkpoint_or_skip -from finn.transformation.fpgadataflow.vitis_build import VitisBuild +from finn.transformation.fpgadataflow.vitis_build import VitisBuild, VitisOptStrategy from finn.transformation.infer_data_layouts import InferDataLayouts from finn.transformation.fpgadataflow.make_deployment import DeployToPYNQ from pkgutil import get_data @@ -162,7 +162,14 @@ def test_end2end_vitis_tfc_w1a1_build(): model = load_test_checkpoint_or_skip( build_dir + "/end2end_vitis_tfc_w1a1_folded.onnx" ) - model = model.transform(VitisBuild(test_fpga_part, target_clk_ns, test_platform)) + model = model.transform( + VitisBuild( + test_fpga_part, + target_clk_ns, + test_platform, + strategy=VitisOptStrategy.BUILD_SPEED, + ) + ) # TODO post-synth resources model.save(build_dir + "/end2end_vitis_tfc_w1a1_build.onnx")