/******************************************************************************* * * MIT License * * Copyright (C) 2022-2025 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace TensileLite { namespace Serialization { struct EmptyContext { }; template struct IOTraits { }; template struct MappingTraits { static const bool flow = false; }; template struct CustomMappingTraits { static const bool flow = false; }; template struct SequenceTraits { using Value = int; static const bool flow = false; }; template struct EnumTraits { }; template struct EmptyMappingTraits { using iot = IOTraits; static_assert(Object::HasValue == false, "Object has a value. Use the value base class."); static void mapping(IO& io, Object& obj) {} const static bool flow = true; }; template struct ValueMappingTraits { using iot = IOTraits; static_assert(Object::HasValue == true, "Object has no value. Use the empty base class."); static void mapping(IO& io, Object& obj) { iot::mapRequired(io, "value", obj.value); } const static bool flow = true; }; template struct IndexMappingTraits { using iot = IOTraits; static_assert(Object::HasIndex == true, "Object doesn't have index/value. Use the empty base class."); static void mapping(IO& io, Object& obj) { iot::mapRequired(io, "index", obj.index); } const static bool flow = true; }; template struct IndexValueMappingTraits { using iot = IOTraits; static_assert(Object::HasIndex == true && Object::HasValue == true, "Object doesn't have index/value. Use the empty base class."); static void mapping(IO& io, Object& obj) { iot::mapRequired(io, "index", obj.index); iot::mapRequired(io, "value", obj.value); } const static bool flow = true; }; template struct AutoMappingTraits { }; template struct AutoMappingTraits : public EmptyMappingTraits { }; template struct AutoMappingTraits : public ValueMappingTraits { }; template struct AutoMappingTraits : public IndexMappingTraits { }; template struct AutoMappingTraits : public IndexValueMappingTraits { }; template struct SubclassMappingTraits { }; template struct PointerMappingTraits; template struct PointerMappingTraits { using iot = IOTraits; template static bool mapping(IO& io, std::shared_ptr& p, Context& ctx) { std::shared_ptr sc; if(iot::outputting(io)) { sc = std::dynamic_pointer_cast(p); } else { sc = std::make_shared(); p = sc; } MappingTraits::mapping(io, *sc, ctx); return true; } }; template struct PointerMappingTraits { using iot = IOTraits; template static bool mapping(IO& io, std::shared_ptr& p) { std::shared_ptr sc; if(iot::outputting(io)) { sc = std::dynamic_pointer_cast(p); } else { sc = std::make_shared(); p = sc; } MappingTraits::mapping(io, *sc); return true; } }; template struct BaseClassMappingTraits { using iot = IOTraits; static void mapping(IO& io, std::shared_ptr& value) { std::string type; if(iot::outputting(io)) type = value->type(); iot::mapRequired(io, "type", type); if(!SubclassMappingTraits::mapping(io, type, value)) iot::setError(io, "Unknown subclass type " + type); } const static bool flow = Flow; }; template struct DefaultSubclassMappingTraits; template struct DefaultSubclassMappingTraits { using iot = IOTraits; using SubclassFn = bool(IO&, typename std::shared_ptr&, Context&); using SubclassMap = std::unordered_map>; template static typename SubclassMap::value_type Pair() { auto f = PointerMappingTraits::template mapping; return typename SubclassMap::value_type(Subclass::Type(), f); } static bool mapping(IO& io, std::string const& type, std::shared_ptr& p, Context& ctx) { auto iter = CRTP_Traits::subclasses.find(type); if(iter != CRTP_Traits::subclasses.end()) return iter->second(io, p, ctx); return false; } }; template struct DefaultSubclassMappingTraits { using iot = IOTraits; using SubclassFn = bool(IO&, typename std::shared_ptr&); using SubclassMap = std::unordered_map>; template static typename SubclassMap::value_type Pair() { auto f = PointerMappingTraits::template mapping; return typename SubclassMap::value_type(Subclass::Type(), f); } static bool mapping(IO& io, std::string const& type, std::shared_ptr& p) { auto iter = CRTP_Traits::subclasses.find(type); if(iter != CRTP_Traits::subclasses.end()) return iter->second(io, p); return false; } }; template struct SequenceTraits, IO> { using Value = Data; static size_t size(IO& io, vector2& v) { return 2; } static Data& element(IO& io, vector2& v, size_t index) { if(index == 0) return v.x; return v.y; } const static bool flow = true; }; template struct SequenceTraits, IO> { using Value = Data; static size_t size(IO& io, vector3& v) { return 3; } static Data& element(IO& io, vector3& v, size_t index) { if(index == 0) return v.x; if(index == 1) return v.y; return v.z; } const static bool flow = true; }; template struct SequenceTraits, IO> { using Value = Data; static size_t size(IO& io, vector4& v) { return 4; } static Data& element(IO& io, vector4& v, size_t index) { if(index == 0) return v.x; if(index == 1) return v.y; if(index == 2) return v.z; return v.w; } const static bool flow = true; }; template struct EnumTraits { using iot = IOTraits; static void enumeration(IO& io, rocisa::DataType& value) { for(int i = 0; i < static_cast(rocisa::DataType::Count); i++) { auto const& info = DataTypeInfo::Get(i); iot::enumCase(io, value, info.name.c_str(), info.dataType); } } }; template struct EnumTraits { using iot = IOTraits; static void enumeration(IO& io, ActivationType& value) { for(int i = 0; i < static_cast(ActivationType::Count); i++) { auto const& info = static_cast(i); iot::enumCase(io, value, TensileLite::ToString(info).c_str(), info); } } }; template struct EnumTraits { using iot = IOTraits; static void enumeration(IO& io, KernelLanguage& value) { for(int i = 0; i < static_cast(KernelLanguage::Count); i++) { auto const& info = KernelLanguageTypeInfo::Get(i); iot::enumCase(io, value, info.name.c_str(), info.m_kernelLanguage); } } }; template struct EnumTraits { using iot = IOTraits; static void enumeration(IO& io, ScalarValue& value) { for(int i = 0; i < static_cast(ScalarValue::Count); i++) { auto const& info = ScalarValueTypeInfo::Get(i); iot::enumCase(io, value, info.name.c_str(), info.m_value); } } }; } // namespace Serialization } // namespace TensileLite