// -*- 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 // //************************************************************************* #ifdef IS_VPI #include "sv_vpi_user.h" #include #else #include "verilated.h" #include "verilated_vcd_c.h" #include "verilated_vpi.h" #include "Vt_vpi_package.h" #include "Vt_vpi_package__Dpi.h" #include "svdpi.h" #endif #include #include #include // These require the above. Comment prevents clang-format moving them #include "TestSimulator.h" #include "TestVpi.h" // __FILE__ is too long #define FILENM "t_vpi_package.cpp" #define DEBUG \ if (0) printf #define CHECK_RESULT_NZ(got) \ if (!(got)) { \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ return __LINE__; \ } #define CHECK_RESULT_Z(got) \ if (got) { \ printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ return __LINE__; \ } #define CHECK_RESULT(got, exp) \ if ((got) != (exp)) { \ std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ << " EXP = " << (exp) << std::endl; \ return __LINE__; \ } #define CHECK_RESULT_CSTR(got, exp) \ if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ (got) ? (got) : "", (exp) ? (exp) : ""); \ return __LINE__; \ } extern "C" { int mon_check() { #ifdef TEST_VERBOSE printf("-mon_check()\n"); #endif TestVpiHandle it = vpi_iterate(vpiModule, NULL); bool found_t = false; while (true) { TestVpiHandle handle = vpi_scan(it); if (handle == NULL) break; if (strcmp("t", vpi_get_str(vpiName, handle))) { return __LINE__; } else { if (found_t) return __LINE__; found_t = true; } } it.freed(); if (!found_t) return __LINE__; it = vpi_iterate(vpiInstance, NULL); found_t = false; bool found_somepackage = false; bool found_dollar_unit = false; while (true) { TestVpiHandle handle = vpi_scan(it); if (handle == NULL) break; const char* name = vpi_get_str(vpiName, handle); const char* fullname = vpi_get_str(vpiFullName, handle); if (!strcmp("t", name)) { if (strcmp("t", fullname)) return __LINE__; if (found_t) return __LINE__; found_t = true; } else if (!strcmp("somepackage", name)) { if (strcmp("somepackage::", fullname)) return __LINE__; if (found_somepackage) return __LINE__; found_somepackage = true; } else if (!strcmp("$unit", name)) { if (strcmp("$unit::", fullname)) return __LINE__; if (found_dollar_unit) return __LINE__; found_dollar_unit = true; } else { return __LINE__; } } it.freed(); if (!found_t) return __LINE__; if (!found_somepackage) return __LINE__; if (!found_dollar_unit) return __LINE__; return 0; // Ok } } //====================================================================== #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) { const std::unique_ptr contextp{new VerilatedContext}; uint64_t sim_time = 1100; contextp->debug(0); contextp->commandArgs(argc, argv); // We're going to be checking for these errors so don't crash out contextp->fatalOnVpiError(0); { // Construct and destroy const std::unique_ptr topp{ new VM_PREFIX{contextp.get(), // Note null name - we're flattening it out ""}}; } // Test second construction const std::unique_ptr topp{new VM_PREFIX{contextp.get(), // Note null name - we're flattening it out ""}}; #ifdef VERILATOR #ifdef TEST_VERBOSE contextp->scopesDump(); #endif #endif #if VM_TRACE contextp->traceEverOn(true); VL_PRINTF("Enabling waves...\n"); VerilatedVcdC* tfp = new VerilatedVcdC; topp->trace(tfp, 99); tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd"); #endif topp->eval(); contextp->timeInc(10); while (contextp->time() < sim_time && !contextp->gotFinish()) { contextp->timeInc(1); topp->eval(); VerilatedVpi::callValueCbs(); // mon_do(); #if VM_TRACE if (tfp) tfp->dump(contextp->time()); #endif } if (!contextp->gotFinish()) { vl_fatal(FILENM, __LINE__, "main", "%Error: Timeout; never got a $finish"); } topp->final(); #if VM_TRACE if (tfp) tfp->close(); #endif return 0; } #endif