Internals: Hoist vpi_put_value_array argument validation to entry point. (#8384)

This commit is contained in:
Nick Brereton
2026-09-17 18:08:16 -04:00
committed by GitHub
parent 1f9c9681a7
commit 3fd16ed498
3 changed files with 94 additions and 25 deletions
+40 -24
View File
@@ -4083,7 +4083,7 @@ bool vl_check_array_format(const VerilatedVar* varp, const p_vpi_arrayvalue arra
case VLVT_UINT8:
case VLVT_UINT16:
case VLVT_UINT32: return true;
default:; // LCOV_EXCL_LINE
default:;
}
break;
case vpiRawTwoStateVal:
@@ -4101,7 +4101,7 @@ bool vl_check_array_format(const VerilatedVar* varp, const p_vpi_arrayvalue arra
switch (varp->vltype()) {
case VLVT_UINT8:
case VLVT_UINT16: return true;
default:; // LCOV_EXCL_LINE
default:;
}
break;
case vpiLongIntVal:
@@ -4110,7 +4110,7 @@ bool vl_check_array_format(const VerilatedVar* varp, const p_vpi_arrayvalue arra
case VLVT_UINT16:
case VLVT_UINT32:
case VLVT_UINT64: return true;
default:; // LCOV_EXCL_LINE
default:;
}
break;
default:;
@@ -4486,17 +4486,8 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const 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();
const 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();
const int index
@@ -4509,113 +4500,128 @@ void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const P
if (varp->vltype() == VLVT_UINT8) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, shortintsp,
vop->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, shortintsp,
vop->readSDatap());
return;
}
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->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, integersp,
vop->readSDatap());
return;
} else if (varp->vltype() == VLVT_UINT32) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, integersp,
vop->readIDatap());
return;
}
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->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
vop->readSDatap());
return;
} else if (varp->vltype() == VLVT_UINT32) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
vop->readIDatap());
return;
} else if (varp->vltype() == VLVT_UINT64) {
vl_put_value_array_integrals(index, num, size, varp->entBits(), leftIsLow, longintsp,
vop->readQDatap());
return;
}
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->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
vectorsp, vop->readSDatap());
return;
} else if (varp->vltype() == VLVT_UINT32) {
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
vectorsp, vop->readIDatap());
return;
} else if (varp->vltype() == VLVT_UINT64) {
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
vectorsp, vop->readQDatap());
return;
} else if (varp->vltype() == VLVT_WDATA) {
vl_put_value_array_vectors(index, num, size, varp->entBits(), leftIsLow, true,
vectorsp, vop->readEDatap());
return;
}
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->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
vop->readSDatap());
return;
} else if (varp->vltype() == VLVT_UINT32) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
vop->readIDatap());
return;
} else if (varp->vltype() == VLVT_UINT64) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
vop->readQDatap());
return;
} else if (varp->vltype() == VLVT_WDATA) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, true, valuep,
vop->readEDatap());
return;
}
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->readCDatap());
return;
} else if (varp->vltype() == VLVT_UINT16) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
vop->readSDatap());
return;
} else if (varp->vltype() == VLVT_UINT32) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
vop->readIDatap());
return;
} else if (varp->vltype() == VLVT_UINT64) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
vop->readQDatap());
return;
} else if (varp->vltype() == VLVT_WDATA) {
vl_put_value_array_rawvals(index, num, size, varp->entBits(), leftIsLow, false, valuep,
vop->readEDatap());
return;
}
return;
}
// Reached only if vl_check_array_format and this dispatch drift apart
// LCOV_EXCL_START
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for '%s'",
__func__, VerilatedVpiError::strFromVpiVal(arrayvalue_p->format),
vop->fullname());
// LCOV_EXCL_STOP
}
void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
@@ -4670,6 +4676,16 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
return;
}
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
const unsigned size = vop->size();
if (VL_UNLIKELY(num > size)) {
VL_VPI_ERROR_(__FILE__, __LINE__,
"%s: Requested elements to set (%u) exceed array size (%u)", __func__, num,
size);
return;
}
if (num == 0) return;
vl_put_value_array(object, arrayvalue_p, index_p, num);
}
+46
View File
@@ -506,6 +506,7 @@ int mon_check_props(void) {
1))
return 1;
if (test_vpiIntVal(write_bytes_rl_name, write_bytes, i, j, NUM_ELEMENTS, 1)) return 1;
if (test_vpiIntVal(write_shorts_name, write_shorts, i, j, NUM_ELEMENTS, 2)) 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;
@@ -667,6 +668,51 @@ int mon_check_props(void) {
TEST_CHECK_ERROR(true);
}
{
// test every remaining format & type combination the dispatch does not handle
TestVpiHandle longs = vpi_handle_by_name((PLI_BYTE8*)"test.write_longs", NULL);
CHECK_RESULT_NZ(longs);
TestVpiHandle customs = vpi_handle_by_name((PLI_BYTE8*)"test.write_customs", NULL);
CHECK_RESULT_NZ(customs);
PLI_INT16 shortdatap[4] = {0, 0, 0, 0};
PLI_INT32 intdatap[4] = {0, 0, 0, 0};
PLI_INT64 longdatap[4] = {0, 0, 0, 0};
s_vpi_vecval vecdatap[12] = {};
PLI_INT32 indexp[1] = {0};
s_vpi_arrayvalue arrayvalue;
arrayvalue.flags = 0;
arrayvalue.format = vpiShortIntVal;
arrayvalue.value.shortints = shortdatap;
vpi_put_value_array(longs, &arrayvalue, indexp, 4);
TEST_CHECK_ERROR(true);
vpi_put_value_array(customs, &arrayvalue, indexp, 4);
TEST_CHECK_ERROR(true);
arrayvalue.format = vpiIntVal;
arrayvalue.value.integers = intdatap;
vpi_put_value_array(longs, &arrayvalue, indexp, 4);
TEST_CHECK_ERROR(true);
vpi_put_value_array(customs, &arrayvalue, indexp, 4);
TEST_CHECK_ERROR(true);
arrayvalue.format = vpiLongIntVal;
arrayvalue.value.longints = longdatap;
vpi_put_value_array(customs, &arrayvalue, indexp, 4);
TEST_CHECK_ERROR(true);
// test num out of bounds is reported by the entry point for every format
vpi_put_value_array(longs, &arrayvalue, indexp, 5);
TEST_CHECK_ERROR(true);
arrayvalue.format = vpiVectorVal;
arrayvalue.value.vectors = vecdatap;
vpi_put_value_array(customs, &arrayvalue, indexp, 5);
TEST_CHECK_ERROR(true);
}
{
// test num out of bounds
TestVpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"test.write_words", NULL);
+8 -1
View File
@@ -11,7 +11,14 @@ vpi_chk_error: vl_check_array_format: Unsupported format (*undefined*) as reques
vpi_chk_error: vpi_put_value_array: Unsupported flags (4000)
vpi_chk_error: vl_check_array_format: Unsupported format (vpiShortIntVal) as requested for 'test.write_words'
vpi_chk_error: vpi_put_value_array: Unsupported flags (4000)
vpi_chk_error: vl_put_value_array: Requested elements to set (5) exceed array size (4)
vpi_chk_error: vl_check_array_format: Unsupported format (vpiShortIntVal) as requested for 'test.write_longs'
vpi_chk_error: vl_check_array_format: Unsupported format (vpiShortIntVal) as requested for 'test.write_customs'
vpi_chk_error: vl_check_array_format: Unsupported format (vpiIntVal) as requested for 'test.write_longs'
vpi_chk_error: vl_check_array_format: Unsupported format (vpiIntVal) as requested for 'test.write_customs'
vpi_chk_error: vl_check_array_format: Unsupported format (vpiLongIntVal) as requested for 'test.write_customs'
vpi_chk_error: vpi_put_value_array: Requested elements to set (5) exceed array size (4)
vpi_chk_error: vpi_put_value_array: Requested elements to set (5) exceed array size (4)
vpi_chk_error: vpi_put_value_array: Requested elements to set (5) exceed array size (4)
vpi_chk_error: Ignoring vpi_get_value_array with null value pointer
vpi_chk_error: Ignoring vpi_get_value_array with null index pointer
*-* All Finished *-*