Custom Op
Submodules
Custom Op Nodes
Base Class
- class qonnx.custom_op.base.CustomOp(onnx_node: NodeProto, onnx_opset_version: int = 1)
Bases:
ABCCustomOp class all custom op nodes are based on. Contains different functions every custom node should have. Some as abstract methods, these have to be filled when writing a new custom op node.
- Opset Version Support:
CustomOp classes use “since version” semantics matching ONNX operators. Version is determined by the class name using _vN suffix convention:
No suffix (e.g., IntQuant): Version 1 (default)
_vN suffix (e.g., IntQuant_v2): Version N
The registry automatically selects the highest version <= requested opset.
- Example:
- class IntQuant(CustomOp):
pass # Version 1 (no suffix)
- class IntQuant_v2(CustomOp):
pass # Version 2, covers opset v2-v3 (if no v3 exists)
- class IntQuant_v4(CustomOp):
pass # Version 4, covers opset v4+
- abstract execute_node(context: dict[str, ndarray[Any, dtype[_ScalarType_co]]], graph: GraphProto) None
Execute this CustomOp instance, given the execution context and ONNX graph.
- get_nodeattr(name: str) int | float | str | bool | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float] | None
Get a node attribute by name. Data is stored inside the ONNX node’s AttributeProto container. Attribute must be part of get_nodeattr_types. Default value is returned if attribute is not set.
- get_nodeattr_allowed_values(name: str) str | bool | int | float | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float] | set | None
Return set of allowed values for given attribute, None if not specified.
- get_nodeattr_def(name: str) tuple[str, bool, int | float | str | bool | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float], set | None]
Return 4-tuple (dtype, required, default_val, allowed_values) for attribute with name. allowed_values will be None if not specified.
- abstract get_nodeattr_types() Mapping[str, tuple[str, bool, int | float | str | bool | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float]] | tuple[str, bool, int | float | str | bool | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float], set | None]]
Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
- abstract infer_node_datatype(model: ModelWrapper) None
Set the DataType annotations corresponding to the outputs of this node.
- make_const_shape_op(shape: Sequence[int] | ndarray[Any, dtype[_ScalarType_co]]) NodeProto
Return an ONNX node that generates the desired output shape for shape inference.
- abstract make_shape_compatible_op(model: ModelWrapper) NodeProto
Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
- set_nodeattr(name: str, value: int | float | str | bool | ndarray[Any, dtype[_ScalarType_co]] | list[str | int | float] | None) None
Set a node attribute by name. Data is stored inside the ONNX node’s AttributeProto container. Attribute must be part of get_nodeattr_types.
- abstract verify_node() None
Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
qonnx.custom_op.registry
- qonnx.custom_op.registry.add_domain_alias(domain: str, module_path: str) None
Map a domain name to a different module path.
- Args:
domain: The ONNX domain name (e.g., “finn.custom_op.fpgadataflow”) module_path: The Python module path to use instead (e.g., “finn_custom_ops.fpgadataflow”)
- qonnx.custom_op.registry.add_op_to_domain(domain: str, op_class: Type[CustomOp]) None
Register a custom op directly to a domain at runtime.
The op_type and version are automatically derived from the class name. Useful for testing and experimentation. For production, define CustomOps in the appropriate module file.
- Args:
domain: ONNX domain name (e.g., “qonnx.custom_op.general”) op_class: CustomOp subclass (version inferred from name)
- Example:
add_op_to_domain(“qonnx.custom_op.general”, MyTestOp) # v1 add_op_to_domain(“qonnx.custom_op.general”, MyTestOp_v2) # v2
- qonnx.custom_op.registry.getCustomOp(node: NodeProto, onnx_opset_version: int | None = None) CustomOp
Get a custom op instance for an ONNX node.
Uses “since version” semantics: selects highest version <= requested opset. Lazy loads only the requested op_type using __all__ for efficiency.
- Args:
node: ONNX node with domain and op_type attributes onnx_opset_version: Opset version from model’s opset_import, or None for highest
- Returns:
CustomOp instance for the node
- Raises:
KeyError: If op_type not found in domain or no suitable version available
- qonnx.custom_op.registry.get_ops_in_domain(domain: str) List[Tuple[str, Type[CustomOp]]]
Get all CustomOp classes available in a domain.
Note: Returns unique op_types. If multiple versions exist, returns the highest version. This function eagerly loads all ops in the domain.
- Args:
domain: ONNX domain name (e.g., “qonnx.custom_op.general”)
- Returns:
List of (op_type, op_class) tuples
- Example:
ops = get_ops_in_domain("qonnx.custom_op.general") for op_name, op_class in ops: print(f"{op_name}: {op_class}")
- qonnx.custom_op.registry.get_supported_versions(domain: str, op_type: str) List[int]
Get list of supported opset versions for a custom op.
Returns all “since versions” where the operator was introduced or changed.
- Args:
domain: ONNX domain name op_type: Operation type name
- Returns:
Sorted list of opset versions
- Raises:
KeyError: If op not found
- qonnx.custom_op.registry.hasCustomOp(domain: str, op_type: str) bool
Deprecated: Use is_custom_op instead.
Check if a custom op exists.
- Args:
domain: The ONNX domain name op_type: The operation type name
- Returns:
True if the op exists, False otherwise
- qonnx.custom_op.registry.is_custom_op(domain: str, op_type: str | None = None) bool
Check if a custom op exists or if a domain has any custom ops.
- Args:
domain: The ONNX domain name op_type: Optional operation type name. If None, checks if domain has any ops.
- Returns:
True if the specific op exists (when op_type given) or if any ops exist for the domain (when op_type=None), False otherwise
- qonnx.custom_op.registry.resolve_domain(domain: str) str
Resolve a domain to its actual module path, handling aliases.
- Args:
domain: The ONNX domain name
- Returns:
Resolved module path