# Defining a UDO

A User-Defined Operation (UDO) allows users to integrate their
custom operations with Qualcomm® Neural Processing SDK to enable execution on any
supported hardware accelerator. The UDO mechanism accepts a
specification of a custom operation (defined below), and
processes that information to process a model containing that
custom operation. This section explains how such a UDO can be
specified. See [Overview of UDO](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_overview.html) for more
details about UDO and [Preparing a model with
UDO](https://docs.qualcomm.com/doc/80-63442-10/topic/preparing_model_with_udo.html) for details on how to
convert a model that contains a UDO into a Qualcomm® Neural Processing SDK DLC for
supported frameworks.

The UDO Configuration Specification

As described in the [Overview of UDO](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_overview.html)
section, a user can express the attributes of their custom
operation with a configuration specification file. This UDO
configuration (henceforth known as UDO config) is a description
of the operation that can be created using the Extensible Markup
Language (XML) (henceforth known as XML OpDef Config) or the
Javascript Object Notation (JSON) syntax and formatting
(henceforth known as JSON UDO Config). The configuration file syntax
defines fields that describe the UDO Operation information.
The fields are pre-determined and will ultimately be
parsed into the required information that constitutes a UDO.
The information provided should be generic and independent of a
particular model, meaning model-specific parameters or names
need not be part of the configuration. The information will be
used to identify the op within a framework model, and then
ultimately serialized into the DLC model. This implies that any
changes in the config would require re-generation of the DLC
model to ensure the correct information is serialized.
The following sections describe the configuration file specification.

The XML OpDef Config Description

The XML OpDef Config describes the operations the package contains as well as the package
information such as the package name, version, and domain. Package information and
operations are described with respect to a predefined XML schema (described below), that
requires information about operation inputs, outputs, and parameters.

The XML OpDef Schema Breakdown

This section provides an overview of the schema used to define
Operation Definitions (Op Defs) in the XML OpDef Config. Op Defs
specify the inputs, outputs, parameters, and descriptive metadata
that constitute an operation. The schema is formalized using
Extensible Markup Language (XML) and XML Schema Definition (XSD).

Operation Definition Schema

The following diagram describes the relationship between these Op Def entities.

![../images/OpDefUml.png](data:image/png;base64,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)

In the above OpDef Schema diagram members prefixed by @ are XML attributes and those with
no prefix are XML elements.

OpDef

An OpDef is an XML element that describes an operation at thehighest level. It contains
the following elements. Elements with content are required and elements that are empty are
optional.

<OpDef>
         <Name>OpName</Name>
    
         <Description>
             <Content></Content>
             <Code></Code>
         </Description>
    
         <Reference Source="" Url=""></Reference>
    
         <!--Requires at least one input-->
         <Input>
             <Name>in[0]</Name>
             <Mandatory>true</Mandatory>
             <Constraint id="" Type=""></Constraint>
             <Datatype>FLOAT_32</Datatype>
             <Shape>
                 <Rank>1D</Rank>
                 <Layout></Layout>
                 <Text></Text>
             </Shape>
             <Default></Default>
             <Repeated></Repeated>
             <IsStaticTensor></IsStaticTensor>
         </Input>
    
         <!--Requires at least one output-->
         <Output>
             <Name>out[0]</Name>
             <Mandatory>true</Mandatory>
             <Constraint id="" Type=""></Constraint>
             <Datatype>FLOAT_32</Datatype>
             <Shape>
                 <Rank>1D</Rank>
                 <Layout></Layout>
                 <Text></Text>
             </Shape>
             <Repeated></Repeated>
         </Output>
    
         <!--Parameters are optional-->
         <Parameter>
             <Name>param</Name>
             <Mandatory>false</Mandatory>
             <Constraint id="" Type=""></Constraint>
             <Datatype>INT_32</Datatype>
             <Shape>
                 <Rank>1D</Rank>
                 <Layout></Layout>
                 <Text></Text>
             </Shape>
             <Default></Default>
             <Enumeration>
                 <Enum></Enum>
             </Enumeration>
         </Parameter>
    
         <UseDefaultTranslation></UseDefaultTranslation>
         <SupportedBackend>DSP_V68</SupportedBackend>
     </OpDef>
    Copy to clipboard

- **Name:** The name of the operation.
- **Description:** Optional; describes the operation through sequences of content and code.

> 
> 
> - **Content:** String describing the operation.
>     - **Code:** String that represents code describing the operation,
> e.g., output\_height = input\_height - crop\_top - crop\_bottom
- **Reference:** Optional; defines one or more references for the operation.

> 
> 
> - **Source:** Attribute for the source of operation.
> E.g. Tensorflow, ONNX, etc.
>     - **Url:** Attribute for the URL of the source.
- **Input:** Defines one or more inputs to the operation.
Inputs are extensions of [Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#op-def-tensor) that have
the following additional field(s):.

> 
> 
> - **IsStaticTensor:** Optional boolean flag that if set
> to True, indicates that an input tensor is a parameter
> which contains or references static data. If unset,
> the tensor is treated as a dynamic input.
>     - **Repeated:** Optional boolean that specifies whether
> this input is repeated. Used for operations which have
> variadic inputs, such as Concat. ^7^
- **Output:** Defines one or more outputs to the operation. Outputs
are extensions of [Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#op-def-tensor)  that have the
following additional field(s):

> 
> 
> - **Repeated:** Optional boolean that specifies whether this
> output is repeated. Used for operations which have variadic
> outputs, such as MultiClassNms. ^7^
- **Parameter:** Optional; defines one or more parameters for
the operation. Parameters are extensions of [Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#op-def-tensor) that
additionally define.

> 
> 
> - **Enumeration:** Optional field for enumerated params.
> Enumerations are composed of subfields called Enum whose
> content gives the name of the enum representing a given value.
> Values are assigned in the order in which the Enum is specified.
- **SupportedBackend:** Field(s) that specify one or more backends
on which this operation is supported. Used when backends share a
common definition of an operation. If fields vary across backend
for the same operation use [SupplementalOpDef](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-opdef)
and mark the field with BACKEND\_SPECIFIC.
- **UseDefaultTranslation:** Boolean field that if set to true,
indicates that a custom operation overrides a QNN native operation.
The custom operation type must match the type of the QNN native
operation for accurate conversion. When set to false, a custom
operation is converted as a generic user defined operation. In the
false mode, the custom op type must match the source framework type.

A key component of creating an OpDef are Inputs, Outputs, and
Parameters, all of which are extensions of Tensors. A Tensor
element is defined as follows:

- **Name:** The name of the tensor.
- **Description:** Optional: describes the operation through sequences of content and code:

> 
> 
> - **Content:** String describing the operation.
>     - **Code:** String that represents code describing the tensor.
> e.g. output\_height = input\_height - crop\_top - crop\_bottom
- **Constraint:** Optional: defines one or more constraints
on the given tensor. The constraint is given as a string in the body
of the element. ^8^

> 
> 
> - **id:** Specifies the ID of the constraint. Used to override constraints for
> supplemental operation definitions.
>     - **Type:** The type of the constraint. Valid types are:
> 
> 
> 
> > 
> > 
> > - **Number:** a constraint characterized by cardinality,
> > e.g., Number of inputs &gt;= 1
> >         - **Shape:** a constraint characterized by a restriction
> > on dimension of the tensor, e.g., Rank &gt;= 1
> >         - **Value:** a constraint characterized by the value of
> > the tensor, e.g., Tensor is only positive.
> >         - **Datatype:** a constraint characterized by a restriction
> > on datatype. Typically used for tensors which can be of several
> > datatypes but must be of the same datatype as another tensor.
> >         - **Description:** a constraint which does not conform to any
> > other category of constraint.
- **Mandatory:** Boolean; indicates if the tensor must be provided/defined. ^9^
- **Datatype:** Defines the allowable datatypes for the tensor.
Must be one of:

> 
> 
> - FLOAT\_16
>     - FLOAT\_32
>     - FIXED\_4
>     - FIXED\_8
>     - FIXED\_16
>     - UINT\_8
>     - UINT\_16
>     - UINT\_32
>     - STRING
>     - BACKEND\_SPECIFIC used to indicate that the datatype is
> dependent on the Backend. Must be used in conjunction
> with a [SupplementalOpDef](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-opdef) to specify a concrete datatype.
- **Shape:** Specifies the shape of the tensor.

> 
> 
> - **Rank:** The rank of the tensor as an enumeration with the following values:
> 
> 
> 
> > 
> > 
> > - SCALAR: Scalar
> >         - 1D: Vector
> >         - 2D: Matrix
> >         - 3D: 3D Tensor or Image
> >         - 4D: 4D Tensor or Batched Image
> >         - ND: Generic N-D Tensor N &gt;= 0
>     - **Layout:** Optional; specifies the layout of the tensor. Must be one of:
> 
> 
> 
> > 
> > 
> > - NHWC
> >         - NHCW
> >         - UNDEFINED used to identify that the layout is neither NHCW or NHWC
> >         - BACKEND\_SPECIFIC used to indicate that the layout is dependent
> > on the Backend. Must be used in conjunction with a
> > [SupplementalOpDef](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-opdef) to specify a concrete layout.
>     - **Text:** Optional; string description for the shape of the tensor.
- **Default:** Optional; string representing the default value for the tensor. Can be one of

> 
> 
> - Tensor: use braces or brackets to create list e.g. [[1, 2], [3, 4]]
>     - Scalar: provide scalar value e.g. 1, 1.1, -1
>     - Boolean: provide either 0 (false) or 1 (true)
>     - String: any other string. If text cannot be resolved into one of
> above categories it will be stored as string.

SupplementalOpDef

SupplementalOpDef’s are XML elements which define content that is variable
across backend(s). SupplementalOpDef’s extend the content defined in
OpDefs, but limits the fields that can be overridden. The SupplementalOpDef
is structured as follows. Elements with content are required, and elements
that are empty are optional.

<SupplementalOpDef>
    
          <Name>OpName</Name>
    
         <!--Only supplemented Inputs are required-->
          <Input>
              <Name>in[0]</Name>
              <Constraint id="" Type=""></Constraint>
              <Datatype></Datatype>
              <Shape>
                  <Layout></Layout>
                  <Text></Text>
              </Shape>
              <OnlyDefaultSupported></OnlyDefaultSupported>
          </Input>
    
           <!--Only supplemented Outputs are required-->
          <Output>
              <Name>out[0]</Name>
              <Constraint id="" Type=""></Constraint>
              <Datatype></Datatype>
              <Shape>
                  <Layout></Layout>
                  <Text></Text>
              </Shape>
              <OnlyDefaultSupported></OnlyDefaultSupported>
          </Output>
    
           <!--Only supplemented Params are required-->
          <Parameter>
              <Name>param</Name>
              <Constraint id="" Type=""></Constraint>
              <Datatype></Datatype>
              <Shape>
                  <Layout></Layout>
                  <Text></Text>
              </Shape>
              <OnlyDefaultSupported></OnlyDefaultSupported>
          </Parameter>
    
    </SupplementalOpDef>
    Copy to clipboard

- **Name:** The name of the operation.
- **Input:** Optional; extends one or more inputs to the
operation. Supplemental inputs are [Supplemental Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-tensor).
- **Output:** Optional; extends one or more outputs to the
operation. Supplemental outputs are [Supplemental Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-tensor).
- **Parameter:** Optional; extends one or more parameters for
the operation. Supplemental parameters are
[Supplemental Tensors](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-tensor).

Inputs, outputs, and parameters are all Supplemental Tensors,
which can only specify certain fields. All fields, except name,
in a supplemental tensor are optional.

- **Name:** The name of the tensor. Must correspond to the name
of the tensor in the original OpDef that is being extended.
- **Constraint:** Optional; defines one or more
constraints on the given tensor. The constraint is given
as a string in the body of the element. ^8^

> 
> 
> - **id:** Specifies the ID of the constraint. Used
> to override constraints for supplemental operation definitions.
>     - **Type:** The type of the constraint. Valid types are:
> 
> 
> 
> > 
> > 
> > - **Number:** a constraint characterized by cardinality.
> > e.g. Number of inputs &gt;= 1
> >         - **Shape:** a constraint characterized by a restriction
> > on dimension of the tensor. e.g. Rank &gt;= 1
> >         - **Value:** a constraint characterized by the value of
> > the tensor. e.g. Tensor is only positive.
> >         - **Datatype:** a constraint characterized by a restriction
> > on datatype. Typically used for tensors which can be of several
> > datatypes but must be of the same datatype as another tensor.
> >         - **Description:** a constraint which does not conform to any
> > other category of constraint.
- **Datatype:** Defines the allowable datatypes for the tensor.
Must be one of:

> 
> 
> - FLOAT\_16
>     - FLOAT\_32
>     - FIXED\_4
>     - FIXED\_8
>     - FIXED\_16
>     - UINT\_8
>     - UINT\_16
>     - UINT\_32
>     - STRING
- **Shape:** Specifies the shape of the tensor.

> 
> 
> - **Layout:** Optional; specifies the layout of the tensor. Must be one of:
> 
> 
> 
> > 
> > 
> > - NHWC
> >         - NHCW
> >         - UNDEFINED used to identify that the layout is neither NHCW or NHWC
> >         - BACKEND\_SPECIFIC used to indicate that the layout is dependent
> > on the Backend. Must be used in conjunction with a SupplementalOpDef
> > to specify a concrete layout.
>     - **Text:** Optional; string description for the shape of the tensor.
- **OnlyDefaultSupported:** Optional; boolean that indicates if the backend only
supports the default value defined in the corresponding OpDef for this tensor.

OpDefList

An OpDefList is an XML element composed of a sequence of [OpDef](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#opdef)
elements. OpDefLists are backend agnostic and only serve as a wrapper
around multiple OpDefs.

<OpDefList>
    
        <!--One or more OpDef-->
        <OpDef>
          <!--OpDef defined above -->
        </OpDef>
    
    </OpDefList>
    Copy to clipboard

SupplementalOpDefList

A SupplementalOpDefList is an XML element composed of a sequence of
[SupplementalOpDef](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-opdef) elements. In addition,
SupplementalOpDefLists contain the following fields.

<SupplementalOpDefList Backend="HTP">
    
       <SupportedOps>
          <OpName></OpName>
       </SupportedOps>
    
       <SupplementalOpDef>
          <!--SupplementalOpDef defined above-->
       </SupplementalOpDef>
    
    </SupplementalOpDefList>
    Copy to clipboard

- **Backend:** Specifies which backend the SupplementalOpDef’s are supplementing.
- **SupportedOps:** Sequence of OpName elements.
Each OpName corresponds to an operation defined in the corresponding
OpDefList and indicates the backend supports the operation. This information
may be redundant with the SupportedBackend field of the OpDef element.

OpDefCollection

The OpDefCollection is the root XML element of the configuration file meant to
be used with the snpe-udo-package-generator. It contains all the information needed
to specify all of a users packages. The OpDefCollection contains the following

<OpDefCollection
         xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
         xs:noNamespaceSchemaLocation="OpDef.xsd"
         PackageName="ExamplePackage"
         Domain="example"
         Version="1.0"
    >
    
       <!--One OpDefList-->
       <OpDefList>
          <!--OpDefList defined above-->
       </OpDefList>
    
       <!--SupplementalOpDefLists are not required-->
       <SupplementalOpDefList Backend="HTP">
          <!--SupplementalOpDefList defined above-->
       </SupplementalOpDefList>
    
    </OpDefCollection>
    Copy to clipboard

- **PackageName:** Specifies the name for the user’s OpPackage.
Because packages are per backend, the actual package name will be the
value specified here appended with &lt;Backend&gt; e.g. MyPackageNameHtp.
- **Domain:** Specifies the domain of the package.
- **Version:** Specifies the version of the package.
- **OpDefList:** One [OpDefList](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#opdef-list) specifying all operations for the package(s).
- **SupplementalOpDefList:** Optional; specifies one or more [SupplementalOpDefList](https://docs.qualcomm.com/doc/80-63442-10/topic/udo_operator_definition.html#supplemental-opdef-list)
to specify per-backend information.

One OpDefCollection element can be used to produce multiple per-backend packages.

The JSON UDO Config Description

The details of the aforementioned UDO config file can be
described below.

{
        "UdoPackage_0":
        {
            "Operators": [
                {
                    "type": "",
                    "inputs":[
                        {"name":"", "per_core_data_types":{"CPU":"FLOAT_32", "GPU":"FLOAT_32", "DSP":"UINT_8"},
                        "static": true, "tensor_layout": "NHWC"},
                        {"name":"", "data_type": "FLOAT_32",
                        "static": true, "tensor_layout": "NHWC"},
                    ],
                    "outputs":[
                        {"name":"", "per_core_data_types":{"CPU":"FLOAT_32", "GPU":"FLOAT_32", "DSP":"UINT_8"}},
                        {"name":"", "data_type": "FLOAT_32"}
                    ],
                    "scalar_params": [
                        {"name":"scalar_param_1", "data_type": "INT_32"}
                    ],
                    "tensor_params": [
                        {"name":"tensor_param_1", "data_type": "FLOAT_32", "tensor_layout": "NHWC"},
                    ],
                    "core_types": ["CPU", "GPU", "DSP"],
                    "dsp_arch_types": ["v66", "v68", "v69", "v73"]
                }
            ],
            "UDO_PACKAGE_NAME": "MyCustomUdoPackage"
        }
    }
    Copy to clipboard

The above description is simply a generic configuration file to
aid the definition of the fields that the user can fill.
Required fields are provided with a specific value, while
optional fields are denoted with empty strings. Note that an
optional field only implies that there is either a default
value if it is not provided, or that an empty string will be
used. The full details of each available field is described
hierarchically below:

- **UdoPackage:** Every UDO package can be described as
*“UdoPackage\_i”* where *i* indicates the order in which the
packages will be generated. The user is also free to use
empty strings but the dictionary structure is
necessary.^1^
- **Operators:** This is a child node of a particular
UdoPackage indicating the number of operators present.
^5^

    - **type:** defines the type of the operation.
    - **inputs:** a list of input tensors to the operation.
Each input is a dictionary object. ^2^

        - **name:** An optional field that describes the name of
the input tensor. Since the name of the input tensor
is variable, the user is not required to provide this.
        - **per\_core\_data\_type:** A dictionary object specifying
the data-type of this input tensor in each core.
Alternatively, if the user wishes to have the same
data-type across all specified cores, then the user
can specify the option “data\_type” followed by the
data-type. The supported data-types are:

            - FLOAT\_16
            - FLOAT\_32
            - FIXED\_4
            - FIXED\_8
            - FIXED\_16
            - UINT\_8
            - UINT\_16
            - UINT\_32
            - STRING
        - **static:** A boolean field that is required if the
input data is static, i.e data is provided in the
model. This field needs to be set if the input tensor
will contain data, otherwise the input will be treated
dynamically, and the data will not be serialized.
        - **tensor\_layout:** A string field that describes the
canonical dimension format of the input tensor. The
supported values are: ^4^

            - NCHW
            - NHWC
    - **outputs:** A list of output tensors to the
operation.^2^
    - **scalar\_params:** A list of scalar-valued
attributes.^3^

        - **name:** A required field that describes the name of
the scalar parameter.
        - **data\_type:** A required field that describes the
data-type supported by this scalar parameter.
    - **tensor\_params:** A list of tensor-valued
attributes.^2^ ^3^
    - **core\_types:** The intended IP cores for this particular
operation. The supported core\_types:

        - CPU
        - GPU
        - DSP
    - **dsp\_arch\_types:** The intended DSP architecture types
for DSP core type. The supported dsp\_arch\_types:

        - v65
        - v66
        - v68
        - v69
        - v73
- **UDO\_PACKAGE\_NAME:** The name of the UDO Package, which can
be any valid string.^1^

Creating a UDO config

The user should aim to fill out the fields described in the
config above to adequately describe a UDO. In some cases, the
information required in this config could be easily obtained
from framework documentation about the operation. However,
there may be subtle caveats, therefore the user is encouraged
to ensure that inputs, outputs and params are properly
categorized and described. A potential caveat is that inputs
can be mis-categorized as parameters and vice versa, if the
config is written only according to documentation. In this
scenario, a useful tip is to visualize the model using an open
source tool such as Netron (found here:
[https://github.com/lutzroeder/netron](https://github.com/lutzroeder/netron)) to assist with crafting
the UDO config correctly.

Once an adequately descriptive config has been created, it can
be used as an argument to the framework converters as described
in [Preparing a model with
UDO](https://docs.qualcomm.com/doc/80-63442-10/topic/preparing_model_with_udo.html).

**Notes:**

1. More than one UDO package can be defined in a single config
file. Users should note that the package name specified here
must match the package name used in creating the
corresponding package.
2. Each input, output and tensor parameter is categorized as
the same kind of tensor object, meaning that all the fields
are shared. The names of inputs and outputs are not required
since the config is a generic description of an operation.
An operator must have at least one input and output.
3. In the case of the parameters, the name field is always
required.
4. The tensor layout is a convention to indicate the
arrangement of data within the tensor. Therefore a tensor
layout of **NHWC** means that the data is organized in
`(batch x height x width x channel)`, where channel is the
fastest changing dimension. Note this is the default
arrangement for Qualcomm® Neural Processing SDK, and that
may have implications on a model containing a UDO if other
tensor layouts are selected. Notably, if a tensor layout of
**NCHW** is selected, then the data and/or tensor parameters
may need to be reshaped to the Qualcomm® Neural Processing
SDK default to maintain dimensional understanding. Should the
user encounter this scenario, they may notice the introduction
of intermediary permute layers prior to the UDO layer which
will ultimately feed the tensors in question.
These caveats should be visible as either converter
warnings, debug messages or through outputs of the
visualization tools described in [Tools](https://docs.qualcomm.com/doc/80-63442-10/topic/SNPE_general_tools.html). For
more details on tensor layouts, the user can consult the
section: [Input Image Formatting](https://docs.qualcomm.com/doc/80-63442-10/topic/image_input.html) of
the documentation.
5. For CPU, GPU and DSP coretypes, there can be an arbitrary
number of operators defined per UDO package. However the
provided skeleton code is tailored to define only one
operation in one package. One subtle distinction is that the
generated DSP V65 or DSP V66 implementation source code
expects one operation per implementation library. While in
the CPU, GPU, and DSP V68 or later cases, there may be an
arbitrary number of operations in a library.
6. The data-type of a tensor determines both how the data
contained in the tensor will be stored in the DLC, and the
type of memory handed over by Qualcomm® Neural
Processing SDK during runtime execution. While tensors
get stored within the DLC in the exact data-type specified
by the UDO definition, there may be runtime restrictions
on the type of memory users can expect to receive depending
on the chosen core-type. Users should visit the following
section: [Compiling a UDO package](https://docs.qualcomm.com/doc/80-63442-10/topic/compiling_udo_package.html)
for more details.
7. Operations with an unknown number of inputs/outputs are
currently not supported on the DSP and HTP backend.
8. Constraints are purely a descriptive field and do not require
mathematical expression. Constraints are currently not enforced.
9. Outputs are not mandatory, but cannot have default values and
are assumed to be NULL if not provided.

Last Published: Jun 04, 2026

[Previous Topic
Overview of UDO](https://docs.qualcomm.com/bundle/publicresource/80-63442-10/topics/udo_overview.md) [Next Topic
Defining a UDO Package](https://docs.qualcomm.com/bundle/publicresource/80-63442-10/topics/udo_package_definition.md)