Internals: Standardize template argument names. No functional change.

This commit is contained in:
Wilson Snyder 2024-11-29 20:20:38 -05:00
parent 990ccd6763
commit 0c820c3068
28 changed files with 524 additions and 521 deletions

View File

@ -1604,26 +1604,26 @@ static inline IData VL_PACK_II(int obits, int lbits, const VlQueue<IData>& q) {
return ret;
}
template <std::size_t T_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<CData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<CData, N_Depth>& q) {
IData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
ret |= static_cast<IData>(q[T_Depth - 1 - i]) << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
ret |= static_cast<IData>(q[N_Depth - 1 - i]) << (i * lbits);
return ret;
}
template <std::size_t T_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<SData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<SData, N_Depth>& q) {
IData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
ret |= static_cast<IData>(q[T_Depth - 1 - i]) << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
ret |= static_cast<IData>(q[N_Depth - 1 - i]) << (i * lbits);
return ret;
}
template <std::size_t T_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<IData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<IData, N_Depth>& q) {
IData ret = 0;
for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i) ret |= q[N_Depth - 1 - i] << (i * lbits);
return ret;
}
@ -1645,27 +1645,27 @@ static inline QData VL_PACK_QI(int obits, int lbits, const VlQueue<IData>& q) {
return ret;
}
template <std::size_t T_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<CData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<CData, N_Depth>& q) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
ret |= static_cast<QData>(q[T_Depth - 1 - i]) << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
ret |= static_cast<QData>(q[N_Depth - 1 - i]) << (i * lbits);
return ret;
}
template <std::size_t T_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<SData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<SData, N_Depth>& q) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
ret |= static_cast<QData>(q[T_Depth - 1 - i]) << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
ret |= static_cast<QData>(q[N_Depth - 1 - i]) << (i * lbits);
return ret;
}
template <std::size_t T_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<IData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked<IData, N_Depth>& q) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
ret |= static_cast<QData>(q[T_Depth - 1 - i]) << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
ret |= static_cast<QData>(q[N_Depth - 1 - i]) << (i * lbits);
return ret;
}
@ -1675,10 +1675,10 @@ static inline QData VL_PACK_QQ(int obits, int lbits, const VlQueue<QData>& q) {
return ret;
}
template <std::size_t T_Depth>
static inline QData VL_PACK_QQ(int obits, int lbits, const VlUnpacked<QData, T_Depth>& q) {
template <std::size_t N_Depth>
static inline QData VL_PACK_QQ(int obits, int lbits, const VlUnpacked<QData, N_Depth>& q) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * lbits);
for (size_t i = 0; i < N_Depth; ++i) ret |= q[N_Depth - 1 - i] << (i * lbits);
return ret;
}
@ -1703,30 +1703,30 @@ static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, const Vl
return owp;
}
template <std::size_t T_Depth>
template <std::size_t N_Depth>
static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp,
const VlUnpacked<CData, T_Depth>& q) {
const VlUnpacked<CData, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
template <std::size_t T_Depth>
template <std::size_t N_Depth>
static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp,
const VlUnpacked<SData, T_Depth>& q) {
const VlUnpacked<SData, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
template <std::size_t T_Depth>
template <std::size_t N_Depth>
static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp,
const VlUnpacked<IData, T_Depth>& q) {
const VlUnpacked<IData, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -1737,30 +1737,30 @@ static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp, const Vl
return owp;
}
template <std::size_t T_Depth>
template <std::size_t N_Depth>
static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp,
const VlUnpacked<QData, T_Depth>& q) {
const VlUnpacked<QData, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WQ(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WQ(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
template <std::size_t N>
template <std::size_t N_Words>
static inline WDataOutP VL_PACK_WW(int obits, int lbits, WDataOutP owp,
const VlQueue<VlWide<N>>& q) {
const VlQueue<VlWide<N_Words>>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WW(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
return owp;
}
template <std::size_t T_Depth, std::size_t N>
template <std::size_t N_Depth, std::size_t N_Words>
static inline WDataOutP VL_PACK_WW(int obits, int lbits, WDataOutP owp,
const VlUnpacked<VlWide<N>, T_Depth>& q) {
const VlUnpacked<VlWide<N_Words>, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WW(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WW(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -2288,8 +2288,8 @@ static inline void VL_UNPACK_QW(int lbits, int rbits, VlQueue<QData>& q, WDataIn
}
}
template <std::size_t N>
static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue<VlWide<N>>& q, WDataInP rwp) {
template <std::size_t N_Words>
static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue<VlWide<N_Words>>& q, WDataInP rwp) {
const int size = (rbits + lbits - 1) / lbits;
q.renew(size);
for (size_t i = 0; i < size; ++i) {
@ -2297,85 +2297,85 @@ static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue<VlWide<N>>& q, WDa
}
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<CData, T_Depth>& q, IData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<CData, N_Depth>& q, IData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<SData, T_Depth>& q, IData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<SData, N_Depth>& q, IData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<IData, T_Depth>& q, IData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<IData, N_Depth>& q, IData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<CData, T_Depth>& q, QData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<CData, N_Depth>& q, QData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<SData, T_Depth>& q, QData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<SData, N_Depth>& q, QData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<IData, T_Depth>& q, QData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked<IData, N_Depth>& q, QData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_QQ(int lbits, int rbits, VlUnpacked<QData, T_Depth>& q, QData from) {
template <std::size_t N_Depth>
static inline void VL_UNPACK_QQ(int lbits, int rbits, VlUnpacked<QData, N_Depth>& q, QData from) {
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask;
for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<CData, T_Depth>& q,
template <std::size_t N_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<CData, N_Depth>& q,
WDataInP rwp) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask;
for (size_t i = 0; i < N_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<SData, T_Depth>& q,
template <std::size_t N_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<SData, N_Depth>& q,
WDataInP rwp) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask;
for (size_t i = 0; i < N_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<IData, T_Depth>& q,
template <std::size_t N_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<IData, N_Depth>& q,
WDataInP rwp) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask;
for (size_t i = 0; i < N_Depth; ++i)
q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask;
}
template <std::size_t T_Depth>
static inline void VL_UNPACK_QW(int lbits, int rbits, VlUnpacked<QData, T_Depth>& q,
template <std::size_t N_Depth>
static inline void VL_UNPACK_QW(int lbits, int rbits, VlUnpacked<QData, N_Depth>& q,
WDataInP rwp) {
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = VL_SEL_QWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask;
for (size_t i = 0; i < N_Depth; ++i)
q[i] = VL_SEL_QWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask;
}
template <std::size_t T_Depth, std::size_t N>
static inline void VL_UNPACK_WW(int lbits, int rbits, VlUnpacked<VlWide<N>, T_Depth>& q,
template <std::size_t N_Depth, std::size_t N_Words>
static inline void VL_UNPACK_WW(int lbits, int rbits, VlUnpacked<VlWide<N_Words>, N_Depth>& q,
WDataInP rwp) {
for (size_t i = 0; i < T_Depth; ++i)
VL_SEL_WWII(lbits, rbits, q[i], rwp, (T_Depth - 1 - i) * lbits, lbits);
for (size_t i = 0; i < N_Depth; ++i)
VL_SEL_WWII(lbits, rbits, q[i], rwp, (N_Depth - 1 - i) * lbits, lbits);
}
// Return QData from double (numeric)

View File

@ -198,7 +198,7 @@ public:
//=============================================================================
// VlPgoProfiler is for collecting profiling data for PGO
template <std::size_t T_Entries>
template <std::size_t N_Entries>
class VlPgoProfiler final {
// TYPES
struct Record final {
@ -207,7 +207,7 @@ class VlPgoProfiler final {
};
// Counters are stored packed, all together to reduce cache effects
std::array<uint64_t, T_Entries> m_counters; // Time spent on this record
std::array<uint64_t, N_Entries> m_counters; // Time spent on this record
std::vector<Record> m_records; // Record information
public:
@ -216,7 +216,7 @@ public:
~VlPgoProfiler() = default;
void write(const char* modelp, const std::string& filename) VL_MT_SAFE;
void addCounter(size_t counter, const std::string& name) {
VL_DEBUG_IF(assert(counter < T_Entries););
VL_DEBUG_IF(assert(counter < N_Entries););
m_records.emplace_back(Record{name, counter});
}
void startCounter(size_t counter) {
@ -227,8 +227,8 @@ public:
void stopCounter(size_t counter) { m_counters[counter] += VL_CPU_TICK(); }
};
template <std::size_t T_Entries>
void VlPgoProfiler<T_Entries>::write(const char* modelp, const std::string& filename) VL_MT_SAFE {
template <std::size_t N_Entries>
void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& filename) VL_MT_SAFE {
static VerilatedMutex s_mutex;
const VerilatedLockGuard lock{s_mutex};

View File

@ -250,11 +250,11 @@ public:
record_arr_table(var, name, dimension, {});
}
}
template <typename T, std::size_t N>
void write_var(VlUnpacked<T, N>& var, int width, const char* name, int dimension,
template <typename T, std::size_t N_Depth>
void write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name] = std::make_shared<const VlRandomArrayVar<VlUnpacked<T, N>>>(
m_vars[name] = std::make_shared<const VlRandomArrayVar<VlUnpacked<T, N_Depth>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
idx = 0;
@ -295,11 +295,11 @@ public:
++idx;
}
}
template <typename T, std::size_t N>
void record_arr_table(VlUnpacked<T, N>& var, const std::string name, int dimension,
template <typename T, std::size_t N_Depth>
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
std::vector<size_t> indices) {
if ((dimension > 0) && (N != 0)) {
for (size_t i = 0; i < N; ++i) {
if ((dimension > 0) && (N_Depth != 0)) {
for (size_t i = 0; i < N_Depth; ++i) {
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
indices.push_back(i);
record_arr_table(var.operator[](i), indexed_name, dimension - 1, indices);

View File

@ -161,10 +161,10 @@ public:
~VlWorkerThread();
// METHODS
template <bool SpinWait>
template <bool N_SpinWait>
void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) {
// Spin for a while, waiting for new data
if VL_CONSTEXPR_CXX17 (SpinWait) {
if VL_CONSTEXPR_CXX17 (N_SpinWait) {
for (unsigned i = 0; i < VL_LOCK_SPINS; ++i) {
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) break;
VL_CPU_RELAX();

View File

@ -164,12 +164,12 @@ inline std::string VL_TO_STRING(const VlProcessRef& p) { return std::string("pro
//===================================================================
// Activity trigger vector
template <std::size_t T_size> //
template <std::size_t N_Size> //
class VlTriggerVec final {
// TODO: static assert T_size > 0, and don't generate when empty
// TODO: static assert N_Size > 0, and don't generate when empty
// MEMBERS
alignas(16) std::array<uint64_t, roundUpToMultipleOf<64>(T_size) / 64> m_flags; // The flags
alignas(16) std::array<uint64_t, roundUpToMultipleOf<64>(N_Size) / 64> m_flags; // The flags
public:
// CONSTRUCTOR
@ -200,12 +200,12 @@ public:
}
// Set all elements true in 'this' that are set in 'other'
void thisOr(const VlTriggerVec<T_size>& other) {
void thisOr(const VlTriggerVec<N_Size>& other) {
for (size_t i = 0; i < m_flags.size(); ++i) m_flags[i] |= other.m_flags[i];
}
// Set elements of 'this' to 'a & !b' element-wise
void andNot(const VlTriggerVec<T_size>& a, const VlTriggerVec<T_size>& b) {
void andNot(const VlTriggerVec<N_Size>& a, const VlTriggerVec<N_Size>& b) {
for (size_t i = 0; i < m_flags.size(); ++i) m_flags[i] = a.m_flags[i] & ~b.m_flags[i];
}
};
@ -309,7 +309,7 @@ public:
size_t operator()() { return VL_MASK_I(31) & vl_rand64(); }
};
template <typename T_Value, uint64_t T_numValues>
template <typename T_Value, uint64_t N_NumValues>
class VlRandC final {
T_Value m_remaining = 0; // Number of values to pull before re-randomize
T_Value m_lfsr = 1; // LFSR state
@ -317,8 +317,8 @@ class VlRandC final {
public:
// CONSTRUCTORS
VlRandC() {
static_assert(T_numValues >= 1, "");
static_assert(sizeof(T_Value) == 8 || (T_numValues < (1ULL << (8 * sizeof(T_Value)))), "");
static_assert(N_NumValues >= 1, "");
static_assert(sizeof(T_Value) == 8 || (N_NumValues < (1ULL << (8 * sizeof(T_Value)))), "");
}
// METHODS
T_Value randomize(VlRNG& rngr) {
@ -337,23 +337,23 @@ public:
0x80000057ULL, // 32
0x100000029ULL // 33
};
constexpr uint32_t clogWidth = VL_CLOG2_CE_Q(T_numValues) + 1;
constexpr uint32_t clogWidth = VL_CLOG2_CE_Q(N_NumValues) + 1;
constexpr uint32_t lfsrWidth = (clogWidth < 2) ? 2 : clogWidth;
constexpr T_Value polynomial = static_cast<T_Value>(s_polynomials[lfsrWidth]);
// printf(" numV=%ld w=%d poly=%x\n", T_numValues, lfsrWidth, polynomial);
// printf(" numV=%ld w=%d poly=%x\n", N_NumValues, lfsrWidth, polynomial);
// Loop until get reasonable value. Because we picked a LFSR of at most one
// extra bit in width, this will only require at most on average 1.5 loops
do {
m_lfsr = (m_lfsr & 1ULL) ? ((m_lfsr >> 1ULL) ^ polynomial) : (m_lfsr >> 1ULL);
} while (m_lfsr > T_numValues); // Note if == then output value 0
} while (m_lfsr > N_NumValues); // Note if == then output value 0
--m_remaining;
T_Value result = (m_lfsr == T_numValues) ? 0 : m_lfsr;
// printf(" result=%x (numv=%ld, rem=%d)\n", result, T_numValues, m_remaining);
T_Value result = (m_lfsr == N_NumValues) ? 0 : m_lfsr;
// printf(" result=%x (numv=%ld, rem=%d)\n", result, N_NumValues, m_remaining);
return result;
}
void reseed(VlRNG& rngr) {
constexpr uint32_t lfsrWidth = VL_CLOG2_CE_Q(T_numValues) + 1;
m_remaining = T_numValues;
constexpr uint32_t lfsrWidth = VL_CLOG2_CE_Q(N_NumValues) + 1;
m_remaining = N_NumValues;
do {
m_lfsr = rngr.rand64() & VL_MASK_Q(lfsrWidth);
// printf(" lfsr.reseed=%x\n", m_lfsr);
@ -414,23 +414,23 @@ public:
static int _vl_cmp_w(int words, WDataInP const lwp, WDataInP const rwp) VL_PURE;
template <std::size_t T_Words>
template <std::size_t N_Words>
struct VlWide;
// Type trait to check if a type is VlWide
template <typename>
struct VlIsVlWide : public std::false_type {};
template <std::size_t T_Words>
struct VlIsVlWide<VlWide<T_Words>> : public std::true_type {};
template <std::size_t N_Words>
struct VlIsVlWide<VlWide<N_Words>> : public std::true_type {};
template <std::size_t T_Words>
template <std::size_t N_Words>
struct VlWide final {
static constexpr size_t Words = T_Words;
static constexpr size_t Words = N_Words;
// MEMBERS
// This should be the only data member, otherwise generated static initializers need updating
EData m_storage[T_Words]; // Contents of the packed array
EData m_storage[N_Words]; // Contents of the packed array
// CONSTRUCTORS
// Default constructors and destructor are used. Note however that C++20 requires that
@ -441,8 +441,8 @@ struct VlWide final {
// Default copy assignment operators are used.
operator WDataOutP() VL_PURE { return &m_storage[0]; } // This also allows []
operator WDataInP() const VL_PURE { return &m_storage[0]; } // This also allows []
bool operator!=(const VlWide<T_Words>& that) const VL_PURE {
for (size_t i = 0; i < T_Words; ++i) {
bool operator!=(const VlWide<N_Words>& that) const VL_PURE {
for (size_t i = 0; i < N_Words; ++i) {
if (m_storage[i] != that.m_storage[i]) return true;
}
return false;
@ -453,21 +453,21 @@ struct VlWide final {
EData& at(size_t index) { return m_storage[index]; }
WData* data() { return &m_storage[0]; }
const WData* data() const { return &m_storage[0]; }
bool operator<(const VlWide<T_Words>& rhs) const {
return _vl_cmp_w(T_Words, data(), rhs.data()) < 0;
bool operator<(const VlWide<N_Words>& rhs) const {
return _vl_cmp_w(N_Words, data(), rhs.data()) < 0;
}
};
// Convert a C array to std::array reference by pointer magic, without copy.
// Data type (second argument) is so the function template can automatically generate.
template <std::size_t T_Words>
VlWide<T_Words>& VL_CVT_W_A(const WDataInP inp, const VlWide<T_Words>&) {
return *((VlWide<T_Words>*)inp);
template <std::size_t N_Words>
VlWide<N_Words>& VL_CVT_W_A(const WDataInP inp, const VlWide<N_Words>&) {
return *((VlWide<N_Words>*)inp);
}
template <std::size_t T_Words>
std::string VL_TO_STRING(const VlWide<T_Words>& obj) {
return VL_TO_STRING_W(T_Words, obj.data());
template <std::size_t N_Words>
std::string VL_TO_STRING(const VlWide<N_Words>& obj) {
return VL_TO_STRING_W(N_Words, obj.data());
}
//===================================================================
@ -477,7 +477,7 @@ std::string VL_TO_STRING(const VlWide<T_Words>& obj) {
//
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
// For dynamic arrays it is always zero
template <typename T_Value, size_t T_MaxSize = 0>
template <typename T_Value, size_t N_MaxSize = 0>
class VlQueue final {
private:
// TYPES
@ -485,8 +485,8 @@ private:
public:
using const_iterator = typename Deque::const_iterator;
template <typename Func>
using WithFuncReturnType = decltype(std::declval<Func>()(0, std::declval<T_Value>()));
template <typename T_Func>
using WithFuncReturnType = decltype(std::declval<T_Func>()(0, std::declval<T_Value>()));
private:
// MEMBERS
@ -506,11 +506,11 @@ public:
bool operator!=(const VlQueue& rhs) const { return m_deque != rhs.m_deque; }
// Standard copy constructor works. Verilog: assoca = assocb
// Also must allow conversion from a different T_MaxSize queue
template <size_t U_MaxSize = 0>
VlQueue operator=(const VlQueue<T_Value, U_MaxSize>& rhs) {
// Also must allow conversion from a different N_MaxSize queue
template <size_t N_RhsMaxSize = 0>
VlQueue operator=(const VlQueue<T_Value, N_RhsMaxSize>& rhs) {
m_deque = rhs.privateDeque();
if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1);
if (VL_UNLIKELY(N_MaxSize && N_MaxSize < m_deque.size())) m_deque.resize(N_MaxSize - 1);
return *this;
}
@ -562,7 +562,7 @@ public:
m_deque.resize(size, atDefault());
}
// Dynamic array new[]() becomes a renew_copy()
void renew_copy(size_t size, const VlQueue<T_Value, T_MaxSize>& rhs) {
void renew_copy(size_t size, const VlQueue<T_Value, N_MaxSize>& rhs) {
if (size == 0) {
clear();
} else {
@ -575,11 +575,11 @@ public:
// function void q.push_front(value)
void push_front(const T_Value& value) {
m_deque.push_front(value);
if (VL_UNLIKELY(T_MaxSize != 0 && m_deque.size() > T_MaxSize)) m_deque.pop_back();
if (VL_UNLIKELY(N_MaxSize != 0 && m_deque.size() > N_MaxSize)) m_deque.pop_back();
}
// function void q.push_back(value)
void push_back(const T_Value& value) {
if (VL_LIKELY(T_MaxSize == 0 || m_deque.size() < T_MaxSize)) m_deque.push_back(value);
if (VL_LIKELY(N_MaxSize == 0 || m_deque.size() < N_MaxSize)) m_deque.push_back(value);
}
// function value_t q.pop_front();
T_Value pop_front() {
@ -600,7 +600,7 @@ public:
T_Value& atWrite(int32_t index) {
// cppcheck-suppress variableScope
static thread_local T_Value t_throwAway;
// Needs to work for dynamic arrays, so does not use T_MaxSize
// Needs to work for dynamic arrays, so does not use N_MaxSize
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
t_throwAway = atDefault();
return t_throwAway;
@ -621,7 +621,7 @@ public:
}
// Accessing. Verilog: v = assoc[index]
const T_Value& at(int32_t index) const {
// Needs to work for dynamic arrays, so does not use T_MaxSize
// Needs to work for dynamic arrays, so does not use N_MaxSize
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
return atDefault();
} else {
@ -665,8 +665,8 @@ public:
// Methods
void sort() { std::sort(m_deque.begin(), m_deque.end()); }
template <typename Func>
void sort(Func with_func) {
template <typename T_Func>
void sort(T_Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
// index number is meaningless with sort, as it changes
@ -674,8 +674,8 @@ public:
});
}
void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); }
template <typename Func>
void rsort(Func with_func) {
template <typename T_Func>
void rsort(T_Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
// index number is meaningless with sort, as it changes
@ -696,8 +696,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue unique(Func with_func) const {
template <typename T_Func>
VlQueue unique(T_Func with_func) const {
VlQueue out;
std::set<decltype(with_func(0, m_deque[0]))> saw;
for (const auto& i : m_deque) {
@ -724,8 +724,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<IData> unique_index(Func with_func) const {
template <typename T_Func>
VlQueue<IData> unique_index(T_Func with_func) const {
VlQueue<IData> out;
IData index = 0;
std::set<decltype(with_func(0, m_deque[0]))> saw;
@ -740,8 +740,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue find(Func with_func) const {
template <typename T_Func>
VlQueue find(T_Func with_func) const {
VlQueue out;
IData index = 0;
for (const auto& i : m_deque) {
@ -750,8 +750,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<IData> find_index(Func with_func) const {
template <typename T_Func>
VlQueue<IData> find_index(T_Func with_func) const {
VlQueue<IData> out;
IData index = 0;
for (const auto& i : m_deque) {
@ -760,8 +760,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue find_first(Func with_func) const {
template <typename T_Func>
VlQueue find_first(T_Func with_func) const {
// Can't use std::find_if as need index number
IData index = 0;
for (const auto& i : m_deque) {
@ -770,8 +770,8 @@ public:
}
return VlQueue{};
}
template <typename Func>
VlQueue<IData> find_first_index(Func with_func) const {
template <typename T_Func>
VlQueue<IData> find_first_index(T_Func with_func) const {
IData index = 0;
for (const auto& i : m_deque) {
if (with_func(index, i)) return VlQueue<IData>::consV(index);
@ -779,8 +779,8 @@ public:
}
return VlQueue<IData>{};
}
template <typename Func>
VlQueue find_last(Func with_func) const {
template <typename T_Func>
VlQueue find_last(T_Func with_func) const {
IData index = m_deque.size() - 1;
for (auto& item : vlstd::reverse_view(m_deque)) {
if (with_func(index, item)) return VlQueue::consV(item);
@ -788,8 +788,8 @@ public:
}
return VlQueue{};
}
template <typename Func>
VlQueue<IData> find_last_index(Func with_func) const {
template <typename T_Func>
VlQueue<IData> find_last_index(T_Func with_func) const {
IData index = m_deque.size() - 1;
for (auto& item : vlstd::reverse_view(m_deque)) {
if (with_func(index, item)) return VlQueue<IData>::consV(index);
@ -804,8 +804,8 @@ public:
const auto it = std::min_element(m_deque.cbegin(), m_deque.cend());
return VlQueue::consV(*it);
}
template <typename Func>
VlQueue min(Func with_func) const {
template <typename T_Func>
VlQueue min(T_Func with_func) const {
if (m_deque.empty()) return VlQueue{};
const auto it = std::min_element(m_deque.cbegin(), m_deque.cend(),
[&with_func](const IData& a, const IData& b) {
@ -818,8 +818,8 @@ public:
const auto it = std::max_element(m_deque.cbegin(), m_deque.cend());
return VlQueue::consV(*it);
}
template <typename Func>
VlQueue max(Func with_func) const {
template <typename T_Func>
VlQueue max(T_Func with_func) const {
if (m_deque.empty()) return VlQueue{};
const auto it = std::max_element(m_deque.cbegin(), m_deque.cend(),
[&with_func](const IData& a, const IData& b) {
@ -833,9 +833,9 @@ public:
for (const auto& i : m_deque) out += i;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_sum(Func with_func) const {
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_sum(T_Func with_func) const {
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
IData index = 0;
for (const auto& i : m_deque) out += with_func(index++, i);
return out;
@ -846,10 +846,10 @@ public:
for (const auto& i : m_deque) out *= i;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_product(Func with_func) const {
if (m_deque.empty()) return WithFuncReturnType<Func>(0); // The big three do it this way
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(1);
template <typename T_Func>
WithFuncReturnType<T_Func> r_product(T_Func with_func) const {
if (m_deque.empty()) return WithFuncReturnType<T_Func>(0); // The big three do it this way
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(1);
IData index = 0;
for (const auto& i : m_deque) out *= with_func(index++, i);
return out;
@ -860,11 +860,11 @@ public:
for (const auto& i : m_deque) out &= i;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_and(Func with_func) const {
if (m_deque.empty()) return WithFuncReturnType<Func>(0); // The big three do it this way
template <typename T_Func>
WithFuncReturnType<T_Func> r_and(T_Func with_func) const {
if (m_deque.empty()) return WithFuncReturnType<T_Func>(0); // The big three do it this way
IData index = 0;
WithFuncReturnType<Func> out = ~WithFuncReturnType<Func>(0);
WithFuncReturnType<T_Func> out = ~WithFuncReturnType<T_Func>(0);
for (const auto& i : m_deque) out &= with_func(index++, i);
return out;
}
@ -873,9 +873,9 @@ public:
for (const auto& i : m_deque) out |= i;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_or(Func with_func) const {
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_or(T_Func with_func) const {
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
IData index = 0;
for (const auto& i : m_deque) out |= with_func(index++, i);
return out;
@ -888,9 +888,9 @@ public:
for (const auto& i : m_deque) out ^= i;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_xor(Func with_func) const {
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_xor(T_Func with_func) const {
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
IData index = 0;
for (const auto& i : m_deque) out ^= with_func(index++, i);
return out;
@ -909,8 +909,8 @@ public:
}
};
template <typename T_Value, size_t T_MaxSize>
std::string VL_TO_STRING(const VlQueue<T_Value, T_MaxSize>& obj) {
template <typename T_Value, size_t N_MaxSize>
std::string VL_TO_STRING(const VlQueue<T_Value, N_MaxSize>& obj) {
return obj.to_string();
}
@ -927,9 +927,9 @@ private:
public:
using const_iterator = typename Map::const_iterator;
template <typename Func>
template <typename T_Func>
using WithFuncReturnType
= decltype(std::declval<Func>()(std::declval<T_Key>(), std::declval<T_Value>()));
= decltype(std::declval<T_Func>()(std::declval<T_Key>(), std::declval<T_Value>()));
private:
// MEMBERS
@ -1038,8 +1038,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Value> unique(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> unique(T_Func with_func) const {
VlQueue<T_Value> out;
T_Key default_key;
using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second));
@ -1066,8 +1066,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Key> unique_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> unique_index(T_Func with_func) const {
VlQueue<T_Key> out;
using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second));
std::set<WithType> saw;
@ -1081,22 +1081,22 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Value> find(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> find(T_Func with_func) const {
VlQueue<T_Value> out;
for (const auto& i : m_map)
if (with_func(i.first, i.second)) out.push_back(i.second);
return out;
}
template <typename Func>
VlQueue<T_Key> find_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> find_index(T_Func with_func) const {
VlQueue<T_Key> out;
for (const auto& i : m_map)
if (with_func(i.first, i.second)) out.push_back(i.first);
return out;
}
template <typename Func>
VlQueue<T_Value> find_first(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> find_first(T_Func with_func) const {
const auto it
= std::find_if(m_map.cbegin(), m_map.cend(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.first, i.second);
@ -1104,8 +1104,8 @@ public:
if (it == m_map.end()) return VlQueue<T_Value>{};
return VlQueue<T_Value>::consV(it->second);
}
template <typename Func>
VlQueue<T_Key> find_first_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> find_first_index(T_Func with_func) const {
const auto it
= std::find_if(m_map.cbegin(), m_map.cend(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.first, i.second);
@ -1113,16 +1113,16 @@ public:
if (it == m_map.end()) return VlQueue<T_Value>{};
return VlQueue<T_Key>::consV(it->first);
}
template <typename Func>
VlQueue<T_Value> find_last(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> find_last(T_Func with_func) const {
const auto it = std::find_if(
m_map.crbegin(), m_map.crend(),
[=](const std::pair<T_Key, T_Value>& i) { return with_func(i.first, i.second); });
if (it == m_map.rend()) return VlQueue<T_Value>{};
return VlQueue<T_Value>::consV(it->second);
}
template <typename Func>
VlQueue<T_Key> find_last_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> find_last_index(T_Func with_func) const {
const auto it = std::find_if(
m_map.crbegin(), m_map.crend(),
[=](const std::pair<T_Key, T_Value>& i) { return with_func(i.first, i.second); });
@ -1140,8 +1140,8 @@ public:
});
return VlQueue<T_Value>::consV(it->second);
}
template <typename Func>
VlQueue<T_Value> min(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> min(T_Func with_func) const {
if (m_map.empty()) return VlQueue<T_Value>();
const auto it = std::min_element(
m_map.cbegin(), m_map.cend(),
@ -1159,8 +1159,8 @@ public:
});
return VlQueue<T_Value>::consV(it->second);
}
template <typename Func>
VlQueue<T_Value> max(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> max(T_Func with_func) const {
if (m_map.empty()) return VlQueue<T_Value>();
const auto it = std::max_element(
m_map.cbegin(), m_map.cend(),
@ -1175,9 +1175,9 @@ public:
for (const auto& i : m_map) out += i.second;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_sum(Func with_func) const {
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_sum(T_Func with_func) const {
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
for (const auto& i : m_map) out += with_func(i.first, i.second);
return out;
}
@ -1187,10 +1187,10 @@ public:
for (const auto& i : m_map) out *= i.second;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_product(Func with_func) const {
if (m_map.empty()) return WithFuncReturnType<Func>(0); // The big three do it this way
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(1);
template <typename T_Func>
WithFuncReturnType<T_Func> r_product(T_Func with_func) const {
if (m_map.empty()) return WithFuncReturnType<T_Func>(0); // The big three do it this way
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(1);
for (const auto& i : m_map) out *= with_func(i.first, i.second);
return out;
}
@ -1200,10 +1200,10 @@ public:
for (const auto& i : m_map) out &= i.second;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_and(Func with_func) const {
if (m_map.empty()) return WithFuncReturnType<Func>(0); // The big three do it this way
WithFuncReturnType<Func> out = ~WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_and(T_Func with_func) const {
if (m_map.empty()) return WithFuncReturnType<T_Func>(0); // The big three do it this way
WithFuncReturnType<T_Func> out = ~WithFuncReturnType<T_Func>(0);
for (const auto& i : m_map) out &= with_func(i.first, i.second);
return out;
}
@ -1212,8 +1212,8 @@ public:
for (const auto& i : m_map) out |= i.second;
return out;
}
template <typename Func>
T_Value r_or(Func with_func) const {
template <typename T_Func>
T_Value r_or(T_Func with_func) const {
T_Value out = T_Value(0);
for (const auto& i : m_map) out |= with_func(i.first, i.second);
return out;
@ -1223,9 +1223,9 @@ public:
for (const auto& i : m_map) out ^= i.second;
return out;
}
template <typename Func>
WithFuncReturnType<Func> r_xor(Func with_func) const {
WithFuncReturnType<Func> out = WithFuncReturnType<Func>(0);
template <typename T_Func>
WithFuncReturnType<T_Func> r_xor(T_Func with_func) const {
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
for (const auto& i : m_map) out ^= with_func(i.first, i.second);
return out;
}
@ -1287,11 +1287,11 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
/// This class may get exposed to a Verilated Model's top I/O, if the top
/// IO has an unpacked array.
template <typename T_Value, std::size_t T_Depth>
template <typename T_Value, std::size_t N_Depth>
class VlUnpacked final {
// TYPES
using T_Key = IData; // Index type, for uniformity with other containers
using Unpacked = T_Value[T_Depth];
using Unpacked = T_Value[N_Depth];
public:
// MEMBERS
@ -1312,41 +1312,41 @@ public:
WData* data() { return &m_storage[0]; }
const WData* data() const { return &m_storage[0]; }
std::size_t size() const { return T_Depth; }
std::size_t size() const { return N_Depth; }
// To fit C++14
template <std::size_t CurrentDimension = 0, typename U = T_Value>
template <std::size_t N_CurrentDimension = 0, typename U = T_Value>
int find_length(int dimension, std::false_type) const {
return size();
}
template <std::size_t CurrentDimension = 0, typename U = T_Value>
template <std::size_t N_CurrentDimension = 0, typename U = T_Value>
int find_length(int dimension, std::true_type) const {
if (dimension == CurrentDimension) {
if (dimension == N_CurrentDimension) {
return size();
} else {
return m_storage[0].template find_length<CurrentDimension + 1>(dimension);
return m_storage[0].template find_length<N_CurrentDimension + 1>(dimension);
}
}
template <std::size_t CurrentDimension = 0>
template <std::size_t N_CurrentDimension = 0>
int find_length(int dimension) const {
return find_length<CurrentDimension>(dimension, std::is_class<T_Value>{});
return find_length<N_CurrentDimension>(dimension, std::is_class<T_Value>{});
}
template <std::size_t CurrentDimension = 0, typename U = T_Value>
template <std::size_t N_CurrentDimension = 0, typename U = T_Value>
auto& find_element(const std::vector<size_t>& indices, std::false_type) {
return m_storage[indices[CurrentDimension]];
return m_storage[indices[N_CurrentDimension]];
}
template <std::size_t CurrentDimension = 0, typename U = T_Value>
template <std::size_t N_CurrentDimension = 0, typename U = T_Value>
auto& find_element(const std::vector<size_t>& indices, std::true_type) {
return m_storage[indices[CurrentDimension]].template find_element<CurrentDimension + 1>(
indices);
return m_storage[indices[N_CurrentDimension]]
.template find_element<N_CurrentDimension + 1>(indices);
}
template <std::size_t CurrentDimension = 0>
template <std::size_t N_CurrentDimension = 0>
auto& find_element(const std::vector<size_t>& indices) {
return find_element<CurrentDimension>(indices, std::is_class<T_Value>{});
return find_element<N_CurrentDimension>(indices, std::is_class<T_Value>{});
}
T_Value& operator[](size_t index) { return m_storage[index]; }
@ -1354,15 +1354,15 @@ public:
// *this != that, which might be used for change detection/trigger computation, but avoid
// operator overloading in VlUnpacked for safety in other contexts.
bool neq(const VlUnpacked<T_Value, T_Depth>& that) const { return neq(*this, that); }
bool neq(const VlUnpacked<T_Value, N_Depth>& that) const { return neq(*this, that); }
// Similar to 'neq' above, *this = that used for change detection
void assign(const VlUnpacked<T_Value, T_Depth>& that) { *this = that; }
bool operator==(const VlUnpacked<T_Value, T_Depth>& that) const { return !neq(that); }
bool operator!=(const VlUnpacked<T_Value, T_Depth>& that) const { return neq(that); }
void assign(const VlUnpacked<T_Value, N_Depth>& that) { *this = that; }
bool operator==(const VlUnpacked<T_Value, N_Depth>& that) const { return !neq(that); }
bool operator!=(const VlUnpacked<T_Value, N_Depth>& that) const { return neq(that); }
// interface to C style arrays (used in ports), see issue #5125
bool neq(const T_Value that[T_Depth]) const { return neq(*this, that); }
void assign(const T_Value that[T_Depth]) { std::copy_n(that, T_Depth, m_storage); }
void operator=(const T_Value that[T_Depth]) { assign(that); }
bool neq(const T_Value that[N_Depth]) const { return neq(*this, that); }
void assign(const T_Value that[N_Depth]) { std::copy_n(that, N_Depth, m_storage); }
void operator=(const T_Value that[N_Depth]) { assign(that); }
// inside (set membership operator)
bool inside(const T_Value& value) const {
@ -1370,8 +1370,8 @@ public:
}
void sort() { std::sort(std::begin(m_storage), std::end(m_storage)); }
template <typename Func>
void sort(Func with_func) {
template <typename T_Func>
void sort(T_Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
std::sort(std::begin(m_storage), std::end(m_storage),
[=](const T_Value& a, const T_Value& b) {
@ -1383,8 +1383,8 @@ public:
void rsort() {
std::sort(std::begin(m_storage), std::end(m_storage), std::greater<T_Value>());
}
template <typename Func>
void rsort(Func with_func) {
template <typename T_Func>
void rsort(T_Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
// std::rbegin/std::rend not available until C++14, so using > below
std::sort(std::begin(m_storage), std::end(m_storage),
@ -1407,8 +1407,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Value> unique(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> unique(T_Func with_func) const {
VlQueue<T_Value> out;
std::set<T_Value> saw;
for (const auto& i : m_storage) {
@ -1435,8 +1435,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Key> unique_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> unique_index(T_Func with_func) const {
VlQueue<T_Key> out;
IData index = 0;
std::set<T_Value> saw;
@ -1451,8 +1451,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Value> find(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> find(T_Func with_func) const {
VlQueue<T_Value> out;
IData index = 0;
for (const auto& i : m_storage) {
@ -1461,8 +1461,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Key> find_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> find_index(T_Func with_func) const {
VlQueue<T_Key> out;
IData index = 0;
for (const auto& i : m_storage) {
@ -1471,8 +1471,8 @@ public:
}
return out;
}
template <typename Func>
VlQueue<T_Value> find_first(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> find_first(T_Func with_func) const {
// Can't use std::find_if as need index number
IData index = 0;
for (const auto& i : m_storage) {
@ -1481,8 +1481,8 @@ public:
}
return VlQueue<T_Value>{};
}
template <typename Func>
VlQueue<T_Key> find_first_index(Func with_func) const {
template <typename T_Func>
VlQueue<T_Key> find_first_index(T_Func with_func) const {
IData index = 0;
for (const auto& i : m_storage) {
if (with_func(index, i)) return VlQueue<IData>::consV(index);
@ -1490,16 +1490,16 @@ public:
}
return VlQueue<T_Key>{};
}
template <typename Func>
VlQueue<T_Value> find_last(Func with_func) const {
for (int i = T_Depth - 1; i >= 0; i--) {
template <typename T_Func>
VlQueue<T_Value> find_last(T_Func with_func) const {
for (int i = N_Depth - 1; i >= 0; i--) {
if (with_func(i, m_storage[i])) return VlQueue<T_Value>::consV(m_storage[i]);
}
return VlQueue<T_Value>{};
}
template <typename Func>
VlQueue<T_Key> find_last_index(Func with_func) const {
for (int i = T_Depth - 1; i >= 0; i--) {
template <typename T_Func>
VlQueue<T_Key> find_last_index(T_Func with_func) const {
for (int i = N_Depth - 1; i >= 0; i--) {
if (with_func(i, m_storage[i])) return VlQueue<IData>::consV(i);
}
return VlQueue<T_Key>{};
@ -1510,8 +1510,8 @@ public:
const auto it = std::min_element(std::begin(m_storage), std::end(m_storage));
return VlQueue<T_Value>::consV(*it);
}
template <typename Func>
VlQueue<T_Value> min(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> min(T_Func with_func) const {
const auto it = std::min_element(std::begin(m_storage), std::end(m_storage),
[&with_func](const IData& a, const IData& b) {
return with_func(0, a) < with_func(0, b);
@ -1522,8 +1522,8 @@ public:
const auto it = std::max_element(std::begin(m_storage), std::end(m_storage));
return VlQueue<T_Value>::consV(*it);
}
template <typename Func>
VlQueue<T_Value> max(Func with_func) const {
template <typename T_Func>
VlQueue<T_Value> max(T_Func with_func) const {
const auto it = std::max_element(std::begin(m_storage), std::end(m_storage),
[&with_func](const IData& a, const IData& b) {
return with_func(0, a) < with_func(0, b);
@ -1535,7 +1535,7 @@ public:
std::string to_string() const {
std::string out = "'{";
std::string comma;
for (int i = 0; i < T_Depth; ++i) {
for (int i = 0; i < N_Depth; ++i) {
out += comma + VL_TO_STRING(m_storage[i]);
comma = ", ";
}
@ -1543,18 +1543,18 @@ public:
}
private:
template <typename T_Val, std::size_t T_Dep>
static bool neq(const VlUnpacked<T_Val, T_Dep>& a, const VlUnpacked<T_Val, T_Dep>& b) {
for (size_t i = 0; i < T_Dep; ++i) {
template <typename T_Val, std::size_t N_Dep>
static bool neq(const VlUnpacked<T_Val, N_Dep>& a, const VlUnpacked<T_Val, N_Dep>& b) {
for (size_t i = 0; i < N_Dep; ++i) {
// Recursive 'neq', in case T_Val is also a VlUnpacked<_, _>
if (neq(a.m_storage[i], b.m_storage[i])) return true;
}
return false;
}
template <typename T_Val, std::size_t T_Dep>
static bool neq(const VlUnpacked<T_Val, T_Dep>& a, const T_Val b[T_Dep]) {
for (size_t i = 0; i < T_Dep; ++i) {
template <typename T_Val, std::size_t N_Dep>
static bool neq(const VlUnpacked<T_Val, N_Dep>& a, const T_Val b[N_Dep]) {
for (size_t i = 0; i < N_Dep; ++i) {
// Recursive 'neq', in case T_Val is also a VlUnpacked<_, _>
if (neq(a.m_storage[i], b[i])) return true;
}
@ -1568,25 +1568,25 @@ private:
}
};
template <typename T_Value, std::size_t T_Depth>
std::string VL_TO_STRING(const VlUnpacked<T_Value, T_Depth>& obj) {
template <typename T_Value, std::size_t N_Depth>
std::string VL_TO_STRING(const VlUnpacked<T_Value, N_Depth>& obj) {
return obj.to_string();
}
//===================================================================
// Helper to apply the given indices to a target expression
template <size_t Curr, size_t Rank, typename T_Target>
template <size_t N_Curr, size_t N_Rank, typename T_Target>
struct VlApplyIndices final {
VL_ATTR_ALWINLINE
static auto& apply(T_Target& target, const size_t* indicesp) {
return VlApplyIndices<Curr + 1, Rank, decltype(target[indicesp[Curr]])>::apply(
target[indicesp[Curr]], indicesp);
return VlApplyIndices<N_Curr + 1, N_Rank, decltype(target[indicesp[N_Curr]])>::apply(
target[indicesp[N_Curr]], indicesp);
}
};
template <size_t Rank, typename T_Target>
struct VlApplyIndices<Rank, Rank, T_Target> final {
template <size_t N_Rank, typename T_Target>
struct VlApplyIndices<N_Rank, N_Rank, T_Target> final {
VL_ATTR_ALWINLINE
static T_Target& apply(T_Target& target, const size_t*) { return target; }
};
@ -1621,17 +1621,17 @@ template <typename T_Target, // Type of the variable this commit queue updates
// The following we could figure out from 'T_Target using type traits, but passing
// explicitly to avoid template expansion, as Verilator already knows them
typename T_Element, // Non-array leaf element type of T_Target array
std::size_t T_Rank // Rank of T_Target (i.e.: how many dimensions it has)
std::size_t N_Rank // Rank of T_Target (i.e.: how many dimensions it has)
>
class VlNBACommitQueue;
// Specialization for whole element updates only
template <typename T_Target, typename T_Element, std::size_t T_Rank>
class VlNBACommitQueue<T_Target, /* Partial: */ false, T_Element, T_Rank> final {
template <typename T_Target, typename T_Element, std::size_t N_Rank>
class VlNBACommitQueue<T_Target, /* Partial: */ false, T_Element, N_Rank> final {
// TYPES
struct Entry final {
T_Element value;
size_t indices[T_Rank];
size_t indices[N_Rank];
};
// STATE
@ -1643,8 +1643,8 @@ public:
VL_UNCOPYABLE(VlNBACommitQueue);
// METHODS
template <typename... Args>
void enqueue(const T_Element& value, Args... indices) {
template <typename... T_Args>
void enqueue(const T_Element& value, T_Args... indices) {
m_pending.emplace_back(Entry{value, {indices...}});
}
@ -1654,20 +1654,20 @@ public:
void commit(T_Commit& target) {
if (m_pending.empty()) return;
for (const Entry& entry : m_pending) {
VlApplyIndices<0, T_Rank, T_Commit>::apply(target, entry.indices) = entry.value;
VlApplyIndices<0, N_Rank, T_Commit>::apply(target, entry.indices) = entry.value;
}
m_pending.clear();
}
};
// With partial element updates
template <typename T_Target, typename T_Element, std::size_t T_Rank>
class VlNBACommitQueue<T_Target, /* Partial: */ true, T_Element, T_Rank> final {
template <typename T_Target, typename T_Element, std::size_t N_Rank>
class VlNBACommitQueue<T_Target, /* Partial: */ true, T_Element, N_Rank> final {
// TYPES
struct Entry final {
T_Element value;
T_Element mask;
size_t indices[T_Rank];
size_t indices[N_Rank];
};
// STATE
@ -1728,8 +1728,8 @@ public:
VL_UNCOPYABLE(VlNBACommitQueue);
// METHODS
template <typename... Args>
void enqueue(const T_Element& value, const T_Element& mask, Args... indices) {
template <typename... T_Args>
void enqueue(const T_Element& value, const T_Element& mask, T_Args... indices) {
m_pending.emplace_back(Entry{value, mask, {indices...}});
}
@ -1739,7 +1739,7 @@ public:
void commit(T_Commit& target) {
if (m_pending.empty()) return;
for (const Entry& entry : m_pending) { //
auto& ref = VlApplyIndices<0, T_Rank, T_Commit>::apply(target, entry.indices);
auto& ref = VlApplyIndices<0, N_Rank, T_Commit>::apply(target, entry.indices);
// Maybe inefficient, but it works for now ...
const auto oldValue = ref;
ref = bOr(bAnd(entry.value, entry.mask), bAnd(oldValue, bNot(entry.mask)));
@ -1961,13 +1961,13 @@ public:
};
};
template <typename T, typename U>
static inline bool VL_CAST_DYNAMIC(VlClassRef<T> in, VlClassRef<U>& outr) {
template <typename T_Lhs, typename T_Out>
static inline bool VL_CAST_DYNAMIC(VlClassRef<T_Lhs> in, VlClassRef<T_Out>& outr) {
if (!in) {
outr = VlNull{};
return true;
}
VlClassRef<U> casted = in.template dynamicCast<U>();
VlClassRef<T_Out> casted = in.template dynamicCast<T_Out>();
if (VL_LIKELY(casted)) {
outr = casted;
return true;
@ -1976,8 +1976,8 @@ static inline bool VL_CAST_DYNAMIC(VlClassRef<T> in, VlClassRef<U>& outr) {
}
}
template <typename T>
static inline bool VL_CAST_DYNAMIC(VlNull in, VlClassRef<T>& outr) {
template <typename T_Lhs>
static inline bool VL_CAST_DYNAMIC(VlNull in, VlClassRef<T_Lhs>& outr) {
outr = VlNull{};
return true;
}

View File

@ -230,7 +230,7 @@ class ActiveNamer final : public VNVisitor {
void visit(AstNode* nodep) override { iterateChildren(nodep); }
// Specialized below for the special sensitivity classes
template <typename SenItemKind>
template <typename T_SenItemKind>
AstActive*& getSpecialActive();
public:
@ -246,17 +246,17 @@ public:
}
// Make a new AstActive sensitive to the given special sensitivity class and return it
template <typename SenItemKind>
template <typename T_SenItemKind>
AstActive* makeSpecialActive(FileLine* const fl) {
AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, SenItemKind{}}};
AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, T_SenItemKind{}}};
return makeActive(fl, senTreep);
}
// Return an AstActive sensitive to the given special sensitivity class (possibly pre-created)
template <typename SenItemKind>
template <typename T_SenItemKind>
AstActive* getSpecialActive(FileLine* fl) {
AstActive*& cachep = getSpecialActive<SenItemKind>();
if (!cachep) cachep = makeSpecialActive<SenItemKind>(fl);
AstActive*& cachep = getSpecialActive<T_SenItemKind>();
if (!cachep) cachep = makeSpecialActive<T_SenItemKind>(fl);
return cachep;
}

View File

@ -2553,21 +2553,21 @@ protected:
inline static bool privateTypeTest(const AstNode* nodep);
// For internal use only.
template <typename TargetType, typename DeclType>
template <typename T_TargetType, typename T_DeclType>
constexpr static bool uselessCast() VL_PURE {
using NonRef = typename std::remove_reference<DeclType>::type;
using NonRef = typename std::remove_reference<T_DeclType>::type;
using NonPtr = typename std::remove_pointer<NonRef>::type;
using NonCV = typename std::remove_cv<NonPtr>::type;
return std::is_base_of<TargetType, NonCV>::value;
return std::is_base_of<T_TargetType, NonCV>::value;
}
// For internal use only.
template <typename TargetType, typename DeclType>
template <typename T_TargetType, typename T_DeclType>
constexpr static bool impossibleCast() VL_PURE {
using NonRef = typename std::remove_reference<DeclType>::type;
using NonRef = typename std::remove_reference<T_DeclType>::type;
using NonPtr = typename std::remove_pointer<NonRef>::type;
using NonCV = typename std::remove_cv<NonPtr>::type;
return !std::is_base_of<NonCV, TargetType>::value;
return !std::is_base_of<NonCV, T_TargetType>::value;
}
public:
@ -2655,12 +2655,12 @@ private:
using ConstCorrectAstNode =
typename std::conditional<std::is_const<T_Arg>::value, const AstNode, AstNode>::type;
template <typename T_Arg, typename Callable>
inline static void foreachImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& f,
template <typename T_Arg, typename T_Callable>
inline static void foreachImpl(ConstCorrectAstNode<T_Arg>* nodep, const T_Callable& f,
bool visitNext);
template <typename T_Arg, bool Default, typename Callable>
inline static bool predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& p);
template <typename T_Arg, bool N_Default, typename T_Callable>
inline static bool predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const T_Callable& p);
public:
// Given a callable 'f' that takes a single argument of some AstNode subtype 'T_Node', traverse
@ -2670,46 +2670,48 @@ public:
// handle a single (or a few) node types, as it's easier to write, but more importantly, the
// dispatch to the callable in 'foreach' should be completely predictable by branch target
// caches in modern CPUs, while it is basically unpredictable for VNVisitor.
template <typename Callable>
void foreach(Callable&& f) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable<Callable, T_Node*>::value
template <typename T_Callable>
void foreach(T_Callable&& f) {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable<T_Callable, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(T_Node*)', "
"T_Callable 'f' must have a signature compatible with 'void(T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
foreachImpl<T_Node>(this, f, /* visitNext: */ false);
}
// Same as above, but for 'const' nodes
template <typename Callable>
void foreach(Callable&& f) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable<Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
template <typename T_Callable>
void foreach(T_Callable&& f) const {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(
vlstd::is_invocable<T_Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"T_Callable 'f' must have a signature compatible with 'void(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
foreachImpl<const T_Node>(this, f, /* visitNext: */ false);
}
// Same as 'foreach' but also traverses 'this->nextp()' transitively
template <typename Callable>
void foreachAndNext(Callable&& f) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable<Callable, T_Node*>::value
template <typename T_Callable>
void foreachAndNext(T_Callable&& f) {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable<T_Callable, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(T_Node*)', "
"T_Callable 'f' must have a signature compatible with 'void(T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
foreachImpl<T_Node>(this, f, /* visitNext: */ true);
}
// Same as above, but for 'const' nodes
template <typename Callable>
void foreachAndNext(Callable&& f) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable<Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
template <typename T_Callable>
void foreachAndNext(T_Callable&& f) const {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(
vlstd::is_invocable<T_Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"T_Callable 'f' must have a signature compatible with 'void(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
foreachImpl<const T_Node>(this, f, /* visitNext: */ true);
}
@ -2718,50 +2720,50 @@ public:
// that satisfies the predicate 'p'. Returns false if no node of type 'T_Node' is present.
// Traversal is performed in some arbitrary order and is terminated as soon as the result can
// be determined.
template <typename Callable>
bool exists(Callable&& p) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, T_Node*>::value
template <typename T_Callable>
bool exists(T_Callable&& p) {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, T_Callable, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
return predicateImpl<T_Node, /* Default: */ false>(this, p);
return predicateImpl<T_Node, /* N_Default: */ false>(this, p);
}
// Same as above, but for 'const' nodes
template <typename Callable>
bool exists(Callable&& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, const T_Node*>::value
template <typename T_Callable>
bool exists(T_Callable&& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, T_Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
return predicateImpl<const T_Node, /* Default: */ false>(this, p);
return predicateImpl<const T_Node, /* N_Default: */ false>(this, p);
}
// Given a predicate 'p' that takes a single argument of some AstNode subtype 'T_Node', return
// true if and only if all nodes of type 'T_Node' in the tree rooted at this node satisfy the
// predicate 'p'. Returns true if no node of type 'T_Node' is present. Traversal is performed
// in some arbitrary order and is terminated as soon as the result can be determined.
template <typename Callable>
bool forall(Callable&& p) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, T_Node*>::value
template <typename T_Callable>
bool forall(T_Callable&& p) {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, T_Callable, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
return predicateImpl<T_Node, /* Default: */ true>(this, p);
return predicateImpl<T_Node, /* N_Default: */ true>(this, p);
}
// Same as above, but for 'const' nodes
template <typename Callable>
bool forall(Callable&& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, const T_Node*>::value
template <typename T_Callable>
bool forall(T_Callable&& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 0>::type;
static_assert(vlstd::is_invocable_r<bool, T_Callable, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
return predicateImpl<const T_Node, /* Default: */ true>(this, p);
return predicateImpl<const T_Node, /* N_Default: */ true>(this, p);
}
int nodeCount() const {
@ -2834,8 +2836,8 @@ constexpr bool AstNode::isLeaf<AstVarXRef>() {
}
// foreach implementation
template <typename T_Arg, typename Callable>
void AstNode::foreachImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& f, bool visitNext) {
template <typename T_Arg, typename T_Callable>
void AstNode::foreachImpl(ConstCorrectAstNode<T_Arg>* nodep, const T_Callable& f, bool visitNext) {
// Pre-order traversal implemented directly (without recursion) for speed reasons. The very
// first iteration (the one that operates on the input nodep) is special, as we might or
// might not need to enqueue nodep->nextp() depending on VisitNext, while in all other
@ -2915,8 +2917,8 @@ void AstNode::foreachImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& f,
}
// predicate implementation
template <typename T_Arg, bool Default, typename Callable>
bool AstNode::predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& p) {
template <typename T_Arg, bool N_Default, typename T_Callable>
bool AstNode::predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const T_Callable& p) {
// Implementation similar to foreach, but abort traversal as soon as result is determined
using T_Arg_NonConst = typename std::remove_const<T_Arg>::type;
using Node = ConstCorrectAstNode<T_Arg>;
@ -2951,7 +2953,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& p
// Type test this node
if (AstNode::privateTypeTest<T_Arg_NonConst>(currp)) {
// Call the client function
if (p(static_cast<T_Arg*>(currp)) != Default) return true;
if (p(static_cast<T_Arg*>(currp)) != N_Default) return true;
// Short circuit if iterating leaf nodes
if VL_CONSTEXPR_CXX17 (isLeaf<T_Arg_NonConst>()) return false;
}
@ -2968,7 +2970,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& p
};
// Visit the root node
if (visit(nodep)) return !Default;
if (visit(nodep)) return !N_Default;
// Visit the rest of the tree
while (VL_LIKELY(topp > basep)) {
@ -2985,10 +2987,10 @@ bool AstNode::predicateImpl(ConstCorrectAstNode<T_Arg>* nodep, const Callable& p
if (headp->nextp()) *topp++ = headp->nextp();
// Visit the head node
if (visit(headp)) return !Default;
if (visit(headp)) return !N_Default;
}
return Default;
return N_Default;
}
inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) {

View File

@ -2401,13 +2401,13 @@ public:
// Iterates top level members of the class, taking into account inheritance (starting from the
// root superclass). Note: after V3Scope, several children are moved under an AstScope and will
// not be found by this.
template <typename Callable>
void foreachMember(const Callable& f) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 1>::type;
template <typename T_Callable>
void foreachMember(const T_Callable& f) {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 1>::type;
static_assert(
vlstd::is_invocable<Callable, AstClass*, T_Node*>::value
vlstd::is_invocable<T_Callable, AstClass*, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
"T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const cextendsp = this->extendsp()) {
cextendsp->classp()->foreachMember(f);
@ -2417,13 +2417,14 @@ public:
}
}
// Same as above, but stops after first match
template <typename Callable>
bool existsMember(const Callable& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 1>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, const AstClass*, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
template <typename T_Callable>
bool existsMember(const T_Callable& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 1>::type;
static_assert(
vlstd::is_invocable_r<bool, T_Callable, const AstClass*, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const cextendsp = this->extendsp()) {
if (cextendsp->classp()->existsMember(p)) return true;
}

View File

@ -27,22 +27,22 @@
#include <utility>
#include <vector>
template <typename T_Node, typename T_Data, int T_UserN>
template <typename T_Node, typename T_Data, int N_UserN>
class AstUserAllocatorBase VL_NOT_FINAL {
static_assert(1 <= T_UserN && T_UserN <= 4, "Wrong user pointer number");
static_assert(1 <= N_UserN && N_UserN <= 4, "Wrong user pointer number");
static_assert(std::is_base_of<AstNode, T_Node>::value, "T_Node must be an AstNode type");
private:
std::deque<T_Data> m_allocated;
T_Data* getUserp(const T_Node* nodep) const {
if VL_CONSTEXPR_CXX17 (T_UserN == 1) {
if VL_CONSTEXPR_CXX17 (N_UserN == 1) {
const VNUser user = nodep->user1u();
return user.to<T_Data*>();
} else if VL_CONSTEXPR_CXX17 (T_UserN == 2) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 2) {
const VNUser user = nodep->user2u();
return user.to<T_Data*>();
} else if VL_CONSTEXPR_CXX17 (T_UserN == 3) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 3) {
const VNUser user = nodep->user3u();
return user.to<T_Data*>();
} else {
@ -52,11 +52,11 @@ private:
}
void setUserp(T_Node* nodep, T_Data* userp) const {
if VL_CONSTEXPR_CXX17 (T_UserN == 1) {
if VL_CONSTEXPR_CXX17 (N_UserN == 1) {
nodep->user1u(VNUser{userp});
} else if VL_CONSTEXPR_CXX17 (T_UserN == 2) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 2) {
nodep->user2u(VNUser{userp});
} else if VL_CONSTEXPR_CXX17 (T_UserN == 3) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 3) {
nodep->user3u(VNUser{userp});
} else {
nodep->user4u(VNUser{userp});
@ -65,11 +65,11 @@ private:
protected:
AstUserAllocatorBase() {
if VL_CONSTEXPR_CXX17 (T_UserN == 1) {
if VL_CONSTEXPR_CXX17 (N_UserN == 1) {
VNUser1InUse::check();
} else if VL_CONSTEXPR_CXX17 (T_UserN == 2) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 2) {
VNUser2InUse::check();
} else if VL_CONSTEXPR_CXX17 (T_UserN == 3) {
} else if VL_CONSTEXPR_CXX17 (N_UserN == 3) {
VNUser3InUse::check();
} else {
VNUser4InUse::check();

View File

@ -534,17 +534,17 @@ class DelayedVisitor final : public VNVisitor {
}
// Scheme::ValueQueuePartial/Scheme::ValueQueueWhole
template <bool Partial>
template <bool N_Partial>
void prepareSchemeValueQueue(AstVarScope* vscp, VarScopeInfo& vscpInfo) {
UASSERT_OBJ(Partial ? vscpInfo.m_scheme == Scheme::ValueQueuePartial
: vscpInfo.m_scheme == Scheme::ValueQueueWhole,
UASSERT_OBJ(N_Partial ? vscpInfo.m_scheme == Scheme::ValueQueuePartial
: vscpInfo.m_scheme == Scheme::ValueQueueWhole,
vscp, "Inconsisten<t NBA s>cheme");
FileLine* const flp = vscp->fileline();
AstScope* const scopep = vscp->scopep();
// Create the commit queue variable
auto* const cqDTypep
= new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), Partial};
= new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), N_Partial};
v3Global.rootp()->typeTablep()->addTypesp(cqDTypep);
const std::string name = "__VdlyCommitQueue" + vscp->varp()->shortName();
AstVarScope* const queueVscp = createTemp(flp, scopep, name, cqDTypep);

View File

@ -427,52 +427,52 @@ public:
// Implementation of dataflow graph vertices with a fixed number of sources
//------------------------------------------------------------------------------
template <size_t Arity>
template <size_t N_Arity>
class DfgVertexWithArity VL_NOT_FINAL : public DfgVertex {
static_assert(1 <= Arity && Arity <= 4, "Arity must be between 1 and 4 inclusive");
static_assert(1 <= N_Arity && N_Arity <= 4, "N_Arity must be between 1 and 4 inclusive");
std::array<DfgEdge, Arity> m_srcs; // Source edges
std::array<DfgEdge, N_Arity> m_srcs; // Source edges
protected:
DfgVertexWithArity(DfgGraph& dfg, VDfgType type, FileLine* flp, AstNodeDType* dtypep)
: DfgVertex{dfg, type, flp, dtypep} {
// Initialize source edges
for (size_t i = 0; i < Arity; ++i) m_srcs[i].init(this);
for (size_t i = 0; i < N_Arity; ++i) m_srcs[i].init(this);
}
~DfgVertexWithArity() override = default;
public:
std::pair<DfgEdge*, size_t> sourceEdges() final override { //
return {m_srcs.data(), Arity};
return {m_srcs.data(), N_Arity};
}
std::pair<const DfgEdge*, size_t> sourceEdges() const final override {
return {m_srcs.data(), Arity};
return {m_srcs.data(), N_Arity};
}
template <size_t Index>
template <size_t N_Index>
DfgEdge* sourceEdge() {
static_assert(Index < Arity, "Source index out of range");
return &m_srcs[Index];
static_assert(N_Index < N_Arity, "Source index out of range");
return &m_srcs[N_Index];
}
template <size_t Index>
template <size_t N_Index>
const DfgEdge* sourceEdge() const {
static_assert(Index < Arity, "Source index out of range");
return &m_srcs[Index];
static_assert(N_Index < N_Arity, "Source index out of range");
return &m_srcs[N_Index];
}
template <size_t Index>
template <size_t N_Index>
DfgVertex* source() const {
static_assert(Index < Arity, "Source index out of range");
return m_srcs[Index].sourcep();
static_assert(N_Index < N_Arity, "Source index out of range");
return m_srcs[N_Index].sourcep();
}
template <size_t Index>
template <size_t N_Index>
void relinkSource(DfgVertex* newSourcep) {
static_assert(Index < Arity, "Source index out of range");
UASSERT_OBJ(m_srcs[Index].sinkp() == this, this, "Inconsistent");
m_srcs[Index].relinkSource(newSourcep);
static_assert(N_Index < N_Arity, "Source index out of range");
UASSERT_OBJ(m_srcs[N_Index].sinkp() == this, this, "Inconsistent");
m_srcs[N_Index].relinkSource(newSourcep);
}
};

View File

@ -37,9 +37,9 @@ namespace {
// Create a DfgVertex out of a AstNodeExpr. For most AstNodeExpr subtypes, this can be done
// automatically. For the few special cases, we provide specializations below
template <typename Vertex, typename Node>
Vertex* makeVertex(const Node* nodep, DfgGraph& dfg) {
return new Vertex{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)};
template <typename T_Vertex, typename T_Node>
T_Vertex* makeVertex(const T_Node* nodep, DfgGraph& dfg) {
return new T_Vertex{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)};
}
//======================================================================

View File

@ -157,8 +157,8 @@ public:
};
};
template <typename Key, typename Val>
using Cache = std::unordered_map<Key, Val, typename Key::Hash, typename Key::Equal>;
template <typename T_Key, typename T_Val>
using Cache = std::unordered_map<T_Key, T_Val, typename T_Key::Hash, typename T_Key::Equal>;
using CacheSel = Cache<KeySel, DfgSel*>;
using CacheUnary = Cache<KeyUnary, DfgVertexUnary*>;
@ -246,10 +246,10 @@ inline void setOperands(DfgVertexTernary* vtxp, DfgVertex* src0p, DfgVertex* src
}
// Get or create (and insert) vertex with given operands
template <typename Vertex, typename Cache, typename... Operands>
inline Vertex* getOrCreate(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep, Cache& cache,
template <typename Vertex, typename T_Cache, typename... Operands>
inline Vertex* getOrCreate(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep, T_Cache& cache,
Operands... operands) {
typename Cache::mapped_type& entrypr = getEntry(cache, dtypep, operands...);
typename T_Cache::mapped_type& entrypr = getEntry(cache, dtypep, operands...);
if (!entrypr) {
Vertex* const newp = new Vertex{dfg, flp, dtypep};
setOperands(newp, operands...);

View File

@ -40,9 +40,9 @@ namespace {
// Create an AstNodeExpr out of a DfgVertex. For most AstNodeExpr subtypes, this can be done
// automatically. For the few special cases, we provide specializations below
template <typename Node, typename Vertex, typename... Ops>
Node* makeNode(const Vertex* vtxp, Ops... ops) {
Node* const nodep = new Node{vtxp->fileline(), ops...};
template <typename T_Node, typename T_Vertex, typename... Ops>
T_Node* makeNode(const T_Vertex* vtxp, Ops... ops) {
T_Node* const nodep = new T_Node{vtxp->fileline(), ops...};
UASSERT_OBJ(nodep->width() == static_cast<int>(vtxp->width()), vtxp,
"Incorrect width in AstNode created from DfgVertex "
<< vtxp->typeName() << ": " << nodep->width() << " vs " << vtxp->width());

View File

@ -146,8 +146,8 @@ public:
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
void emitVarDecl(const AstVar* nodep, bool asRef = false);
void emitVarAccessors(const AstVar* nodep);
template <typename F>
static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) {
template <typename T_Callable>
static void forModCUse(const AstNodeModule* modp, VUseType useType, T_Callable action) {
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
if (AstCUse* const usep = VN_CAST(itemp, CUse)) {
if (usep->useType().containsAny(useType)) {

View File

@ -36,8 +36,8 @@ class CMakeEmitter final {
// STATIC FUNCTIONS
// Concatenate all strings in 'strs' with ' ' between them.
template <typename List>
static string cmake_list(const List& strs) {
template <typename T_List>
static string cmake_list(const T_List& strs) {
string s;
for (auto it = strs.begin(); it != strs.end(); ++it) {
s += '"';

View File

@ -32,25 +32,25 @@ struct FunctionTraits final
: public FunctionTraits<decltype(&std::remove_reference<T>::type::operator())> {};
// Specialization for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType (ClassType::*)(Args...) const> VL_NOT_FINAL {
template <typename T_ClassType, typename T_ReturnType, typename... Args>
struct FunctionTraits<T_ReturnType (T_ClassType::*)(Args...) const> VL_NOT_FINAL {
// Number of arguments
static constexpr size_t arity = sizeof...(Args);
// Type of result
using result_type = ReturnType;
using result_type = T_ReturnType;
// Type of arguments
template <std::size_t I>
template <std::size_t N>
struct arg final {
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
template <typename T_Callable, size_t index>
template <typename T_Callable, size_t N_Index>
struct FunctionArgNoPointerNoCV final {
using Traits = FunctionTraits<T_Callable>;
using T_Arg = typename Traits::template arg<index>::type;
using T_Arg = typename Traits::template arg<N_Index>::type;
using T_ArgNoPtr = typename std::remove_pointer<T_Arg>::type;
using type = typename std::remove_cv<T_ArgNoPtr>::type;
};

View File

@ -79,12 +79,12 @@ void V3GraphVertex::rerouteEdges(V3Graph* graphp) {
unlinkEdges(graphp);
}
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
V3GraphEdge* V3GraphVertex::findConnectingEdgep(V3GraphVertex* waywardp) {
// O(edges) linear search. Searches search both nodes' edge lists in
// parallel. The lists probably aren't _both_ huge, so this is
// unlikely to blow up even on fairly nasty graphs.
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay inv = way.invert();
auto& aEdges = this->edges<way>();
auto aIt = aEdges.begin();

View File

@ -187,9 +187,9 @@ public:
uint64_t user() const { return m_user; }
V3GraphVertex* fromp() const { return m_fromp; }
V3GraphVertex* top() const { return m_top; }
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
V3GraphVertex* furtherp() const {
return T_Way == GraphWay::FORWARD ? top() : fromp();
return N_Way == GraphWay::FORWARD ? top() : fromp();
}
// STATIC ACCESSORS
static bool followNotCutable(const V3GraphEdge* edgep) { return !edgep->m_cutable; }
@ -301,9 +301,9 @@ public:
void* userp() const VL_MT_STABLE { return m_userp; }
V3GraphEdge::IList& inEdges() { return m_ins; }
const V3GraphEdge::IList& inEdges() const { return m_ins; }
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
inline auto& edges();
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
inline const auto& edges() const;
bool inEmpty() const { return m_ins.empty(); }
bool inSize1() const { return m_ins.hasSingleElement(); }
@ -320,7 +320,7 @@ public:
void rerouteEdges(V3Graph* graphp) VL_MT_DISABLED;
// Find the edge connecting this vertex to the given vertex.
// If edge is not found returns nullptr. O(edges) performance.
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
V3GraphEdge* findConnectingEdgep(V3GraphVertex* otherp) VL_MT_DISABLED;
};

View File

@ -53,9 +53,9 @@ struct GraphPCNode final {
//######################################################################
// GraphPathChecker implementation
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void GraphPathChecker::initHalfCriticalPaths(bool checkOnly) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay rev = way.invert();
GraphStreamUnordered order(m_graphp, way);
while (const V3GraphVertex* const vertexp = order.nextp()) {

View File

@ -53,7 +53,7 @@ public:
private:
bool pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp,
unsigned* costp = nullptr) VL_MT_DISABLED;
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void initHalfCriticalPaths(bool checkOnly) VL_MT_DISABLED;
void incGeneration() { ++m_generation; }

View File

@ -264,9 +264,9 @@ public:
}
private:
template <uint8_t T_Way> //
template <uint8_t N_Way> //
VL_ATTR_NOINLINE void init(V3Graph* graphp) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
// Assign every vertex without an incoming edge to ready, others to waiting
for (V3GraphVertex& vertex : graphp->vertices()) {
const uint32_t nDeps = vertex.edges<way.invert()>().size();
@ -275,9 +275,9 @@ private:
}
}
template <uint8_t T_Way> //
template <uint8_t N_Way> //
VL_ATTR_NOINLINE const V3GraphVertex* unblock(const V3GraphVertex* resultp) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
for (const V3GraphEdge& edge : resultp->edges<way>()) {
V3GraphVertex* const vertexp = edge.furtherp<way>();
#if VL_DEBUG

View File

@ -89,7 +89,7 @@ class V3List final {
// Iterator class template for V3List. This is just enough to support range based for loops
// and basic usage. Feel free to extend as required.
template <typename T_IteratorElement, bool T_Reverse>
template <typename T_IteratorElement, bool N_Reverse>
class SimpleItertatorImpl final {
static_assert(std::is_same<T_IteratorElement, T_Element>::value
|| std::is_same<T_IteratorElement, const T_Element>::value,
@ -99,7 +99,7 @@ class V3List final {
template <typename B, V3ListLinks<B>& (B::*)(), typename>
friend class V3List;
using IteratorType = SimpleItertatorImpl<T_IteratorElement, T_Reverse>;
using IteratorType = SimpleItertatorImpl<T_IteratorElement, N_Reverse>;
T_Base* m_currp; // Currently iterated element, or 'nullptr' for 'end()' iterator
@ -109,7 +109,7 @@ class V3List final {
VL_ATTR_ALWINLINE
static T_Base* step(T_Base* currp) {
if VL_CONSTEXPR_CXX17 (T_Reverse) {
if VL_CONSTEXPR_CXX17 (N_Reverse) {
return toLinks(currp).m_prevp;
} else {
return toLinks(currp).m_nextp;
@ -145,8 +145,8 @@ class V3List final {
bool operator!=(const IteratorType& other) const { return m_currp != other.m_currp; }
// Convert to const iterator
VL_ATTR_ALWINLINE
operator SimpleItertatorImpl<const T_IteratorElement, T_Reverse>() const {
return SimpleItertatorImpl<const T_IteratorElement, T_Reverse>{m_currp};
operator SimpleItertatorImpl<const T_IteratorElement, N_Reverse>() const {
return SimpleItertatorImpl<const T_IteratorElement, N_Reverse>{m_currp};
}
};
@ -221,10 +221,10 @@ class V3List final {
};
public:
using iterator = SimpleItertatorImpl<T_Element, /* T_Reverse: */ false>;
using const_iterator = SimpleItertatorImpl<const T_Element, /* T_Reverse: */ false>;
using reverse_iterator = SimpleItertatorImpl<T_Element, /* T_Reverse: */ true>;
using const_reverse_iterator = SimpleItertatorImpl<const T_Element, /* T_Reverse: */ true>;
using iterator = SimpleItertatorImpl<T_Element, /* N_Reverse: */ false>;
using const_iterator = SimpleItertatorImpl<const T_Element, /* N_Reverse: */ false>;
using reverse_iterator = SimpleItertatorImpl<T_Element, /* N_Reverse: */ true>;
using const_reverse_iterator = SimpleItertatorImpl<const T_Element, /* N_Reverse: */ true>;
// CONSTRUCTOR
V3List() = default;

View File

@ -37,14 +37,14 @@ struct V3OptionParser::Impl final {
VALUE // "-opt val"
};
// Base class of actual action classes
template <en MODE, bool ALLOW_PARTIAL_MATCH = false>
template <en N_Mode, bool N_Allow_Partial_Match = false>
class ActionBase VL_NOT_FINAL : public ActionIfs {
bool m_undocumented = false; // This option is not documented
public:
bool isValueNeeded() const override final { return MODE == en::VALUE; }
bool isFOnOffAllowed() const override final { return MODE == en::FONOFF; }
bool isOnOffAllowed() const override final { return MODE == en::ONOFF; }
bool isPartialMatchAllowed() const override final { return ALLOW_PARTIAL_MATCH; }
bool isValueNeeded() const override final { return N_Mode == en::VALUE; }
bool isFOnOffAllowed() const override final { return N_Mode == en::FONOFF; }
bool isOnOffAllowed() const override final { return N_Mode == en::ONOFF; }
bool isPartialMatchAllowed() const override final { return N_Allow_Partial_Match; }
bool isUndocumented() const override { return m_undocumented; }
void undocumented() override { m_undocumented = true; }
};
@ -52,9 +52,9 @@ struct V3OptionParser::Impl final {
// Actual action classes
template <typename T>
class ActionSet; // "-opt" for bool-ish, "-opt val" for int and string
template <typename BOOL>
template <typename N_Bool>
class ActionFOnOff; // "-fopt" and "-fno-opt" for bool-ish
template <typename BOOL>
template <typename N_Bool>
class ActionOnOff; // "-opt" and "-no-opt" for bool-ish
class ActionCbCall; // Callback without argument for "-opt"
class ActionCbFOnOff; // Callback for "-fopt" and "-fno-opt"
@ -171,10 +171,10 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) {
return nullptr;
}
template <typename ACT, typename ARG>
V3OptionParser::ActionIfs& V3OptionParser::add(const std::string& opt, ARG arg) {
template <typename T_Act, typename T_Arg>
V3OptionParser::ActionIfs& V3OptionParser::add(const std::string& opt, T_Arg arg) {
UASSERT(!m_pimpl->m_isFinalized, "Cannot add after finalize() is called");
std::unique_ptr<ACT> act{new ACT{std::move(arg)}};
std::unique_ptr<T_Act> act{new T_Act{std::move(arg)}};
UASSERT(opt.size() >= 2, opt << " is too short");
UASSERT(opt[0] == '-' || opt[0] == '+', opt << " does not start with either '-' or '+'");
UASSERT(!(opt[0] == '-' && opt[1] == '-'), "Option must have single '-', but " << opt);

View File

@ -65,8 +65,8 @@ private:
// METHODS
ActionIfs* find(const char* optp) VL_MT_DISABLED;
template <typename ACT, typename ARG>
ActionIfs& add(const string& opt, ARG arg) VL_MT_DISABLED;
template <typename T_Act, typename T_Arg>
ActionIfs& add(const string& opt, T_Arg arg) VL_MT_DISABLED;
// Returns true if strp starts with "-fno"
static bool hasPrefixFNo(const char* strp) VL_MT_DISABLED;
// Returns true if strp starts with "-no"

View File

@ -268,7 +268,7 @@ static_assert(!std::is_polymorphic<SiblingMC>::value, "Should not have a vtable"
class MTaskEdge final : public V3GraphEdge, public MergeCandidate {
VL_RTTI_IMPL(MTaskEdge, V3GraphEdge)
friend class LogicMTask;
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
friend class PropagateCp;
// MEMBERS
@ -280,7 +280,7 @@ public:
// CONSTRUCTORS
MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int weight);
// METHODS
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
inline LogicMTask* furtherMTaskp() const;
inline LogicMTask* fromMTaskp() const;
inline LogicMTask* toMTaskp() const;
@ -307,7 +307,7 @@ private:
class LogicMTask final : public V3GraphVertex {
VL_RTTI_IMPL(LogicMTask, V3GraphVertex)
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
friend class PropagateCp;
public:
@ -419,28 +419,28 @@ public:
#endif
}
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void addRelativeEdge(MTaskEdge* edgep) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay inv = way.invert();
// Add to the edge heap
LogicMTask* const relativep = edgep->furtherMTaskp<T_Way>();
LogicMTask* const relativep = edgep->furtherMTaskp<N_Way>();
// Value is !way cp to this edge
const uint32_t cp = relativep->stepCost() + relativep->critPathCost(inv);
//
m_edgeHeap[way].insert(&edgep->m_edgeHeapNode[way], {relativep->id(), cp});
}
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void stealRelativeEdge(MTaskEdge* edgep) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
// Make heap node insertable, ruining the heap it is currently in.
edgep->m_edgeHeapNode[way].yank();
// Add the edge as new
addRelativeEdge<T_Way>(edgep);
addRelativeEdge<N_Way>(edgep);
}
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void removeRelativeEdge(MTaskEdge* edgep) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
// Remove from the edge heap
m_edgeHeap[way].remove(&edgep->m_edgeHeapNode[way]);
}
@ -456,12 +456,12 @@ public:
}
bool hasRelativeMTask(LogicMTask* relativep) const { return m_edgeSet.count(relativep); }
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
void checkRelativesCp() const {
constexpr GraphWay way{T_Way};
for (const V3GraphEdge& edge : edges<T_Way>()) {
constexpr GraphWay way{N_Way};
for (const V3GraphEdge& edge : edges<N_Way>()) {
const LogicMTask* const relativep
= static_cast<const LogicMTask*>(edge.furtherp<T_Way>());
= static_cast<const LogicMTask*>(edge.furtherp<N_Way>());
const uint32_t cachedCp = static_cast<const MTaskEdge&>(edge).cachedCp(way);
const uint32_t cp = relativep->critPathCost(way.invert()) + relativep->stepCost();
partCheckCachedScoreVsActual(cachedCp, cp);
@ -479,14 +479,14 @@ public:
void setCritPathCost(GraphWay way, uint32_t cost) { m_critPathCost[way] = cost; }
uint32_t critPathCost(GraphWay way) const { return m_critPathCost[way]; }
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
uint32_t critPathCostWithout(const V3GraphEdge* withoutp) const {
const GraphWay way{T_Way};
const GraphWay way{N_Way};
const GraphWay inv = way.invert();
// Compute the critical path cost wayward to this node, without considering edge
// 'withoutp'. We need to look at two edges at most, the critical path if that is not via
// 'withoutp', or the second-worst path, if the critical path is via 'withoutp'.
UDEBUGONLY(UASSERT(withoutp->furtherp<T_Way>() == this,
UDEBUGONLY(UASSERT(withoutp->furtherp<N_Way>() == this,
"In critPathCostWithout(), edge 'withoutp' must further to 'this'"););
const EdgeHeap& edgeHeap = m_edgeHeap[inv];
const EdgeHeap::Node* const maxp = edgeHeap.max();
@ -690,9 +690,9 @@ MTaskEdge::MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int we
top->addRelativeEdge<GraphWay::REVERSE>(this);
}
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
LogicMTask* MTaskEdge::furtherMTaskp() const {
return static_cast<LogicMTask*>(this->furtherp<T_Way>());
return static_cast<LogicMTask*>(this->furtherp<N_Way>());
}
LogicMTask* MTaskEdge::fromMTaskp() const { return static_cast<LogicMTask*>(fromp()); }
LogicMTask* MTaskEdge::toMTaskp() const { return static_cast<LogicMTask*>(top()); }
@ -716,9 +716,9 @@ void MTaskEdge::resetCriticalPaths() {
// Look at vertex costs (in one way) to form critical paths for each
// vertex.
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
static void partInitHalfCriticalPaths(V3Graph& mTaskGraph, bool checkOnly) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay rev = way.invert();
GraphStreamUnordered order{&mTaskGraph, way};
for (const V3GraphVertex* vertexp; (vertexp = order.nextp());) {
@ -776,7 +776,7 @@ static void partCheckCriticalPaths(V3Graph& mTaskGraph) {
// ######################################################################
// PropagateCp
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
class PropagateCp final {
// Propagate increasing critical path (CP) costs through a graph.
//
@ -862,7 +862,7 @@ private:
public:
void cpHasIncreased(V3GraphVertex* vxp, uint32_t newInclusiveCp) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay inv{way.invert()};
// For *vxp, whose CP-inclusive has just increased to
@ -871,7 +871,7 @@ public:
for (V3GraphEdge& graphEdge : vxp->edges<way>()) {
MTaskEdge& edge = static_cast<MTaskEdge&>(graphEdge);
LogicMTask* const relativep = edge.furtherMTaskp<T_Way>();
LogicMTask* const relativep = edge.furtherMTaskp<N_Way>();
EdgeHeap::Node& edgeHeapNode = edge.m_edgeHeapNode[inv];
if (newInclusiveCp > edgeHeapNode.key().m_score) {
relativep->m_edgeHeap[inv].increaseKey(&edgeHeapNode, newInclusiveCp);
@ -899,7 +899,7 @@ public:
}
void go() {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
constexpr GraphWay inv{way.invert()};
// m_pending maps each pending vertex to the amount that it wayward
@ -982,7 +982,7 @@ public:
partInitCriticalPaths(graph);
PropagateCp<T_Way> prop{true};
PropagateCp<N_Way> prop{true};
// Seed the propagator with every input node;
// This should result in the complete graph getting all CP's assigned.
@ -1316,9 +1316,9 @@ public:
}
private:
template <GraphWay::en T_Way>
template <GraphWay::en N_Way>
NewCp newCp(LogicMTask* mtaskp, LogicMTask* otherp, MTaskEdge* mergeEdgep) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
// Return new wayward-CP for mtaskp reflecting its upcoming merge
// with otherp. Set 'result.propagate' if mtaskp's wayward
// relatives will see a new wayward CP from this merge.
@ -1528,9 +1528,9 @@ private:
}
}
template <GraphWay::en T_Way, bool Exhaustive>
template <GraphWay::en N_Way, bool N_Exhaustive>
void siblingPairFromRelatives(V3GraphVertex* mtaskp) {
constexpr GraphWay way{T_Way};
constexpr GraphWay way{N_Way};
// Need at least 2 edges
auto& edges = mtaskp->edges<way>();
if (!edges.hasMultipleElements()) return;
@ -1575,7 +1575,7 @@ private:
// Just make a few pairs.
constexpr size_t MAX_NONEXHAUSTIVE_PAIRS = 3;
if (Exhaustive || n <= 2 * MAX_NONEXHAUSTIVE_PAIRS) {
if (N_Exhaustive || n <= 2 * MAX_NONEXHAUSTIVE_PAIRS) {
const size_t end = n & ~static_cast<size_t>(1); // Round down to even, (we want pairs)
std::sort(sortRecs.begin(), sortRecs.begin() + n);
for (size_t i = 0; i < end; i += 2) {

View File

@ -934,14 +934,14 @@ class CaptureVisitor final : public VNVisitor {
return false;
}
template <typename NodeT>
void fixupClassOrPackage(AstNode* memberp, NodeT refp) {
template <typename T_Node>
void fixupClassOrPackage(AstNode* memberp, T_Node refp) {
AstNodeModule* const declClassp = VN_AS(memberp->user2p(), NodeModule);
if (declClassp != m_targetp) refp->classOrPackagep(declClassp);
}
template <typename NodeT>
bool isReferenceToInnerMember(NodeT nodep) {
template <typename T_Node>
bool isReferenceToInnerMember(T_Node nodep) {
return VN_IS(nodep->fromp(), LambdaArgRef);
}

View File

@ -233,8 +233,8 @@ class TimingSuspendableVisitor final : public VNVisitor {
if (passFlag(parentp, depp, flag)) propagateFlags(depVxp, flag);
}
}
template <typename Predicate>
void propagateFlagsIf(DepVtx* const vxp, NodeFlag flag, Predicate p) {
template <typename T_Predicate>
void propagateFlagsIf(DepVtx* const vxp, NodeFlag flag, T_Predicate p) {
auto* const parentp = vxp->nodep();
for (V3GraphEdge& edge : vxp->outEdges()) {
auto* const depVxp = static_cast<DepVtx*>(edge.top());
@ -242,8 +242,8 @@ class TimingSuspendableVisitor final : public VNVisitor {
if (p(&edge) && passFlag(parentp, depp, flag)) propagateFlagsIf(depVxp, flag, p);
}
}
template <typename Predicate>
void propagateFlagsReversedIf(DepVtx* const vxp, NodeFlag flag, Predicate p) {
template <typename T_Predicate>
void propagateFlagsReversedIf(DepVtx* const vxp, NodeFlag flag, T_Predicate p) {
auto* const parentp = vxp->nodep();
for (V3GraphEdge& edge : vxp->inEdges()) {
auto* const depVxp = static_cast<DepVtx*>(edge.fromp());