// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #pragma once #include #include {% if op.data_fields_helper is defined and op.data_fields_helper %} #include {% endif %} #include #include #include #include namespace hipdnn_frontend::detail { [[nodiscard]] inline Error {{ op.frontend.unpacker_function }}( hipdnnBackendDescriptor_t opDesc, std::unordered_map>& tensorMap, graph::{{ op.frontend.attributes_class }}& attributes) { {% for tf in op.tensor_fields %} {% set ft = op.tensor_field_frontend_map.get(tf.name) %} {% if ft %} // Unpack {{ ft.name }} tensor std::shared_ptr {{ ft.camel_name }}Tensor; {% if tf.required %} HIPDNN_CHECK_ERROR(unpackAndRegisterTensor( opDesc, {{ op.operation_attr_prefix }}_{{ tf.attr_suffix }}, tensorMap, {{ ft.camel_name }}Tensor, "{{ op.effective_error_label }} {{ tf.attr_suffix }} tensor")); attributes.{{ ft.effective_setter_name }}({{ ft.camel_name }}Tensor); {% else %} HIPDNN_CHECK_ERROR(unpackOptionalTensor( opDesc, {{ op.operation_attr_prefix }}_{{ tf.attr_suffix }}, tensorMap, {{ ft.camel_name }}Tensor, "{{ op.effective_error_label }} {{ tf.attr_suffix }} tensor")); if({{ ft.camel_name }}Tensor) { attributes.{{ ft.effective_setter_name }}({{ ft.camel_name }}Tensor); } {% endif %} {% endif %} {% endfor %} {% if op.data_fields_helper is defined and op.data_fields_helper %} // Unpack shared {{ op.data_fields_helper.label }} parameters HIPDNN_CHECK_ERROR({{ op.data_fields_helper.unpack_function }}(opDesc, attributes, "{{ op.effective_error_label }}")); {% else %} {% for df in op.data_fields %} {% if df.is_vector %} // Unpack {{ df.name }} std::vector {{ df.camel_name }}; HIPDNN_CHECK_ERROR(getDescriptorAttrVec( opDesc, {{ df.attr_name }}, {{ df.camel_name }}, "{{ op.effective_error_label }} {{ df.name }}")); {% if df.frontend_uses_member_access %} attributes.{{ df.frontend_member_name }} = std::move({{ df.camel_name }}); {% else %} attributes.{{ df.frontend_setter_name }}(std::move({{ df.camel_name }})); {% endif %} {% elif df.is_mode %} // Unpack {{ df.name }} {{ df.test_c_type }} {{ df.camel_name }}{}; HIPDNN_CHECK_ERROR(getDescriptorAttrScalar(opDesc, {{ df.attr_name }}, {{ df.backend_type }}, {{ df.camel_name }}, "{{ op.effective_error_label }} {{ df.name }}")); auto [{{ df.camel_name }}Result, {{ df.camel_name }}Err] = {{ df.frontend_inverse_converter }}({{ df.camel_name }}); if({{ df.camel_name }}Err.is_bad()) { return {{ df.camel_name }}Err; } {% if df.frontend_uses_member_access %} attributes.{{ df.frontend_member_name }} = {{ df.camel_name }}Result; {% else %} attributes.{{ df.frontend_setter_name }}({{ df.camel_name }}Result); {% endif %} {% elif df.is_enum %} // Unpack {{ df.name }} int64_t {{ df.camel_name }}Raw = 0; HIPDNN_CHECK_ERROR(getDescriptorAttrScalar(opDesc, {{ df.attr_name }}, HIPDNN_TYPE_INT64, {{ df.camel_name }}Raw, "{{ op.effective_error_label }} {{ df.name }}")); {% if df.frontend_uses_member_access %} attributes.{{ df.frontend_member_name }} = static_cast<{{ df.cpp_enum }}>({{ df.camel_name }}Raw); {% else %} attributes.{{ df.frontend_setter_name }}(static_cast<{{ df.cpp_enum }}>({{ df.camel_name }}Raw)); {% endif %} {% elif df.is_optional_scalar %} // Unpack {{ df.name }} (optional) { std::optional<{{ df.cpp_type }}> {{ df.camel_name }}; HIPDNN_CHECK_ERROR(getDescriptorAttrOptionalScalar(opDesc, {{ df.attr_name }}, {{ df.backend_type }}, {{ df.camel_name }}, "{{ op.effective_error_label }} {{ df.name }}")); if({{ df.camel_name }}.has_value()) { {% if df.frontend_uses_member_access %} attributes.{{ df.frontend_member_name }} = *{{ df.camel_name }}; {% else %} attributes.{{ df.frontend_setter_name }}(*{{ df.camel_name }}); {% endif %} } } {% elif df.is_scalar %} // Unpack {{ df.name }} {% if df.type == "scalar_float" %} float {{ df.camel_name }} = 0.0f; {% elif df.type == "bool" %} bool {{ df.camel_name }} = false; {% else %} {{ df.cpp_type }} {{ df.camel_name }} = 0; {% endif %} HIPDNN_CHECK_ERROR(getDescriptorAttrScalar(opDesc, {{ df.attr_name }}, {{ df.backend_type }}, {{ df.camel_name }}, "{{ op.effective_error_label }} {{ df.name }}")); {% if df.frontend_uses_member_access %} attributes.{{ df.frontend_member_name }} = {{ df.camel_name }}; {% else %} attributes.{{ df.frontend_setter_name }}({{ df.camel_name }}); {% endif %} {% endif %} {% endfor %} {% if op.has_compute_data_type %} // Unpack compute data type auto [dt, dtErr] = unpackGraphDataType(opDesc, {{ op.compute_data_type_attr }}, "{{ op.effective_error_label }} compute data type"); if(dtErr.is_bad()) { return dtErr; } attributes.set_compute_data_type(dt); {% endif %} {% endif %} {% for edt in op.extra_data_type_fields %} // Unpack {{ edt.name }} { {% if edt.sentinel %} // Packer omits this attribute when the value is {{ edt.sentinel }}; the // backend reports count=0 in that case and unpackGraphDataType returns // DataType::NOT_SET, which is the default we want to keep. Real // backend failures (descriptor errors, type-conversion failures) still // propagate via the explicit Err check. {% endif %} auto [{{ edt.camel_name }}, {{ edt.camel_name }}Err] = unpackGraphDataType( opDesc, {{ edt.attr_name }}, "{{ op.effective_error_label }} {{ edt.effective_error_label }}"); if({{ edt.camel_name }}Err.is_bad()) { return {{ edt.camel_name }}Err; } {% if edt.frontend_uses_member_access %} attributes.{{ edt.frontend_member_name }} = {{ edt.camel_name }}; {% else %} attributes.{{ edt.frontend_setter_name }}({{ edt.camel_name }}); {% endif %} } {% endfor %} {% for taf in op.tensor_array_fields %} // Unpack {{ taf.name }} tensor array { std::vector> {{ taf.camel_name }}Attrs; HIPDNN_CHECK_ERROR(unpackAndRegisterTensorArray( opDesc, {{ taf.attr_name }}, tensorMap, {{ taf.camel_name }}Attrs, "{{ op.effective_error_label }} {{ taf.name }}")); if(!{{ taf.camel_name }}Attrs.empty()) { attributes.{{ taf.frontend_setter_name }}({{ taf.camel_name }}Attrs); } } {% endfor %} // Unpack operation name std::string opName; HIPDNN_CHECK_ERROR( getDescriptorAttrString(opDesc, HIPDNN_ATTR_OPERATION_NAME_EXT, opName, "operation name")); attributes.set_name(opName); return {}; } } // namespace hipdnn_frontend::detail