forked from github/verilator
parent
701d2277cd
commit
f27cf4c804
@ -281,7 +281,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
|
|||||||
|
|
||||||
static uint32_t vl_sys_rand32() VL_MT_SAFE {
|
static uint32_t vl_sys_rand32() VL_MT_SAFE {
|
||||||
// Return random 32-bits using system library.
|
// Return random 32-bits using system library.
|
||||||
// Used only to construct seed for Verilator's PNRG.
|
// Used only to construct seed for Verilator's PRNG.
|
||||||
static VerilatedMutex s_mutex;
|
static VerilatedMutex s_mutex;
|
||||||
const VerilatedLockGuard lock{s_mutex}; // Otherwise rand is unsafe
|
const VerilatedLockGuard lock{s_mutex}; // Otherwise rand is unsafe
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
@ -2223,7 +2223,7 @@ static const char* vl_time_str(int scale) VL_PURE {
|
|||||||
return names[2 - scale];
|
return names[2 - scale];
|
||||||
}
|
}
|
||||||
double vl_time_multiplier(int scale) VL_PURE {
|
double vl_time_multiplier(int scale) VL_PURE {
|
||||||
// Return timescale multipler -18 to +18
|
// Return timescale multiplier -18 to +18
|
||||||
// For speed, this does not check for illegal values
|
// For speed, this does not check for illegal values
|
||||||
// cppcheck-has-bug-suppress arrayIndexOutOfBoundsCond
|
// cppcheck-has-bug-suppress arrayIndexOutOfBoundsCond
|
||||||
if (scale < 0) {
|
if (scale < 0) {
|
||||||
@ -2340,8 +2340,8 @@ void VerilatedContext::checkMagic(const VerilatedContext* contextp) {
|
|||||||
|
|
||||||
VerilatedContext::Serialized::Serialized() {
|
VerilatedContext::Serialized::Serialized() {
|
||||||
constexpr int8_t picosecond = -12;
|
constexpr int8_t picosecond = -12;
|
||||||
m_timeunit = picosecond; // Initial value until overriden by _Vconfigure
|
m_timeunit = picosecond; // Initial value until overridden by _Vconfigure
|
||||||
m_timeprecision = picosecond; // Initial value until overriden by _Vconfigure
|
m_timeprecision = picosecond; // Initial value until overridden by _Vconfigure
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedContext::assertOn(bool flag) VL_MT_SAFE {
|
void VerilatedContext::assertOn(bool flag) VL_MT_SAFE {
|
||||||
@ -2659,7 +2659,7 @@ void VerilatedContext::randSeed(int val) VL_MT_SAFE {
|
|||||||
const VerilatedLockGuard lock{VerilatedContextImp::s().s_randMutex};
|
const VerilatedLockGuard lock{VerilatedContextImp::s().s_randMutex};
|
||||||
m_s.m_randSeed = val;
|
m_s.m_randSeed = val;
|
||||||
const uint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
|
const uint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
|
||||||
// Obververs must see new epoch AFTER seed updated
|
// Observers must see new epoch AFTER seed updated
|
||||||
std::atomic_signal_fence(std::memory_order_release);
|
std::atomic_signal_fence(std::memory_order_release);
|
||||||
VerilatedContextImp::s().s_randSeedEpoch = newEpoch;
|
VerilatedContextImp::s().s_randSeedEpoch = newEpoch;
|
||||||
}
|
}
|
||||||
@ -3117,7 +3117,7 @@ void VlDeleter::deleteAll() {
|
|||||||
if (m_newGarbage.empty()) break;
|
if (m_newGarbage.empty()) break;
|
||||||
VerilatedLockGuard deleteLock{m_deleteMutex};
|
VerilatedLockGuard deleteLock{m_deleteMutex};
|
||||||
std::swap(m_newGarbage, m_toDelete);
|
std::swap(m_newGarbage, m_toDelete);
|
||||||
lock.unlock(); // So destuctors can enqueue new objects
|
lock.unlock(); // So destructors can enqueue new objects
|
||||||
for (VlDeletable* const objp : m_toDelete) delete objp;
|
for (VlDeletable* const objp : m_toDelete) delete objp;
|
||||||
m_toDelete.clear();
|
m_toDelete.clear();
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@ public:
|
|||||||
void errorLimit(int val) VL_MT_SAFE;
|
void errorLimit(int val) VL_MT_SAFE;
|
||||||
/// Return number of errors/assertions before stop
|
/// Return number of errors/assertions before stop
|
||||||
int errorLimit() const VL_MT_SAFE { return m_s.m_errorLimit; }
|
int errorLimit() const VL_MT_SAFE { return m_s.m_errorLimit; }
|
||||||
/// Set to throw fatal error on $stop/non-fatal ettot
|
/// Set to throw fatal error on $stop/non-fatal error
|
||||||
void fatalOnError(bool flag) VL_MT_SAFE;
|
void fatalOnError(bool flag) VL_MT_SAFE;
|
||||||
/// Return if to throw fatal error on $stop/non-fatal
|
/// Return if to throw fatal error on $stop/non-fatal
|
||||||
bool fatalOnError() const VL_MT_SAFE { return m_s.m_fatalOnError; }
|
bool fatalOnError() const VL_MT_SAFE { return m_s.m_fatalOnError; }
|
||||||
|
@ -1394,7 +1394,7 @@ static inline IData VL_STREAML_FAST_III(int lbits, IData ld, IData rd_log2) VL_P
|
|||||||
//
|
//
|
||||||
// If lbits is not a multiple of the slice size (i.e., lbits % rd != 0),
|
// If lbits is not a multiple of the slice size (i.e., lbits % rd != 0),
|
||||||
// then we end up with a "gap" in our reversed result. For example, if we
|
// then we end up with a "gap" in our reversed result. For example, if we
|
||||||
// have a 5-bit Verlilog signal (lbits=5) in an 8-bit C data type:
|
// have a 5-bit Verilog signal (lbits=5) in an 8-bit C data type:
|
||||||
//
|
//
|
||||||
// ld = ---43210
|
// ld = ---43210
|
||||||
//
|
//
|
||||||
|
@ -119,7 +119,7 @@ VerilatedVirtualBase* VlExecutionProfiler::construct(VerilatedContext& context)
|
|||||||
},
|
},
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
// Wait until initializationis complete
|
// Wait until initialization is complete
|
||||||
threadPoolp->workerp(i)->wait();
|
threadPoolp->workerp(i)->wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ public:
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VlTriggerScheduler stores coroutines to be resumed by a trigger. It does not keep track of its
|
// VlTriggerScheduler stores coroutines to be resumed by a trigger. It does not keep track of its
|
||||||
// trigger, relying on calling code to resume when appropriate. Coroutines are kept in two stages
|
// trigger, relying on calling code to resume when appropriate. Coroutines are kept in two stages
|
||||||
// - 'uncommitted' and 'ready'. Whenever a coroutine is suspended, it lands in the 'uncommited'
|
// - 'uncommitted' and 'ready'. Whenever a coroutine is suspended, it lands in the 'uncommitted'
|
||||||
// stage. Only when commit() is called, these coroutines get moved to the 'ready' stage. That's
|
// stage. Only when commit() is called, these coroutines get moved to the 'ready' stage. That's
|
||||||
// when they can be resumed. This is done to avoid resuming processes before they start waiting.
|
// when they can be resumed. This is done to avoid resuming processes before they start waiting.
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ static std::string doubleToTimescale(double value) {
|
|||||||
template <>
|
template <>
|
||||||
uint32_t* VerilatedTrace<VL_SUB_T, VL_BUF_T>::getOffloadBuffer() {
|
uint32_t* VerilatedTrace<VL_SUB_T, VL_BUF_T>::getOffloadBuffer() {
|
||||||
uint32_t* bufferp;
|
uint32_t* bufferp;
|
||||||
// Some jitter is expected, so some number of alternative offlaod buffers are
|
// Some jitter is expected, so some number of alternative offload buffers are
|
||||||
// required, but don't allocate more than 8 buffers.
|
// required, but don't allocate more than 8 buffers.
|
||||||
if (m_numOffloadBuffers < 8) {
|
if (m_numOffloadBuffers < 8) {
|
||||||
// Allocate a new buffer if none is available
|
// Allocate a new buffer if none is available
|
||||||
@ -348,7 +348,7 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::traceInit() VL_MT_UNSAFE {
|
|||||||
// Else if was empty, m_sigs_enabledp = nullptr to short circuit tests
|
// Else if was empty, m_sigs_enabledp = nullptr to short circuit tests
|
||||||
// But it isn't, so alloc one bit for each code to indicate enablement
|
// But it isn't, so alloc one bit for each code to indicate enablement
|
||||||
// We don't want to still use m_signs_enabledVec as std::vector<bool> is not
|
// We don't want to still use m_signs_enabledVec as std::vector<bool> is not
|
||||||
// guarenteed to be fast
|
// guaranteed to be fast
|
||||||
m_sigs_enabledp = new uint32_t[1 + VL_WORDS_I(nextCode())]{0};
|
m_sigs_enabledp = new uint32_t[1 + VL_WORDS_I(nextCode())]{0};
|
||||||
m_sigs_enabledVec.reserve(nextCode());
|
m_sigs_enabledVec.reserve(nextCode());
|
||||||
for (size_t code = 0; code < nextCode(); ++code) {
|
for (size_t code = 0; code < nextCode(); ++code) {
|
||||||
@ -513,7 +513,7 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runCallbacks(const std::vector<Callback
|
|||||||
mainThreadWorkerData.push_back(itemp);
|
mainThreadWorkerData.push_back(itemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Execute main thead jobs
|
// Execute main thread jobs
|
||||||
for (ParallelWorkerData* const itemp : mainThreadWorkerData) {
|
for (ParallelWorkerData* const itemp : mainThreadWorkerData) {
|
||||||
parallelWorkerTask(itemp, false);
|
parallelWorkerTask(itemp, false);
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,7 @@ public:
|
|||||||
void sort(Func with_func) {
|
void sort(Func with_func) {
|
||||||
// with_func returns arbitrary type to use for the sort comparison
|
// 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) {
|
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
|
||||||
// index number is meaninless with sort, as it changes
|
// index number is meaningless with sort, as it changes
|
||||||
return with_func(0, a) < with_func(0, b);
|
return with_func(0, a) < with_func(0, b);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -421,7 +421,7 @@ public:
|
|||||||
void rsort(Func with_func) {
|
void rsort(Func with_func) {
|
||||||
// with_func returns arbitrary type to use for the sort comparison
|
// 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) {
|
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
|
||||||
// index number is meaninless with sort, as it changes
|
// index number is meaningless with sort, as it changes
|
||||||
return with_func(0, a) < with_func(0, b);
|
return with_func(0, a) < with_func(0, b);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -475,7 +475,7 @@ void VerilatedVcd::declare(uint32_t code, const char* name, const char* wirep, b
|
|||||||
m_suffixes.resize(nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE * 2, 0);
|
m_suffixes.resize(nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE * 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep upper bound on bytes a single signal cna emit into the buffer
|
// Keep upper bound on bytes a single signal can emit into the buffer
|
||||||
m_maxSignalBytes = std::max<size_t>(m_maxSignalBytes, bits + 32);
|
m_maxSignalBytes = std::max<size_t>(m_maxSignalBytes, bits + 32);
|
||||||
// Make sure write buffer is large enough, plus header
|
// Make sure write buffer is large enough, plus header
|
||||||
bufferResize(m_maxSignalBytes + 1024);
|
bufferResize(m_maxSignalBytes + 1024);
|
||||||
@ -571,7 +571,7 @@ void VerilatedVcd::declDouble(uint32_t code, const char* name, bool array, int a
|
|||||||
VerilatedVcd::Buffer* VerilatedVcd::getTraceBuffer() {
|
VerilatedVcd::Buffer* VerilatedVcd::getTraceBuffer() {
|
||||||
VerilatedVcd::Buffer* const bufp = new Buffer{*this};
|
VerilatedVcd::Buffer* const bufp = new Buffer{*this};
|
||||||
if (parallel()) {
|
if (parallel()) {
|
||||||
// Note: This is called from VeriltedVcd::dump, which already holds the lock
|
// Note: This is called from VerilatedVcd::dump, which already holds the lock
|
||||||
// If no buffer available, allocate a new one
|
// If no buffer available, allocate a new one
|
||||||
if (m_freeBuffers.empty()) {
|
if (m_freeBuffers.empty()) {
|
||||||
constexpr size_t pageSize = 4096;
|
constexpr size_t pageSize = 4096;
|
||||||
@ -594,7 +594,7 @@ VerilatedVcd::Buffer* VerilatedVcd::getTraceBuffer() {
|
|||||||
|
|
||||||
void VerilatedVcd::commitTraceBuffer(VerilatedVcd::Buffer* bufp) {
|
void VerilatedVcd::commitTraceBuffer(VerilatedVcd::Buffer* bufp) {
|
||||||
if (parallel()) {
|
if (parallel()) {
|
||||||
// Note: This is called from VeriltedVcd::dump, which already holds the lock
|
// Note: This is called from VerilatedVcd::dump, which already holds the lock
|
||||||
// Resize output buffer. Note, we use the full size of the trace buffer, as
|
// Resize output buffer. Note, we use the full size of the trace buffer, as
|
||||||
// this is a lot more stable than the actual occupancy of the trace buffer.
|
// this is a lot more stable than the actual occupancy of the trace buffer.
|
||||||
// This helps us to avoid re-allocations due to small size changes.
|
// This helps us to avoid re-allocations due to small size changes.
|
||||||
@ -695,7 +695,7 @@ void VerilatedVcdBuffer::finishLine(uint32_t code, char* writep) {
|
|||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitEvent(uint32_t code, VlEvent newval) {
|
void VerilatedVcdBuffer::emitEvent(uint32_t code, VlEvent newval) {
|
||||||
const bool triggered = newval.isTriggered();
|
const bool triggered = newval.isTriggered();
|
||||||
// TODO : It seems that untriggerd events are not filtered
|
// TODO : It seems that untriggered events are not filtered
|
||||||
// should be tested before this last step
|
// should be tested before this last step
|
||||||
if (triggered) {
|
if (triggered) {
|
||||||
// Don't prefetch suffix as it's a bit too late;
|
// Don't prefetch suffix as it's a bit too late;
|
||||||
|
@ -168,7 +168,7 @@ void VerilatedVcd::Super::dumpvars(int level, const std::string& hier);
|
|||||||
// VerilatedVcdBuffer
|
// VerilatedVcdBuffer
|
||||||
|
|
||||||
class VerilatedVcdBuffer VL_NOT_FINAL {
|
class VerilatedVcdBuffer VL_NOT_FINAL {
|
||||||
// Give the trace file ans sub-classes access to the private bits
|
// Give the trace file and sub-classes access to the private bits
|
||||||
friend VerilatedVcd;
|
friend VerilatedVcd;
|
||||||
friend VerilatedVcd::Super;
|
friend VerilatedVcd::Super;
|
||||||
friend VerilatedVcd::Buffer;
|
friend VerilatedVcd::Buffer;
|
||||||
|
@ -1792,11 +1792,11 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
|
|||||||
// align so least significant 3 bits represent octal char
|
// align so least significant 3 bits represent octal char
|
||||||
val >>= idx.rem;
|
val >>= idx.rem;
|
||||||
if (i == (chars - 1)) {
|
if (i == (chars - 1)) {
|
||||||
// most signifcant char, mask off non existant bits when vector
|
// most significant char, mask off nonexistent bits when vector
|
||||||
// size is not a multiple of 3
|
// size is not a multiple of 3
|
||||||
const unsigned int rem = varp->packed().elements() % 3;
|
const unsigned int rem = varp->packed().elements() % 3;
|
||||||
if (rem) {
|
if (rem) {
|
||||||
// generate bit mask & zero non existant bits
|
// generate bit mask & zero nonexistent bits
|
||||||
val &= (1 << rem) - 1;
|
val &= (1 << rem) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1842,11 +1842,11 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
|
|||||||
for (i = 0; i < chars; ++i) {
|
for (i = 0; i < chars; ++i) {
|
||||||
char val = (datap[i >> 1] >> ((i & 1) << 2)) & 15;
|
char val = (datap[i >> 1] >> ((i & 1) << 2)) & 15;
|
||||||
if (i == (chars - 1)) {
|
if (i == (chars - 1)) {
|
||||||
// most signifcant char, mask off non existant bits when vector
|
// most significant char, mask off nonexistent bits when vector
|
||||||
// size is not a multiple of 4
|
// size is not a multiple of 4
|
||||||
const unsigned int rem = varp->packed().elements() & 3;
|
const unsigned int rem = varp->packed().elements() & 3;
|
||||||
if (rem) {
|
if (rem) {
|
||||||
// generate bit mask & zero non existant bits
|
// generate bit mask & zero nonexistent bits
|
||||||
val &= (1 << rem) - 1;
|
val &= (1 << rem) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2269,7 +2269,7 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
|
|||||||
VerilatedVpiImp::assertOneCheck();
|
VerilatedVpiImp::assertOneCheck();
|
||||||
p_vpi_error_info const _error_info_p = VerilatedVpiImp::error_info()->getError();
|
p_vpi_error_info const _error_info_p = VerilatedVpiImp::error_info()->getError();
|
||||||
if (error_info_p && _error_info_p) *error_info_p = *_error_info_p;
|
if (error_info_p && _error_info_p) *error_info_p = *_error_info_p;
|
||||||
if (!_error_info_p) return 0; // no error occured
|
if (!_error_info_p) return 0; // no error occurred
|
||||||
return _error_info_p->level; // return error severity level
|
return _error_info_p->level; // return error severity level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
/// Class for namespace-like groupng of Verilator VPI functions.
|
/// Class for namespace-like grouping of Verilator VPI functions.
|
||||||
|
|
||||||
class VerilatedVpi final {
|
class VerilatedVpi final {
|
||||||
public:
|
public:
|
||||||
|
@ -111,12 +111,12 @@
|
|||||||
# define VL_ATTR_WEAK ///< Attribute that function external that is optionally defined
|
# define VL_ATTR_WEAK ///< Attribute that function external that is optionally defined
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_CAPABILITY
|
#ifndef VL_CAPABILITY
|
||||||
# define VL_ACQUIRE(...) ///< Function aquires a capability/lock (-fthread-safety)
|
# define VL_ACQUIRE(...) ///< Function acquires a capability/lock (-fthread-safety)
|
||||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
# define VL_ACQUIRE_SHARED(...) ///< Function acquires a shared capability/lock (-fthread-safety)
|
||||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if acquired a capability (-fthread-safety)
|
||||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired shared (-fthread-safety)
|
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if acquired shared (-fthread-safety)
|
||||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||||
|
@ -88,7 +88,7 @@ protected:
|
|||||||
// Recursively traverse the graph to determine whether every control 'BLOCK' has an assignment
|
// Recursively traverse the graph to determine whether every control 'BLOCK' has an assignment
|
||||||
// to the output we are currently analysing (the output whose 'user() is set), if so return
|
// to the output we are currently analysing (the output whose 'user() is set), if so return
|
||||||
// true. Where a BLOCK contains a BRANCH, both the if and else sides of the branch must return
|
// true. Where a BLOCK contains a BRANCH, both the if and else sides of the branch must return
|
||||||
// true for the BRANCH to evalute to true. A BLOCK however needs only a single one of its
|
// true for the BRANCH to evaluate to true. A BLOCK however needs only a single one of its
|
||||||
// siblings to evaluate true in order to evaluate true itself. On output vertex only evaluates
|
// siblings to evaluate true in order to evaluate true itself. On output vertex only evaluates
|
||||||
// true if it is the vertex we are analyzing on this check
|
// true if it is the vertex we are analyzing on this check
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ private:
|
|||||||
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
||||||
if (AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
|
if (AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
|
||||||
AstPropSpec* propExprp = getPropertyExprp(propp);
|
AstPropSpec* propExprp = getPropertyExprp(propp);
|
||||||
// Substitute inner property call befory copying in order to not doing the same for
|
// Substitute inner property call before copying in order to not doing the same for
|
||||||
// each call of outer property call.
|
// each call of outer property call.
|
||||||
propExprp = substitutePropertyCall(propExprp);
|
propExprp = substitutePropertyCall(propExprp);
|
||||||
// Clone subtree after substitution. It is needed, because property might be called
|
// Clone subtree after substitution. It is needed, because property might be called
|
||||||
|
@ -112,7 +112,7 @@ string AstNode::encodeName(const string& namein) {
|
|||||||
}
|
}
|
||||||
// Shorten names
|
// Shorten names
|
||||||
// TODO long term use VName in place of "string name"
|
// TODO long term use VName in place of "string name"
|
||||||
// Then we also won't need to save the table of hased values
|
// Then we also won't need to save the table of hashed values
|
||||||
VName vname{out};
|
VName vname{out};
|
||||||
return vname.hashedName();
|
return vname.hashedName();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ public:
|
|||||||
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
|
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
|
||||||
// Single bit range extraction, perhaps with non-constant selection or array selection
|
// Single bit range extraction, perhaps with non-constant selection or array selection
|
||||||
// @astgen alias op1 := fromp // Expression we are indexing into
|
// @astgen alias op1 := fromp // Expression we are indexing into
|
||||||
// @astgen alias op2 := bitp // The index // TOOD: rename to idxp
|
// @astgen alias op2 := bitp // The index // TODO: rename to idxp
|
||||||
protected:
|
protected:
|
||||||
AstNodeSel(VNType t, FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
|
AstNodeSel(VNType t, FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
|
||||||
: AstNodeBiop{t, fl, fromp, bitp} {}
|
: AstNodeBiop{t, fl, fromp, bitp} {}
|
||||||
@ -4178,7 +4178,7 @@ public:
|
|||||||
|
|
||||||
// === AstNodeCond ===
|
// === AstNodeCond ===
|
||||||
class AstCond final : public AstNodeCond {
|
class AstCond final : public AstNodeCond {
|
||||||
// Conditional ?: expressoin
|
// Conditional ?: expression
|
||||||
public:
|
public:
|
||||||
AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep)
|
AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep)
|
||||||
: ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {}
|
: ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {}
|
||||||
@ -4463,7 +4463,7 @@ public:
|
|||||||
int instrCount() const override { return INSTR_COUNT_DBL; }
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
||||||
};
|
};
|
||||||
class AstIsUnbounded final : public AstNodeUniop {
|
class AstIsUnbounded final : public AstNodeUniop {
|
||||||
// True if is unmbounded ($)
|
// True if is unbounded ($)
|
||||||
public:
|
public:
|
||||||
AstIsUnbounded(FileLine* fl, AstNodeExpr* lhsp)
|
AstIsUnbounded(FileLine* fl, AstNodeExpr* lhsp)
|
||||||
: ASTGEN_SUPER_IsUnbounded(fl, lhsp) {
|
: ASTGEN_SUPER_IsUnbounded(fl, lhsp) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// This files contains all 'AstNode' sub-types that relate to other constructs
|
// This files contains all 'AstNode' sub-types that relate to other constructs
|
||||||
// not covered by the more speficic V3AstNode*.h files.
|
// not covered by the more specific V3AstNode*.h files.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ private:
|
|||||||
bool m_isHideProtected : 1; // Verilog protected
|
bool m_isHideProtected : 1; // Verilog protected
|
||||||
bool m_pure : 1; // DPI import pure (vs. virtual pure)
|
bool m_pure : 1; // DPI import pure (vs. virtual pure)
|
||||||
bool m_pureVirtual : 1; // Pure virtual
|
bool m_pureVirtual : 1; // Pure virtual
|
||||||
bool m_recursive : 1; // Recusive or part of recursion
|
bool m_recursive : 1; // Recursive or part of recursion
|
||||||
bool m_underGenerate : 1; // Under generate (for warning)
|
bool m_underGenerate : 1; // Under generate (for warning)
|
||||||
bool m_virtual : 1; // Virtual method in class
|
bool m_virtual : 1; // Virtual method in class
|
||||||
VLifetime m_lifetime; // Lifetime
|
VLifetime m_lifetime; // Lifetime
|
||||||
@ -175,7 +175,7 @@ public:
|
|||||||
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
||||||
};
|
};
|
||||||
class AstNodeFile VL_NOT_FINAL : public AstNode {
|
class AstNodeFile VL_NOT_FINAL : public AstNode {
|
||||||
// Emitted Otput file
|
// Emitted Output file
|
||||||
// Parents: NETLIST
|
// Parents: NETLIST
|
||||||
// @astgen op1 := tblockp : Optional[AstTextBlock]
|
// @astgen op1 := tblockp : Optional[AstTextBlock]
|
||||||
private:
|
private:
|
||||||
@ -210,7 +210,7 @@ private:
|
|||||||
bool m_modTrace : 1; // Tracing this module
|
bool m_modTrace : 1; // Tracing this module
|
||||||
bool m_inLibrary : 1; // From a library, no error if not used, never top level
|
bool m_inLibrary : 1; // From a library, no error if not used, never top level
|
||||||
bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors
|
bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors
|
||||||
bool m_hierBlock : 1; // Hiearchical Block marked by HIER_BLOCK pragma
|
bool m_hierBlock : 1; // Hierarchical Block marked by HIER_BLOCK pragma
|
||||||
bool m_internal : 1; // Internally created
|
bool m_internal : 1; // Internally created
|
||||||
bool m_recursive : 1; // Recursive module
|
bool m_recursive : 1; // Recursive module
|
||||||
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
|
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
|
||||||
@ -356,7 +356,7 @@ class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt {
|
|||||||
// @astgen op1 := propp : AstNode
|
// @astgen op1 := propp : AstNode
|
||||||
// @astgen op2 := sentreep : Optional[AstSenTree]
|
// @astgen op2 := sentreep : Optional[AstSenTree]
|
||||||
// op3 used by some sub-types only
|
// op3 used by some sub-types only
|
||||||
// @astgen op4 := passsp: List[AstNode] // Statments when propp is passing/truthly
|
// @astgen op4 := passsp: List[AstNode] // Statements when propp is passing/truthly
|
||||||
string m_name; // Name to report
|
string m_name; // Name to report
|
||||||
const bool m_immediate; // Immediate assertion/cover
|
const bool m_immediate; // Immediate assertion/cover
|
||||||
public:
|
public:
|
||||||
@ -1183,7 +1183,7 @@ public:
|
|||||||
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
||||||
};
|
};
|
||||||
class AstPin final : public AstNode {
|
class AstPin final : public AstNode {
|
||||||
// A port or parameter assignment on an instantiaton
|
// A port or parameter assignment on an instantiation
|
||||||
// @astgen op1 := exprp : Optional[AstNode] // NodeExpr or NodeDType (nullptr if unconnected)
|
// @astgen op1 := exprp : Optional[AstNode] // NodeExpr or NodeDType (nullptr if unconnected)
|
||||||
private:
|
private:
|
||||||
int m_pinNum; // Pin number
|
int m_pinNum; // Pin number
|
||||||
@ -3353,7 +3353,7 @@ public:
|
|||||||
|
|
||||||
// === AstNodeCoverOrAssert ===
|
// === AstNodeCoverOrAssert ===
|
||||||
class AstAssert final : public AstNodeCoverOrAssert {
|
class AstAssert final : public AstNodeCoverOrAssert {
|
||||||
// @astgen op3 := failsp: List[AstNode] // Statments when propp is failing/falsey
|
// @astgen op3 := failsp: List[AstNode] // Statements when propp is failing/falsey
|
||||||
public:
|
public:
|
||||||
ASTGEN_MEMBERS_AstAssert;
|
ASTGEN_MEMBERS_AstAssert;
|
||||||
AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate,
|
AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate,
|
||||||
@ -3364,7 +3364,7 @@ public:
|
|||||||
};
|
};
|
||||||
class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
|
class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
|
||||||
// A $cast or other compiler inserted assert, that must run even without --assert option
|
// A $cast or other compiler inserted assert, that must run even without --assert option
|
||||||
// @astgen op3 := failsp: List[AstNode] // Statments when propp is failing/falsey
|
// @astgen op3 := failsp: List[AstNode] // Statements when propp is failing/falsey
|
||||||
public:
|
public:
|
||||||
ASTGEN_MEMBERS_AstAssertIntrinsic;
|
ASTGEN_MEMBERS_AstAssertIntrinsic;
|
||||||
AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp,
|
AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp,
|
||||||
|
@ -114,7 +114,7 @@ private:
|
|||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (m_packageScopep) {
|
if (m_packageScopep) {
|
||||||
if (m_ftaskp && m_ftaskp->lifetime().isStatic()) {
|
if (m_ftaskp && m_ftaskp->lifetime().isStatic()) {
|
||||||
// Move later, or we wouldn't keep interating the class
|
// Move later, or we wouldn't keep iterating the class
|
||||||
// We're really moving the VarScope but we might not
|
// We're really moving the VarScope but we might not
|
||||||
// have a pointer to it yet
|
// have a pointer to it yet
|
||||||
m_toScopeMoves.emplace_back(std::make_pair(nodep, m_packageScopep));
|
m_toScopeMoves.emplace_back(std::make_pair(nodep, m_packageScopep));
|
||||||
@ -145,7 +145,7 @@ private:
|
|||||||
}
|
}
|
||||||
void visit(AstCFunc* nodep) override {
|
void visit(AstCFunc* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Don't move now, or wouldn't keep interating the class
|
// Don't move now, or wouldn't keep iterating the class
|
||||||
// TODO move function statics only
|
// TODO move function statics only
|
||||||
// if (m_classScopep) {
|
// if (m_classScopep) {
|
||||||
// m_toScopeMoves.push_back(std::make_pair(nodep, m_classScopep));
|
// m_toScopeMoves.push_back(std::make_pair(nodep, m_classScopep));
|
||||||
|
@ -258,7 +258,7 @@ class V3ConfigFile final {
|
|||||||
using WaiverSetting = std::pair<V3ErrorCode, std::string>; // Waive code if string matches
|
using WaiverSetting = std::pair<V3ErrorCode, std::string>; // Waive code if string matches
|
||||||
using Waivers = std::vector<WaiverSetting>; // List of {code,wildcard string}
|
using Waivers = std::vector<WaiverSetting>; // List of {code,wildcard string}
|
||||||
|
|
||||||
LineAttrMap m_lineAttrs; // Atributes to line mapping
|
LineAttrMap m_lineAttrs; // Attributes to line mapping
|
||||||
IgnLines m_ignLines; // Ignore line settings
|
IgnLines m_ignLines; // Ignore line settings
|
||||||
Waivers m_waivers; // Waive messages
|
Waivers m_waivers; // Waive messages
|
||||||
|
|
||||||
@ -416,7 +416,7 @@ public:
|
|||||||
for (const auto& ent : m_entries) {
|
for (const auto& ent : m_entries) {
|
||||||
// We apply shortest match first for each rule component
|
// We apply shortest match first for each rule component
|
||||||
// (Otherwise the levels would be useless as "--scope top* --levels 1" would
|
// (Otherwise the levels would be useless as "--scope top* --levels 1" would
|
||||||
// always match at every scopepart, and we wound't know how to count levels)
|
// always match at every scopepart, and we wouldn't know how to count levels)
|
||||||
int partLevel = 1;
|
int partLevel = 1;
|
||||||
for (string::size_type partEnd = 0; true;) {
|
for (string::size_type partEnd = 0; true;) {
|
||||||
partEnd = scope.find('.', partEnd + 1);
|
partEnd = scope.find('.', partEnd + 1);
|
||||||
|
@ -835,7 +835,7 @@ public:
|
|||||||
|
|
||||||
// Set width of masks to expected result width. This is required to prevent later removal
|
// Set width of masks to expected result width. This is required to prevent later removal
|
||||||
// of the masking node e.g. by the "AND with all ones" rule. If the result width happens
|
// of the masking node e.g. by the "AND with all ones" rule. If the result width happens
|
||||||
// to be 1, we still need to ensure the AstAnd is not dropped, so use a wider maks in this
|
// to be 1, we still need to ensure the AstAnd is not dropped, so use a wider mask in this
|
||||||
// special case.
|
// special case.
|
||||||
const int maskWidth = resultWidth == 1 ? VL_IDATASIZE : resultWidth;
|
const int maskWidth = resultWidth == 1 ? VL_IDATASIZE : resultWidth;
|
||||||
|
|
||||||
@ -1051,7 +1051,7 @@ private:
|
|||||||
// Push down a AND into conditional, when one side of conditional is constant
|
// Push down a AND into conditional, when one side of conditional is constant
|
||||||
// (otherwise we'd be trading one operation for two operations)
|
// (otherwise we'd be trading one operation for two operations)
|
||||||
// V3Clean often makes this pattern, as it postpones the AND until
|
// V3Clean often makes this pattern, as it postpones the AND until
|
||||||
// as high as possible, which is usally the right choice, except for this.
|
// as high as possible, which is usually the right choice, except for this.
|
||||||
AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond);
|
AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond);
|
||||||
if (!condp) return false;
|
if (!condp) return false;
|
||||||
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
||||||
|
@ -306,7 +306,7 @@ class ExtractCyclicComponents final {
|
|||||||
void mergeSCCs() {
|
void mergeSCCs() {
|
||||||
// Ensure that component boundaries are always at variables, by merging SCCs. Merging stops
|
// Ensure that component boundaries are always at variables, by merging SCCs. Merging stops
|
||||||
// at variable boundaries, so we don't need to iterate variables. Constants are reachable
|
// at variable boundaries, so we don't need to iterate variables. Constants are reachable
|
||||||
// from their sinks, or ar unused, so we don't need to iterate them either.
|
// from their sinks, or are unused, so we don't need to iterate them either.
|
||||||
for (DfgVertex *vtxp = m_dfg.opVerticesBeginp(), *nextp; vtxp; vtxp = nextp) {
|
for (DfgVertex *vtxp = m_dfg.opVerticesBeginp(), *nextp; vtxp; vtxp = nextp) {
|
||||||
nextp = vtxp->verticesNext();
|
nextp = vtxp->verticesNext();
|
||||||
DfgVertex& vtx = *vtxp;
|
DfgVertex& vtx = *vtxp;
|
||||||
|
@ -226,7 +226,7 @@ void V3DfgPasses::removeUnused(DfgGraph& dfg) {
|
|||||||
|
|
||||||
// Head of work list. Note that we want all next pointers in the list to be non-zero (including
|
// Head of work list. Note that we want all next pointers in the list to be non-zero (including
|
||||||
// that of the last element). This allows as to do two important things: detect if an element
|
// that of the last element). This allows as to do two important things: detect if an element
|
||||||
// is in the list by checking for a non-zero next poitner, and easy prefetching without
|
// is in the list by checking for a non-zero next pointer, and easy prefetching without
|
||||||
// conditionals. The address of the graph is a good sentinel as it is a valid memory address,
|
// conditionals. The address of the graph is a good sentinel as it is a valid memory address,
|
||||||
// and we can easily check for the end of the list.
|
// and we can easily check for the end of the list.
|
||||||
DfgVertex* const sentinelp = reinterpret_cast<DfgVertex*>(&dfg);
|
DfgVertex* const sentinelp = reinterpret_cast<DfgVertex*>(&dfg);
|
||||||
|
@ -141,7 +141,7 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||||||
AstNodeDType* const m_bitDType = DfgVertex::dtypeForWidth(1); // Common, so grab it up front
|
AstNodeDType* const m_bitDType = DfgVertex::dtypeForWidth(1); // Common, so grab it up front
|
||||||
// Head of work list. Note that we want all next pointers in the list to be non-zero (including
|
// Head of work list. Note that we want all next pointers in the list to be non-zero (including
|
||||||
// that of the last element). This allows as to do two important things: detect if an element
|
// that of the last element). This allows as to do two important things: detect if an element
|
||||||
// is in the list by checking for a non-zero next poitner, and easy prefetching without
|
// is in the list by checking for a non-zero next pointer, and easy prefetching without
|
||||||
// conditionals. The 'this' pointer is a good sentinel as it is a valid memory address, and we
|
// conditionals. The 'this' pointer is a good sentinel as it is a valid memory address, and we
|
||||||
// can easily check for the end of the list.
|
// can easily check for the end of the list.
|
||||||
DfgVertex* m_workListp = reinterpret_cast<DfgVertex*>(this);
|
DfgVertex* m_workListp = reinterpret_cast<DfgVertex*>(this);
|
||||||
|
@ -543,7 +543,7 @@ class EmitCImp final : EmitCFunc {
|
|||||||
m_modp = modp;
|
m_modp = modp;
|
||||||
|
|
||||||
// Emit implementation of this module, if this is an AstClassPackage, then put the
|
// Emit implementation of this module, if this is an AstClassPackage, then put the
|
||||||
// corresponding AstClass implementation in the same file as often optimziations are
|
// corresponding AstClass implementation in the same file as often optimizations are
|
||||||
// possible when both are seen by the compiler
|
// possible when both are seen by the compiler
|
||||||
// TODO: is the above comment still true?
|
// TODO: is the above comment still true?
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ private:
|
|||||||
// Not defining main_time/vl_time_stamp, so
|
// Not defining main_time/vl_time_stamp, so
|
||||||
v3Global.opt.addCFlags("-DVL_TIME_CONTEXT"); // On MSVC++ anyways
|
v3Global.opt.addCFlags("-DVL_TIME_CONTEXT"); // On MSVC++ anyways
|
||||||
|
|
||||||
// Heavly commented output, as users are likely to look at or copy this code
|
// Heavily commented output, as users are likely to look at or copy this code
|
||||||
ofp()->putsHeader();
|
ofp()->putsHeader();
|
||||||
puts("// DESCRIPTION: main() calling loop, created with Verilator --main\n");
|
puts("// DESCRIPTION: main() calling loop, created with Verilator --main\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
@ -81,7 +81,7 @@ class FileLineSingleton final {
|
|||||||
msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet);
|
msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet);
|
||||||
// Add index of default bitset
|
// Add index of default bitset
|
||||||
msgEnSetIdx_t defaultMsgEnIndex();
|
msgEnSetIdx_t defaultMsgEnIndex();
|
||||||
// Set bitIdx to value in bitset at interned idnex setIdx, return interned index of result
|
// Set bitIdx to value in bitset at interned index setIdx, return interned index of result
|
||||||
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, size_t bitIdx, bool value);
|
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, size_t bitIdx, bool value);
|
||||||
// Return index to intersection set
|
// Return index to intersection set
|
||||||
msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx);
|
msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx);
|
||||||
|
@ -785,7 +785,7 @@ private:
|
|||||||
std::unordered_set<AstNode*> m_nodeDeleteds; // Any node in this hash was deleted
|
std::unordered_set<AstNode*> m_nodeDeleteds; // Any node in this hash was deleted
|
||||||
|
|
||||||
bool same(AstNode* node1p, AstNode* node2p) {
|
bool same(AstNode* node1p, AstNode* node2p) {
|
||||||
// Regarding the complexity of this funcition 'same':
|
// Regarding the complexity of this function 'same':
|
||||||
// Applying this comparison function to a a set of n trees pairwise is O(n^2) in the
|
// Applying this comparison function to a a set of n trees pairwise is O(n^2) in the
|
||||||
// number of comparisons (number of pairs). AstNode::sameTree itself, is O(sizeOfTree) in
|
// number of comparisons (number of pairs). AstNode::sameTree itself, is O(sizeOfTree) in
|
||||||
// the worst case, which happens if the operands of sameTree are indeed identical copies,
|
// the worst case, which happens if the operands of sameTree are indeed identical copies,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Common implemenetations
|
// DESCRIPTION: Verilator: Common implementations
|
||||||
//
|
//
|
||||||
// Code available from: https://verilator.org
|
// Code available from: https://verilator.org
|
||||||
//
|
//
|
||||||
|
@ -126,7 +126,7 @@ public:
|
|||||||
V3Global() {}
|
V3Global() {}
|
||||||
void boot();
|
void boot();
|
||||||
void clear();
|
void clear();
|
||||||
void shutdown(); // Release allocated resorces
|
void shutdown(); // Release allocated resources
|
||||||
// ACCESSORS (general)
|
// ACCESSORS (general)
|
||||||
AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
|
AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
|
||||||
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
||||||
|
@ -118,7 +118,7 @@ V3HierBlock::StrGParams V3HierBlock::stringifyParams(const GParams& gparams, boo
|
|||||||
// V3Param.cpp. See also ParamVisitor::checkSupportedParam() in the file.
|
// V3Param.cpp. See also ParamVisitor::checkSupportedParam() in the file.
|
||||||
if (constp->isDouble()) {
|
if (constp->isDouble()) {
|
||||||
// 64 bit width of hex can be expressed with 16 chars.
|
// 64 bit width of hex can be expressed with 16 chars.
|
||||||
// 32 chars must be long enough for hexadecial floating point
|
// 32 chars must be long enough for hexadecimal floating point
|
||||||
// considering prefix of '0x', '.', and 'P'.
|
// considering prefix of '0x', '.', and 'P'.
|
||||||
std::vector<char> hexFpStr(32, '\0');
|
std::vector<char> hexFpStr(32, '\0');
|
||||||
const int len = VL_SNPRINTF(hexFpStr.data(), hexFpStr.size(), "%a",
|
const int len = VL_SNPRINTF(hexFpStr.data(), hexFpStr.size(), "%a",
|
||||||
@ -377,7 +377,7 @@ V3HierBlockPlan::HierVector V3HierBlockPlan::hierBlocksSorted() const {
|
|||||||
const V3HierBlock* hblockp = sorted[i];
|
const V3HierBlock* hblockp = sorted[i];
|
||||||
const V3HierBlock::HierBlockSet& p = hblockp->parents();
|
const V3HierBlock::HierBlockSet& p = hblockp->parents();
|
||||||
for (V3HierBlock::HierBlockSet::const_iterator it = p.begin(); it != p.end(); ++it) {
|
for (V3HierBlock::HierBlockSet::const_iterator it = p.begin(); it != p.end(); ++it) {
|
||||||
// Delete hblockp from parrents. If a parent does not have a child anymore, then it is
|
// Delete hblockp from parents. If a parent does not have a child anymore, then it is
|
||||||
// a leaf too.
|
// a leaf too.
|
||||||
const auto parentIt = childrenOfHierBlock.find(*it);
|
const auto parentIt = childrenOfHierBlock.find(*it);
|
||||||
UASSERT_OBJ(parentIt != childrenOfHierBlock.end(), (*it)->modp(), "must be included");
|
UASSERT_OBJ(parentIt != childrenOfHierBlock.end(), (*it)->modp(), "must be included");
|
||||||
|
@ -87,14 +87,14 @@ public:
|
|||||||
string hierGenerated(bool withDir) const;
|
string hierGenerated(bool withDir) const;
|
||||||
// Returns the original HDL file if it is not included in v3Global.opt.vFiles().
|
// Returns the original HDL file if it is not included in v3Global.opt.vFiles().
|
||||||
string vFileIfNecessary() const;
|
string vFileIfNecessary() const;
|
||||||
// Write command line argumuents to .f file for this hierarchical block
|
// Write command line arguments to .f file for this hierarchical block
|
||||||
void writeCommandArgsFile(bool forCMake) const;
|
void writeCommandArgsFile(bool forCMake) const;
|
||||||
string commandArgsFileName(bool forCMake) const;
|
string commandArgsFileName(bool forCMake) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
// Holds relashonship between AstNodeModule and V3HierBlock
|
// Holds relationship between AstNodeModule and V3HierBlock
|
||||||
class V3HierBlockPlan final {
|
class V3HierBlockPlan final {
|
||||||
using HierMap = std::unordered_map<const AstNodeModule*, V3HierBlock*>;
|
using HierMap = std::unordered_map<const AstNodeModule*, V3HierBlock*>;
|
||||||
HierMap m_blocks;
|
HierMap m_blocks;
|
||||||
|
@ -510,7 +510,7 @@ public:
|
|||||||
// If a pin connection is "simple" leave it as-is
|
// If a pin connection is "simple" leave it as-is
|
||||||
// Else create a intermediate wire to perform the interconnect
|
// Else create a intermediate wire to perform the interconnect
|
||||||
// Return the new assignment, if one was made
|
// Return the new assignment, if one was made
|
||||||
// Note this module calles cloneTree() via new AstVar
|
// Note this module calls cloneTree() via new AstVar
|
||||||
AstVar* const pinVarp = pinp->modVarp();
|
AstVar* const pinVarp = pinp->modVarp();
|
||||||
if (!pinp->exprp()) {
|
if (!pinp->exprp()) {
|
||||||
// No-connect, perhaps promote based on `unconnected_drive,
|
// No-connect, perhaps promote based on `unconnected_drive,
|
||||||
|
@ -560,7 +560,7 @@ private:
|
|||||||
AstNode* scanp = nodep;
|
AstNode* scanp = nodep;
|
||||||
// Skip over the New's statement
|
// Skip over the New's statement
|
||||||
for (; scanp && !VN_IS(scanp, StmtExpr); scanp = scanp->backp()) {}
|
for (; scanp && !VN_IS(scanp, StmtExpr); scanp = scanp->backp()) {}
|
||||||
if (VN_IS(scanp, StmtExpr)) { // Ignore warnign if something not understood
|
if (VN_IS(scanp, StmtExpr)) { // Ignore warning if something not understood
|
||||||
scanp = scanp->backp();
|
scanp = scanp->backp();
|
||||||
for (; scanp; scanp = scanp->backp()) {
|
for (; scanp; scanp = scanp->backp()) {
|
||||||
if (VN_IS(scanp, NodeStmt) || VN_IS(scanp, NodeModule)
|
if (VN_IS(scanp, NodeStmt) || VN_IS(scanp, NodeModule)
|
||||||
|
@ -177,7 +177,7 @@ class CodeMotionAnalysisVisitor final : public VNVisitor {
|
|||||||
std::vector<V3DupFinder> m_stack;
|
std::vector<V3DupFinder> m_stack;
|
||||||
StmtProperties* m_propsp = nullptr; // StmtProperties structure of current AstNodeStmt
|
StmtProperties* m_propsp = nullptr; // StmtProperties structure of current AstNodeStmt
|
||||||
|
|
||||||
// Extract condition expression from a megeable conditional statement, if any
|
// Extract condition expression from a mergeable conditional statement, if any
|
||||||
static AstNodeExpr* extractCondition(const AstNodeStmt* nodep) {
|
static AstNodeExpr* extractCondition(const AstNodeStmt* nodep) {
|
||||||
AstNodeExpr* conditionp = nullptr;
|
AstNodeExpr* conditionp = nullptr;
|
||||||
if (const AstNodeAssign* const assignp = VN_CAST(nodep, NodeAssign)) {
|
if (const AstNodeAssign* const assignp = VN_CAST(nodep, NodeAssign)) {
|
||||||
@ -590,7 +590,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fold the RHS expression of an assignment assuming the given condition state.
|
// Fold the RHS expression of an assignment assuming the given condition state.
|
||||||
// Unlink bits from the RHS which is only used once, and can be reused (is an unomdified
|
// Unlink bits from the RHS which is only used once, and can be reused (is an unmodified
|
||||||
// sub-tree). What remains of the RHS is expected to be deleted by the caller.
|
// sub-tree). What remains of the RHS is expected to be deleted by the caller.
|
||||||
AstNodeExpr* foldAndUnlink(AstNodeExpr* rhsp, bool condTrue) {
|
AstNodeExpr* foldAndUnlink(AstNodeExpr* rhsp, bool condTrue) {
|
||||||
if (rhsp->sameTree(m_mgCondp)) {
|
if (rhsp->sameTree(m_mgCondp)) {
|
||||||
@ -793,7 +793,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this node is the next expected node and is helpful to add to the list, do so,
|
// If this node is the next expected node and is helpful to add to the list, do so,
|
||||||
// otherwise end the current merge. Return ture if added, false if ended merge.
|
// otherwise end the current merge. Return true if added, false if ended merge.
|
||||||
bool addIfHelpfulElseEndMerge(AstNodeStmt* nodep) {
|
bool addIfHelpfulElseEndMerge(AstNodeStmt* nodep) {
|
||||||
UASSERT_OBJ(m_mgFirstp, nodep, "List must be open");
|
UASSERT_OBJ(m_mgFirstp, nodep, "List must be open");
|
||||||
if (!checkOrMakeMergeable(nodep)) return false;
|
if (!checkOrMakeMergeable(nodep)) return false;
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
class VOptionBool;
|
class VOptionBool;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Typycal usage would look as below.
|
// Typical usage would look as below.
|
||||||
// See also V3Options::parseOptsList() in V3Optoins.cpp for more detailed usage.
|
// See also V3Options::parseOptsList() in V3Options.cpp for more detailed usage.
|
||||||
//
|
//
|
||||||
// V3OptionParser parser;
|
// V3OptionParser parser;
|
||||||
// V3OptionParser::AppendHelper DECL_OPTION{parser};
|
// V3OptionParser::AppendHelper DECL_OPTION{parser};
|
||||||
@ -89,8 +89,8 @@ class V3OptionParser::ActionIfs VL_NOT_FINAL {
|
|||||||
public:
|
public:
|
||||||
virtual ~ActionIfs() = default;
|
virtual ~ActionIfs() = default;
|
||||||
virtual bool isValueNeeded() const = 0; // Need val of "-opt val"
|
virtual bool isValueNeeded() const = 0; // Need val of "-opt val"
|
||||||
virtual bool isFOnOffAllowed() const = 0; // true if "-fno-opt" is allowd
|
virtual bool isFOnOffAllowed() const = 0; // true if "-fno-opt" is allowed
|
||||||
virtual bool isOnOffAllowed() const = 0; // true if "-no-opt" is allowd
|
virtual bool isOnOffAllowed() const = 0; // true if "-no-opt" is allowed
|
||||||
virtual bool isPartialMatchAllowed() const = 0; // true if "-Wno-" matches "-Wno-fatal"
|
virtual bool isPartialMatchAllowed() const = 0; // true if "-Wno-" matches "-Wno-fatal"
|
||||||
virtual bool isUndocumented() const = 0; // Will not be suggested in typo
|
virtual bool isUndocumented() const = 0; // Will not be suggested in typo
|
||||||
// Set a value or run callback
|
// Set a value or run callback
|
||||||
@ -117,7 +117,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
V3OptionParser& m_parser; // The actual option registory
|
V3OptionParser& m_parser; // The actual option registry
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
|
@ -173,7 +173,7 @@ class OrderBuildVisitor final : public VNVisitor {
|
|||||||
|
|
||||||
// Current AstScope being processed
|
// Current AstScope being processed
|
||||||
AstScope* m_scopep = nullptr;
|
AstScope* m_scopep = nullptr;
|
||||||
// Sensitivity list for clocked logic, nullptr for combinational and hybird logic
|
// Sensitivity list for clocked logic, nullptr for combinational and hybrid logic
|
||||||
AstSenTree* m_domainp = nullptr;
|
AstSenTree* m_domainp = nullptr;
|
||||||
// Sensitivity list for hybrid logic, nullptr for everything else
|
// Sensitivity list for hybrid logic, nullptr for everything else
|
||||||
AstSenTree* m_hybridp = nullptr;
|
AstSenTree* m_hybridp = nullptr;
|
||||||
@ -810,7 +810,7 @@ class OrderProcess final : VNDeleter {
|
|||||||
|
|
||||||
SenTreeFinder m_finder; // Global AstSenTree manager
|
SenTreeFinder m_finder; // Global AstSenTree manager
|
||||||
AstSenTree* const m_deleteDomainp; // Dummy AstSenTree indicating needs deletion
|
AstSenTree* const m_deleteDomainp; // Dummy AstSenTree indicating needs deletion
|
||||||
const string m_tag; // Subtring to add to generated names
|
const string m_tag; // Substring to add to generated names
|
||||||
const bool m_slow; // Ordering slow code
|
const bool m_slow; // Ordering slow code
|
||||||
std::vector<AstNode*> m_result; // The result nodes (~statements) in their sequential order
|
std::vector<AstNode*> m_result; // The result nodes (~statements) in their sequential order
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minimal convenience acessors and operators
|
// Minimal convenience accessors and operators
|
||||||
VL_ATTR_ALWINLINE Node* ptr() const { return m_ptr; }
|
VL_ATTR_ALWINLINE Node* ptr() const { return m_ptr; }
|
||||||
VL_ATTR_ALWINLINE operator bool() const { return m_ptr; }
|
VL_ATTR_ALWINLINE operator bool() const { return m_ptr; }
|
||||||
VL_ATTR_ALWINLINE bool operator!() const { return !m_ptr; }
|
VL_ATTR_ALWINLINE bool operator!() const { return !m_ptr; }
|
||||||
@ -214,7 +214,7 @@ public:
|
|||||||
if (nodep == m_root.ptr()) return;
|
if (nodep == m_root.ptr()) return;
|
||||||
// Otherwise we do have a little work to do
|
// Otherwise we do have a little work to do
|
||||||
if (!nodep->m_kids) {
|
if (!nodep->m_kids) {
|
||||||
// If the node has no children, replace it with its siblings (migtht be null)
|
// If the node has no children, replace it with its siblings (might be null)
|
||||||
nodep->replaceWith(nodep->m_next.unlink());
|
nodep->replaceWith(nodep->m_next.unlink());
|
||||||
} else if (!nodep->m_next) {
|
} else if (!nodep->m_next) {
|
||||||
// If the node has no siblings, replace it with its children
|
// If the node has no siblings, replace it with its children
|
||||||
|
@ -198,7 +198,7 @@ public:
|
|||||||
}
|
}
|
||||||
return v3EpsilonEqual(var, hierOptParamp->num().toDouble());
|
return v3EpsilonEqual(var, hierOptParamp->num().toDouble());
|
||||||
} else { // Now integer type is assumed
|
} else { // Now integer type is assumed
|
||||||
// Bitwidth of hierOptParamp is accurate because V3Width already caluclated in the
|
// Bitwidth of hierOptParamp is accurate because V3Width already calculated in the
|
||||||
// previous run. Bitwidth of pinValuep is before width analysis, so pinValuep is casted
|
// previous run. Bitwidth of pinValuep is before width analysis, so pinValuep is casted
|
||||||
// to hierOptParamp width.
|
// to hierOptParamp width.
|
||||||
V3Number varNum{pinValuep, hierOptParamp->num().width()};
|
V3Number varNum{pinValuep, hierOptParamp->num().width()};
|
||||||
@ -495,7 +495,7 @@ class ParamProcessor final {
|
|||||||
if (varp->isGParam()) {
|
if (varp->isGParam()) {
|
||||||
AstConst* const constp = VN_CAST(varp->valuep(), Const);
|
AstConst* const constp = VN_CAST(varp->valuep(), Const);
|
||||||
// constp can be nullptr if the parameter is not used to instantiate sub
|
// constp can be nullptr if the parameter is not used to instantiate sub
|
||||||
// module. varp->valuep() is not contified yet in the case.
|
// module. varp->valuep() is not constified yet in the case.
|
||||||
// nullptr means that the parameter is using some default value.
|
// nullptr means that the parameter is using some default value.
|
||||||
params.emplace(varp->name(), constp);
|
params.emplace(varp->name(), constp);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == VVarType::GENVAR) {
|
if (type == VVarType::GENVAR) {
|
||||||
// Should be impossible as the grammer blocks this, but...
|
// Should be impossible as the grammar blocks this, but...
|
||||||
if (arrayp) fileline->v3error("Genvars may not be arrayed: " << name); // LCOV_EXCL_LINE
|
if (arrayp) fileline->v3error("Genvars may not be arrayed: " << name); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bison sometimes needs error context without a token, so remember last token's line
|
// Bison sometimes needs error context without a token, so remember last token's line
|
||||||
// Only use this if do not have and cannot get a token-relevent fileline
|
// Only use this if do not have and cannot get a token-relevant fileline
|
||||||
FileLine* bisonLastFileline() const { return m_bisonLastFileline; }
|
FileLine* bisonLastFileline() const { return m_bisonLastFileline; }
|
||||||
|
|
||||||
// Return next token, for bison, since bison isn't class based, use a global THIS
|
// Return next token, for bison, since bison isn't class based, use a global THIS
|
||||||
|
@ -1002,7 +1002,7 @@ int V3PreProcImp::getStateToken() {
|
|||||||
|
|
||||||
if (tok == VP_DEFREF_JOIN) {
|
if (tok == VP_DEFREF_JOIN) {
|
||||||
// Here's something fun and unspecified as yet:
|
// Here's something fun and unspecified as yet:
|
||||||
// The existence of non-existance of a base define changes `` expansion
|
// The existence of non-existence of a base define changes `` expansion
|
||||||
// `define QA_b zzz
|
// `define QA_b zzz
|
||||||
// `define Q1 `QA``_b
|
// `define Q1 `QA``_b
|
||||||
// 1Q1 -> zzz
|
// 1Q1 -> zzz
|
||||||
@ -1249,7 +1249,7 @@ int V3PreProcImp::getStateToken() {
|
|||||||
refp->nextarg(refp->nextarg() + rtn);
|
refp->nextarg(refp->nextarg() + rtn);
|
||||||
goto next_tok;
|
goto next_tok;
|
||||||
} else if (tok == VP_STRIFY) {
|
} else if (tok == VP_STRIFY) {
|
||||||
// We must expand stringinfication, when done will return to this state
|
// We must expand stringification, when done will return to this state
|
||||||
statePush(ps_STRIFY);
|
statePush(ps_STRIFY);
|
||||||
goto next_tok;
|
goto next_tok;
|
||||||
} else {
|
} else {
|
||||||
|
@ -151,7 +151,7 @@ private:
|
|||||||
|
|
||||||
// Timescale
|
// Timescale
|
||||||
if (v3Global.opt.hierChild() && v3Global.rootp()->timescaleSpecified()) {
|
if (v3Global.opt.hierChild() && v3Global.rootp()->timescaleSpecified()) {
|
||||||
// Emit timescale for hierarhical verilation if input HDL specifies timespec
|
// Emit timescale for hierarchical verilation if input HDL specifies timespec
|
||||||
txtp->addText(fl, std::string{"timeunit "} + modp->timeunit().ascii() + ";\n");
|
txtp->addText(fl, std::string{"timeunit "} + modp->timeunit().ascii() + ";\n");
|
||||||
txtp->addText(fl, std::string{"timeprecision "}
|
txtp->addText(fl, std::string{"timeprecision "}
|
||||||
+ +v3Global.rootp()->timeprecision().ascii() + ";\n");
|
+ +v3Global.rootp()->timeprecision().ascii() + ";\n");
|
||||||
|
@ -349,7 +349,7 @@ AstSenTree* createTriggerSenTree(AstNetlist* netlistp, AstVarScope* const vscp,
|
|||||||
// Utility for extra trigger allocation
|
// Utility for extra trigger allocation
|
||||||
|
|
||||||
class ExtraTriggers final {
|
class ExtraTriggers final {
|
||||||
std::vector<string> m_descriptions; // Human readable descirption of extra triggers
|
std::vector<string> m_descriptions; // Human readable description of extra triggers
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExtraTriggers() = default;
|
ExtraTriggers() = default;
|
||||||
|
@ -79,7 +79,7 @@ struct LogicClasses final {
|
|||||||
LogicByScope m_initial; // initial blocks
|
LogicByScope m_initial; // initial blocks
|
||||||
LogicByScope m_final; // final blocks
|
LogicByScope m_final; // final blocks
|
||||||
LogicByScope m_comb; // Combinational logic (logic with implicit sensitivities)
|
LogicByScope m_comb; // Combinational logic (logic with implicit sensitivities)
|
||||||
LogicByScope m_clocked; // Clocked (or sequential) logic (logic with explictit sensitivities)
|
LogicByScope m_clocked; // Clocked (or sequential) logic (logic with explicit sensitivities)
|
||||||
LogicByScope m_hybrid; // Hybrid logic (combinational logic with some explicit sensitivities)
|
LogicByScope m_hybrid; // Hybrid logic (combinational logic with some explicit sensitivities)
|
||||||
LogicByScope m_postponed; // Postponed logic ($strobe)
|
LogicByScope m_postponed; // Postponed logic ($strobe)
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class SenExprBuilder final {
|
|||||||
AstScope* const m_scopep; // The scope
|
AstScope* const m_scopep; // The scope
|
||||||
|
|
||||||
std::vector<AstVar*> m_locals; // Trigger eval local variables
|
std::vector<AstVar*> m_locals; // Trigger eval local variables
|
||||||
std::vector<AstNodeStmt*> m_inits; // Initialization statements for prevoius values
|
std::vector<AstNodeStmt*> m_inits; // Initialization statements for previous values
|
||||||
std::vector<AstNodeStmt*> m_preUpdates; // Pre update assignments
|
std::vector<AstNodeStmt*> m_preUpdates; // Pre update assignments
|
||||||
std::vector<AstNodeStmt*> m_postUpdates; // Post update assignments
|
std::vector<AstNodeStmt*> m_postUpdates; // Post update assignments
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class SenExprBuilder final {
|
|||||||
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_curr; // The 'current value' signals
|
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_curr; // The 'current value' signals
|
||||||
std::unordered_set<VNRef<AstNode>> m_hasPreUpdate; // Whether the given sen expression already
|
std::unordered_set<VNRef<AstNode>> m_hasPreUpdate; // Whether the given sen expression already
|
||||||
// has an update statement in m_preUpdates
|
// has an update statement in m_preUpdates
|
||||||
std::unordered_set<VNRef<AstNode>> m_hasPostUpdate; // Likewis for m_postUpdates
|
std::unordered_set<VNRef<AstNode>> m_hasPostUpdate; // Likewise for m_postUpdates
|
||||||
|
|
||||||
V3UniqueNames m_currNames{"__Vtrigcurrexpr"}; // For generating unique current value
|
V3UniqueNames m_currNames{"__Vtrigcurrexpr"}; // For generating unique current value
|
||||||
// signal names
|
// signal names
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3SplitVar divides a variable into multiple variables to avoid UNOPTFLAT warning
|
// V3SplitVar divides a variable into multiple variables to avoid UNOPTFLAT warning
|
||||||
// and get better perfomance.
|
// and get better performance.
|
||||||
// Variables to be split must be marked by /*verilator split_var*/ metacomment.
|
// Variables to be split must be marked by /*verilator split_var*/ metacomment.
|
||||||
// There are sveral kinds of data types that may cause the warning.
|
// There are several kinds of data types that may cause the warning.
|
||||||
// 1) Unpacked arrays
|
// 1) Unpacked arrays
|
||||||
// 2) Packed arrays
|
// 2) Packed arrays
|
||||||
// 3) Unpacked structs
|
// 3) Unpacked structs
|
||||||
@ -1142,7 +1142,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If varp is an argument of task/func, need to update temporary var
|
// If varp is an argument of task/func, need to update temporary var
|
||||||
// everytime the var is updated. See also another call of connectPortAndVar() in
|
// every time the var is updated. See also another call of connectPortAndVar() in
|
||||||
// split()
|
// split()
|
||||||
if (varp->isIO() && (varp->isFuncLocal() || varp->isFuncReturn()))
|
if (varp->isIO() && (varp->isFuncLocal() || varp->isFuncReturn()))
|
||||||
connectPortAndVar(vars, varp, ref.nodep());
|
connectPortAndVar(vars, varp, ref.nodep());
|
||||||
|
@ -656,7 +656,7 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||||||
void aggregateTriSameStrength(AstNodeModule* nodep, AstVar* const varp, AstVar* const envarp,
|
void aggregateTriSameStrength(AstNodeModule* nodep, AstVar* const varp, AstVar* const envarp,
|
||||||
RefStrengthVec::iterator beginStrength,
|
RefStrengthVec::iterator beginStrength,
|
||||||
RefStrengthVec::iterator endStrength) {
|
RefStrengthVec::iterator endStrength) {
|
||||||
// For each driver seperate variables (normal and __en) are created and initialized with
|
// For each driver separate variables (normal and __en) are created and initialized with
|
||||||
// values. In case of normal variable, the original expression is reused. Their values are
|
// values. In case of normal variable, the original expression is reused. Their values are
|
||||||
// aggregated using | to form one expression, which are assigned to varp end envarp.
|
// aggregated using | to form one expression, which are assigned to varp end envarp.
|
||||||
AstNodeExpr* orp = nullptr;
|
AstNodeExpr* orp = nullptr;
|
||||||
|
@ -386,7 +386,7 @@ private:
|
|||||||
if (m_inBBox || nodep->access().isReadOrRW()
|
if (m_inBBox || nodep->access().isReadOrRW()
|
||||||
|| fdrv
|
|| fdrv
|
||||||
// Inouts have only isWrite set, as we don't have more
|
// Inouts have only isWrite set, as we don't have more
|
||||||
// information and operating on module boundry, treat as
|
// information and operating on module boundary, treat as
|
||||||
// both read and writing
|
// both read and writing
|
||||||
|| m_inInoutPin)
|
|| m_inInoutPin)
|
||||||
entryp->usedWhole();
|
entryp->usedWhole();
|
||||||
|
@ -1138,7 +1138,7 @@ private:
|
|||||||
if (nodep->didWidthAndSet()) return;
|
if (nodep->didWidthAndSet()) return;
|
||||||
if (m_vup && m_vup->prelim()) {
|
if (m_vup && m_vup->prelim()) {
|
||||||
if (VN_IS(nodep->dtypep()->skipRefToEnump(), EnumDType)) {
|
if (VN_IS(nodep->dtypep()->skipRefToEnump(), EnumDType)) {
|
||||||
// Assume this constant was properly casted ealier
|
// Assume this constant was properly casted earlier
|
||||||
// (Otherwise it couldn't have an enum data type)
|
// (Otherwise it couldn't have an enum data type)
|
||||||
} else if (nodep->num().isString()) {
|
} else if (nodep->num().isString()) {
|
||||||
nodep->dtypeSetString();
|
nodep->dtypeSetString();
|
||||||
@ -1713,7 +1713,7 @@ private:
|
|||||||
userIterate(nodep->subDTypep(), nullptr);
|
userIterate(nodep->subDTypep(), nullptr);
|
||||||
nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep()));
|
nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep()));
|
||||||
nodep->typedefp(nullptr); // Note until line above subDTypep() may have followed this
|
nodep->typedefp(nullptr); // Note until line above subDTypep() may have followed this
|
||||||
// Widths are resolved, but special iterate to check for recurstion
|
// Widths are resolved, but special iterate to check for recursion
|
||||||
userIterate(nodep->subDTypep(), nullptr);
|
userIterate(nodep->subDTypep(), nullptr);
|
||||||
}
|
}
|
||||||
// Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp());
|
// Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp());
|
||||||
@ -1732,7 +1732,7 @@ private:
|
|||||||
<< refp->warnOther()
|
<< refp->warnOther()
|
||||||
<< "... Location of reference\n"
|
<< "... Location of reference\n"
|
||||||
<< refp->warnContextSecondary());
|
<< refp->warnContextSecondary());
|
||||||
// May cause internel error but avoids infinite loop on dump
|
// May cause internal error but avoids infinite loop on dump
|
||||||
refp->typedefp(nullptr);
|
refp->typedefp(nullptr);
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||||
return;
|
return;
|
||||||
@ -3789,7 +3789,7 @@ private:
|
|||||||
const auto it = patmap.find(memp);
|
const auto it = patmap.find(memp);
|
||||||
AstPatMember* patp = nullptr;
|
AstPatMember* patp = nullptr;
|
||||||
if (it == patmap.end()) {
|
if (it == patmap.end()) {
|
||||||
// default or deafult_type assignment
|
// default or default_type assignment
|
||||||
if (AstNodeUOrStructDType* const memp_nested_vdtypep
|
if (AstNodeUOrStructDType* const memp_nested_vdtypep
|
||||||
= VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) {
|
= VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) {
|
||||||
newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp, newp,
|
newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp, newp,
|
||||||
|
Loading…
Reference in New Issue
Block a user