// -*- 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 #include namespace V3Rtti { // Use 'V3Rtti::isInstanceOf(objp)' to check if 'objp' is of subtype 'T' (downcasting) template bool isInstanceOf(SuperClass* objp) { static_assert(std::is_base_of::value, "Impossible 'isInstanceOf'"); static_assert(!std::is_same::value, "Useless 'isInstanceOf'"); static_assert(std::is_same< // typename std::remove_cv::type, // typename SubClass::V3RttiThisClass // >::value, "Missing VL_RTTI_IMPL(...) in 'SubClass'"); return objp->v3RttiIsInstanceOfImpl(SubClass::v3RttiClassId()); } namespace internal { // Returns true iff 'id' equals the 'rttiClassId()' of either 'T', or any of its base classes template inline bool matchClassId(uintptr_t id) VL_PURE { return id == T::v3RttiClassId() || matchClassId(id); } // Specialization for the root class, which have 'void' for 'V3RttiBaseClass' template <> inline bool matchClassId(uintptr_t) VL_PURE { return false; } } // namespace internal } // namespace V3Rtti // Common code used by VL_RTTI_COMMON_IMPL and VL_RTTI_COMMON_IMPL_BASE. #define V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass, OVERRIDE) \ using V3RttiThisClass = ThisClass; \ /* A type used only for implementation of the static_assert below. */ \ struct RttiUniqueTypeForThisClass {}; \ static_assert( \ std::is_same::value, \ "'ThisClass' argument (" #ThisClass ") does not match the class name"); \ /* The implementation can pick up the private members */ \ template \ friend bool V3Rtti::internal::matchClassId(uintptr_t id); \ template \ friend bool V3Rtti::isInstanceOf(U*); \ /* Returns unique type ID of the class. */ \ static uintptr_t v3RttiClassId() VL_PURE { \ /* Don't complain this function is unused */ (void)&v3RttiClassId; \ /* The address of this static variable is used as the unique class type ID. */ \ static char s_vlrttiClassId; \ return reinterpret_cast(&s_vlrttiClassId); \ } \ /* Dispatch to matchClassId with the correct sub type (this type) */ \ virtual bool v3RttiIsInstanceOfImpl(uintptr_t id) const OVERRIDE VL_PURE { \ return ::V3Rtti::internal::matchClassId(id); \ } // 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) \ private: \ using V3RttiBaseClass = DirectBaseClass; \ V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass, override) \ private: // Call this macro at the beginning of a base class to implement class type // usable with V3Rtti::InstanceOf #define VL_RTTI_IMPL_BASE(ThisClass) \ private: \ using V3RttiBaseClass = void; \ V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass, /* base */) \ private: #endif // Guard