// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // // Copyright 2010-2011 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 // //************************************************************************* #include "vpi_user.h" #include #include #include #include extern "C" { #include } // These require the above. Comment prevents clang-format moving them #include "TestCheck.h" #include "TestSimulator.h" #include "TestVpi.h" int errors = 0; unsigned int callback_count1 = 0; unsigned int callback_count2 = 0; unsigned int callback_time1 = 0; unsigned int callback_time2 = 0; //====================================================================== static int _never_cb(p_cb_data cb_data) { TEST_CHECK_EQ(0, 1); // Should never get called return 0; } static int _time_cb1(p_cb_data cb_data) { s_vpi_time t; t.type = vpiSimTime; vpi_get_time(0, &t); TEST_VERBOSE_PRINTF("time_cb1: %d\n", t.low); ++callback_count1; if (callback_time1) TEST_CHECK_EQ(callback_time1, t.low); callback_time1 = t.low + 1; // Next call t_cb_data cb_data_n; bzero(&cb_data_n, sizeof(cb_data_n)); { cb_data_n.reason = cbAfterDelay; t.type = vpiSimTime; t.high = 0; t.low = 1; cb_data_n.time = &t; cb_data_n.cb_rtn = _time_cb1; TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n); TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n1_h), vpiCallback); } { // Test cancelling a callback cb_data_n.reason = cbAfterDelay; t.type = vpiSimTime; t.high = 0; t.low = 1; cb_data_n.time = &t; cb_data_n.cb_rtn = _never_cb; TestVpiHandle cb_h = vpi_register_cb(&cb_data_n); vpi_remove_cb(cb_h); cb_h.freed(); } return 0; } static int _time_cb2(p_cb_data cb_data) { // One-shot s_vpi_time t; t.type = vpiSimTime; vpi_get_time(0, &t); TEST_VERBOSE_PRINTF("time_cb2: %d\n", t.low); if (callback_time2) TEST_CHECK_EQ(callback_time2, t.low); ++callback_count2; t_cb_data cb_data_n; bzero(&cb_data_n, sizeof(cb_data_n)); cb_data_n.reason = cbAfterDelay; t.type = vpiSimTime; t.high = 0; t.low = 1; cb_data_n.time = &t; cb_data_n.cb_rtn = _time_cb2; TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n); TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n2_h), vpiCallback); return 0; } static vpiHandle callback_handles3[2] = {NULL, NULL}; static int _time_cb3(p_cb_data cb_data) { size_t cb_id = (size_t)cb_data->user_data; size_t cb_id_other = cb_id ? 0 : 1; TEST_VERBOSE_PRINTF("time_cb_3: %d\n", (int)cb_id); TEST_CHECK_NZ(callback_handles3[cb_id]); TEST_CHECK_NZ(callback_handles3[cb_id_other]); vpi_remove_cb(callback_handles3[cb_id_other]); callback_handles3[0] = callback_handles3[1] = NULL; return 0; } extern "C" void dpii_init() { TEST_VERBOSE_PRINTF("-dpii_init()\n"); t_cb_data cb_data_n1, cb_data_n2, cb_data_n3; bzero(&cb_data_n1, sizeof(cb_data_n1)); bzero(&cb_data_n2, sizeof(cb_data_n2)); bzero(&cb_data_n3, sizeof(cb_data_n3)); s_vpi_time t1, t2, t3; cb_data_n1.reason = cbAfterDelay; t1.type = vpiSimTime; t1.high = 0; t1.low = 3; cb_data_n1.time = &t1; cb_data_n1.cb_rtn = _time_cb1; TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n1); TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n1_h), vpiCallback); cb_data_n2.reason = cbAfterDelay; t2.type = vpiSimTime; t2.high = 0; t2.low = 4; cb_data_n2.time = &t2; cb_data_n2.cb_rtn = _time_cb2; TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n2); cb_data_n3.reason = cbAfterDelay; t3.type = vpiSimTime; t3.high = 0; t3.low = 5; cb_data_n3.time = &t3; cb_data_n3.cb_rtn = _time_cb3; cb_data_n3.user_data = (PLI_BYTE8*)0; callback_handles3[0] = vpi_register_cb(&cb_data_n3); cb_data_n3.user_data = (PLI_BYTE8*)1; callback_handles3[1] = vpi_register_cb(&cb_data_n3); } extern "C" void dpii_final() { TEST_VERBOSE_PRINTF("-dpii_final()\n"); // Allow some slop as cb might be before/after this call TEST_CHECK(callback_count1, 1010, (callback_count1 >= 1000 && callback_count1 <= 1020)); TEST_CHECK(callback_count2, 1010, (callback_count2 >= 1000 && callback_count2 <= 1020)); if (errors) { vpi_control(vpiStop); } else { printf("*-* All Finished *-*\n"); } }