From b7d9003720ce7257337b929c313611a87e750c21 Mon Sep 17 00:00:00 2001
From: auphelia <jakobapk@web.de>
Date: Wed, 15 Jan 2020 14:52:30 +0000
Subject: [PATCH] [Code Generation - npysim] Added functionality that npysim is
 only performed in execution of node when sim_mode = "npysim"

---
 src/finn/custom_op/fpgadataflow/__init__.py   | 23 ++++--
 .../fpgadataflow/convolutioninputgenerator.py | 77 +++++++++++--------
 .../test_fpgadataflow_convinputgenerator.py   |  4 +-
 3 files changed, 64 insertions(+), 40 deletions(-)

diff --git a/src/finn/custom_op/fpgadataflow/__init__.py b/src/finn/custom_op/fpgadataflow/__init__.py
index 362b7a64e..9905d7f1d 100644
--- a/src/finn/custom_op/fpgadataflow/__init__.py
+++ b/src/finn/custom_op/fpgadataflow/__init__.py
@@ -164,12 +164,23 @@ compilation transformations?
         process_execute.communicate()
 
     def execute_node(self, context, graph):
-        # save input(s)
-        self.dynamic_input_to_npy(context, 1)
-        # execute the precompiled model
-        self.exec_precompiled_singlenode_model()
-        # load output npy file
-        self.npy_to_dynamic_output(context)
+        mode = self.get_nodeattr("sim_mode")
+        if mode == "npysim":
+            # save input(s)
+            self.dynamic_input_to_npy(context, 1)
+            # execute the precompiled model
+            self.exec_precompiled_singlenode_model()
+            # load output npy file
+            self.npy_to_dynamic_output(context)
+        elif mode == "rtlsim":
+            pass
+        else:
+            raise Exception(
+                """Invalid value for attribute sim_mode! Is currently set to: {}
+            has to be set to one of the following value ("npysim", "rtlsim")""".format(
+                    mode
+                )
+            )
 
     def generate_params(self, model):
         pass
diff --git a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py
index 7f834cf5c..22139fc53 100644
--- a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py
+++ b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py
@@ -45,39 +45,50 @@ class ConvolutionInputGenerator(HLSCustomOp):
         return self.get_nodeattr("SIMD") * self.get_nodeattr("Input_precision")
 
     def execute_node(self, context, graph):
-        node = self.onnx_node
-        k = self.get_nodeattr("ConvKernelDim")
-        ifm_dim = self.get_nodeattr("IFMDim")
-        ifm_ch = self.get_nodeattr("IFMChannels")
-        ofm_dim = self.get_nodeattr("OFMDim")
-        out_pix = ofm_dim * ofm_dim
-        idt = self.get_input_datatype()
-        if idt == DataType.BIPOLAR:
-            # use binary for bipolar storage
-            idt = DataType.BINARY
-
-        # TODO ensure codegen dir exists
-        code_gen_dir = self.get_nodeattr("code_gen_dir_npysim")
-        # create a npy file for input of the node
-
-        inp = context[node.input[0]]
-        assert str(inp.dtype) == "float32"
-        assert inp.shape == (1, ifm_ch, ifm_dim, ifm_dim)
-        reshaped_inp = inp.transpose(0, 2, 3, 1)
-        np.save(os.path.join(code_gen_dir, "input_0.npy"), reshaped_inp)
-        # execute the precompiled model
-        super().exec_precompiled_singlenode_model()
-        # load output npy file
-        super().npy_to_dynamic_output(context)
-        if self.get_output_datatype() == DataType.BIPOLAR:
-            out = context[node.output[0]]
-            out = 2 * out - 1
-            context[node.output[0]] = out
-        assert context[node.output[0]].shape == (1, out_pix, k * k, ifm_ch)
-        # reshape output to have expected shape
-        context[node.output[0]] = context[node.output[0]].reshape(
-            1, out_pix, k * k * ifm_ch
-        )
+        mode = self.get_nodeattr("sim_mode")
+        if mode == "npysim":
+            node = self.onnx_node
+            k = self.get_nodeattr("ConvKernelDim")
+            ifm_dim = self.get_nodeattr("IFMDim")
+            ifm_ch = self.get_nodeattr("IFMChannels")
+            ofm_dim = self.get_nodeattr("OFMDim")
+            out_pix = ofm_dim * ofm_dim
+            idt = self.get_input_datatype()
+            if idt == DataType.BIPOLAR:
+                # use binary for bipolar storage
+                idt = DataType.BINARY
+
+            # TODO ensure codegen dir exists
+            code_gen_dir = self.get_nodeattr("code_gen_dir_npysim")
+            # create a npy file for input of the node
+
+            inp = context[node.input[0]]
+            assert str(inp.dtype) == "float32"
+            assert inp.shape == (1, ifm_ch, ifm_dim, ifm_dim)
+            reshaped_inp = inp.transpose(0, 2, 3, 1)
+            np.save(os.path.join(code_gen_dir, "input_0.npy"), reshaped_inp)
+            # execute the precompiled model
+            super().exec_precompiled_singlenode_model()
+            # load output npy file
+            super().npy_to_dynamic_output(context)
+            if self.get_output_datatype() == DataType.BIPOLAR:
+                out = context[node.output[0]]
+                out = 2 * out - 1
+                context[node.output[0]] = out
+            assert context[node.output[0]].shape == (1, out_pix, k * k, ifm_ch)
+            # reshape output to have expected shape
+            context[node.output[0]] = context[node.output[0]].reshape(
+                1, out_pix, k * k * ifm_ch
+            )
+        elif mode == "rtlsim":
+            pass
+        else:
+            raise Exception(
+                """Invalid value for attribute sim_mode! Is currently set to: {}
+            has to be set to one of the following value ("npysim", "rtlsim")""".format(
+                    mode
+                )
+            )
 
     def global_includes(self):
         self.code_gen_dict["$GLOBALS$"] = ['#include "slidingwindow.h"']
diff --git a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py
index 450fdcd13..e32d8b765 100644
--- a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py
+++ b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py
@@ -12,6 +12,7 @@ from finn.transformation.fpgadataflow.codegen_ipgen import CodeGen_ipgen
 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_sim_mode import SetSimMode
 from finn.transformation.general import GiveUniqueNodeNames
 
 
@@ -145,7 +146,7 @@ def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride):
     model = make_single_slidingwindow_modelwrapper(
         k, ifm_ch, ifm_dim, ofm_dim, simd, stride, idt
     )
-
+    model = model.transform(SetSimMode("npysim"))
     model = model.transform(CodeGen_npysim())
     model = model.transform(Compile())
 
@@ -164,4 +165,5 @@ def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride):
     model = model.transform(GiveUniqueNodeNames())
     model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5))
     model = model.transform(HLSSynth_IPGen())
+    model = model.transform(SetSimMode("rtlsim"))
     model = model.transform(CleanUp())
-- 
GitLab