From 698f46508f7ad93fdaf4525979904c6aa275c6f2 Mon Sep 17 00:00:00 2001 From: auphelia <jakobapk@web.de> Date: Fri, 13 Mar 2020 11:44:11 +0000 Subject: [PATCH] [StreamingFC] Generation of .dat file into generate_params function --- .../fpgadataflow/streamingfclayer_batch.py | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py b/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py index 4b00549d3..af8fe9302 100644 --- a/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py +++ b/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py @@ -40,6 +40,7 @@ from finn.util.data_packing import ( npy_to_rtlsim_input, numpy_to_hls_code, rtlsim_output_to_npy, + pack_innermost_dim_as_hex_string, ) # ONNX i/o tensor shape assumptions for StreamingFCLayer: @@ -428,14 +429,14 @@ class StreamingFCLayer_Batch(HLSCustomOp): # convert weights into hlslib-compatible format weight_tensor = self.get_hls_compatible_weight_tensor(weights) export_wdt = self.get_weight_datatype() + # we have converted bipolar weights to binary for export, + # so use it as such for weight generation + if self.get_weight_datatype() == DataType.BIPOLAR: + export_wdt = DataType.BINARY code_gen_dir = path if mem_mode == "const": """Saves weights into params.h""" - # we have converted bipolar weights to binary for export, - # so use it as such for weight generation - if self.get_weight_datatype() == DataType.BIPOLAR: - export_wdt = DataType.BINARY weight_hls_code = numpy_to_hls_code( weight_tensor, export_wdt, "weights", True, True ) @@ -477,6 +478,23 @@ class StreamingFCLayer_Batch(HLSCustomOp): np.save( os.path.join(code_gen_dir, "weights.npy"), weight_tensor, ) + """Saves weights into .dat file""" + # convert weight value sinto hexstring + weight_width = self.get_weightstream_width() + weight_tensor = pack_innermost_dim_as_hex_string( + weight_tensor, export_wdt, weight_width + ) + weight_pad = np.zeros((1024), int).astype(str) + weight_tensor = weight_tensor.flatten() + # delete "0x" in the beginning of the hexstring + for i in range(len(weight_tensor)): + weight_tensor[i] = weight_tensor[i][2:] + weight_pad[: weight_tensor.shape[0]] = weight_tensor + f = open("{}/memblock_0.dat".format(code_gen_dir), "w+") + for val in weight_pad: + f.write(val + "\n") + f.close() + else: raise Exception( """Please set mem_mode to "const"i or "decoupled", currently no other @@ -597,31 +615,12 @@ class StreamingFCLayer_Batch(HLSCustomOp): # reshape output to have expected shape context[node.output[0]] = context[node.output[0]].reshape(1, mh) elif mode == "rtlsim": - # check mem mode if set to "decoupled" to convert - # weights.npy file into .dat file + # set top name depending on mem_mode mem_mode = self.get_nodeattr("mem_mode") - if mem_mode == "decoupled": - # iterate over array and save in memblock_0.dat - weights = np.load("{}/weights.npy".format(code_gen_dir)) - weights = weights.flatten() - wdt = self.get_weight_datatype() - f = open( - "{}/project_{}/sol1/impl/verilog/memblock_0.dat".format( - code_gen_dir, self.onnx_node.name - ), - "w+", - ) - for val in weights: - # convert signed values into unsigned integer - if wdt.name.startswith("INT"): - bitwidth = wdt.bitwidth() - if val < 0: - val = int(bin(int(val) + 2 ** bitwidth), 2) - - f.write(str(int(val)) + "\n") - f.close() - - prefixed_top_name = "%s_%s" % (node.name, node.name) + if mem_mode == "const": + prefixed_top_name = "%s_%s" % (node.name, node.name) + elif mem_mode == "decoupled": + prefixed_top_name == "%s_memstream" % (node.name) # check if needed file exists verilog_file = "{}/project_{}/sol1/impl/verilog/{}.v".format( code_gen_dir, node.name, prefixed_top_name -- GitLab