From 2298a5dc261c23b5a32468c6db00f598f0bd3c64 Mon Sep 17 00:00:00 2001 From: auphelia <jakobapk@web.de> Date: Tue, 10 Dec 2019 12:29:50 +0000 Subject: [PATCH] [Execution and Test] Added verification (and test) for xnorpopcountmatmul and streamingfclayer --- .../custom_op/verify_custom_op_construct.py | 66 ++++++++++++++++--- tests/test_verify_custom_ops.py | 63 +++++++++++++++++- 2 files changed, 117 insertions(+), 12 deletions(-) diff --git a/src/finn/custom_op/verify_custom_op_construct.py b/src/finn/custom_op/verify_custom_op_construct.py index c9ad0815c..07d47a959 100644 --- a/src/finn/custom_op/verify_custom_op_construct.py +++ b/src/finn/custom_op/verify_custom_op_construct.py @@ -3,27 +3,27 @@ from finn.core.utils import get_by_name class CustomOp_Construct(Enum): MultiThreshold = auto() - #XnorPopcountMatMul = auto() + XnorPopcountMatMul = auto() #StreamingMaxPool_Batch = auto() - #StreamingFCLayer_Batch = auto() + StreamingFCLayer_Batch = auto() - def verify_layout(self, node): + def verify_construct(self, node): assert self.verify_num_of_attr(node) == True, 'Number of attributes is not correct' assert self.verify_domain_is_finn(node) == True, 'Domain name is not "finn"' if self.name in ["StreamingMaxPool_Batch", "StreamingFCLayer_Batch"]: assert self.verify_backend_is_fpgadataflow(node) == True, 'Attribute backend has to be set to "fpgadataflow"' assert self.verify_all_attr(node) == True, 'The attributes are not correct' assert self.verify_num_of_inputs(node) == True, 'The number of inputs is wrong' - + def verify_num_of_attr(self, node): if self.name == "MultiThreshold": num_of_attr = 3 - #elif self.name == "XnorPopcountMatMul": - #num_of_attr = + elif self.name == "XnorPopcountMatMul": + num_of_attr = 0 #elif self.name == "StreamingMaxPool_Batch": #num_of_attr = - #elif self.name == "StreamingFCLayer_Batch": - #num_of_attr = + elif self.name == "StreamingFCLayer_Batch": + num_of_attr = 14 if len(node.attribute) == num_of_attr: return True else: @@ -40,7 +40,7 @@ class CustomOp_Construct(Enum): def verify_backend_is_fpgadataflow(self, node): #only for HLS CustomOp backend_value = get_by_name(node.attribute, "backend") - if backend_value == "fpgadataflow": + if backend_value.s.decode("UTF-8") == "fpgadataflow": return True else: return False @@ -54,6 +54,29 @@ class CustomOp_Construct(Enum): return True except: return False + + elif self.name == "XnorPopcountMatMul": + return True + #elif self.name == "StreamingMaxPool_Batch": + elif self.name == "StreamingFCLayer_Batch": + try: + get_by_name(node.attribute, "code_gen_dir") + get_by_name(node.attribute, "executable_path") + get_by_name(node.attribute, "resType") + get_by_name(node.attribute, "MW") + get_by_name(node.attribute, "MH") + get_by_name(node.attribute, "SIMD") + get_by_name(node.attribute, "PE") + get_by_name(node.attribute, "inputDataType") + get_by_name(node.attribute, "weightDataType") + get_by_name(node.attribute, "outputDataType") + get_by_name(node.attribute, "ActVal") + get_by_name(node.attribute, "binaryXnorMode") + get_by_name(node.attribute, "noActivation") + return True + except: + return False + def verify_num_of_inputs(self, node): if self.name == "MultiThreshold": @@ -61,6 +84,31 @@ class CustomOp_Construct(Enum): return True else: return False + elif self.name == "XnorPopcountMatMul": + if len(node.input) == 2: + return True + else: + return False + #elif self.name == "StreamingMaxPool_Batch": + elif self.name == "StreamingFCLayer_Batch": + # check noActivation value to determine the number of inputs + no_act = get_by_name(node.attribute, "noActivation") + no_act = no_act.i + + if no_act == 1: + if len(node.input) == 2: + return True + else: + return False + elif no_act == 0: + if len(node.input) == 3: + return True + else: + return False + else: + Exception("noActivation attribute contains {} should be 0 or 1".format(no_act)) + else: + Exception("CustomOp {} is not supported".format(node.op_type)) diff --git a/tests/test_verify_custom_ops.py b/tests/test_verify_custom_ops.py index 5d49303b0..c05278b1d 100644 --- a/tests/test_verify_custom_ops.py +++ b/tests/test_verify_custom_ops.py @@ -1,8 +1,9 @@ -import onnx +from onnx import helper from finn.custom_op.verify_custom_op_construct import CustomOp_Construct def test_verify_layout_custom_ops(): - m_node = onnx.helper.make_node( + # MultiThreshold + m_node = helper.make_node( "MultiThreshold", ["v", "thresholds"], ["out"], @@ -13,5 +14,61 @@ def test_verify_layout_custom_ops(): ) inst = CustomOp_Construct[m_node.op_type] - inst.verify_layout(m_node) + inst.verify_construct(m_node) + + # XnorPopcountMatMul + xnor_node = helper.make_node( + "XnorPopcountMatMul", ["x", "W"], ["out"], domain="finn" + ) + + inst = CustomOp_Construct[xnor_node.op_type] + inst.verify_construct(xnor_node) + + # StreamingFCLayer_Batch - no activation + FCLayer_node = helper.make_node( + "StreamingFCLayer_Batch", + ["in", "weights"], + ["out"], + domain="finn", + backend="fpgadataflow", + code_gen_dir="", + executable_path="", + resType="ap_resource_lut()", + MW=8, + MH=8, + SIMD=4, + PE=4, + inputDataType="<FINN DataType>", + weightDataType="<FINN DataType>", + outputDataType="<FINN DataType>", + ActVal=0, + binaryXnorMode=1, + noActivation=1 + + inst = CustomOp_Construct[FCLayer_node.op_type] + inst.verify_construct(FCLayer_node) + + # StreamingFCLayer_Batch - with activation + FCLayer_node = helper.make_node( + "StreamingFCLayer_Batch", + ["in", "weights", "threshs"], + ["out"], + domain="finn", + backend="fpgadataflow", + code_gen_dir="", + executable_path="", + resType="ap_resource_lut()", + MW=8, + MH=8, + SIMD=4, + PE=4, + inputDataType="<FINN DataType>", + weightDataType="<FINN DataType>", + outputDataType="<FINN DataType>", + ActVal=0, + binaryXnorMode=1, + noActivation=0 + ) + inst = CustomOp_Construct[FCLayer_node.op_type] + inst.verify_construct(FCLayer_node) -- GitLab