diff --git a/src/finn/core/rtlsim_exec.py b/src/finn/core/rtlsim_exec.py index 0841fedebcd473a488b2e62db4dc763f283789e1..af84a75e299d666c059df54211be42b691f5ccf2 100644 --- a/src/finn/core/rtlsim_exec.py +++ b/src/finn/core/rtlsim_exec.py @@ -35,11 +35,18 @@ from finn.util.fpgadataflow import ( pyverilate_stitched_ip, ) +try: + from pyverilator import PyVerilator +except ModuleNotFoundError: + PyVerilator = None + def rtlsim_exec(model, execution_context): """Use PyVerilator to execute given model with stitched IP. The execution context contains the input values.""" + if PyVerilator is None: + raise ImportError("Installation of PyVerilator is required.") # ensure stitched ip project already exists assert os.path.isfile( model.get_metadata_prop("wrapper_filename") @@ -74,7 +81,12 @@ def rtlsim_exec(model, execution_context): packed_input = npy_to_rtlsim_input(i_tensor, i_dt, i_stream_w) num_out_values = last_node.get_number_output_values() # prepare pyverilator model - sim = pyverilate_stitched_ip(model) + rtlsim_so = model.get_metadata_prop("rtlsim_so") + if (rtlsim_so is None) or (not os.path.isfile(rtlsim_so)): + sim = pyverilate_stitched_ip(model) + model.set_metadata_prop("rtlsim_so", sim.lib._name) + else: + sim = PyVerilator(rtlsim_so) _reset_rtlsim(sim) _toggle_clk(sim) ret = _run_rtlsim(sim, packed_input, num_out_values, trace_file) diff --git a/src/finn/custom_op/fpgadataflow/__init__.py b/src/finn/custom_op/fpgadataflow/__init__.py index 4fc69985f7cdf09298f79055e159f63b2eabaf97..5de97fd976f8d57c7c389c04ad33e02340f13e56 100644 --- a/src/finn/custom_op/fpgadataflow/__init__.py +++ b/src/finn/custom_op/fpgadataflow/__init__.py @@ -38,6 +38,11 @@ from finn.util.fpgadataflow import ( ) from . import templates +try: + from pyverilator import PyVerilator +except ModuleNotFoundError: + PyVerilator = None + class HLSCustomOp(CustomOp): """HLSCustomOp class all custom ops that correspond to a finn-hlslib @@ -76,8 +81,64 @@ class HLSCustomOp(CustomOp): "res_estimate": ("s", False, ""), "res_hls": ("s", False, ""), "res_synth": ("s", False, ""), + "rtlsim_so": ("s", False, ""), } + def get_verilog_top_module_name(self): + "Return the Verilog top module name for this node." + + node = self.onnx_node + prefixed_top_name = "%s_%s" % (node.name, node.name) + return prefixed_top_name + + def get_verilog_top_filename(self): + "Return the Verilog top module filename for this node." + + verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( + self.get_nodeattr("code_gen_dir_ipgen"), + self.onnx_node.name, + self.get_verilog_top_module_name(), + ) + return verilog_file + + def prepare_rtlsim(self): + """Creates a Verilator emulation library for the RTL code generated + for this node, sets the rtlsim_so attribute to its path and returns + a PyVerilator wrapper around it.""" + + if PyVerilator is None: + raise ImportError("Installation of PyVerilator is required.") + # ensure that code is generated + code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") + assert ( + code_gen_dir != "" + ), """Node attribute "code_gen_dir_ipgen" is + not set. Please run HLSSynth_IPGen first.""" + verilog_file = self.get_verilog_top_filename() + assert os.path.isfile(verilog_file), "Cannot find top-level Verilog file." + # build the Verilator emu library + sim = PyVerilator.build( + verilog_file, + verilog_path=[ + "{}/project_{}/sol1/impl/verilog/".format( + code_gen_dir, self.onnx_node.name + ) + ], + ) + # save generated lib filename in attribute + self.set_nodeattr("rtlsim_so", sim.lib._name) + return sim + + def get_rtlsim(self): + """Return a PyVerilator wrapper for the Verilator emulation library + for this node.""" + + rtlsim_so = self.get_nodeattr("rtlsim_so") + assert os.path.isfile(rtlsim_so), "Cannot find rtlsim library." + # create PyVerilator wrapper + sim = PyVerilator(rtlsim_so) + return sim + def node_res_estimation(self): """Returns summarized resource estimation of BRAMs and LUTs of the node as a dictionary.""" diff --git a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py index 2ef5d350fb972e448b9a3745eb8c98197ab87d94..e05b2dcea7e17231617f9d3880b778d1978b4ead 100644 --- a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py +++ b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py @@ -30,11 +30,6 @@ import os import numpy as np -try: - from pyverilator import PyVerilator -except ModuleNotFoundError: - PyVerilator = None - from finn.core.datatype import DataType from finn.custom_op.fpgadataflow import HLSCustomOp from finn.custom_op.im2col import compute_conv_output_dim @@ -208,52 +203,26 @@ class ConvolutionInputGenerator(HLSCustomOp): did not produce expected ofolded utput shape" context[node.output[0]] = context[node.output[0]].reshape(*exp_oshape) elif mode == "rtlsim": - if PyVerilator is None: - raise ImportError("Installation of PyVerilator is required.") - - prefixed_top_name = "%s_%s" % (node.name, node.name) - # check if needed file exists - verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( - code_gen_dir, node.name, prefixed_top_name + sim = self.get_rtlsim() + nbits = self.get_instream_width() + rtlsim_inp = npy_to_rtlsim_input( + "{}/input_0.npy".format(code_gen_dir), export_idt, nbits ) - if os.path.isfile(verilog_file): - nbits = self.get_instream_width() - rtlsim_inp = npy_to_rtlsim_input( - "{}/input_0.npy".format(code_gen_dir), export_idt, nbits - ) - sim = PyVerilator.build( - verilog_file, - verilog_path=[ - "{}/project_{}/sol1/impl/verilog/".format( - code_gen_dir, node.name - ) - ], - ) - super().reset_rtlsim(sim) - super().toggle_clk(sim) - rtlsim_output = self.rtlsim(sim, rtlsim_inp) - odt = export_idt - target_bits = odt.bitwidth() - packed_bits = self.get_outstream_width() - out_npy_path = "{}/output.npy".format(code_gen_dir) - out_shape = self.get_folded_output_shape() - rtlsim_output_to_npy( - rtlsim_output, - out_npy_path, - odt, - out_shape, - packed_bits, - target_bits, - ) - # load and reshape output - output = np.load(out_npy_path) - output = np.asarray([output], dtype=np.float32).reshape(*exp_oshape) - context[node.output[0]] = output - else: - raise Exception( - """Found no verilog files for this node, - did you run the codegen_ipgen transformation?""" - ) + super().reset_rtlsim(sim) + super().toggle_clk(sim) + rtlsim_output = self.rtlsim(sim, rtlsim_inp) + odt = export_idt + target_bits = odt.bitwidth() + packed_bits = self.get_outstream_width() + out_npy_path = "{}/output.npy".format(code_gen_dir) + out_shape = self.get_folded_output_shape() + rtlsim_output_to_npy( + rtlsim_output, out_npy_path, odt, out_shape, packed_bits, target_bits + ) + # load and reshape output + output = np.load(out_npy_path) + output = np.asarray([output], dtype=np.float32).reshape(*exp_oshape) + context[node.output[0]] = output else: raise Exception( """Invalid value for attribute exec_mode! Is currently set to: {} diff --git a/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py b/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py index 5e4c99aa41216b05f66da8341870269c620c6c40..6a4070528ee50d97e62881d00b57355d2a2baf2d 100644 --- a/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py +++ b/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py @@ -29,10 +29,6 @@ import os import numpy as np -try: - from pyverilator import PyVerilator -except ModuleNotFoundError: - PyVerilator = None from finn.custom_op.fpgadataflow import HLSCustomOp from finn.core.datatype import DataType from onnx import TensorProto, helper @@ -351,52 +347,26 @@ class StreamingDataWidthConverter_Batch(HLSCustomOp): context[node.output[0]] = output elif mode == "rtlsim": - if PyVerilator is None: - raise ImportError("Installation of PyVerilator is required.") - - prefixed_top_name = "%s_%s" % (node.name, node.name) - # check if needed file exists - verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( - code_gen_dir, node.name, prefixed_top_name + sim = self.get_rtlsim() + nbits = self.get_instream_width() + rtlsim_inp = npy_to_rtlsim_input( + "{}/input_0.npy".format(code_gen_dir), export_idt, nbits ) - if os.path.isfile(verilog_file): - nbits = self.get_instream_width() - rtlsim_inp = npy_to_rtlsim_input( - "{}/input_0.npy".format(code_gen_dir), export_idt, nbits - ) - sim = PyVerilator.build( - verilog_file, - verilog_path=[ - "{}/project_{}/sol1/impl/verilog/".format( - code_gen_dir, node.name - ) - ], - ) - super().reset_rtlsim(sim) - super().toggle_clk(sim) - rtlsim_output = self.rtlsim(sim, rtlsim_inp) - odt = export_idt - target_bits = odt.bitwidth() - packed_bits = self.get_outstream_width() - out_npy_path = "{}/output.npy".format(code_gen_dir) - out_shape = self.get_folded_output_shape() - rtlsim_output_to_npy( - rtlsim_output, - out_npy_path, - odt, - out_shape, - packed_bits, - target_bits, - ) - # load and reshape output - output = np.load(out_npy_path) - output = np.asarray([output], dtype=np.float32).reshape(exp_shape) - context[node.output[0]] = output - else: - raise Exception( - """Found no verilog files for this node, - did you run the codegen_ipgen transformation?""" - ) + super().reset_rtlsim(sim) + super().toggle_clk(sim) + rtlsim_output = self.rtlsim(sim, rtlsim_inp) + odt = export_idt + target_bits = odt.bitwidth() + packed_bits = self.get_outstream_width() + out_npy_path = "{}/output.npy".format(code_gen_dir) + out_shape = self.get_folded_output_shape() + rtlsim_output_to_npy( + rtlsim_output, out_npy_path, odt, out_shape, packed_bits, target_bits + ) + # load and reshape output + output = np.load(out_npy_path) + output = np.asarray([output], dtype=np.float32).reshape(exp_shape) + context[node.output[0]] = output else: raise Exception( """Invalid value for attribute exec_mode! Is currently set to: {} diff --git a/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py b/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py index 7784024aae102989338df9b040fcfc1f9dc36983..49709886b96d5094569779a7f83c55e8f69f8128 100644 --- a/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py +++ b/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py @@ -33,10 +33,6 @@ from shutil import copy import numpy as np -try: - from pyverilator import PyVerilator -except ModuleNotFoundError: - PyVerilator = None from onnx import TensorProto, helper from finn.core.datatype import DataType from finn.custom_op.fpgadataflow import HLSCustomOp @@ -97,6 +93,23 @@ class StreamingFCLayer_Batch(HLSCustomOp): my_attrs.update(super().get_nodeattr_types()) return my_attrs + def get_verilog_top_module_name(self): + "Return the Verilog top module name for this node." + + node = self.onnx_node + # set top name depending on mem_mode + mem_mode = self.get_nodeattr("mem_mode") + if mem_mode == "const": + prefixed_top_name = "%s_%s" % (node.name, node.name) + elif mem_mode == "decoupled": + prefixed_top_name = "%s_memstream" % (node.name) + else: + raise Exception( + """Please set mem_mode to "const" or "decoupled", currently no other + parameter value is supported!""" + ) + return prefixed_top_name + def calc_wmem(self): """Calculates and returns WMEM.""" mw = self.get_nodeattr("MW") @@ -640,61 +653,28 @@ class StreamingFCLayer_Batch(HLSCustomOp): oshape = self.get_normal_output_shape() context[node.output[0]] = context[node.output[0]].reshape(*oshape) elif mode == "rtlsim": - if PyVerilator is None: - raise ImportError("Installation of PyVerilator is required.") - - # set top name depending on mem_mode - mem_mode = self.get_nodeattr("mem_mode") - if mem_mode == "const": - prefixed_top_name = "%s_%s" % (node.name, node.name) - elif mem_mode == "decoupled": - prefixed_top_name = "%s_memstream" % (node.name) - else: - raise Exception( - """Please set mem_mode to "const" or "decoupled", currently no other - parameter value is supported!""" - ) - # check if needed file exists - verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( - code_gen_dir, node.name, prefixed_top_name + sim = self.get_rtlsim() + nbits = self.get_instream_width() + inp = npy_to_rtlsim_input( + "{}/input_0.npy".format(code_gen_dir), export_idt, nbits + ) + super().reset_rtlsim(sim) + super().toggle_clk(sim) + output = self.rtlsim(sim, inp) + odt = self.get_output_datatype() + target_bits = odt.bitwidth() + packed_bits = self.get_outstream_width() + out_npy_path = "{}/output.npy".format(code_gen_dir) + out_shape = self.get_folded_output_shape() + rtlsim_output_to_npy( + output, out_npy_path, odt, out_shape, packed_bits, target_bits ) - if os.path.isfile(verilog_file): - nbits = self.get_instream_width() - inp = npy_to_rtlsim_input( - "{}/input_0.npy".format(code_gen_dir), export_idt, nbits - ) - sim = PyVerilator.build( - verilog_file, - verilog_path=[ - "{}/project_{}/sol1/impl/verilog/".format( - code_gen_dir, node.name - ) - ], - ) - super().reset_rtlsim(sim) - super().toggle_clk(sim) - output = self.rtlsim(sim, inp) - odt = self.get_output_datatype() - target_bits = odt.bitwidth() - packed_bits = self.get_outstream_width() - out_npy_path = "{}/output.npy".format(code_gen_dir) - out_shape = self.get_folded_output_shape() - rtlsim_output_to_npy( - output, out_npy_path, odt, out_shape, packed_bits, target_bits - ) - - # load and reshape output - output = np.load(out_npy_path) - oshape = self.get_normal_output_shape() - output = np.asarray([output], dtype=np.float32).reshape(*oshape) - context[node.output[0]] = output - - else: - raise Exception( - """Found no verilog files for this node, - did you run the codegen_ipgen transformation?""" - ) + # load and reshape output + output = np.load(out_npy_path) + oshape = self.get_normal_output_shape() + output = np.asarray([output], dtype=np.float32).reshape(*oshape) + context[node.output[0]] = output else: raise Exception( """Invalid value for attribute exec_mode! Is currently set to: {} diff --git a/src/finn/custom_op/fpgadataflow/streamingmaxpool_batch.py b/src/finn/custom_op/fpgadataflow/streamingmaxpool_batch.py index a7c2d5166b6af41327abcfeaa5cb5ae25fd23856..f370d417aa0ac1ce5d62af878575332941e2c1d0 100644 --- a/src/finn/custom_op/fpgadataflow/streamingmaxpool_batch.py +++ b/src/finn/custom_op/fpgadataflow/streamingmaxpool_batch.py @@ -29,10 +29,6 @@ import os import numpy as np -try: - from pyverilator import PyVerilator -except ModuleNotFoundError: - PyVerilator = None from finn.custom_op.fpgadataflow import HLSCustomOp from finn.custom_op.im2col import compute_conv_output_dim from finn.core.datatype import DataType @@ -302,52 +298,26 @@ class StreamingMaxPool_Batch(HLSCustomOp): did not produce expected ofolded utput shape" context[node.output[0]] = context[node.output[0]].reshape(*exp_oshape) elif mode == "rtlsim": - if PyVerilator is None: - raise ImportError("Installation of PyVerilator is required.") - - prefixed_top_name = "%s_%s" % (node.name, node.name) - # check if needed file exists - verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( - code_gen_dir, node.name, prefixed_top_name + sim = self.get_rtlsim() + nbits = self.get_instream_width() + rtlsim_inp = npy_to_rtlsim_input( + "{}/input_0.npy".format(code_gen_dir), export_idt, nbits ) - if os.path.isfile(verilog_file): - nbits = self.get_instream_width() - rtlsim_inp = npy_to_rtlsim_input( - "{}/input_0.npy".format(code_gen_dir), export_idt, nbits - ) - sim = PyVerilator.build( - verilog_file, - verilog_path=[ - "{}/project_{}/sol1/impl/verilog/".format( - code_gen_dir, node.name - ) - ], - ) - super().reset_rtlsim(sim) - super().toggle_clk(sim) - rtlsim_output = self.rtlsim(sim, rtlsim_inp) - odt = export_idt - target_bits = odt.bitwidth() - packed_bits = self.get_outstream_width() - out_npy_path = "{}/output.npy".format(code_gen_dir) - out_shape = self.get_folded_output_shape() - rtlsim_output_to_npy( - rtlsim_output, - out_npy_path, - odt, - out_shape, - packed_bits, - target_bits, - ) - # load and reshape output - output = np.load(out_npy_path) - output = np.asarray([output], dtype=np.float32).reshape(*exp_oshape) - context[node.output[0]] = output - else: - raise Exception( - """Found no verilog files for this node, - did you run the codegen_ipgen transformation?""" - ) + super().reset_rtlsim(sim) + super().toggle_clk(sim) + rtlsim_output = self.rtlsim(sim, rtlsim_inp) + odt = export_idt + target_bits = odt.bitwidth() + packed_bits = self.get_outstream_width() + out_npy_path = "{}/output.npy".format(code_gen_dir) + out_shape = self.get_folded_output_shape() + rtlsim_output_to_npy( + rtlsim_output, out_npy_path, odt, out_shape, packed_bits, target_bits + ) + # load and reshape output + output = np.load(out_npy_path) + output = np.asarray([output], dtype=np.float32).reshape(*exp_oshape) + context[node.output[0]] = output else: raise Exception( """Invalid value for attribute exec_mode! Is currently set to: {} diff --git a/src/finn/transformation/fpgadataflow/prepare_rtlsim.py b/src/finn/transformation/fpgadataflow/prepare_rtlsim.py new file mode 100644 index 0000000000000000000000000000000000000000..4474831381425268d2a59e7de835bba31c55a733 --- /dev/null +++ b/src/finn/transformation/fpgadataflow/prepare_rtlsim.py @@ -0,0 +1,76 @@ +# Copyright (c) 2020, Xilinx +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of FINN nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import finn.custom_op.registry as registry +import finn.util.basic as util +from finn.transformation import NodeLocalTransformation + +try: + from pyverilator import PyVerilator +except ModuleNotFoundError: + PyVerilator = None + + +class PrepareRTLSim(NodeLocalTransformation): + """For a graph with generated RTL sources (after HLSSynth_IPGen), create a + Verilator emulation library for each node to prepare for rtlsim + execution and set the rtlsim_so property to the path to the generated + emulation library. + + To use these libraries, exec_mode must be set to "rtlsim" (using + SetExecMode) and the model has to be executed using execute_onnx() from + finn.core.onnx_exec + + * num_workers (int or None) number of parallel workers, see documentation in + NodeLocalTransformation for more details. + """ + + def __init__(self, num_workers=None): + super().__init__(num_workers=num_workers) + + def applyNodeLocal(self, node): + op_type = node.op_type + if node.domain == "finn": + backend_attribute = util.get_by_name(node.attribute, "backend") + if backend_attribute is not None: + backend_value = backend_attribute.s.decode("UTF-8") + if backend_value == "fpgadataflow": + try: + # lookup op_type in registry of CustomOps + inst = registry.custom_op[op_type](node) + inst.prepare_rtlsim() + # ensure that executable path is now set + assert ( + inst.get_nodeattr("rtlsim_so") != "" + ), "Failed to prepare RTLSim, no rtlsim_so attribute found." + except KeyError: + # exception if op_type is not supported + raise Exception( + "Custom op_type %s is currently not supported." % op_type + ) + return (node, False) diff --git a/tests/end2end/test_end2end_cnv_w1a1.py b/tests/end2end/test_end2end_cnv_w1a1.py index 75dc6c84f28fb03197e36bed3588670b5d37d2db..53f34d4d772a458eed3d417cdeb8a962338b099c 100644 --- a/tests/end2end/test_end2end_cnv_w1a1.py +++ b/tests/end2end/test_end2end_cnv_w1a1.py @@ -71,7 +71,7 @@ from finn.transformation.fpgadataflow.make_deployment import DeployToPYNQ from finn.util.basic import pynq_part_map from finn.util.test import get_test_model_trained from finn.transformation.fpgadataflow.annotate_resources import AnnotateResources - +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim build_dir = "/tmp/" + os.environ["FINN_INST_NAME"] test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1") @@ -199,6 +199,7 @@ def test_end2end_cnv_w1a1_verify_dataflow_part(): res_npysim = ret_npysim[out_name] # node-by-node rtlsim model = model.transform(SetExecMode("rtlsim")) + model = model.transform(PrepareRTLSim()) fc_layers = model.get_nodes_by_op_type("StreamingFCLayer_Batch") for fcl in fc_layers: getCustomOp(fcl).set_nodeattr("rtlsim_trace", "default") diff --git a/tests/end2end/test_end2end_tfc_w1a1.py b/tests/end2end/test_end2end_tfc_w1a1.py index 03d6f92f1c148ce444f08fd65a867ad9390a18fd..020d49216f987ab17219817fdfa45f54d6a3154f 100644 --- a/tests/end2end/test_end2end_tfc_w1a1.py +++ b/tests/end2end/test_end2end_tfc_w1a1.py @@ -71,6 +71,7 @@ from finn.transformation.streamline.round_thresholds import RoundAndClipThreshol from finn.util.basic import pynq_part_map from finn.util.test import get_test_model_trained from finn.transformation.fpgadataflow.annotate_resources import AnnotateResources +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim build_dir = "/tmp/" + os.environ["FINN_INST_NAME"] test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1") @@ -182,6 +183,7 @@ def test_end2end_tfc_w1a1_verify_dataflow_part(): res_npysim = ret_npysim[out_name] # node-by-node rtlsim model = model.transform(SetExecMode("rtlsim")) + model = model.transform(PrepareRTLSim()) fc_layers = model.get_nodes_by_op_type("StreamingFCLayer_Batch") for fcl in fc_layers: getCustomOp(fcl).set_nodeattr("rtlsim_trace", "default") diff --git a/tests/end2end/test_end2end_tfc_w1a2.py b/tests/end2end/test_end2end_tfc_w1a2.py index 7fef331b99a78b43f8e808c8cdf978a5c8233f92..b55d985e07ac40fc875c49ba201c9552fd62c411 100644 --- a/tests/end2end/test_end2end_tfc_w1a2.py +++ b/tests/end2end/test_end2end_tfc_w1a2.py @@ -67,6 +67,7 @@ from finn.transformation.streamline import Streamline from finn.util.basic import pynq_part_map from finn.util.test import get_test_model_trained from finn.transformation.fpgadataflow.annotate_resources import AnnotateResources +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim build_dir = "/tmp/" + os.environ["FINN_INST_NAME"] test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1") @@ -173,6 +174,7 @@ def test_end2end_tfc_w1a2_verify_dataflow_part(): res_npysim = ret_npysim[out_name] # node-by-node rtlsim model = model.transform(SetExecMode("rtlsim")) + model = model.transform(PrepareRTLSim()) fc_layers = model.get_nodes_by_op_type("StreamingFCLayer_Batch") for fcl in fc_layers: getCustomOp(fcl).set_nodeattr("rtlsim_trace", "default") diff --git a/tests/end2end/test_end2end_tfc_w2a2.py b/tests/end2end/test_end2end_tfc_w2a2.py index c78be7b66fe2c2f84e6f9a1a520c3e22e769c82f..92b8b18bc0253a07eec988c2bace9a9178682147 100644 --- a/tests/end2end/test_end2end_tfc_w2a2.py +++ b/tests/end2end/test_end2end_tfc_w2a2.py @@ -67,6 +67,7 @@ from finn.transformation.streamline import Streamline from finn.util.basic import pynq_part_map from finn.util.test import get_test_model_trained from finn.transformation.fpgadataflow.annotate_resources import AnnotateResources +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim build_dir = "/tmp/" + os.environ["FINN_INST_NAME"] test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1") @@ -173,6 +174,7 @@ def test_end2end_tfc_w2a2_verify_dataflow_part(): res_npysim = ret_npysim[out_name] # node-by-node rtlsim model = model.transform(SetExecMode("rtlsim")) + model = model.transform(PrepareRTLSim()) fc_layers = model.get_nodes_by_op_type("StreamingFCLayer_Batch") for fcl in fc_layers: getCustomOp(fcl).set_nodeattr("rtlsim_trace", "default") diff --git a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py index 92d98f57c62aeb93fc17091c37214a62e78ebb8f..2ec47915b01c92c7b7c11d0cf160543fb71dd27d 100644 --- a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py +++ b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py @@ -38,6 +38,7 @@ from finn.transformation.fpgadataflow.codegen_npysim import CodeGen_npysim from finn.transformation.fpgadataflow.compile import Compile from finn.transformation.fpgadataflow.hlssynth_ipgen import HLSSynth_IPGen from finn.transformation.fpgadataflow.set_exec_mode import SetExecMode +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim from finn.transformation.general import GiveUniqueNodeNames from finn.util.basic import gen_finn_dt_tensor @@ -152,6 +153,7 @@ def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride, exec_mode): model = model.transform(GiveUniqueNodeNames()) model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) model = model.transform(HLSSynth_IPGen()) + model = model.transform(PrepareRTLSim()) else: raise Exception("Unknown exec_mode in test_fpgadataflow_slidingwindow") diff --git a/tests/fpgadataflow/test_fpgadataflow_dwc.py b/tests/fpgadataflow/test_fpgadataflow_dwc.py index 651df836ab4dfd320e4c67ff3dd49f31ec13c110..1465881830b4fec61d1b1aa6e8465a41766fd9de 100644 --- a/tests/fpgadataflow/test_fpgadataflow_dwc.py +++ b/tests/fpgadataflow/test_fpgadataflow_dwc.py @@ -7,6 +7,7 @@ from finn.core.modelwrapper import ModelWrapper from finn.transformation.fpgadataflow.codegen_ipgen import CodeGen_ipgen from finn.transformation.fpgadataflow.hlssynth_ipgen import HLSSynth_IPGen from finn.transformation.fpgadataflow.set_exec_mode import SetExecMode +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim from finn.transformation.general import GiveUniqueNodeNames from finn.util.basic import gen_finn_dt_tensor import finn.core.onnx_exec as oxe @@ -66,6 +67,7 @@ def test_fpgadataflow_dwc_rtlsim(Shape, INWidth, OUTWidth, finn_dtype): model = model.transform(GiveUniqueNodeNames()) model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) model = model.transform(HLSSynth_IPGen()) + model = model.transform(PrepareRTLSim()) y = oxe.execute_onnx(model, input_dict)["outp"] assert ( diff --git a/tests/fpgadataflow/test_fpgadataflow_fclayer.py b/tests/fpgadataflow/test_fpgadataflow_fclayer.py index 80c9e84ba92c93e8a5d57ffaceb22b5abf188963..b81ae6da2fc48b061b78189c44d9421b218f9dd4 100644 --- a/tests/fpgadataflow/test_fpgadataflow_fclayer.py +++ b/tests/fpgadataflow/test_fpgadataflow_fclayer.py @@ -44,7 +44,11 @@ from finn.transformation.fpgadataflow.compile import Compile from finn.transformation.fpgadataflow.hlssynth_ipgen import HLSSynth_IPGen from finn.transformation.fpgadataflow.set_exec_mode import SetExecMode from finn.transformation.general import GiveUniqueNodeNames +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim from finn.util.basic import calculate_signed_dot_prod_range, gen_finn_dt_tensor +from finn.transformation.fpgadataflow.replace_verilog_relpaths import ( + ReplaceVerilogRelPaths, +) def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=None): @@ -295,6 +299,8 @@ def test_fpgadataflow_fclayer_rtlsim(mem_mode, idt, wdt, act, nf, sf, mw, mh): model = model.transform(GiveUniqueNodeNames()) model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) model = model.transform(HLSSynth_IPGen()) + model = model.transform(ReplaceVerilogRelPaths()) + model = model.transform(PrepareRTLSim()) y_produced = oxe.execute_onnx(model, input_dict)["outp"] assert (y_produced.reshape(y_expected.shape) == y_expected).all(), "rtlsim failed" diff --git a/tests/fpgadataflow/test_layer_streaming_maxpool_batch.py b/tests/fpgadataflow/test_layer_streaming_maxpool_batch.py index a9acebb3114059f988aa0f21cad70e617d3d6f77..a7a731aaa5593a9fd680061d2b8ad3fc47e9f490 100644 --- a/tests/fpgadataflow/test_layer_streaming_maxpool_batch.py +++ b/tests/fpgadataflow/test_layer_streaming_maxpool_batch.py @@ -38,6 +38,7 @@ from finn.transformation.fpgadataflow.codegen_npysim import CodeGen_npysim from finn.transformation.fpgadataflow.compile import Compile from finn.transformation.fpgadataflow.hlssynth_ipgen import HLSSynth_IPGen from finn.transformation.fpgadataflow.set_exec_mode import SetExecMode +from finn.transformation.fpgadataflow.prepare_rtlsim import PrepareRTLSim from finn.transformation.general import GiveUniqueNodeNames from finn.util.basic import gen_finn_dt_tensor @@ -144,6 +145,7 @@ def test_fpgadataflow_streamingmaxpool(idt, k, ifm_dim, ifm_ch, exec_mode): model = model.transform(GiveUniqueNodeNames()) model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) model = model.transform(HLSSynth_IPGen()) + model = model.transform(PrepareRTLSim()) else: raise Exception("Unknown exec_mode in test_fpgadataflow_slidingwindow")