// -*- 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 extern "C" { #include } // These require the above. Comment prevents clang-format moving them #include "TestSimulator.h" #include "TestVpi.h" #include //====================================================================== 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 test_data_four_state; test_data_four_state.resize(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 test_data_vectors; test_data_vectors.resize(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(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 test_data_integers; test_data_integers.resize(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(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 test_data_shortints; test_data_shortints.resize(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 test_data_longints; test_data_longints.resize(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(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(0xad), static_cast(0xde), static_cast(0xef), static_cast(0xbe)}; PLI_BYTE8 write_shorts[NUM_ELEMENTS * 2] = { static_cast(0xad), static_cast(0xde), static_cast(0xef), static_cast(0xbe), static_cast(0xfe), static_cast(0xca), static_cast(0x0d), static_cast(0xf0)}; PLI_BYTE8 write_words[NUM_ELEMENTS * 4] = { static_cast(0xef), static_cast(0xbe), static_cast(0xad), static_cast(0xde), static_cast(0x0d), static_cast(0xf0), static_cast(0xfe), static_cast(0xca), static_cast(0x03), static_cast(0x02), static_cast(0x01), static_cast(0x00), static_cast(0x07), static_cast(0x06), static_cast(0x05), static_cast(0x04)}; PLI_BYTE8 write_longs[NUM_ELEMENTS * 8] = { static_cast(0x0d), static_cast(0xf0), static_cast(0xfe), static_cast(0xca), static_cast(0xef), static_cast(0xbe), static_cast(0xad), static_cast(0xde), static_cast(0x07), static_cast(0x06), static_cast(0x05), static_cast(0x04), static_cast(0x03), static_cast(0x02), static_cast(0x01), static_cast(0x00), static_cast(0x0F), static_cast(0x0E), static_cast(0x0D), static_cast(0x0C), static_cast(0x0B), static_cast(0x0A), static_cast(0x09), static_cast(0x08), static_cast(0x17), static_cast(0x16), static_cast(0x15), static_cast(0x14), static_cast(0x13), static_cast(0x12), static_cast(0x11), static_cast(0x10)}; PLI_BYTE8 write_customs[NUM_ELEMENTS * 9] = { static_cast(0x0d), static_cast(0xf0), static_cast(0xfe), static_cast(0xca), static_cast(0xef), static_cast(0xbe), static_cast(0xad), static_cast(0xde), static_cast(0x1A), static_cast(0x07), static_cast(0x06), static_cast(0x05), static_cast(0x04), static_cast(0x03), static_cast(0x02), static_cast(0x01), static_cast(0x00), static_cast(0x15), static_cast(0x0F), static_cast(0x0E), static_cast(0x0D), static_cast(0x0C), static_cast(0x0B), static_cast(0x0A), static_cast(0x09), static_cast(0x08), static_cast(0x0A), static_cast(0x17), static_cast(0x16), static_cast(0x15), static_cast(0x14), static_cast(0x13), static_cast(0x12), static_cast(0x11), static_cast(0x10), static_cast(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 contextp{new VerilatedContext}; const std::unique_ptr 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