diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index ce4c5001e..890d01dfe 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -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(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(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(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(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); } diff --git a/test_regress/t/t_vpi_put_value_array.cpp b/test_regress/t/t_vpi_put_value_array.cpp index 744834be3..010fd297c 100644 --- a/test_regress/t/t_vpi_put_value_array.cpp +++ b/test_regress/t/t_vpi_put_value_array.cpp @@ -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); diff --git a/test_regress/t/t_vpi_put_value_array.out b/test_regress/t/t_vpi_put_value_array.out index 887a28663..1e051b7cc 100644 --- a/test_regress/t/t_vpi_put_value_array.out +++ b/test_regress/t/t_vpi_put_value_array.out @@ -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 *-*