// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // // Code available from: https://verilator.org // // Copyright 2003-2023 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 // //************************************************************************* /// /// \file /// \brief Verilated symbol inspection header /// /// This file is for inclusion by internal files that need to inspect /// specific symbols. Applications typically use the VPI instead. /// /// User wrapper code wanting to inspect the symbol table should use /// verilated_syms.h instead. /// //************************************************************************* // These classes are thread safe, and read only. #ifndef VERILATOR_VERILATED_SYM_PROPS_H_ #define VERILATOR_VERILATED_SYM_PROPS_H_ #include "verilatedos.h" #include //=========================================================================== // Verilator range // Thread safety: Assume is constructed only with model, then any number of readers // See also V3Ast::VNumRange class VerilatedRange final { int m_left = 0; int m_right = 0; protected: friend class VerilatedVarProps; friend class VerilatedScope; VerilatedRange() = default; void init(int left, int right) { m_left = left; m_right = right; } public: VerilatedRange(int left, int right) : m_left{left} , m_right{right} {} ~VerilatedRange() = default; int left() const VL_PURE { return m_left; } int right() const VL_PURE { return m_right; } int low() const VL_PURE { return (m_left < m_right) ? m_left : m_right; } int high() const VL_PURE { return (m_left > m_right) ? m_left : m_right; } int elements() const VL_PURE { return (VL_LIKELY(m_left >= m_right) ? (m_left - m_right + 1) : (m_right - m_left + 1)); } int increment() const VL_PURE { return (m_left >= m_right) ? 1 : -1; } }; //=========================================================================== // Verilator variable // Thread safety: Assume is constructed only with model, then any number of readers class VerilatedVarProps VL_NOT_FINAL { // TYPES static constexpr uint32_t MAGIC = 0xddc4f829UL; // MEMBERS const uint32_t m_magic; // Magic number const VerilatedVarType m_vltype; // Data type const VerilatedVarFlags m_vlflags; // Direction const int m_pdims; // Packed dimensions, 0 = none const int m_udims; // Unpacked dimensions, 0 = none VerilatedRange m_packed; // Packed array range std::vector m_unpacked; // Unpacked array ranges void initUnpacked(const int* ulims) { for (int i = 0; i < m_udims; ++i) { const int uleft = ulims ? ulims[2 * i + 0] : 0; const int uright = ulims ? ulims[2 * i + 1] : 0; m_unpacked.emplace_back(uleft, uright); } } // CONSTRUCTORS protected: friend class VerilatedScope; VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims) : m_magic{MAGIC} , m_vltype{vltype} , m_vlflags{vlflags} , m_pdims{pdims} , m_udims{udims} { initUnpacked(nullptr); } public: class Unpacked {}; // Without packed VerilatedVarProps(VerilatedVarType vltype, int vlflags) : m_magic{MAGIC} , m_vltype{vltype} , m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning , m_pdims{0} , m_udims{0} {} VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int udims, const int* ulims) : m_magic{MAGIC} , m_vltype{vltype} , m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning , m_pdims{0} , m_udims{udims} { initUnpacked(ulims); } // With packed class Packed {}; VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr) : m_magic{MAGIC} , m_vltype{vltype} , m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning , m_pdims{1} , m_udims{0} , m_packed{pl, pr} {} VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked, int udims, const int* ulims) : m_magic{MAGIC} , m_vltype{vltype} , m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning , m_pdims{1} , m_udims{udims} , m_packed{pl, pr} { initUnpacked(ulims); } ~VerilatedVarProps() = default; // METHODS bool magicOk() const { return m_magic == MAGIC; } VerilatedVarType vltype() const VL_MT_SAFE { return m_vltype; } VerilatedVarFlags vldir() const { return static_cast(static_cast(m_vlflags) & VLVF_MASK_DIR); } uint32_t entSize() const VL_MT_SAFE; bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); } // DPI compatible C standard layout bool isDpiCLayout() const { return ((m_vlflags & VLVF_DPI_CLAY) != 0); } int udims() const VL_MT_SAFE { return m_udims; } int dims() const { return m_pdims + m_udims; } const VerilatedRange& packed() const VL_MT_SAFE { return m_packed; } const VerilatedRange& unpacked() const { return m_unpacked[0]; } // DPI accessors int left(int dim) const VL_MT_SAFE { return dim == 0 ? m_packed.left() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].left() : 0; } int right(int dim) const VL_MT_SAFE { return dim == 0 ? m_packed.right() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].right() : 0; } int low(int dim) const VL_MT_SAFE { return dim == 0 ? m_packed.low() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].low() : 0; } int high(int dim) const VL_MT_SAFE { return dim == 0 ? m_packed.high() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].high() : 0; } int increment(int dim) const { return dim == 0 ? m_packed.increment() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].increment() : 0; } int elements(int dim) const VL_MT_SAFE { return dim == 0 ? m_packed.elements() : VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].elements() : 0; } // Total size in bytes (note DPI limited to 4GB) size_t totalSize() const; // Adjust a data pointer to access a given array element, NULL if something goes bad void* datapAdjustIndex(void* datap, int dim, int indx) const VL_MT_SAFE; }; //=========================================================================== // Verilator DPI open array variable class VerilatedDpiOpenVar final { // MEMBERS const VerilatedVarProps* const m_propsp; // Variable properties void* const m_datap; // Location of data (local to thread always, so safe) public: // CONSTRUCTORS VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap) : m_propsp{propsp} , m_datap{datap} {} VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap) : m_propsp{propsp} , m_datap{const_cast(datap)} {} ~VerilatedDpiOpenVar() = default; // METHODS void* datap() const VL_MT_SAFE { return m_datap; } // METHODS - from VerilatedVarProps bool magicOk() const { return m_propsp->magicOk(); } VerilatedVarType vltype() const { return m_propsp->vltype(); } bool isDpiStdLayout() const { return m_propsp->isDpiCLayout(); } const VerilatedRange& packed() const { return m_propsp->packed(); } const VerilatedRange& unpacked() const { return m_propsp->unpacked(); } int udims() const VL_MT_SAFE { return m_propsp->udims(); } int left(int dim) const VL_MT_SAFE { return m_propsp->left(dim); } int right(int dim) const VL_MT_SAFE { return m_propsp->right(dim); } int low(int dim) const { return m_propsp->low(dim); } int high(int dim) const { return m_propsp->high(dim); } int increment(int dim) const { return m_propsp->increment(dim); } int elements(int dim) const { return m_propsp->elements(dim); } size_t totalSize() const { return m_propsp->totalSize(); } void* datapAdjustIndex(void* datap, int dim, int indx) const VL_MT_SAFE { return m_propsp->datapAdjustIndex(datap, dim, indx); } }; //=========================================================================== // Verilator variable // Thread safety: Assume is constructed only with model, then any number of readers class VerilatedVar final : public VerilatedVarProps { // MEMBERS void* const m_datap; // Location of data const char* const m_namep; // Name - slowpath protected: const bool m_isParam; friend class VerilatedScope; // CONSTRUCTORS VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims, bool isParam) : VerilatedVarProps{vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0)} , m_datap{datap} , m_namep{namep} , m_isParam{isParam} {} public: ~VerilatedVar() = default; // ACCESSORS void* datap() const { return m_datap; } const VerilatedRange& range() const { return packed(); } // Deprecated const VerilatedRange& array() const { return unpacked(); } // Deprecated const char* name() const { return m_namep; } bool isParam() const { return m_isParam; } }; #endif // Guard