* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file schema_base.h
* \brief
*/
#pragma once
#ifndef SCHEMA_TRACE_BASE_H
#define SCHEMA_TRACE_BASE_H
#include <cstdint>
#include <cstddef>
#include <cstring>
#include <fstream>
#include <memory>
#include <sstream>
#include <vector>
#include <unordered_map>
#include "securec.h"
namespace npu::tile_fwk::schema::type {
#define SCHEMA_ATTR_KEYWORD_PREFIX(top) (top ? "#" : "")
#define SCHEMA_ATTR_VALUE_LBOUND "{"
#define SCHEMA_ATTR_VALUE_RBOUND "}"
#define SCHEMA_ATTR_VALUE_SEPARATOR ","
#define SCHEMA_ARRAY_LBOUND "["
#define SCHEMA_ARRAY_RBOUND "]"
#define SCHEMA_ADDRESS_PREFIX "0x"
struct TypeBase {};
template <typename Ty0, typename... Tys>
struct MaxTypeSize {
constexpr static int size =
std::max(static_cast<size_t>(sizeof(Ty0)), static_cast<size_t>(MaxTypeSize<Tys...>::size));
};
template <typename Ty0>
struct MaxTypeSize<Ty0> {
constexpr static int size = sizeof(Ty0);
};
template <typename Ty0, typename... Tys>
struct TypeCount {
constexpr static int size = 1 + TypeCount<Tys...>::size;
};
template <typename Ty0>
struct TypeCount<Ty0> {
constexpr static int size = 1;
};
template <typename BaseType, char prefix = 0>
struct IntegralTypeBase {
IntegralTypeBase() = default;
IntegralTypeBase(int data) : data_(data) {}
std::string Dump(bool top __attribute__((unused)) = false) const
{
std::string data = std::to_string(data_);
if (prefix != 0) {
data = std::string(1, prefix) + data;
}
return data;
}
private:
BaseType data_{0};
};
struct Int32Type : IntegralTypeBase<int32_t, 0> {
Int32Type() = default;
template <typename... TyArgs>
Int32Type(const TyArgs&... args) : IntegralTypeBase<int32_t, 0>(args...)
{}
};
struct Int64Type : IntegralTypeBase<int64_t, 0> {
Int64Type() = default;
template <typename... TyArgs>
Int64Type(const TyArgs&... args) : IntegralTypeBase<int64_t, 0>(args...)
{}
};
struct UInt32Type : IntegralTypeBase<uint32_t, 0> {
UInt32Type() = default;
template <typename... TyArgs>
UInt32Type(const TyArgs&... args) : IntegralTypeBase<uint32_t, 0>(args...)
{}
};
struct UInt64Type : IntegralTypeBase<uint64_t, 0> {
UInt64Type() = default;
template <typename... TyArgs>
UInt64Type(const TyArgs&... args) : IntegralTypeBase<uint64_t, 0>(args...)
{}
};
template <char prefix = 0>
struct Int64IdType : IntegralTypeBase<int64_t, prefix> {
Int64IdType() = default;
template <typename... TyArgs>
Int64IdType(const TyArgs&... args) : IntegralTypeBase<int64_t, prefix>(args...)
{}
};
struct AddressType : TypeBase {
AddressType() = default;
AddressType(uintptr_t addr) : addr_(addr) {}
static constexpr int addressWidth = 16;
std::string Dump(bool top __attribute__((unused)) = false) const
{
std::ostringstream oss;
oss << SCHEMA_ADDRESS_PREFIX << std::hex << addr_;
return oss.str();
}
private:
uintptr_t addr_{0};
};
struct StringType : TypeBase {
StringType() = default;
StringType(const std::string& str) : str_(str) {}
std::string Dump(bool top __attribute__((unused)) = false) const { return "\"" + str_ + "\""; }
private:
std::string str_;
};
struct TextType : TypeBase {
TextType() = default;
TextType(const std::string& text) : text_(text) {}
std::string Dump(bool top __attribute__((unused)) = false) const { return text_; }
private:
std::string text_;
};
struct CoordType : TypeBase {
CoordType() = default;
template <typename... TyArgs>
CoordType(const TyArgs&... args) : size_(TypeCount<TyArgs...>::size), dim_{args...}
{}
std::string Dump(bool top __attribute__((unused)) = false) const
{
std::ostringstream oss;
oss << SCHEMA_ARRAY_LBOUND;
for (int index = 0; index < size_; index++) {
oss << (index == 0 ? "" : SCHEMA_ATTR_VALUE_SEPARATOR);
oss << Int64Type(dim_[index]).Dump();
}
oss << SCHEMA_ARRAY_RBOUND;
return oss.str();
}
private:
int size_;
int64_t dim_[0x8];
};
template <typename ElementType>
struct ArrayType : TypeBase {
ArrayType() = default;
template <typename ContainerType>
ArrayType(const ContainerType& container, bool dumpIndex = false)
: elementList_(container.begin(), container.end()), dumpIndex_(dumpIndex)
{}
static std::string DumpIndex(int index) { return "/*" + std::to_string(index) + "*/"; }
std::string Dump(bool top __attribute__((unused)) = false) const
{
std::ostringstream oss;
oss << SCHEMA_ARRAY_LBOUND;
int index = 0;
for (auto& element : elementList_) {
oss << (index == 0 ? "" : SCHEMA_ATTR_VALUE_SEPARATOR);
if (dumpIndex_) {
oss << DumpIndex(index);
}
oss << element.Dump(top);
index++;
}
oss << SCHEMA_ARRAY_RBOUND;
return oss.str();
}
private:
std::vector<ElementType> elementList_;
bool dumpIndex_;
};
struct AttributeId : TypeBase {
AttributeId() = default;
AttributeId(const std::string& name) : name_(name) {}
const std::string& Name() const { return name_; }
std::string Dump(bool top = true) const { return SCHEMA_ATTR_KEYWORD_PREFIX(top) + name_; }
private:
std::string name_;
};
template <typename Ty0>
struct AttributeCall_1 : AttributeId {
using Base = AttributeId;
AttributeCall_1() = default;
AttributeCall_1(const std::string& name) : Base(name) {}
AttributeCall_1(const std::string& name, const Ty0& arg0) : Base(name), arg0_(arg0) {}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return arg0_.Dump(false); }
private:
Ty0 arg0_;
};
template <typename Ty0, typename Ty1>
struct AttributeCall_2 : AttributeCall_1<Ty0> {
using Base = AttributeCall_1<Ty0>;
AttributeCall_2() = default;
AttributeCall_2(const std::string& name) : Base(name){};
AttributeCall_2(const std::string& name, const Ty0& arg0, const Ty1& arg1) : Base(name, arg0), arg1_(arg1) {}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return Base::ArgDump() + SCHEMA_ATTR_VALUE_SEPARATOR + arg1_.Dump(false); }
private:
Ty1 arg1_;
};
template <typename Ty0, typename Ty1, typename Ty2>
struct AttributeCall_3 : AttributeCall_2<Ty0, Ty1> {
using Base = AttributeCall_2<Ty0, Ty1>;
AttributeCall_3() = default;
AttributeCall_3(const std::string& name) : Base(name){};
AttributeCall_3(const std::string& name, const Ty0& arg0, const Ty1& arg1, const Ty2& arg2)
: Base(name, arg0, arg1), arg2_(arg2)
{}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return Base::ArgDump() + SCHEMA_ATTR_VALUE_SEPARATOR + arg2_.Dump(false); }
private:
Ty2 arg2_;
};
template <typename Ty0, typename Ty1, typename Ty2, typename Ty3>
struct AttributeCall_4 : AttributeCall_3<Ty0, Ty1, Ty2> {
using Base = AttributeCall_3<Ty0, Ty1, Ty2>;
AttributeCall_4() = default;
AttributeCall_4(const std::string& name) : Base(name){};
AttributeCall_4(const std::string& name, const Ty0& arg0, const Ty1& arg1, const Ty2& arg2, const Ty3& arg3)
: Base(name, arg0, arg1, arg2), arg3_(arg3)
{}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return Base::ArgDump() + SCHEMA_ATTR_VALUE_SEPARATOR + arg3_.Dump(false); }
private:
Ty3 arg3_;
};
template <typename Ty0, typename Ty1, typename Ty2, typename Ty3, typename Ty4>
struct AttributeCall_5 : AttributeCall_4<Ty0, Ty1, Ty2, Ty3> {
using Base = AttributeCall_4<Ty0, Ty1, Ty2, Ty3>;
AttributeCall_5() = default;
AttributeCall_5(const std::string& name) : Base(name){};
AttributeCall_5(
const std::string& name, const Ty0& arg0, const Ty1& arg1, const Ty2& arg2, const Ty3& arg3, const Ty4& arg4)
: Base(name, arg0, arg1, arg2, arg3), arg4_(arg4)
{}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return Base::ArgDump() + SCHEMA_ATTR_VALUE_SEPARATOR + arg4_.Dump(false); }
private:
Ty4 arg4_;
};
template <typename Ty0, typename Ty1, typename Ty2, typename Ty3, typename Ty4, typename Ty5>
struct AttributeCall_6 : AttributeCall_5<Ty0, Ty1, Ty2, Ty3, Ty4> {
using Base = AttributeCall_5<Ty0, Ty1, Ty2, Ty3, Ty4>;
AttributeCall_6() = default;
AttributeCall_6(const std::string& name) : Base(name){};
AttributeCall_6(
const std::string& name, const Ty0& arg0, const Ty1& arg1, const Ty2& arg2, const Ty3& arg3, const Ty4& arg4,
const Ty5& arg5)
: Base(name, arg0, arg1, arg2, arg3, arg4), arg5_(arg5)
{}
std::string Dump(bool top = true) const
{
return SCHEMA_ATTR_KEYWORD_PREFIX(top) + Base::Name() + SCHEMA_ATTR_VALUE_LBOUND + ArgDump() +
SCHEMA_ATTR_VALUE_RBOUND;
}
protected:
std::string ArgDump() const { return Base::ArgDump() + SCHEMA_ATTR_VALUE_SEPARATOR + arg5_.Dump(false); }
private:
Ty5 arg5_;
};
template <typename Ty0, typename... Tys>
static inline std::string UnionTypeDump(const Ty0* arg0, Tys... args)
{
if (arg0) {
return arg0->Dump(false);
} else {
return UnionTypeDump(args...);
}
}
template <typename Ty0>
static inline std::string UnionTypeDump(const Ty0* arg0)
{
if (arg0) {
return arg0->Dump(false);
} else {
return "";
}
}
template <typename Ty0, typename... Tys>
struct UnionTypeSelect {
using Base = UnionTypeSelect<Tys...>;
UnionTypeSelect() = default;
void Construct(const Ty0& arg0, unsigned char* thisUnionData)
{
val0_ = reinterpret_cast<Ty0*>(thisUnionData);
new (val0_) Ty0(arg0);
}
template <typename Ty>
void Construct(const Ty& arg, unsigned char* thisUnionData)
{
val0_ = nullptr;
base_.Construct(arg, thisUnionData);
}
void Assign(const UnionTypeSelect<Ty0, Tys...>& arg, unsigned char* thisUnionData)
{
if (arg.val0_) {
AssignArg(*arg.val0_, thisUnionData);
} else {
base_.Assign(arg.base_, thisUnionData);
}
}
void Clear()
{
if (val0_) {
val0_->~Ty0();
val0_ = nullptr;
} else {
base_.Clear();
}
}
std::string Dump(bool top = false) const
{
if (val0_) {
return val0_->Dump(top);
} else {
return base_.Dump(top);
}
}
private:
void AssignArg(const Ty0& arg0, unsigned char* thisUnionData)
{
val0_ = reinterpret_cast<Ty0*>(thisUnionData);
new (val0_) Ty0(arg0);
}
Ty0* val0_{nullptr};
Base base_;
};
template <typename Ty0>
struct UnionTypeSelect<Ty0> {
UnionTypeSelect() = default;
void Construct(const Ty0& arg0, unsigned char* thisUnionData)
{
val0_ = reinterpret_cast<Ty0*>(thisUnionData);
new (val0_) Ty0(arg0);
}
void Assign(const UnionTypeSelect<Ty0>& arg, unsigned char* thisUnionData)
{
if (arg.val0_ != nullptr) {
AssignArg(*arg.val0_, thisUnionData);
}
}
void Clear()
{
if (val0_) {
val0_->~Ty0();
val0_ = nullptr;
}
}
std::string Dump(bool top = false) const
{
if (val0_) {
return val0_->Dump(top);
} else {
return "";
}
}
private:
void AssignArg(const Ty0& arg0, unsigned char* thisUnionData)
{
val0_ = reinterpret_cast<Ty0*>(thisUnionData);
new (val0_) Ty0(arg0);
}
Ty0* val0_{nullptr};
};
template <typename Ty0, typename... Tys>
struct UnionType {
UnionType() = default;
template <typename Ty>
UnionType(const Ty& arg)
{
memset_s(data_, sizeof(data_), 0, sizeof(data_));
select_.Construct(arg, data_);
}
~UnionType() { select_.Clear(); }
UnionType(const UnionType<Ty0, Tys...>& arg)
{
memset_s(data_, sizeof(data_), 0, sizeof(data_));
select_.Assign(arg.select_, data_);
}
UnionType<Ty0, Tys...>& operator=(const UnionType<Ty0, Tys...>& arg)
{
select_.Clear();
memset_s(data_, sizeof(data_), 0, sizeof(data_));
select_.Assign(arg.select_, data_);
return *this;
}
std::string Dump(bool top = true) const { return select_.Dump(top); }
private:
UnionTypeSelect<Ty0, Tys...> select_;
unsigned char data_[MaxTypeSize<Ty0, Tys...>::size];
UnionType(UnionType<Ty0, Tys...>&& arg) = delete;
UnionType<Ty0, Tys...>& operator=(UnionType<Ty0, Tys...>&& arg) = delete;
};
#define SCHEMA_DEF_TYPE_INHERIT(name, baseType) \
typedef npu::tile_fwk::schema::type::baseType name##Base; \
struct name : name##Base { \
name() = default; \
template <typename... TyArgs> \
name(const TyArgs&... args) : name##Base(args...) \
{} \
};
#define SCHEMA_DEF_TYPE_INHERIT_ID(name, baseType, prefix) \
typedef npu::tile_fwk::schema::type::baseType<prefix> name##Base; \
struct name : name##Base { \
name() = default; \
template <typename... TyArgs> \
name(const TyArgs&... args) : name##Base(args...) \
{} \
};
#define SCHEMA_DEF_TYPE_INT32(name) SCHEMA_DEF_TYPE_INHERIT(name, Int32Type)
#define SCHEMA_DEF_TYPE_UINT32(name) SCHEMA_DEF_TYPE_INHERIT(name, UInt32Type)
#define SCHEMA_DEF_TYPE_INT64_1(name) SCHEMA_DEF_TYPE_INHERIT(name, Int64Type)
#define SCHEMA_DEF_TYPE_INT64_2(name, prefix) SCHEMA_DEF_TYPE_INHERIT_ID(name, Int64IdType, prefix)
#define SCHEMA_DEF_TYPE_INT64(...) \
SCHEMA_DEF_ATTR_CONCAT(SCHEMA_DEF_TYPE_INT64_, SCHEMA_DEF_ATTR_NR(__VA_ARGS__))(__VA_ARGS__)
#define SCHEMA_DEF_TYPE_UINT64(name) SCHEMA_DEF_TYPE_INHERIT(name, UInt64Type)
#define SCHEMA_DEF_TYPE_ADDRESS(name) SCHEMA_DEF_TYPE_INHERIT(name, AddressType)
#define SCHEMA_DEF_TYPE_STRING(name) SCHEMA_DEF_TYPE_INHERIT(name, StringType)
#define SCHEMA_DEF_TYPE_COORD(name) SCHEMA_DEF_TYPE_INHERIT(name, CoordType)
#define SCHEMA_DEF_TYPE_TEXT(name) SCHEMA_DEF_TYPE_INHERIT(name, TextType)
#define SCHEMA_DEF_TYPE_ARRAY(name, element) \
typedef npu::tile_fwk::schema::type::ArrayType<element> name##Base; \
struct name : name##Base { \
name() = default; \
template <typename... TyArgs> \
name(const TyArgs&... args) : name##Base(args...) \
{} \
}
#define SCHEMA_DEF_TYPE_UNION(name, ...) \
typedef npu::tile_fwk::schema::type::UnionType<__VA_ARGS__> name##Base; \
struct name : name##Base { \
name() = default; \
template <typename... TyArgs> \
name(const TyArgs&... args) : name##Base(args...) \
{} \
}
#define SCHEMA_DEF_ATTR_NR_(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, v, ...) v
#define SCHEMA_DEF_ATTR_NR(...) SCHEMA_DEF_ATTR_NR_(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define SCHEMA_DEF_ATTR_CONCAT_(name, nr) name##nr
#define SCHEMA_DEF_ATTR_CONCAT(name, nr) SCHEMA_DEF_ATTR_CONCAT_(name, nr)
#define SCHEMA_DEF_ATTR_KEYWORD_(name) \
typedef npu::tile_fwk::schema::type::AttributeId name##Base; \
struct name : name##Base { \
name() : name##Base(#name) {} \
static const std::string Name() { return #name; } \
};
#define SCHEMA_DEF_ATTR_CALL_(name, ...) \
typedef npu::tile_fwk::schema::type::SCHEMA_DEF_ATTR_CONCAT( \
AttributeCall_, SCHEMA_DEF_ATTR_NR(__VA_ARGS__))<__VA_ARGS__> \
name##Base; \
struct name : name##Base { \
name() : name##Base(#name) {} \
template <typename... TyArgs> \
name(const TyArgs&... args) : name##Base(#name, args...) \
{} \
static const std::string Name() { return #name; } \
};
#define SCHEMA_DEF_ATTR_NAME(name, text) \
typedef npu::tile_fwk::schema::type::AttributeId name##Base; \
struct name : name##Base { \
name() : name##Base(#text) {} \
static const std::string Name() { return #text; } \
};
#define SCHEMA_DEF_ATTR_1(name) SCHEMA_DEF_ATTR_KEYWORD_(name)
#define SCHEMA_DEF_ATTR_2(name, arg0) SCHEMA_DEF_ATTR_CALL_(name, arg0)
#define SCHEMA_DEF_ATTR_3(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_4(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_5(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_6(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_7(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_8(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_9(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_10(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_11(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_12(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_13(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_14(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR_15(name, arg0, ...) SCHEMA_DEF_ATTR_CALL_(name, arg0, __VA_ARGS__)
#define SCHEMA_DEF_ATTR(...) SCHEMA_DEF_ATTR_CONCAT(SCHEMA_DEF_ATTR_, SCHEMA_DEF_ATTR_NR(__VA_ARGS__))(__VA_ARGS__)
}
#endif