Add method to check if there are VPI callbacks of the given type (#5399)

This commit is contained in:
Kaleb Barrett 2024-08-27 16:36:51 -05:00 committed by GitHub
parent 155dcc5658
commit e04ef5d83a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 26 deletions

View File

@ -896,6 +896,9 @@ public:
if (VL_LIKELY(it != s().m_futureCbs.cend())) return it->first.first;
return ~0ULL; // maxquad
}
static bool hasCbs(const uint32_t reason) VL_MT_UNSAFE_ONE {
return !s().m_cbCurrentLists[reason].empty();
}
static bool callCbs(const uint32_t reason) VL_MT_UNSAFE_ONE {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: callCbs reason=%u\n", reason););
assertOneCheck();
@ -1056,6 +1059,10 @@ bool VerilatedVpi::callCbs(uint32_t reason) VL_MT_UNSAFE_ONE {
return VerilatedVpiImp::callCbs(reason);
}
bool VerilatedVpi::hasCbs(uint32_t reason) VL_MT_UNSAFE_ONE {
return VerilatedVpiImp::hasCbs(reason);
}
// Historical, before we had multiple kinds of timed callbacks
void VerilatedVpi::callTimedCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::callCbs(cbAfterDelay); }

View File

@ -49,6 +49,9 @@ public:
/// Call callbacks of arbitrary types.
/// User wrapper code should call this from their main loops.
static bool callCbs(uint32_t reason) VL_MT_UNSAFE_ONE;
/// Returns true if there are callbacks of the given reason registered.
/// User wrapper code should call this from their main loops.
static bool hasCbs(uint32_t reason) VL_MT_UNSAFE_ONE;
/// Returns time of the next registered VPI callback, or
/// ~(0ULL) if none are registered
static QData cbNextDeadline() VL_MT_UNSAFE_ONE;

View File

@ -107,32 +107,22 @@ int main(int argc, char** argv) {
#endif
while (!contextp->gotFinish()) {
// Call registered timed callbacks (e.g. clock timer)
// These are called at the beginning of the time step
// before the iterative regions (IEEE 1800-2012 4.4.1)
VerilatedVpi::callTimedCbs();
do {
// We must evaluate whole design until we process all 'events' for
// this time step
do {
top->eval_step();
VerilatedVpi::clearEvalNeeded();
VerilatedVpi::doInertialPuts();
settle_value_callbacks();
} while (VerilatedVpi::evalNeeded());
// Call Value Change callbacks triggered by Timer callbacks
// These can modify signal values
settle_value_callbacks();
// Run ReadWrite callback as we are done processing this eval step
VerilatedVpi::callCbs(cbReadWriteSynch);
VerilatedVpi::doInertialPuts();
settle_value_callbacks();
} while (VerilatedVpi::evalNeeded() || VerilatedVpi::hasCbs(cbReadWriteSynch));
// We must evaluate whole design until we process all 'events'
bool again = true;
while (again) {
// Evaluate design
top->eval_step();
// Call Value Change callbacks triggered by eval()
// These can modify signal values
again = settle_value_callbacks();
// Call registered ReadWrite callbacks
again |= VerilatedVpi::callCbs(cbReadWriteSynch);
// Call Value Change callbacks triggered by ReadWrite callbacks
// These can modify signal values
again |= settle_value_callbacks();
}
top->eval_end_step();
// Call ReadOnly callbacks
@ -161,9 +151,12 @@ int main(int argc, char** argv) {
// It should be called in simulation cycle before everything else
// but not on first cycle
VerilatedVpi::callCbs(cbNextSimTime);
settle_value_callbacks();
// Call Value Change callbacks triggered by NextTimeStep callbacks
// These can modify signal values
// Call registered timed callbacks (e.g. clock timer)
// These are called at the beginning of the time step
// before the iterative regions (IEEE 1800-2012 4.4.1)
VerilatedVpi::callTimedCbs();
settle_value_callbacks();
}