Fix multiple VPI variable callbacks, bug679.
This commit is contained in:
parent
39c494260b
commit
24e32420b7
1
Changes
1
Changes
|
|
@ -5,6 +5,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
* Verilator 3.854 devel
|
||||
|
||||
**** Fix multiple VPI variable callbacks, bug679. [Rich Porter]
|
||||
|
||||
|
||||
* Verilator 3.853 2013-09-30
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
// Internal macros
|
||||
|
||||
#define _VL_VPI_INTERNAL VerilatedVpi::error_info()->setMessage(vpiInternal)->setMessage
|
||||
#define _VL_VPI_SYSTEM VerilatedVpi::error_info()->setMessage(vpiSystem )->setMessage
|
||||
#define _VL_VPI_SYSTEM VerilatedVpi::error_info()->setMessage(vpiSystem )->setMessage
|
||||
#define _VL_VPI_ERROR VerilatedVpi::error_info()->setMessage(vpiError )->setMessage
|
||||
#define _VL_VPI_WARNING VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage
|
||||
#define _VL_VPI_NOTICE VerilatedVpi::error_info()->setMessage(vpiNotice )->setMessage
|
||||
|
|
@ -52,6 +52,8 @@
|
|||
// Implementation
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
|
||||
#define VL_VPI_LINE_SIZE 8192
|
||||
|
|
@ -301,7 +303,7 @@ class VerilatedVpiError;
|
|||
|
||||
class VerilatedVpi {
|
||||
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
|
||||
typedef set<VerilatedVpioCb*> VpioCbSet;
|
||||
typedef list<VerilatedVpioCb*> VpioCbList;
|
||||
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
|
||||
struct product_info {
|
||||
|
|
@ -309,7 +311,7 @@ class VerilatedVpi {
|
|||
PLI_BYTE8* version;
|
||||
};
|
||||
|
||||
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioTimedCbs m_timedCbs; // Time based callbacks
|
||||
VerilatedVpiError* m_errorInfop; // Container for vpi error info
|
||||
|
||||
|
|
@ -325,17 +327,14 @@ public:
|
|||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
s_s.m_cbObjSets[vop->reason()].insert(vop);
|
||||
s_s.m_cbObjLists[vop->reason()].push_back(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
|
||||
}
|
||||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
|
||||
VpioCbSet::iterator it=cbObjSet.find(cbp);
|
||||
if (VL_LIKELY(it != cbObjSet.end())) {
|
||||
cbObjSet.erase(it);
|
||||
}
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
|
||||
cbObjList.remove(cbp);
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
|
||||
|
|
@ -364,8 +363,8 @@ public:
|
|||
}
|
||||
}
|
||||
static void callCbs(vluint32_t reason) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
|
||||
|
|
@ -373,8 +372,9 @@ public:
|
|||
}
|
||||
}
|
||||
static void callValueCbs() {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
|
||||
set<VerilatedVpioVar*> update; // set of objects to update after callbacks
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
|
|
@ -386,12 +386,15 @@ public:
|
|||
if (memcmp(prevDatap, newDatap, varop->entSize())) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
memcpy(prevDatap, newDatap, varop->entSize());
|
||||
update.insert(varop);
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (set<VerilatedVpioVar*>::iterator it=update.begin(); it!=update.end(); it++ ) {
|
||||
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
|
||||
}
|
||||
}
|
||||
|
||||
static VerilatedVpiError* error_info(); // getter for vpi error info
|
||||
|
|
|
|||
|
|
@ -30,13 +30,28 @@
|
|||
|
||||
#define TEST_MSG if (0) printf
|
||||
|
||||
struct countdown {
|
||||
int count;
|
||||
vpiHandle callback;
|
||||
countdown(int count) : count(count) {};
|
||||
int decrement() {
|
||||
if (!--count) {
|
||||
vpi_remove_cb(callback);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
PLI_BYTE8* ptr() {
|
||||
return (PLI_BYTE8*)this;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned int main_time = false;
|
||||
unsigned int callback_count = false;
|
||||
unsigned int callback_count_half = false;
|
||||
unsigned int callback_count_quad = false;
|
||||
unsigned int callback_count_strs = false;
|
||||
unsigned int callback_count_strs_max = 500;
|
||||
|
||||
countdown cd(200);
|
||||
//======================================================================
|
||||
|
||||
|
||||
|
|
@ -142,6 +157,10 @@ int _value_callback(p_cb_data cb_data) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int _value_callback_countdown(p_cb_data cb_data) {
|
||||
return ((countdown*)(cb_data->user_data))->decrement() < 1;
|
||||
};
|
||||
|
||||
int _value_callback_half(p_cb_data cb_data) {
|
||||
CHECK_RESULT(cb_data->value->value.integer*2+10, main_time);
|
||||
callback_count_half++;
|
||||
|
|
@ -170,10 +189,15 @@ int _mon_check_value_callbacks() {
|
|||
cb_data.cb_rtn = _value_callback;
|
||||
cb_data.obj = vh1;
|
||||
cb_data.value = &v;
|
||||
|
||||
vpiHandle vh = vpi_register_cb(&cb_data);
|
||||
CHECK_RESULT_NZ(vh);
|
||||
|
||||
// add another callback to same signal
|
||||
cb_data.cb_rtn = _value_callback_countdown;
|
||||
cb_data.user_data = cd.ptr();
|
||||
cd.callback = vpi_register_cb(&cb_data);
|
||||
CHECK_RESULT_NZ(cd.callback);
|
||||
|
||||
vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.half_count", NULL);
|
||||
CHECK_RESULT_NZ(vh1);
|
||||
|
||||
|
|
@ -628,6 +652,7 @@ int main(int argc, char **argv, char **env) {
|
|||
CHECK_RESULT(callback_count_half, 250);
|
||||
CHECK_RESULT(callback_count_quad, 2);
|
||||
CHECK_RESULT(callback_count_strs, callback_count_strs_max);
|
||||
CHECK_RESULT(cd.count, 0)
|
||||
if (!Verilated::gotFinish()) {
|
||||
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue