Support VPI array accessors (#5612)
This commit is contained in:
parent
283f6c7433
commit
ac659d525b
|
@ -41,6 +41,7 @@ David Metz
|
|||
David Stanford
|
||||
David Turner
|
||||
Dercury
|
||||
Diego Roux
|
||||
Don Williamson
|
||||
Drew Ranck
|
||||
Drew Taussig
|
||||
|
@ -99,6 +100,7 @@ Jesse Taube
|
|||
Jevin Sweval
|
||||
Jiacheng Qian
|
||||
Jiamin Zhu
|
||||
Jitesh Nayak
|
||||
Jinyan Xu
|
||||
Jiuyang Liu
|
||||
Joey Liu
|
||||
|
|
|
@ -2884,13 +2884,637 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void vpi_get_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/,
|
||||
PLI_INT32* /*index_p*/, PLI_UINT32 /*num*/) {
|
||||
VL_VPI_UNIMP_();
|
||||
bool vl_check_array_format(const VerilatedVar* varp, const p_vpi_arrayvalue arrayvalue_p,
|
||||
const char* fullname) {
|
||||
if (arrayvalue_p->format == vpiVectorVal) {
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
case VLVT_UINT16:
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: return true;
|
||||
default:;
|
||||
}
|
||||
} else if (arrayvalue_p->format == vpiIntVal) {
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
case VLVT_UINT16:
|
||||
case VLVT_UINT32: return true;
|
||||
default:;
|
||||
}
|
||||
} else if ((arrayvalue_p->format == vpiRawTwoStateVal)
|
||||
|| (arrayvalue_p->format == vpiRawFourStateVal)) {
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
case VLVT_UINT16:
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: return true;
|
||||
default:;
|
||||
}
|
||||
} else if (arrayvalue_p->format == vpiShortIntVal) {
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
case VLVT_UINT16: return true;
|
||||
default:;
|
||||
}
|
||||
} else if (arrayvalue_p->format == vpiLongIntVal) {
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
case VLVT_UINT16:
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64: return true;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", __func__,
|
||||
VerilatedVpiError::strFromVpiVal(arrayvalue_p->format), fullname);
|
||||
|
||||
return false;
|
||||
}
|
||||
void vpi_put_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/,
|
||||
PLI_INT32* /*index_p*/, PLI_UINT32 /*num*/) {
|
||||
VL_VPI_UNIMP_();
|
||||
|
||||
template <typename T, typename K>
|
||||
void vl_get_value_array_integrals(unsigned index, const unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow, const T* src,
|
||||
K* dst) {
|
||||
static_assert(sizeof(K) >= sizeof(T), "size of type K is less than size of type T");
|
||||
for (int i = 0; i < num; i++) {
|
||||
dst[i] = src[index];
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename K>
|
||||
void vl_put_value_array_integrals(unsigned index, const unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow, const T* src,
|
||||
K* dst) {
|
||||
static_assert(std::is_integral<T>::value, "type T is not an integral type");
|
||||
static_assert(std::is_unsigned<T>::value, "type T is not unsigned");
|
||||
static_assert(sizeof(T) >= sizeof(K), "size of type T is less than size of type K");
|
||||
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
|
||||
const T mask = element_size_bytes == sizeof(T)
|
||||
? static_cast<T>(-1)
|
||||
: ~(static_cast<T>(-1) << (element_size_bytes * 8));
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
dst[index] = src[i] & static_cast<T>(mask);
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow, const T* src,
|
||||
p_vpi_vecval dst) {
|
||||
static_assert(std::is_unsigned<T>::value,
|
||||
"type T is not unsigned"); // ensure logical right shift
|
||||
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_words = VL_WORDS_I(packedSize);
|
||||
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
|
||||
if (sizeof(T) == sizeof(QData)) {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
dst[i * 2].aval = static_cast<QData>(src[index]);
|
||||
dst[i * 2].bval = 0;
|
||||
dst[(i * 2) + 1].aval = static_cast<QData>(src[index]) >> 32;
|
||||
dst[(i * 2) + 1].bval = 0;
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const size_t dst_index = i * element_size_words;
|
||||
const size_t src_index = index * element_size_words;
|
||||
for (unsigned j = 0; j < element_size_words; j++) {
|
||||
dst[dst_index + j].aval = src[src_index + j];
|
||||
dst[dst_index + j].bval = 0;
|
||||
}
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void vl_put_value_array_vectors(unsigned index, const unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow,
|
||||
const bool fourState, const p_vpi_vecval src, T* dst) {
|
||||
static_assert(std::is_unsigned<T>::value, "type T is not unsigned");
|
||||
static_assert(std::is_integral<T>::value, "type T is not an integral type");
|
||||
const unsigned element_size_bytes VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_words VL_WORDS_I(packedSize);
|
||||
if (sizeof(T) == sizeof(QData)) { //destination is QDATA
|
||||
const QData mask = element_size_bytes == sizeof(T)
|
||||
? static_cast<QData>(-1)
|
||||
: ~(static_cast<QData>(-1) << (element_size_bytes * 8));
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
dst[index] = src[i * 2].aval;
|
||||
dst[index]
|
||||
|= (static_cast<QData>(src[(i * 2) + 1].aval) << (sizeof(PLI_UINT32) * 8)) & mask;
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
unsigned bytes_stored = 0;
|
||||
for (unsigned j = 0; j < element_size_words; j++) {
|
||||
if (bytes_stored >= element_size_bytes) break;
|
||||
const T mask
|
||||
= (element_size_bytes - bytes_stored) >= sizeof(PLI_UINT32)
|
||||
? static_cast<T>(-1)
|
||||
: ~(static_cast<T>(-1) << ((element_size_bytes - bytes_stored) * 8));
|
||||
dst[(index * element_size_words) + j]
|
||||
= static_cast<T>(src[(i * element_size_words) + j].aval) & mask;
|
||||
bytes_stored += sizeof(PLI_UINT32);
|
||||
}
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void vl_get_value_array_rawvals(unsigned index, unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow,
|
||||
const bool fourState, const T* src, PLI_BYTE8* dst) {
|
||||
static_assert(std::is_unsigned<T>::value,
|
||||
"type T is not unsigned"); //ensure loigcal right shift
|
||||
const unsigned element_size_bytes VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
|
||||
size_t dst_index = 0;
|
||||
while (num-- > 0) {
|
||||
const size_t src_offset = index * element_size_repr;
|
||||
unsigned bytes_copied = 0;
|
||||
for (unsigned j = 0; j < element_size_repr; j++) {
|
||||
const T& src_data = src[src_offset + j];
|
||||
for (unsigned k = 0; k < sizeof(T); k++) {
|
||||
if (bytes_copied++ == element_size_bytes) break;
|
||||
dst[dst_index++] = src_data >> (k * 8);
|
||||
}
|
||||
}
|
||||
if (fourState) {
|
||||
std::fill(dst + dst_index, dst + dst_index + element_size_bytes, 0);
|
||||
dst_index += element_size_bytes;
|
||||
}
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsigned size,
|
||||
const unsigned packedSize, const bool leftIsLow,
|
||||
const bool fourState, const PLI_UBYTE8* src, T* dst) {
|
||||
const unsigned element_size_bytes VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
unsigned bytes_copied = 0;
|
||||
const size_t dst_offset = index * element_size_repr;
|
||||
const size_t src_offset = i * element_size_bytes;
|
||||
for (unsigned j = 0; j < element_size_repr; j++) {
|
||||
T& dst_data = dst[dst_offset + j];
|
||||
for (unsigned k = 0; k < sizeof(T); k++) {
|
||||
if (bytes_copied == element_size_bytes) break;
|
||||
const unsigned src_index
|
||||
= fourState ? (src_offset * 2) + bytes_copied : (src_offset) + bytes_copied;
|
||||
dst_data &= ~((static_cast<T>(0xFF) & 0xFF) << (k * 8));
|
||||
dst_data |= ((static_cast<T>(src[src_index]) & 0xFF) << (k * 8));
|
||||
bytes_copied++;
|
||||
}
|
||||
}
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
: index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
static thread_local EData out_data[VL_VALUE_STRING_MAX_WORDS * 2];
|
||||
|
||||
const unsigned size = vop->size();
|
||||
if (VL_UNCOVERABLE(num > size)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: requested elements (%u) exceed array size (%u)",
|
||||
__func__, num, size);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
||||
int index
|
||||
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||
|
||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||
if (VL_UNCOVERABLE((sizeof(PLI_INT16) * num) >= VL_VALUE_STRING_MAX_CHARS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
PLI_INT16* shortintsp = (PLI_INT16*)out_data;
|
||||
arrayvalue_p->value.shortints = shortintsp;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
const CData* ptr = reinterpret_cast<CData*>(vop->varDatap());
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varCDatap(), shortintsp);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varSDatap(), shortintsp);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiIntVal) {
|
||||
if (VL_UNCOVERABLE(num >= VL_VALUE_STRING_MAX_WORDS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
PLI_INT32* integersp = (PLI_INT32*)out_data;
|
||||
arrayvalue_p->value.integers = integersp;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varCDatap(), integersp);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varSDatap(), integersp);
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varIDatap(), integersp);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiLongIntVal) {
|
||||
if (VL_UNCOVERABLE((sizeof(PLI_INT64) * num) >= VL_VALUE_STRING_MAX_CHARS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
PLI_INT64* longintsp = (PLI_INT64*)out_data;
|
||||
arrayvalue_p->value.longints = longintsp;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varCDatap(), longintsp);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varSDatap(), longintsp);
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varIDatap(), longintsp);
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_get_value_array_integrals(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varQDatap(), longintsp);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiVectorVal) {
|
||||
if (VL_UNCOVERABLE((VL_WORDS_I(varp->entBits()) * 2 * num) >= VL_VALUE_STRING_MAX_WORDS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
p_vpi_vecval vectorsp = (p_vpi_vecval)out_data;
|
||||
arrayvalue_p->value.vectors = vectorsp;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_get_value_array_vectors(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varCDatap(), vectorsp);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_vectors(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varSDatap(), vectorsp);
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_get_value_array_vectors(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varIDatap(), vectorsp);
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_get_value_array_vectors(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varQDatap(), vectorsp);
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_get_value_array_vectors(index, num, size, varp->entBits(), leftIsLow,
|
||||
vop->varEDatap(), vectorsp);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiRawFourStateVal) {
|
||||
if (VL_UNCOVERABLE((VL_BYTES_I(varp->entBits()) * 2 * num) >= VL_VALUE_STRING_MAX_CHARS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
PLI_BYTE8* valuep = (PLI_BYTE8*)out_data;
|
||||
arrayvalue_p->value.rawvals = valuep;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vop->varCDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vop->varSDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vop->varIDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vop->varQDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vop->varEDatap(), valuep);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiRawTwoStateVal) {
|
||||
if (VL_UNCOVERABLE((VL_BYTES_I(varp->entBits()) * num) >= VL_VALUE_STRING_MAX_CHARS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value_array with more than VL_VALUE_STRING_MAX_WORDS; "
|
||||
"increase and recompile");
|
||||
}
|
||||
|
||||
PLI_BYTE8* valuep = (PLI_BYTE8*)out_data;
|
||||
arrayvalue_p->value.rawvals = valuep;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false,
|
||||
vop->varCDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false,
|
||||
vop->varSDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false,
|
||||
vop->varIDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false,
|
||||
vop->varQDatap(), valuep);
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_get_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false,
|
||||
vop->varEDatap(), valuep);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", __func__,
|
||||
VerilatedVpiError::strFromVpiVal(arrayvalue_p->format), vop->fullname());
|
||||
}
|
||||
|
||||
void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value_array %p\n", object););
|
||||
VerilatedVpiImp::assertOneCheck();
|
||||
|
||||
VL_VPI_ERROR_RESET_();
|
||||
if (VL_UNLIKELY(!object)) return;
|
||||
|
||||
if (VL_UNLIKELY(!arrayvalue_p)) {
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
"Ignoring vpi_get_value_array with null value pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(!index_p)) {
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
"Ignoring vpi_get_value_array with null index pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", __func__, object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vop->type() != vpiRegArray) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported type (%p, %s)", __func__, object,
|
||||
VerilatedVpiError::strFromVpiObjType(vop->type()));
|
||||
return;
|
||||
}
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
int lowRange = vop->rangep()->low();
|
||||
int highRange = vop->rangep()->high();
|
||||
|
||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
|
||||
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||
return;
|
||||
}
|
||||
|
||||
if (arrayvalue_p->flags & vpiUserAllocFlag) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vpiUserAllocFlag (%x)", __func__,
|
||||
arrayvalue_p->flags);
|
||||
return;
|
||||
}
|
||||
|
||||
vl_get_value_array(object, arrayvalue_p, index_p, num);
|
||||
}
|
||||
|
||||
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
int size = vop->size();
|
||||
if (VL_UNCOVERABLE(num > size)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__,
|
||||
"%s: requested elements to set (%u) exceed array size (%u)", __func__, num,
|
||||
size);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
||||
int index
|
||||
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||
|
||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||
const PLI_UINT16* shortintsp
|
||||
= reinterpret_cast<PLI_UINT16*>(arrayvalue_p->value.shortints);
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, shortintsp,
|
||||
vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, shortintsp,
|
||||
vop->varSDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiIntVal) {
|
||||
const PLI_UINT32* integersp = reinterpret_cast<PLI_UINT32*>(arrayvalue_p->value.integers);
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, integersp,
|
||||
vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, integersp,
|
||||
vop->varSDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, integersp,
|
||||
vop->varIDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiLongIntVal) {
|
||||
const PLI_UINT64* longintsp = reinterpret_cast<PLI_UINT64*>(arrayvalue_p->value.longints);
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
|
||||
vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
|
||||
vop->varSDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
|
||||
vop->varIDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
|
||||
vop->varQDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiVectorVal) {
|
||||
const p_vpi_vecval vectorsp = arrayvalue_p->value.vectors;
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vectorsp, vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vectorsp, vop->varSDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vectorsp, vop->varIDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vectorsp, vop->varQDatap());
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
|
||||
vectorsp, vop->varEDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiRawFourStateVal) {
|
||||
const PLI_UBYTE8* valuep = reinterpret_cast<PLI_UBYTE8*>(arrayvalue_p->value.rawvals);
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
|
||||
vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
|
||||
vop->varSDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
|
||||
vop->varIDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
|
||||
vop->varQDatap());
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
|
||||
vop->varEDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (arrayvalue_p->format == vpiRawTwoStateVal) {
|
||||
const PLI_UBYTE8* valuep = reinterpret_cast<PLI_UBYTE8*>(arrayvalue_p->value.rawvals);
|
||||
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
|
||||
vop->varCDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT16) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
|
||||
vop->varSDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT32) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
|
||||
vop->varIDatap());
|
||||
} else if (varp->vltype() == VLVT_UINT64) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
|
||||
vop->varQDatap());
|
||||
} else if (varp->vltype() == VLVT_WDATA) {
|
||||
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
|
||||
vop->varEDatap());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", __func__,
|
||||
VerilatedVpiError::strFromVpiVal(arrayvalue_p->format), vop->fullname());
|
||||
}
|
||||
|
||||
void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value_array %p\n", object););
|
||||
VerilatedVpiImp::assertOneCheck();
|
||||
VL_VPI_ERROR_RESET_();
|
||||
|
||||
if (VL_UNLIKELY(!arrayvalue_p)) {
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
"Ignoring vpi_put_value_array with null value pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(!index_p)) {
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
"Ignoring vpi_put_value_array with null index pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", __func__, object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vop->type() != vpiRegArray) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported type (%p, %s)", __func__, object,
|
||||
VerilatedVpiError::strFromVpiObjType(vop->type()));
|
||||
return;
|
||||
}
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
int lowRange = vop->rangep()->low();
|
||||
int highRange = vop->rangep()->high();
|
||||
|
||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
|
||||
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||
return;
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__,
|
||||
"Ignoring vpi_put_value_array to signal marked read-only,"
|
||||
" use public_flat_rw instead: %s",
|
||||
vop->fullname());
|
||||
return;
|
||||
}
|
||||
|
||||
if (arrayvalue_p->flags & (vpiPropagateOff | vpiOneValue)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported flags (%x)", __func__,
|
||||
arrayvalue_p->flags);
|
||||
return;
|
||||
}
|
||||
|
||||
vl_put_value_array(object, arrayvalue_p, index_p, num);
|
||||
}
|
||||
|
||||
// time processing
|
||||
|
|
|
@ -474,6 +474,7 @@ using ssize_t = uint32_t; ///< signed size_t; returned from read()
|
|||
#ifndef VL_VALUE_STRING_MAX_WORDS
|
||||
#define VL_VALUE_STRING_MAX_WORDS 64 ///< Max size in words of String conversion operation
|
||||
#endif
|
||||
#define VL_VALUE_STRING_MAX_CHARS (VL_VALUE_STRING_MAX_WORDS) * 4
|
||||
|
||||
//=========================================================================
|
||||
// Base macros
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "sv_vpi_user.h"
|
||||
#include "vpi_user.h"
|
||||
#include <iostream>
|
||||
|
||||
// Avoid C++11 in this file as not all simulators allow it
|
||||
|
||||
|
|
|
@ -0,0 +1,695 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef IS_VPI
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
#include "Vt_vpi_get_value_array.h"
|
||||
|
||||
#endif
|
||||
|
||||
// These require the above. Comment prevents clang-format moving them
|
||||
#include "TestSimulator.h"
|
||||
#include "TestVpi.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//======================================================================
|
||||
|
||||
int test_vpiRawFourStateVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRawFourStateVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", (i * 2 * elem_size) + j, (offset * elem_size) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(i * 2 * elem_size) + j],
|
||||
test_data[(offset * elem_size) + j]);
|
||||
}
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(((i * 2) + 1) * elem_size) + j], 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiRawTwoStateVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw two state
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRawTwoStateVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", (i * elem_size) + j, (offset * elem_size) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(i * elem_size) + j],
|
||||
test_data[(offset * elem_size) + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiVectorVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
const unsigned elem_size_words = (elem_size + 3) / sizeof(PLI_UINT32);
|
||||
const unsigned vec_size = elem_size_words * size;
|
||||
std::vector<s_vpi_vecval> test_data_vectors;
|
||||
test_data_vectors.reserve(vec_size);
|
||||
unsigned test_data_index = 0;
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
unsigned count = 0;
|
||||
for (unsigned j = 0; j < elem_size_words; j++) {
|
||||
PLI_UINT32& aval = test_data_vectors[(i * elem_size_words) + j].aval;
|
||||
test_data_vectors[(i * elem_size_words) + j].bval = UINT32_MAX;
|
||||
aval = 0;
|
||||
for (unsigned k = 0; k < sizeof(PLI_UINT32); k++) {
|
||||
if (count++ == elem_size) break;
|
||||
aval |= static_cast<PLI_UINT32>(test_data[test_data_index++] & 0xFF) << (k * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test vector
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiVectorVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < vec_size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.vectors[i].aval, i,
|
||||
test_data_vectors[i].aval);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size_words; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("array[%u] == test[%u]\n", (i * elem_size_words) + j,
|
||||
(offset * elem_size_words) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.vectors[(i * elem_size_words) + j].aval,
|
||||
test_data_vectors[(offset * elem_size_words) + j].aval);
|
||||
CHECK_RESULT_HEX(arrayvalue.value.vectors[(i * elem_size_words) + j].bval, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT32> test_data_integers;
|
||||
test_data_integers.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
PLI_INT32& integer = test_data_integers[i];
|
||||
integer = 0;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
integer |= (static_cast<PLI_INT32>(test_data[(i * elem_size) + j]) & 0xFF) << (j * 8);
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.integers[i], i,
|
||||
test_data_integers[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("array[%u] == test[%u]\n", i, offset);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.integers[i], test_data_integers[offset]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiShortIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT16> test_data_shortints;
|
||||
test_data_shortints.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
if (elem_size == 2) {
|
||||
test_data_shortints[i] = test_data[i * 2] & 0xFF;
|
||||
test_data_shortints[i] |= test_data[(i * 2) + 1] << 8;
|
||||
} else {
|
||||
test_data_shortints[i] = test_data[i] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiShortIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.shortints = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.shortints[i], i,
|
||||
test_data_shortints[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("array[%u] == test[%u]\n", i, offset);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.shortints[i], test_data_shortints[offset]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiLongIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned low,
|
||||
const unsigned num, const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u low=%u num=%u size=%u elem_size=%u\n\n", __func__, name,
|
||||
index, low, num, size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT64> test_data_longints;
|
||||
test_data_longints.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
PLI_INT64& longint = test_data_longints[i];
|
||||
longint = 0;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
longint |= (static_cast<PLI_INT64>(test_data[(i * elem_size) + j]) & 0xFF) << (j * 8);
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiLongIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.longints = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// compare to test data
|
||||
index -= low;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("array[%u] == test[%u]\n", i, offset);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.longints[i], test_data_longints[offset]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mon_check_props() {
|
||||
// skip test if not verilator (value_array accessors unimplemented in other sims)
|
||||
if (!TestSimulator::is_verilator()) {
|
||||
#ifdef VERILATOR
|
||||
printf("TestSimulator indicating not verilator, but VERILATOR macro is defined\n");
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned NUM_ELEMENTS = 4;
|
||||
|
||||
PLI_BYTE8 read_bytes[NUM_ELEMENTS]
|
||||
= {static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde),
|
||||
static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe)};
|
||||
|
||||
PLI_BYTE8 read_shorts[NUM_ELEMENTS * 2] = {
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0xef),
|
||||
static_cast<PLI_BYTE8>(0xbe), static_cast<PLI_BYTE8>(0xfe), static_cast<PLI_BYTE8>(0xca),
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0)};
|
||||
|
||||
PLI_BYTE8 read_words[NUM_ELEMENTS * 4] = {
|
||||
static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe), static_cast<PLI_BYTE8>(0xad),
|
||||
static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0),
|
||||
static_cast<PLI_BYTE8>(0xfe), static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0x03),
|
||||
static_cast<PLI_BYTE8>(0x02), static_cast<PLI_BYTE8>(0x01), static_cast<PLI_BYTE8>(0x00),
|
||||
static_cast<PLI_BYTE8>(0x07), static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05),
|
||||
static_cast<PLI_BYTE8>(0x04)};
|
||||
|
||||
PLI_BYTE8 read_longs[NUM_ELEMENTS * 8] = {
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0), static_cast<PLI_BYTE8>(0xfe),
|
||||
static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe),
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x07),
|
||||
static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05), static_cast<PLI_BYTE8>(0x04),
|
||||
static_cast<PLI_BYTE8>(0x03), static_cast<PLI_BYTE8>(0x02), static_cast<PLI_BYTE8>(0x01),
|
||||
static_cast<PLI_BYTE8>(0x00), static_cast<PLI_BYTE8>(0x0F), static_cast<PLI_BYTE8>(0x0E),
|
||||
static_cast<PLI_BYTE8>(0x0D), static_cast<PLI_BYTE8>(0x0C), static_cast<PLI_BYTE8>(0x0B),
|
||||
static_cast<PLI_BYTE8>(0x0A), static_cast<PLI_BYTE8>(0x09), static_cast<PLI_BYTE8>(0x08),
|
||||
static_cast<PLI_BYTE8>(0x17), static_cast<PLI_BYTE8>(0x16), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x14), static_cast<PLI_BYTE8>(0x13), static_cast<PLI_BYTE8>(0x12),
|
||||
static_cast<PLI_BYTE8>(0x11), static_cast<PLI_BYTE8>(0x10)};
|
||||
|
||||
PLI_BYTE8 read_customs[NUM_ELEMENTS * 9] = {
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0), static_cast<PLI_BYTE8>(0xfe),
|
||||
static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe),
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x1A),
|
||||
static_cast<PLI_BYTE8>(0x07), static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05),
|
||||
static_cast<PLI_BYTE8>(0x04), static_cast<PLI_BYTE8>(0x03), static_cast<PLI_BYTE8>(0x02),
|
||||
static_cast<PLI_BYTE8>(0x01), static_cast<PLI_BYTE8>(0x00), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x0F), static_cast<PLI_BYTE8>(0x0E), static_cast<PLI_BYTE8>(0x0D),
|
||||
static_cast<PLI_BYTE8>(0x0C), static_cast<PLI_BYTE8>(0x0B), static_cast<PLI_BYTE8>(0x0A),
|
||||
static_cast<PLI_BYTE8>(0x09), static_cast<PLI_BYTE8>(0x08), static_cast<PLI_BYTE8>(0x0A),
|
||||
static_cast<PLI_BYTE8>(0x17), static_cast<PLI_BYTE8>(0x16), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x14), static_cast<PLI_BYTE8>(0x13), static_cast<PLI_BYTE8>(0x12),
|
||||
static_cast<PLI_BYTE8>(0x11), static_cast<PLI_BYTE8>(0x10), static_cast<PLI_BYTE8>(0x05)};
|
||||
|
||||
char read_bytes_name[] = "test.read_bytes";
|
||||
char read_bytes_nonzero_index_name[] = "test.read_bytes_nonzero_index";
|
||||
char read_bytes_rl_name[] = "test.read_bytes_rl";
|
||||
char read_shorts_name[] = "test.read_shorts";
|
||||
char read_words_name[] = "test.read_words";
|
||||
char read_integers_name[] = "test.read_integers";
|
||||
char read_longs_name[] = "test.read_longs";
|
||||
char read_customs_name[] = "test.read_customs";
|
||||
char read_customs_nonzero_index_rl_name[] = "test.read_customs_nonzero_index_rl";
|
||||
|
||||
for (unsigned i = 0; i < NUM_ELEMENTS; i++) {
|
||||
for (unsigned j = 0; j < (NUM_ELEMENTS + 1); j++) {
|
||||
if (test_vpiRawFourStateVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_shorts_name, read_shorts, i, 0, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_words_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_integers_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_longs_name, read_longs, i, 0, j, NUM_ELEMENTS, 8))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_customs_name, read_customs, i, 0, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(read_customs_nonzero_index_rl_name, read_customs, i + 1, 1,
|
||||
j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiRawTwoStateVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_shorts_name, read_shorts, i, 0, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_words_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_integers_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_longs_name, read_longs, i, 0, j, NUM_ELEMENTS, 8))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_customs_name, read_customs, i, 0, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(read_customs_nonzero_index_rl_name, read_customs, i + 1, 1,
|
||||
j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiVectorVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiVectorVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(read_shorts_name, read_shorts, i, 0, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(read_words_name, read_words, i, 0, j, NUM_ELEMENTS, 4)) return 1;
|
||||
if (test_vpiVectorVal(read_integers_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(read_longs_name, read_longs, i, 0, j, NUM_ELEMENTS, 8)) return 1;
|
||||
if (test_vpiVectorVal(read_customs_name, read_customs, i, 0, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(read_customs_nonzero_index_rl_name, read_customs, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiShortIntVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(read_shorts_name, read_shorts, i, 0, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
|
||||
if (test_vpiIntVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiIntVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiIntVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiIntVal(read_words_name, read_words, i, 0, j, NUM_ELEMENTS, 4)) return 1;
|
||||
if (test_vpiIntVal(read_integers_name, read_words, i, 0, j, NUM_ELEMENTS, 4)) return 1;
|
||||
|
||||
if (test_vpiLongIntVal(read_bytes_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_bytes_nonzero_index_name, read_bytes, i + 1, 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_bytes_rl_name, read_bytes, i, 0, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_shorts_name, read_shorts, i, 0, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_words_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_integers_name, read_words, i, 0, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(read_longs_name, read_longs, i, 0, j, NUM_ELEMENTS, 8))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported format
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_longs", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRealVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported foramt
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiShortRealVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported format
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_longs", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiTimeVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported TestVpiHandle
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported type
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_scalar", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test indexp out of bounds
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_bounds", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {4};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
indexp[0] = 0;
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported flags
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = vpiUserAllocFlag;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported format & vltype combination
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiShortIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, NUM_ELEMENTS);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test num out of bounds
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, indexp, 5);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test null arrayvalue
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, 0, indexp, 0);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test null indexp
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.read_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = 0;
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, 0, 0);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int mon_check(void) { return mon_check_props(); }
|
||||
|
||||
#ifdef IS_VPI
|
||||
static int mon_check_vpi() {
|
||||
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
|
||||
s_vpi_value vpi_value;
|
||||
|
||||
vpi_value.format = vpiIntVal;
|
||||
vpi_value.value.integer = mon_check();
|
||||
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s_vpi_systf_data vpi_systf_data[] = {{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check",
|
||||
(PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
|
||||
0};
|
||||
|
||||
// cver entry
|
||||
void vpi_compat_bootstrap(void) {
|
||||
p_vpi_systf_data systf_data_p;
|
||||
systf_data_p = &(vpi_systf_data[0]);
|
||||
while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
|
||||
}
|
||||
|
||||
// icarus entry
|
||||
void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
const std::unique_ptr<VM_PREFIX> top{new VM_PREFIX{contextp.get(), ""}};
|
||||
contextp->fatalOnVpiError(0);
|
||||
|
||||
#ifdef VERILATOR
|
||||
#ifdef TEST_VERBOSE
|
||||
contextp->scopesDump();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (!contextp->gotFinish()) { top->eval(); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(make_top_shell=False,
|
||||
make_main=False,
|
||||
make_pli=True,
|
||||
verilator_flags2=["--exe --vpi --no-l2name", test.pli_filename],
|
||||
iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI"],
|
||||
v_flags2=["+define+USE_VPI_NOT_DPI +define+VERILATOR_COMMENTS"])
|
||||
|
||||
test.execute(use_libvpi=True)
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,105 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
`ifdef VERILATOR_COMMENTS
|
||||
`define PUBLIC_FLAT_RD /*verilator public_flat_rd*/
|
||||
`define PUBLIC_FLAT_RW /*verilator public_flat_rw*/
|
||||
`else
|
||||
`define PUBLIC_FLAT_RD
|
||||
`define PUBLIC_FLAT_RW
|
||||
`endif
|
||||
|
||||
module test ();
|
||||
|
||||
`ifdef VERILATOR
|
||||
`systemc_header
|
||||
extern "C" int mon_check();
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
reg [7:0] read_bytes [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [7:0] read_bytes_nonzero_index [1:4] `PUBLIC_FLAT_RD;
|
||||
reg [7:0] read_bytes_rl [3:0] `PUBLIC_FLAT_RD;
|
||||
|
||||
reg [15:0] read_shorts [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [31:0] read_words [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [31:0] read_words_rl [3:0] `PUBLIC_FLAT_RD;
|
||||
reg [63:0] read_longs [0:3] `PUBLIC_FLAT_RD;
|
||||
integer read_integers [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [68:0] read_customs [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [68:0] read_customs_nonzero_index_rl [4:1] `PUBLIC_FLAT_RD;
|
||||
|
||||
reg [7:0] read_scalar `PUBLIC_FLAT_RD;
|
||||
reg [7:0] read_bounds [1:3] `PUBLIC_FLAT_RD;
|
||||
|
||||
integer status;
|
||||
|
||||
initial begin
|
||||
read_bytes[0] = 8'had;
|
||||
read_bytes[1] = 8'hde;
|
||||
read_bytes[2] = 8'hef;
|
||||
read_bytes[3] = 8'hbe;
|
||||
|
||||
read_bytes_rl[3] = 8'had;
|
||||
read_bytes_rl[2] = 8'hde;
|
||||
read_bytes_rl[1] = 8'hef;
|
||||
read_bytes_rl[0] = 8'hbe;
|
||||
|
||||
read_bytes_nonzero_index[1] = 8'had;
|
||||
read_bytes_nonzero_index[2] = 8'hde;
|
||||
read_bytes_nonzero_index[3] = 8'hef;
|
||||
read_bytes_nonzero_index[4] = 8'hbe;
|
||||
|
||||
read_shorts[0] = 16'hdead;
|
||||
read_shorts[1] = 16'hbeef;
|
||||
read_shorts[2] = 16'hcafe;
|
||||
read_shorts[3] = 16'hf00d;
|
||||
|
||||
read_words[0] = 32'hdeadbeef;
|
||||
read_words[1] = 32'hcafef00d;
|
||||
read_words[2] = 32'h00010203;
|
||||
read_words[3] = 32'h04050607;
|
||||
|
||||
read_integers[0] = 32'hdeadbeef;
|
||||
read_integers[1] = 32'hcafef00d;
|
||||
read_integers[2] = 32'h00010203;
|
||||
read_integers[3] = 32'h04050607;
|
||||
|
||||
read_longs[0] = 64'hdeadbeefcafef00d;
|
||||
read_longs[1] = 64'h0001020304050607;
|
||||
read_longs[2] = 64'h08090a0b0c0d0e0f;
|
||||
read_longs[3] = 64'h1011121314151617;
|
||||
|
||||
read_customs[0] = 69'hFAdeadbeefcafef00d; //0x001F'FFFF'FFFF'FFFF'FFFF
|
||||
read_customs[1] = 69'hF50001020304050607;
|
||||
read_customs[2] = 69'h0A08090a0b0c0d0e0f;
|
||||
read_customs[3] = 69'h051011121314151617;
|
||||
|
||||
read_customs_nonzero_index_rl[4] = 69'hFAdeadbeefcafef00d; //0x001F'FFFF'FFFF'FFFF'FFFF
|
||||
read_customs_nonzero_index_rl[3] = 69'hF50001020304050607;
|
||||
read_customs_nonzero_index_rl[2] = 69'h0A08090a0b0c0d0e0f;
|
||||
read_customs_nonzero_index_rl[1] = 69'h051011121314151617;
|
||||
|
||||
|
||||
`ifdef IVERILOG
|
||||
status = $mon_check;
|
||||
`endif
|
||||
|
||||
`ifdef VERILATOR
|
||||
status = $c32("mon_check()");
|
||||
`endif
|
||||
|
||||
if (status != 0) begin
|
||||
$write("%%Error: t_vpi_get_value_array.cpp:%0d: C Test failed\n", status);
|
||||
$stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
|
@ -0,0 +1,759 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef IS_VPI
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
#include "Vt_vpi_put_value_array.h"
|
||||
|
||||
#endif
|
||||
|
||||
// These require the above. Comment prevents clang-format moving them
|
||||
#include "TestSimulator.h"
|
||||
#include "TestVpi.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//======================================================================
|
||||
|
||||
int test_vpiRawFourStateVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index and test data arrays
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_BYTE8> test_data_four_state;
|
||||
test_data_four_state.reserve(size * elem_size * 2);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
test_data_four_state[(i * 2 * elem_size) + j] = test_data[(i * elem_size) + j];
|
||||
}
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
test_data_four_state[(((i * 2) + 1) * elem_size) + j] = -1; // bval should be ignored
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRawFourStateVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.rawvals = test_data_four_state.data();
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to nu
|
||||
arrayvalue.value.rawvals = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < (2 * size * elem_size); i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.rawvals[i] & 0xFF, i,
|
||||
test_data_four_state[i] & 0xFF);
|
||||
}
|
||||
#endif
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", (i * 2 * elem_size) + j, (i * elem_size) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(i * 2 * elem_size) + j],
|
||||
test_data[(i * elem_size) + j]);
|
||||
}
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(((i * 2) + 1) * elem_size) + j], 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiRawTwoStateVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRawTwoStateVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.rawvals = test_data;
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to check
|
||||
arrayvalue.value.rawvals = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < (size * elem_size); i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.rawvals[i] & 0xFF, i,
|
||||
test_data[i] & 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", (i * elem_size) + j, (i * elem_size) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.rawvals[(i * elem_size) + j],
|
||||
test_data[(i * elem_size) + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiVectorVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
const unsigned elem_size_words = (elem_size + 3) / sizeof(PLI_UINT32);
|
||||
const unsigned vec_size = elem_size_words * size;
|
||||
std::vector<s_vpi_vecval> test_data_vectors;
|
||||
test_data_vectors.reserve(vec_size);
|
||||
unsigned test_data_index = 0;
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
unsigned count = 0;
|
||||
for (unsigned j = 0; j < elem_size_words; j++) {
|
||||
PLI_UINT32& aval = test_data_vectors[(i * elem_size_words) + j].aval;
|
||||
test_data_vectors[(i * elem_size_words) + j].bval = UINT32_MAX;
|
||||
aval = 0;
|
||||
for (unsigned k = 0; k < sizeof(PLI_UINT32); k++) {
|
||||
if (count++ == elem_size) break;
|
||||
aval |= static_cast<PLI_UINT32>(test_data[test_data_index++] & 0xFF) << (k * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiVectorVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.vectors = test_data_vectors.data();
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to check
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < vec_size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.vectors[i].aval, i,
|
||||
test_data_vectors[i].aval);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
const unsigned offset = (index + i) % size;
|
||||
for (unsigned j = 0; j < elem_size_words; j++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", (i * elem_size_words) + j, (i * elem_size_words) + j);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.vectors[(i * elem_size_words) + j].aval,
|
||||
test_data_vectors[(i * elem_size_words) + j].aval);
|
||||
}
|
||||
for (unsigned j = 0; j < elem_size_words; j++) {
|
||||
CHECK_RESULT_HEX(arrayvalue.value.vectors[(i * elem_size_words) + j].bval, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT32> test_data_integers;
|
||||
test_data_integers.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
PLI_INT32& integer = test_data_integers[i];
|
||||
integer = 0;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
integer |= (static_cast<PLI_INT32>(test_data[(i * elem_size) + j]) & 0xFF) << (j * 8);
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = test_data_integers.data();
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to check
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.integers[i], i,
|
||||
test_data_integers[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", i, i);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.integers[i], test_data_integers[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiShortIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT16> test_data_shortints;
|
||||
test_data_shortints.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
if (elem_size == 2) {
|
||||
test_data_shortints[i] = test_data[i * 2] & 0xFF;
|
||||
test_data_shortints[i] |= test_data[(i * 2) + 1] << 8;
|
||||
} else {
|
||||
test_data_shortints[i] = test_data[i] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiShortIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.shortints = test_data_shortints.data();
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to check
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
printf("arr[%u]=%x test[%u]=%x\n", i, arrayvalue.value.shortints[i], i,
|
||||
test_data_shortints[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", i, i);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.shortints[i], test_data_shortints[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_vpiLongIntVal(char* name, PLI_BYTE8* test_data, int index, const unsigned num,
|
||||
const unsigned size, const unsigned elem_size) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("%%\n%s: name=%s index=%u num=%u size=%u elem_size=%u\n\n", __func__, name, index, num,
|
||||
size, elem_size);
|
||||
#endif
|
||||
|
||||
// prepare index
|
||||
int index_arr[1] = {index};
|
||||
std::vector<PLI_INT64> test_data_longints;
|
||||
test_data_longints.reserve(size);
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
PLI_INT64& longint = test_data_longints[i];
|
||||
longint = 0;
|
||||
for (unsigned j = 0; j < elem_size; j++) {
|
||||
longint |= (static_cast<PLI_INT64>(test_data[(i * elem_size) + j]) & 0xFF) << (j * 8);
|
||||
}
|
||||
}
|
||||
|
||||
// get array handle
|
||||
TestVpiHandle arrayhandle = vpi_handle_by_name(name, NULL);
|
||||
CHECK_RESULT_NZ(arrayhandle);
|
||||
|
||||
// test raw fourstate
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiLongIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.longints = test_data_longints.data();
|
||||
vpi_put_value_array(arrayhandle, &arrayvalue, index_arr, num);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// get value to check
|
||||
arrayvalue.value.vectors = 0;
|
||||
vpi_get_value_array(arrayhandle, &arrayvalue, index_arr, size);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(0));
|
||||
|
||||
// compare to test data
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
#ifdef TEST_VERBOSE
|
||||
printf("arr[%u] == test[%u]\n", i, i);
|
||||
#endif
|
||||
CHECK_RESULT_HEX(arrayvalue.value.longints[i], test_data_longints[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mon_check_props(void) {
|
||||
// skip test if not verilator (value_array accessors unimplemented in other sims)
|
||||
if (!TestSimulator::is_verilator()) {
|
||||
#ifdef VERILATOR
|
||||
printf("TestSimulator indicating not verilator, but VERILATOR macro is defined\n");
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned NUM_ELEMENTS = 4;
|
||||
|
||||
PLI_BYTE8 write_bytes[NUM_ELEMENTS]
|
||||
= {static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde),
|
||||
static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe)};
|
||||
|
||||
PLI_BYTE8 write_shorts[NUM_ELEMENTS * 2] = {
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0xef),
|
||||
static_cast<PLI_BYTE8>(0xbe), static_cast<PLI_BYTE8>(0xfe), static_cast<PLI_BYTE8>(0xca),
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0)};
|
||||
|
||||
PLI_BYTE8 write_words[NUM_ELEMENTS * 4] = {
|
||||
static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe), static_cast<PLI_BYTE8>(0xad),
|
||||
static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0),
|
||||
static_cast<PLI_BYTE8>(0xfe), static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0x03),
|
||||
static_cast<PLI_BYTE8>(0x02), static_cast<PLI_BYTE8>(0x01), static_cast<PLI_BYTE8>(0x00),
|
||||
static_cast<PLI_BYTE8>(0x07), static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05),
|
||||
static_cast<PLI_BYTE8>(0x04)};
|
||||
|
||||
PLI_BYTE8 write_longs[NUM_ELEMENTS * 8] = {
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0), static_cast<PLI_BYTE8>(0xfe),
|
||||
static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe),
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x07),
|
||||
static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05), static_cast<PLI_BYTE8>(0x04),
|
||||
static_cast<PLI_BYTE8>(0x03), static_cast<PLI_BYTE8>(0x02), static_cast<PLI_BYTE8>(0x01),
|
||||
static_cast<PLI_BYTE8>(0x00), static_cast<PLI_BYTE8>(0x0F), static_cast<PLI_BYTE8>(0x0E),
|
||||
static_cast<PLI_BYTE8>(0x0D), static_cast<PLI_BYTE8>(0x0C), static_cast<PLI_BYTE8>(0x0B),
|
||||
static_cast<PLI_BYTE8>(0x0A), static_cast<PLI_BYTE8>(0x09), static_cast<PLI_BYTE8>(0x08),
|
||||
static_cast<PLI_BYTE8>(0x17), static_cast<PLI_BYTE8>(0x16), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x14), static_cast<PLI_BYTE8>(0x13), static_cast<PLI_BYTE8>(0x12),
|
||||
static_cast<PLI_BYTE8>(0x11), static_cast<PLI_BYTE8>(0x10)};
|
||||
|
||||
PLI_BYTE8 write_customs[NUM_ELEMENTS * 9] = {
|
||||
static_cast<PLI_BYTE8>(0x0d), static_cast<PLI_BYTE8>(0xf0), static_cast<PLI_BYTE8>(0xfe),
|
||||
static_cast<PLI_BYTE8>(0xca), static_cast<PLI_BYTE8>(0xef), static_cast<PLI_BYTE8>(0xbe),
|
||||
static_cast<PLI_BYTE8>(0xad), static_cast<PLI_BYTE8>(0xde), static_cast<PLI_BYTE8>(0x1A),
|
||||
static_cast<PLI_BYTE8>(0x07), static_cast<PLI_BYTE8>(0x06), static_cast<PLI_BYTE8>(0x05),
|
||||
static_cast<PLI_BYTE8>(0x04), static_cast<PLI_BYTE8>(0x03), static_cast<PLI_BYTE8>(0x02),
|
||||
static_cast<PLI_BYTE8>(0x01), static_cast<PLI_BYTE8>(0x00), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x0F), static_cast<PLI_BYTE8>(0x0E), static_cast<PLI_BYTE8>(0x0D),
|
||||
static_cast<PLI_BYTE8>(0x0C), static_cast<PLI_BYTE8>(0x0B), static_cast<PLI_BYTE8>(0x0A),
|
||||
static_cast<PLI_BYTE8>(0x09), static_cast<PLI_BYTE8>(0x08), static_cast<PLI_BYTE8>(0x0A),
|
||||
static_cast<PLI_BYTE8>(0x17), static_cast<PLI_BYTE8>(0x16), static_cast<PLI_BYTE8>(0x15),
|
||||
static_cast<PLI_BYTE8>(0x14), static_cast<PLI_BYTE8>(0x13), static_cast<PLI_BYTE8>(0x12),
|
||||
static_cast<PLI_BYTE8>(0x11), static_cast<PLI_BYTE8>(0x10), static_cast<PLI_BYTE8>(0x05)};
|
||||
|
||||
char write_bytes_name[] = "test.write_bytes";
|
||||
char write_bytes_nonzero_index_name[] = "test.write_bytes_nonzero_index";
|
||||
char write_bytes_rl_name[] = "test.write_bytes_rl";
|
||||
char write_shorts_name[] = "test.write_shorts";
|
||||
char write_words_name[] = "test.write_words";
|
||||
char write_integers_name[] = "test.write_integers";
|
||||
char write_longs_name[] = "test.write_longs";
|
||||
char write_customs_name[] = "test.write_customs";
|
||||
char write_customs_nonzero_index_rl_name[] = "test.write_customs_nonzero_index_rl";
|
||||
|
||||
for (unsigned i = 0; i < NUM_ELEMENTS; i++) {
|
||||
for (unsigned j = 0; j < (NUM_ELEMENTS + 1); j++) {
|
||||
if (test_vpiRawFourStateVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_words_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_integers_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_longs_name, write_longs, i, j, NUM_ELEMENTS, 8))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_customs_name, write_customs, i, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiRawFourStateVal(write_customs_nonzero_index_rl_name, write_customs, i + 1,
|
||||
j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiRawTwoStateVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_words_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_integers_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_longs_name, write_longs, i, j, NUM_ELEMENTS, 8))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_customs_name, write_customs, i, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiRawTwoStateVal(write_customs_nonzero_index_rl_name, write_customs, i + 1,
|
||||
j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiVectorVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiVectorVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(write_words_name, write_words, i, j, NUM_ELEMENTS, 4)) return 1;
|
||||
if (test_vpiVectorVal(write_integers_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(write_longs_name, write_longs, i, j, NUM_ELEMENTS, 8)) return 1;
|
||||
if (test_vpiVectorVal(write_customs_name, write_customs, i, j, NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
if (test_vpiVectorVal(write_customs_nonzero_index_rl_name, write_customs, i + 1, j,
|
||||
NUM_ELEMENTS, 9))
|
||||
return 1;
|
||||
|
||||
if (test_vpiShortIntVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiShortIntVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
|
||||
if (test_vpiIntVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiIntVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j, NUM_ELEMENTS,
|
||||
1))
|
||||
return 1;
|
||||
if (test_vpiIntVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiIntVal(write_words_name, write_words, i, j, NUM_ELEMENTS, 4)) return 1;
|
||||
if (test_vpiIntVal(write_integers_name, write_words, i, j, NUM_ELEMENTS, 4)) return 1;
|
||||
|
||||
if (test_vpiLongIntVal(write_bytes_name, write_bytes, i, j, NUM_ELEMENTS, 1)) return 1;
|
||||
if (test_vpiLongIntVal(write_bytes_nonzero_index_name, write_bytes, i + 1, j,
|
||||
NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(write_words_name, write_words, i, j, NUM_ELEMENTS, 4)) return 1;
|
||||
if (test_vpiLongIntVal(write_integers_name, write_words, i, j, NUM_ELEMENTS, 4))
|
||||
return 1;
|
||||
if (test_vpiLongIntVal(write_longs_name, write_longs, i, j, NUM_ELEMENTS, 8)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported format
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_longs", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
double datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiRealVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.reals = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
arrayvalue.format = vpiShortRealVal;
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
arrayvalue.format = vpiTimeVal;
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test null array value
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, 0, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported TestVpiHandle
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported type
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_scalar", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test index out of bounds
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_bounds", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {4};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
indexp[0] = 0;
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test inaccessible
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_inaccessible", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported flags
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiPropagateOff;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
arrayvalue.flags = vpiOneValue;
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test unsupported format & type combination
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiShortIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
|
||||
arrayvalue.flags = vpiOneValue;
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 4);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test num out of bounds
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_put_value_array(object, &arrayvalue, indexp, 5);
|
||||
CHECK_RESULT_NZ(~vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test null arrayvalue
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
PLI_INT32 indexp[1] = {0};
|
||||
|
||||
vpi_get_value_array(object, 0, indexp, 0);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
{
|
||||
// test null indexp
|
||||
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
|
||||
CHECK_RESULT_NZ(object);
|
||||
|
||||
int datap[4] = {0, 0, 0, 0};
|
||||
s_vpi_arrayvalue arrayvalue;
|
||||
arrayvalue.format = vpiIntVal;
|
||||
arrayvalue.flags = 0;
|
||||
arrayvalue.value.integers = datap;
|
||||
|
||||
vpi_get_value_array(object, &arrayvalue, 0, 0);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int mon_check(void) { return mon_check_props(); }
|
||||
|
||||
#ifdef IS_VPI
|
||||
|
||||
static int mon_check_vpi() {
|
||||
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
|
||||
s_vpi_value vpi_value;
|
||||
|
||||
vpi_value.format = vpiIntVal;
|
||||
vpi_value.value.integer = mon_check();
|
||||
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s_vpi_systf_data vpi_systf_data[] = {{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check",
|
||||
(PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
|
||||
0};
|
||||
|
||||
// cver entry
|
||||
void vpi_compat_bootstrap(void) {
|
||||
p_vpi_systf_data systf_data_p;
|
||||
systf_data_p = &(vpi_systf_data[0]);
|
||||
while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
|
||||
}
|
||||
|
||||
// icarus entry
|
||||
void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
const std::unique_ptr<VM_PREFIX> top{new VM_PREFIX{contextp.get(), ""}};
|
||||
contextp->fatalOnVpiError(0);
|
||||
|
||||
#ifdef VERILATOR
|
||||
#ifdef TEST_VERBOSE
|
||||
contextp->scopesDump();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (!contextp->gotFinish()) { top->eval(); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(make_top_shell=False,
|
||||
make_main=False,
|
||||
make_pli=True,
|
||||
verilator_flags2=["--exe --vpi --no-l2name", test.pli_filename],
|
||||
iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI"],
|
||||
v_flags2=["+define+USE_VPI_NOT_DPI +define+VERILATOR_COMMENTS"])
|
||||
|
||||
test.execute(use_libvpi=True)
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,76 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
`ifdef VERILATOR_COMMENTS
|
||||
`define PUBLIC_FLAT_RD /*verilator public_flat_rd*/
|
||||
`define PUBLIC_FLAT_RW /*verilator public_flat_rw*/
|
||||
`else
|
||||
`define PUBLIC_FLAT_RD
|
||||
`define PUBLIC_FLAT_RW
|
||||
`endif
|
||||
|
||||
module test ();
|
||||
|
||||
`ifdef VERILATOR
|
||||
`systemc_header
|
||||
extern "C" int mon_check();
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
reg [7:0] write_bytes [0:3] `PUBLIC_FLAT_RW;
|
||||
reg [7:0] write_bytes_rl [3:0] `PUBLIC_FLAT_RW;
|
||||
reg [7:0] write_bytes_nonzero_index [1:4] `PUBLIC_FLAT_RW;
|
||||
|
||||
reg [15:0] write_shorts [0:3] `PUBLIC_FLAT_RW;
|
||||
reg [31:0] write_words [0:3] `PUBLIC_FLAT_RW;
|
||||
reg [63:0] write_longs [0:3] `PUBLIC_FLAT_RW;
|
||||
reg [68:0] write_customs [0:3] `PUBLIC_FLAT_RW;
|
||||
reg [68:0] write_customs_nonzero_index_rl [4:1] `PUBLIC_FLAT_RW;
|
||||
|
||||
integer write_integers [0:3] `PUBLIC_FLAT_RW;
|
||||
|
||||
reg [7:0] write_scalar `PUBLIC_FLAT_RW;
|
||||
reg [7:0] write_bounds [1:3] `PUBLIC_FLAT_RW;
|
||||
reg [7:0] write_inaccessible [0:3] `PUBLIC_FLAT_RD;
|
||||
|
||||
`ifdef IVERILOG
|
||||
// stop icarus optimizing signals away
|
||||
wire redundant = write_bytes[0][0] |
|
||||
write_bytes[0][0] |
|
||||
write_bytes_rl[0][0] |
|
||||
write_bytes_nonzero_index[1][0] |
|
||||
write_shorts[0][0] |
|
||||
write_words[0][0] |
|
||||
write_longs[0][0] |
|
||||
write_customs[0][0] |
|
||||
write_customs_nonzero_index_rl[1][0] |
|
||||
write_integers[0][0] |
|
||||
write_scalar[0] |
|
||||
write_bounds[1][0] |
|
||||
write_inaccessible[0][0];
|
||||
`endif
|
||||
integer status;
|
||||
|
||||
initial begin
|
||||
`ifdef IVERILOG
|
||||
status = $mon_check;
|
||||
`endif
|
||||
|
||||
`ifdef VERILATOR
|
||||
status = $c32("mon_check()");
|
||||
`endif
|
||||
|
||||
if (status != 0) begin
|
||||
$write("%%Error: t_vpi_put_value_array.cpp:%0d: C Test failed\n", status);
|
||||
$stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
|
@ -57,8 +57,6 @@ int _mon_check_unimpl(p_cb_data cb_data) {
|
|||
vpi_get64(0, NULL);
|
||||
vpi_get_delays(NULL, NULL);
|
||||
vpi_put_delays(NULL, NULL);
|
||||
vpi_get_value_array(NULL, NULL, NULL, 0);
|
||||
vpi_put_value_array(NULL, NULL, NULL, 0);
|
||||
vpi_get_time(NULL, NULL);
|
||||
vpi_mcd_name(0);
|
||||
vpi_compare_objects(NULL, NULL);
|
||||
|
|
Loading…
Reference in New Issue