mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add VPI eval needed tracking (#5065)
This commit is contained in:
parent
a9664b8d16
commit
25fd8ef5c0
@ -407,6 +407,12 @@ only a couple of instructions.
|
||||
For signal callbacks to work the main loop of the program must call
|
||||
:code:`VerilatedVpi::callValueCbs()`.
|
||||
|
||||
Verilator also tracks when the model state has been modified via the VPI with
|
||||
an :code:`evalNeeded` flag. This flag can be checked with :code:`VerilatedVpi::evalNeeded()`
|
||||
and it can be cleared with :code:`VerilatedVpi::clearEvalNeeded()`. Used together
|
||||
it is possible to skip :code:`eval()` calls if no model state has been changed
|
||||
since the last :code:`eval()`.
|
||||
|
||||
|
||||
.. _VPI Example:
|
||||
|
||||
|
@ -655,6 +655,7 @@ class VerilatedVpiImp final {
|
||||
VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info
|
||||
VerilatedAssertOneThread m_assertOne; // Assert only called from single thread
|
||||
uint64_t m_nextCallbackId = 1; // Id to identify callback
|
||||
bool m_evalNeeded = false; // Model has had signals updated via vpi_put_value()
|
||||
|
||||
static VerilatedVpiImp& s() { // Singleton
|
||||
static VerilatedVpiImp s_s;
|
||||
@ -813,6 +814,8 @@ public:
|
||||
}
|
||||
static void dumpCbs() VL_MT_UNSAFE_ONE;
|
||||
static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE; // getter for vpi error info
|
||||
static void evalNeeded(bool evalNeeded) { s().m_evalNeeded = evalNeeded; }
|
||||
static bool evalNeeded() { return s().m_evalNeeded; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
@ -915,6 +918,9 @@ PLI_INT32 VerilatedVpioReasonCb::dovpi_remove_cb() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void VerilatedVpi::clearEvalNeeded() VL_MT_UNSAFE_ONE { VerilatedVpiImp::evalNeeded(false); }
|
||||
bool VerilatedVpi::evalNeeded() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::evalNeeded(); }
|
||||
|
||||
//======================================================================
|
||||
// VerilatedVpiImp implementation
|
||||
|
||||
@ -2445,6 +2451,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
||||
VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", vop->fullname(),
|
||||
valuep->format, valuep->value.integer);
|
||||
VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", vop->varp()->datap(), vop->varDatap()););
|
||||
VerilatedVpiImp::evalNeeded(true);
|
||||
|
||||
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
|
@ -54,6 +54,11 @@ public:
|
||||
static QData cbNextDeadline() VL_MT_UNSAFE_ONE;
|
||||
/// Debug dump of callbacks
|
||||
static void dumpCbs() VL_MT_UNSAFE_ONE;
|
||||
/// Checks VPI dirty state (i.e. whether vpi_put_value() has
|
||||
/// been called since the last clearEvalNeeded())
|
||||
static bool evalNeeded() VL_MT_UNSAFE_ONE;
|
||||
/// Clears VPI dirty state (see evalNeeded())
|
||||
static void clearEvalNeeded() VL_MT_UNSAFE_ONE;
|
||||
|
||||
// Self test, for internal use only
|
||||
static void selfTest() VL_MT_UNSAFE_ONE;
|
||||
|
@ -443,6 +443,19 @@ int _mon_check_varlist() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void touch_signal() {
|
||||
TestVpiHandle vh1 = VPI_HANDLE("count");
|
||||
TEST_CHECK_NZ(vh1);
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
s_vpi_time t;
|
||||
t.type = vpiSimTime;
|
||||
t.high = 0;
|
||||
t.low = 0;
|
||||
v.value.integer = 0;
|
||||
vpi_put_value(vh1, &v, &t, vpiNoDelay);
|
||||
}
|
||||
|
||||
int _mon_check_ports() {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("-mon_check_ports()\n");
|
||||
@ -959,6 +972,14 @@ int main(int argc, char** argv) {
|
||||
CHECK_RESULT(callback_count_half, 250);
|
||||
CHECK_RESULT(callback_count_quad, 2);
|
||||
CHECK_RESULT(callback_count_strs, callback_count_strs_max);
|
||||
VerilatedVpi::clearEvalNeeded();
|
||||
if (VerilatedVpi::evalNeeded()) {
|
||||
vl_fatal(FILENM, __LINE__, "main", "%Error: Unexpected VPI dirty state");
|
||||
}
|
||||
touch_signal();
|
||||
if (!VerilatedVpi::evalNeeded()) {
|
||||
vl_fatal(FILENM, __LINE__, "main", "%Error: Unexpected VPI clean state");
|
||||
}
|
||||
if (!contextp->gotFinish()) {
|
||||
vl_fatal(FILENM, __LINE__, "main", "%Error: Timeout; never got a $finish");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user