132 lines
5.2 KiB
C++
132 lines
5.2 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Simple and efficient Run-Time Type Information
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
// Version 2.0.
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
//
|
|
//*************************************************************************
|
|
|
|
#ifndef VERILATOR_V3RTTI_H_
|
|
#define VERILATOR_V3RTTI_H_
|
|
|
|
#include "verilatedos.h"
|
|
|
|
#include <cstdint>
|
|
#include <type_traits>
|
|
|
|
// Holds list of types as template parameter pack.
|
|
// Useful in compile-time code generation.
|
|
template <typename... TN>
|
|
struct VTypeList final {
|
|
template <typename... UN>
|
|
constexpr VTypeList<TN..., UN...> operator+(VTypeList<UN...>) const {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
// Holds one type.
|
|
// Can be safely used as a return or argument type, and even instantiated, without triggering any
|
|
// potential limitations or effects of the held type.
|
|
template <typename T>
|
|
struct VTypeWrapper final {
|
|
using type_t = T;
|
|
};
|
|
|
|
// Implementation details of other constructs defined in this header.
|
|
namespace V3RttiInternal {
|
|
|
|
// Helper function for extracting first type from VTypeList.
|
|
template <typename T0, typename... TN>
|
|
static inline constexpr VTypeWrapper<T0> vlTypeListFront(VTypeList<T0, TN...>) {
|
|
return {};
|
|
}
|
|
|
|
// Overload for empty type list. Returns false.
|
|
inline static constexpr bool isClassIdOfOneOf(uintptr_t id, VTypeList<>) VL_PURE { return false; }
|
|
|
|
// Returns true iff `id` has the same value as `T::rttiClassId()`, where `T` is any type held by
|
|
// `VTypeList` object passed as the second argument.
|
|
template <typename Base0, typename... BaseN>
|
|
inline static constexpr bool isClassIdOfOneOf(uintptr_t id, VTypeList<Base0, BaseN...>) VL_PURE {
|
|
return id == Base0::rttiClassId() || isClassIdOfOneOf(id, VTypeList<BaseN...>{});
|
|
}
|
|
|
|
} // namespace V3RttiInternal
|
|
|
|
// Alias for the first (frontmost) type held by type list `TL`.
|
|
template <typename TL>
|
|
using VTypeListFront = typename decltype(::V3RttiInternal::vlTypeListFront(TL{}))::type_t;
|
|
|
|
// `VTypeList` holding types from type lists `TL1` followed by types from type list `TL2`.
|
|
template <typename TL1, typename TL2>
|
|
using VJoinedTypeLists = decltype(TL1{} + TL2{});
|
|
|
|
// Common code used by VL_RTTI_COMMON_IMPL and VL_RTTI_COMMON_IMPL_BASE.
|
|
#define V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
|
|
private: \
|
|
/* A type used only for implementation of the static_assert below. */ \
|
|
struct RttiUniqueTypeForThisClass {}; \
|
|
static_assert( \
|
|
std::is_same<RttiUniqueTypeForThisClass, ThisClass::RttiUniqueTypeForThisClass>::value, \
|
|
"'ThisClass' argument (" #ThisClass ") does not match the class name"); \
|
|
\
|
|
public: \
|
|
/* Returns unique ID of the class. Useful with `isInstanceOfClassWithId()` method. */ \
|
|
static uintptr_t rttiClassId() VL_PURE { \
|
|
/* The only purpose of the following variable is to occupy an unique memory address. */ \
|
|
/* This address is used as an unique class ID. */ \
|
|
static char aStaticVariable; \
|
|
return reinterpret_cast<uintptr_t>(&aStaticVariable); \
|
|
}
|
|
|
|
// Call this macro at the beginning of class definition if the class derives from a
|
|
// class with VL_RTTI_IMPL or VL_RTTI_IMPL_BASE calls.
|
|
#define VL_RTTI_IMPL(ThisClass, DirectBaseClass) \
|
|
V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
|
|
static_assert( \
|
|
std::is_same<DirectBaseClass, \
|
|
VTypeListFront<DirectBaseClass::RttiThisAndBaseClassesList>>::value, \
|
|
"Missing VL_RTTI_IMPL(...) in the direct base class (" #DirectBaseClass ")"); \
|
|
\
|
|
public: \
|
|
/* Type list containing this class and all classes from the inheritance chain. */ \
|
|
using RttiThisAndBaseClassesList \
|
|
= VJoinedTypeLists<VTypeList<ThisClass>, \
|
|
typename DirectBaseClass::RttiThisAndBaseClassesList>; \
|
|
\
|
|
protected: \
|
|
/* Returns true iff `id` has the same value as `T::rttiClassId()`, where `T` is either this \
|
|
* class or any class from this class' inheritance chain. */ \
|
|
bool isInstanceOfClassWithId(uintptr_t id) const override VL_PURE { \
|
|
return ::V3RttiInternal::isClassIdOfOneOf(id, RttiThisAndBaseClassesList{}); \
|
|
} \
|
|
\
|
|
private: /* Revert to private visibility after this macro */
|
|
|
|
// Call this macro at the beginning of a base class to implement class type queries using
|
|
// `p->isInstanceOfClassWithId(ClassName::rttiClassId())`.
|
|
#define VL_RTTI_IMPL_BASE(ThisClass) \
|
|
V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
|
|
public: \
|
|
/* Type list containing this class and all classes from the inheritance chain. */ \
|
|
using RttiThisAndBaseClassesList = VTypeList<ThisClass>; \
|
|
\
|
|
protected: \
|
|
/* Returns true iff `id` has the same value as value returned by this class' \
|
|
`rttiClassId()` method. */ \
|
|
virtual bool isInstanceOfClassWithId(uintptr_t id) const VL_PURE { \
|
|
return id == rttiClassId(); \
|
|
} \
|
|
\
|
|
private: /* Revert to private visibility after this macro */
|
|
|
|
#endif // Guard
|