From ec400ddf1ecd4ee5bfe7fae87f7dcb1f0b6d9ee6 Mon Sep 17 00:00:00 2001 From: Yaman Umuroglu <maltanar@gmail.com> Date: Fri, 4 Sep 2020 00:31:18 +0200 Subject: [PATCH] [Test] bring Alveo/Vitis into end2end test --- tests/end2end/test_end2end.py | 127 +++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/tests/end2end/test_end2end.py b/tests/end2end/test_end2end.py index 1e787e469..0a7e74626 100644 --- a/tests/end2end/test_end2end.py +++ b/tests/end2end/test_end2end.py @@ -60,7 +60,7 @@ from finn.transformation.general import ( from finn.transformation.infer_datatypes import InferDataTypes from finn.transformation.infer_shapes import InferShapes from finn.transformation.streamline import Streamline -from finn.util.basic import pynq_part_map +from finn.util.basic import pynq_part_map, 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.infer_data_layouts import InferDataLayouts @@ -86,10 +86,9 @@ from finn.transformation.fpgadataflow.insert_fifo import InsertFIFO from finn.transformation.fpgadataflow.annotate_cycles import AnnotateCycles from finn.analysis.fpgadataflow.dataflow_performance import dataflow_performance from finn.core.modelwrapper import ModelWrapper +from finn.transformation.fpgadataflow.vitis_build import VitisBuild, VitisOptStrategy build_dir = "/tmp/" + os.environ["FINN_INST_NAME"] -test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1") -test_fpga_part = pynq_part_map[test_pynq_board] target_clk_ns = 10 mem_mode = "decoupled" rtlsim_trace = False @@ -235,6 +234,37 @@ def execute_parent(parent_path, child_path, input_tensor_npy): return y +def get_build_env(kind): + ret = {} + if kind == "zynq": + ret["board"] = os.getenv("PYNQ_BOARD", default="Pynq-Z1") + ret["part"] = pynq_part_map[ret["board"]] + ret["ip"] = os.getenv("PYNQ_IP", "") + ret["username"] = os.getenv("PYNQ_USERNAME", "xilinx") + ret["password"] = os.getenv("PYNQ_PASSWORD", "xilinx") + ret["port"] = os.getenv("PYNQ_PORT", 22) + ret["target_dir"] = os.getenv("PYNQ_TARGET_DIR", "/home/xilinx/finn") + ret["build_fxn"] = ZynqBuild(ret["board"], target_clk_ns) + elif kind == "alveo": + ret["board"] = os.getenv("ALVEO_BOARD", default="U250") + ret["part"] = alveo_part_map[ret["board"]] + ret["platform"] = alveo_default_platform[ret["board"]] + ret["ip"] = os.getenv("ALVEO_IP", "") + ret["username"] = os.getenv("ALVEO_USERNAME", "") + ret["password"] = os.getenv("ALVEO_PASSWORD", "") + ret["port"] = os.getenv("ALVEO_PORT", 22) + ret["target_dir"] = os.getenv("ALVEO_TARGET_DIR", "/tmp/finn_alveo_deploy") + ret["build_fxn"] = VitisBuild( + ret["part"], + target_clk_ns, + ret["platform"], + strategy=VitisOptStrategy.BUILD_SPEED, + ) + else: + raise Exception("Unknown test build environment spec") + return ret + + @pytest.mark.parametrize("wbits", [1, 2]) @pytest.mark.parametrize("abits", [1, 2]) @pytest.mark.parametrize("topology", ["tfc", "cnv"]) @@ -332,6 +362,7 @@ class TestEnd2End: def test_ipgen(self, topology, wbits, abits): prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "fold") model = load_test_checkpoint_or_skip(prev_chkpt_name) + test_fpga_part = get_build_env("zynq")["part"] model = model.transform(GiveUniqueNodeNames()) model = model.transform(PrepareIP(test_fpga_part, target_clk_ns)) model = model.transform(HLSSynthIP()) @@ -340,6 +371,7 @@ class TestEnd2End: def test_ipstitch_rtlsim(self, topology, wbits, abits): prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "ipgen") model = load_test_checkpoint_or_skip(prev_chkpt_name) + test_fpga_part = get_build_env("zynq")["part"] model = model.transform(InsertDWC()) model = model.transform(InsertFIFO()) model = model.transform(GiveUniqueNodeNames()) @@ -370,10 +402,14 @@ class TestEnd2End: warnings.warn("Estimated & rtlsim performance: " + str(perf)) assert np.isclose(y, output_tensor_npy).all() - def test_build(self, topology, wbits, abits): + @pytest.mark.parametrize("kind", ["zynq", "alveo"]) + def test_build(self, topology, wbits, abits, kind): + if kind == "alveo" and ("VITIS_PATH" not in os.environ): + pytest.skip("VITIS_PATH not set") prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "ipgen") model = load_test_checkpoint_or_skip(prev_chkpt_name) - model = model.transform(ZynqBuild(test_pynq_board, target_clk_ns)) + cfg = get_build_env(kind) + model = model.transform(cfg["build_fxn"]) model = model.transform(AnnotateResources("synth")) warnings.warn( "Post-synthesis resources (excluding shell): " @@ -383,52 +419,47 @@ class TestEnd2End: "Post-synthesis resources (all inclusive): " + model.get_metadata_prop("res_total_top_synth") ) - model.save(get_checkpoint_name(topology, wbits, abits, "build")) + model.save(get_checkpoint_name(topology, wbits, abits, "build_" + kind)) - def test_deploy(self, topology, wbits, abits): - prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "build") + @pytest.mark.parametrize("kind", ["zynq", "alveo"]) + def test_deploy(self, topology, wbits, abits, kind): + prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "build_" + kind) model = load_test_checkpoint_or_skip(prev_chkpt_name) - try: - ip = os.environ["PYNQ_IP"] # no fault for this one; skip if not defined - if ip == "": - pytest.skip("PYNQ board IP address not specified") - username = os.getenv("PYNQ_USERNAME", "xilinx") - password = os.getenv("PYNQ_PASSWORD", "xilinx") - port = os.getenv("PYNQ_PORT", 22) - target_dir = os.getenv("PYNQ_TARGET_DIR", "/home/xilinx/finn") - model = model.transform( - DeployToPYNQ(ip, port, username, password, target_dir) - ) - # save the model to be able to link it to the parent - model.save(get_checkpoint_name(topology, wbits, abits, "deploy")) - except KeyError: + cfg = get_build_env(kind) + if cfg["ip"] == "": pytest.skip("PYNQ board IP address not specified") + model = model.transform( + DeployToPYNQ( + cfg["ip"], + cfg["port"], + cfg["username"], + cfg["password"], + cfg["target_dir"], + ) + ) + # save the model to be able to link it to the parent + model.save(get_checkpoint_name(topology, wbits, abits, "deploy_" + kind)) - def test_run_on_pynq(self, topology, wbits, abits): - prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "deploy") + @pytest.mark.parametrize("kind", ["zynq", "alveo"]) + def test_run_on_pynq(self, topology, wbits, abits, kind): + prev_chkpt_name = get_checkpoint_name(topology, wbits, abits, "deploy_" + kind) model = load_test_checkpoint_or_skip(prev_chkpt_name) # NOQA - try: - ip = os.environ["PYNQ_IP"] # no fault for this one; skip if not defined - if ip == "": - pytest.skip("PYNQ board IP address not specified") - (input_tensor_npy, output_tensor_npy) = get_golden_io_pair( - topology, wbits, abits - ) - parent_model = load_test_checkpoint_or_skip( - get_checkpoint_name(topology, wbits, abits, "dataflow_parent") - ) - iname = parent_model.graph.input[0].name - oname = parent_model.graph.output[0].name - sdp_node = parent_model.get_nodes_by_op_type("StreamingDataflowPartition")[ - 0 - ] - sdp_node = getCustomOp(sdp_node) - sdp_chkpt = get_checkpoint_name(topology, wbits, abits, "deploy") - load_test_checkpoint_or_skip(sdp_chkpt) - sdp_node.set_nodeattr("model", sdp_chkpt) - ret = execute_onnx(parent_model, {iname: input_tensor_npy}, True) - y = ret[oname] - assert np.isclose(y, output_tensor_npy).all() - - except KeyError: + cfg = get_build_env(kind) + if cfg["ip"] == "": pytest.skip("PYNQ board IP address not specified") + (input_tensor_npy, output_tensor_npy) = get_golden_io_pair( + topology, wbits, abits + ) + parent_model = load_test_checkpoint_or_skip( + get_checkpoint_name(topology, wbits, abits, "dataflow_parent") + ) + iname = parent_model.graph.input[0].name + oname = parent_model.graph.output[0].name + sdp_node = parent_model.get_nodes_by_op_type("StreamingDataflowPartition")[0] + sdp_node = getCustomOp(sdp_node) + sdp_chkpt = get_checkpoint_name(topology, wbits, abits, "deploy") + load_test_checkpoint_or_skip(sdp_chkpt) + sdp_node.set_nodeattr("model", sdp_chkpt) + ret = execute_onnx(parent_model, {iname: input_tensor_npy}, True) + y = ret[oname] + assert np.isclose(y, output_tensor_npy).all() -- GitLab