diff --git a/src/finn/custom_op/__init__.py b/src/finn/custom_op/__init__.py index 47806456f4493e9ced8d19f85e23460f9feedbb1..f7a34ebd3b00c1fe72e2504143fd9b4f33f819f9 100644 --- a/src/finn/custom_op/__init__.py +++ b/src/finn/custom_op/__init__.py @@ -81,5 +81,5 @@ class CustomOp(ABC): pass def verify_node(self): - inst = CustomOp_Construct[self.onnx_node.op_type] - inst.verify_construct(self.onnx_node) + inst = CustomOp_Construct[self.onnx_node.op_type] + inst.verify_construct(self.onnx_node) diff --git a/src/finn/custom_op/verify_custom_op_construct.py b/src/finn/custom_op/verify_custom_op_construct.py index 42ce2e6e2277b34be8a08ad91932ffe24106d639..28bf2dcd9e3668a84041974ecf7b16ef5520431a 100644 --- a/src/finn/custom_op/verify_custom_op_construct.py +++ b/src/finn/custom_op/verify_custom_op_construct.py @@ -1,6 +1,8 @@ from enum import Enum, auto + from finn.core.utils import get_by_name + class CustomOp_Construct(Enum): MultiThreshold = auto() XnorPopcountMatMul = auto() @@ -8,12 +10,14 @@ class CustomOp_Construct(Enum): StreamingFCLayer_Batch = auto() 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"' + self.verify_num_of_attr(node) + assert self.verify_domain_is_finn(node) is 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' + assert ( + self.verify_backend_is_fpgadataflow(node) is True + ), 'Attribute backend has to be set to "fpgadataflow"' + self.verify_all_attr(node) + self.verify_num_of_inputs(node) def verify_num_of_attr(self, node): if self.name == "MultiThreshold": @@ -30,7 +34,11 @@ class CustomOp_Construct(Enum): if len(node.attribute) == num_of_attr: return True else: - return False + Exception( + "Your {} nod has {} attributes, need {} attributes!".format( + node.op_type, len(node.attribute), num_of_attr + ) + ) def verify_domain_is_finn(self, node): domain_value = node.domain @@ -41,7 +49,7 @@ class CustomOp_Construct(Enum): return False def verify_backend_is_fpgadataflow(self, node): - #only for HLS CustomOp + # only for HLS CustomOp backend_value = get_by_name(node.attribute, "backend") if backend_value.s.decode("UTF-8") == "fpgadataflow": return True @@ -55,8 +63,11 @@ class CustomOp_Construct(Enum): get_by_name(node.attribute, "out_bias") get_by_name(node.attribute, "out_dtype") return True - except: - return False + except AttributeError: + Exception( + """MultiThreshold needs the following attributes: + out_scale, out_bias, out_dtype""" + ) elif self.name == "XnorPopcountMatMul": return True @@ -68,8 +79,11 @@ class CustomOp_Construct(Enum): get_by_name(node.attribute, "PoolDim") get_by_name(node.attribute, "NumChannels") return True - except: - return False + except AttributeError: + Exception( + """StreamingMaxPool_Batch needs the following attributes: + code_gen_dir, executable_path, ImgDim, PoolDim, NumChannels""" + ) elif self.name == "StreamingFCLayer_Batch": try: @@ -87,45 +101,57 @@ class CustomOp_Construct(Enum): get_by_name(node.attribute, "binaryXnorMode") get_by_name(node.attribute, "noActivation") return True - except: - return False + except AttributeError: + Exception( + """StreamingFCLayer_Batch needs the following attributes: + code_gen_dir, executable_path, resType, MW, MH, SIMD, PE, + inputDataType, weightDataType, outputDataType, ActVal, + binaryXnorMode, noActivation""" + ) - def verify_num_of_inputs(self, node): if self.name == "MultiThreshold": if len(node.input) == 2: return True else: - return False + Exception( + """MultiThreshold needs 2 inputs + (data input and threshold values)""" + ) elif self.name == "XnorPopcountMatMul": if len(node.input) == 2: return True else: - return False + Exception("XnorPopcountMatMul needs 2 data inputs") elif self.name == "StreamingMaxPool_Batch": if len(node.input) == 1: return True else: - return False + Exception("StreamingMaxPool_Batch needs 1 data input") 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 + Exception( + """StreamingFCLayer_Batch needs in no + activation mode 2 inputs (data input and weights)""" + ) elif no_act == 0: if len(node.input) == 3: return True else: - return False + Exception( + """StreamingFCLayer_Batch needs 3 inputs + (data input and weights and threshold values)""" + ) else: - Exception("noActivation attribute contains {} should be 0 or 1".format(no_act)) + 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 dd54c5312f6f370fe08b05d7189dfa1b6cd5547a..c242afa230c2e8142c293c29f667150625dae8a0 100644 --- a/tests/test_verify_custom_ops.py +++ b/tests/test_verify_custom_ops.py @@ -1,6 +1,8 @@ from onnx import helper + from finn.custom_op.verify_custom_op_construct import CustomOp_Construct + def test_verify_layout_custom_ops(): # MultiThreshold m_node = helper.make_node( @@ -11,10 +13,10 @@ def test_verify_layout_custom_ops(): out_scale=2.0, out_bias=-1.0, out_dtype="", - ) + ) - inst = CustomOp_Construct[m_node.op_type] - inst.verify_construct(m_node) + inst = CustomOp_Construct[m_node.op_type] + inst.verify_construct(m_node) # XnorPopcountMatMul xnor_node = helper.make_node( @@ -40,9 +42,7 @@ def test_verify_layout_custom_ops(): inst = CustomOp_Construct[MaxPool_batch_node.op_type] inst.verify_construct(MaxPool_batch_node) - - - + # StreamingFCLayer_Batch - no activation FCLayer_node = helper.make_node( "StreamingFCLayer_Batch", @@ -64,7 +64,7 @@ def test_verify_layout_custom_ops(): binaryXnorMode=1, noActivation=1, ) - + inst = CustomOp_Construct[FCLayer_node.op_type] inst.verify_construct(FCLayer_node) @@ -87,8 +87,7 @@ def test_verify_layout_custom_ops(): outputDataType="<FINN DataType>", ActVal=0, binaryXnorMode=1, - noActivation=0 + noActivation=0, ) inst = CustomOp_Construct[FCLayer_node.op_type] inst.verify_construct(FCLayer_node) -