// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // // Copyright 2020 by Geza Lore. 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 #include #include // clang-format off #if defined(NCSC) // Used by NC's svdpi.h to pick up svLogicVecVal with _.aval and _.bval fields, // rather than the IEEE 1800-2005 version which has _.a and _.b fields. # define DPI_COMPATIBILITY_VERSION_1800v2012 #endif #include "svdpi.h" #if defined(VERILATOR) // Verilator # include "Vt_dpi_arg_input_type__Dpi.h" typedef long long sv_longint_t; typedef unsigned long long sv_longint_unsigned_t; # define NO_SHORTREAL # define CONSTARG const #elif defined(VCS) // VCS # include "../vc_hdrs.h" typedef long long sv_longint_t; typedef unsigned long long sv_longint_unsigned_t; # define NO_TIME # define CONSTARG const #elif defined(NCSC) // NC # include "dpi-exp.h" # include "dpi-imp.h" typedef long long sv_longint_t; typedef unsigned long long sv_longint_unsigned_t; # define NO_TIME # define NO_INTEGER # define NO_SHORTREAL // Sadly NC does not declare pass-by reference input arguments as const # define CONSTARG #elif defined(MS) // ModelSim # include "dpi.h" typedef int64_t sv_longint_t; typedef uint64_t sv_longint_unsigned_t; # define CONSTARG const #else # error "Unknown simulator for DPI test" #endif // clang-format on //====================================================================== // Implementations of imported functions //====================================================================== #define stop() \ do { \ printf(__FILE__ ":%d Bad value\n", __LINE__); \ abort(); \ } while (0) void check_bvals(CONSTARG svLogicVecVal* v, unsigned n); void check_bvals(CONSTARG svLogicVecVal* v, unsigned n) { for (unsigned i = 0; i < n; i++) { if (v[i].bval != 0) { printf(__FILE__ ":%d Bad svLogicVecVal bval\n", __LINE__); abort(); } } } // Basic types as per IEEE 1800-2017 35.5.6 void i_byte(char i) { static int n = 0; if (i != 10 - n++) stop(); } void i_byte_unsigned(unsigned char i) { static int n = 0; if (i != 20 - n++) stop(); } void i_shortint(short i) { static int n = 0; if (i != 30 - n++) stop(); } void i_shortint_unsigned(unsigned short i) { static int n = 0; if (i != 40 - n++) stop(); } void i_int(int i) { static int n = 0; if (i != 50 - n++) stop(); } void i_int_unsigned(unsigned i) { static int n = 0; if (i != 60 - n++) stop(); } void i_longint(sv_longint_t i) { static int n = 0; if (i != 70 - n++) stop(); } void i_longint_unsigned(sv_longint_unsigned_t i) { static int n = 0; if (i != 80 - n++) stop(); } #ifndef NO_TIME void i_time(CONSTARG svLogicVecVal* i) { static int n = 0; if (i[0].aval != 90 - n++) stop(); if (i[1].aval != 0) stop(); check_bvals(i, 2); } #endif #ifndef NO_INTEGER void i_integer(CONSTARG svLogicVecVal* i) { static int n = 0; if (i[0].aval != 100 - n++) stop(); check_bvals(i, 1); } #endif void i_real(double i) { static int n = 0; if (i != (-2.0 * n++ - 1.0) / 2.0) stop(); } #ifndef NO_SHORTREAL void i_shortreal(float i) { static int n = 0; if (i != (-4.0f * n++ - 1.0f) / 4.0f) stop(); } #endif void i_chandle(void* i) { static int n = 0; printf("i_chandle %d\n", n); if (i) stop(); n++; } void i_string(const char* i) { static int n = 0; printf("i_string %d\n", n); if (n++ % 2 == 0) { if (strcmp(i, "World") != 0) stop(); } else { if (strcmp(i, "Hello") != 0) stop(); } } void i_bit(svBit i) { static int n = 0; printf("i_bit %d\n", n); if (i != !(n++ % 2)) stop(); } void i_logic(svLogic i) { static int n = 0; printf("i_logic %d\n", n); if (i != n++ % 2) stop(); } // Basic types via typedefs void i_byte_t(char i) { static int n = 0; if (i != 10 - n) stop(); n += 2; } void i_byte_unsigned_t(unsigned char i) { static int n = 0; if (i != 20 - n) stop(); n += 2; } void i_shortint_t(short i) { static int n = 0; if (i != 30 - n) stop(); n += 2; } void i_shortint_unsigned_t(unsigned short i) { static int n = 0; if (i != 40 - n) stop(); n += 2; } void i_int_t(int i) { static int n = 0; if (i != 50 - n) stop(); n += 2; } void i_int_unsigned_t(unsigned i) { static int n = 0; if (i != 60 - n) stop(); n += 2; } void i_longint_t(sv_longint_t i) { static int n = 0; if (i != 70 - n) stop(); n += 2; } void i_longint_unsigned_t(sv_longint_unsigned_t i) { static int n = 0; if (i != 80 - n) stop(); n += 2; } #ifndef NO_TIME void i_time_t(CONSTARG svLogicVecVal* i) { static int n = 0; if (i[0].aval != 90 - n) stop(); if (i[1].aval != 0) stop(); check_bvals(i, 2); n += 2; } #endif #ifndef NO_INTEGER void i_integer_t(CONSTARG svLogicVecVal* i) { static int n = 0; if (i[0].aval != 100 - n) stop(); check_bvals(i, 1); n += 2; } #endif void i_real_t(double i) { static int n = 0; if (i != (-2.0 * n - 1.0) / 2.0) stop(); n += 2; } #ifndef NO_SHORTREAL void i_shortreal_t(float i) { static int n = 0; if (i != (-4.0f * n - 1.0f) / 4.0f) stop(); n += 2; } #endif void i_chandle_t(void* i) { static int n = 0; printf("i_chandle_t %d\n", n); if (i) stop(); n++; } void i_string_t(const char* i) { static int n = 0; printf("i_string_t %d\n", n); if (n++ % 2 == 0) { if (strcmp(i, "World") != 0) stop(); } else { if (strcmp(i, "Hello") != 0) stop(); } } void i_bit_t(svBit i) { static int n = 0; printf("i_bit_t %d\n", n); if (i != !(n++ % 2)) stop(); } void i_logic_t(svLogic i) { static int n = 0; printf("i_logic_t %d\n", n); if (i != n++ % 2) stop(); } // 2-state packed arrays void i_array_2_state_1(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_1 %d\n", n); if ((*i & 1) != !(n++ % 2)) stop(); } void i_array_2_state_32(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_32 %d\n", n); if (*i != 0xffffffffU << n++) stop(); } void i_array_2_state_33(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_33 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if ((i[1] & 1) != 1) stop(); } void i_array_2_state_64(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_64 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); } void i_array_2_state_65(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_65 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if ((i[2] & 1) != 1) stop(); } void i_array_2_state_128(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_array_2_state_128 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if (i[2] != -1) stop(); if (i[3] != -1) stop(); } // 2-state packed structures void i_struct_2_state_1(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_1 %d\n", n); if ((*i & 1) != !(n++ % 2)) stop(); } void i_struct_2_state_32(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_32 %d\n", n); if (*i != 0xffffffffU << n++) stop(); } void i_struct_2_state_33(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_33 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if ((i[1] & 1) != 1) stop(); } void i_struct_2_state_64(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_64 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); } void i_struct_2_state_65(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_65 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if ((i[2] & 1) != 1) stop(); } void i_struct_2_state_128(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_struct_2_state_128 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if (i[2] != -1) stop(); if (i[3] != -1) stop(); } // 2-state packed unions void i_union_2_state_1(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_1 %d\n", n); if ((*i & 1) != !(n++ % 2)) stop(); } void i_union_2_state_32(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_32 %d\n", n); if (*i != 0xffffffffU << n++) stop(); } void i_union_2_state_33(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_33 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if ((i[1] & 1) != 1) stop(); } void i_union_2_state_64(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_64 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); } void i_union_2_state_65(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_65 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if ((i[2] & 1) != 1) stop(); } void i_union_2_state_128(CONSTARG svBitVecVal* i) { static int n = 0; printf("i_union_2_state_128 %d\n", n); if (i[0] != 0xffffffffU << n++) stop(); if (i[1] != -1) stop(); if (i[2] != -1) stop(); if (i[3] != -1) stop(); } // 4-state packed arrays void i_array_4_state_1(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_1 %d\n", n); if ((i->aval & 1) != !(n++ % 2)) stop(); check_bvals(i, 1); } void i_array_4_state_32(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_32 %d\n", n); if (i->aval != 0xffffffffU << n++) stop(); check_bvals(i, 1); } void i_array_4_state_33(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_33 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if ((i[1].aval & 1) != 1) stop(); check_bvals(i, 2); } void i_array_4_state_64(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_64 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); check_bvals(i, 2); } void i_array_4_state_65(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_65 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if ((i[2].aval & 1) != 1) stop(); check_bvals(i, 3); } void i_array_4_state_128(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_array_4_state_128 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if (i[2].aval != -1) stop(); if (i[3].aval != -1) stop(); check_bvals(i, 4); } // 4-state packed structures void i_struct_4_state_1(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_1 %d\n", n); if ((i->aval & 1) != !(n++ % 2)) stop(); check_bvals(i, 1); } void i_struct_4_state_32(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_32 %d\n", n); if (i->aval != 0xffffffffU << n++) stop(); check_bvals(i, 1); } void i_struct_4_state_33(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_33 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if ((i[1].aval & 1) != 1) stop(); check_bvals(i, 2); } void i_struct_4_state_64(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_64 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); check_bvals(i, 2); } void i_struct_4_state_65(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_65 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if ((i[2].aval & 1) != 1) stop(); check_bvals(i, 3); } void i_struct_4_state_128(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_struct_4_state_128 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if (i[2].aval != -1) stop(); if (i[3].aval != -1) stop(); check_bvals(i, 4); } // 4-state packed unions void i_union_4_state_1(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_1 %d\n", n); if ((i->aval & 1) != !(n++ % 2)) stop(); check_bvals(i, 1); } void i_union_4_state_32(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_32 %d\n", n); if (i->aval != 0xffffffffU << n++) stop(); check_bvals(i, 1); } void i_union_4_state_33(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_33 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if ((i[1].aval & 1) != 1) stop(); check_bvals(i, 2); } void i_union_4_state_64(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_64 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); check_bvals(i, 2); } void i_union_4_state_65(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_65 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if ((i[2].aval & 1) != 1) stop(); check_bvals(i, 3); } void i_union_4_state_128(CONSTARG svLogicVecVal* i) { static int n = 0; printf("i_union_4_state_128 %d\n", n); if (i[0].aval != 0xffffffffU << n++) stop(); if (i[1].aval != -1) stop(); if (i[2].aval != -1) stop(); if (i[3].aval != -1) stop(); check_bvals(i, 4); } //====================================================================== // Check exported functions //====================================================================== void set_bvals(svLogicVecVal* v, unsigned n); void set_bvals(svLogicVecVal* v, unsigned n) { for (unsigned i = 0; i < n; i++) v[i].bval = 0; } void check_exports() { static int n = 0; #ifndef NO_TIME svLogicVecVal x_time[2]; svLogicVecVal x_time_t[2]; #endif #ifndef NO_INTEGER svLogicVecVal x_integer[1]; svLogicVecVal x_integer_t[1]; #endif #ifndef NO_TIME set_bvals(x_time, 2); set_bvals(x_time_t, 2); #endif #ifndef NO_INTEGER set_bvals(x_integer, 1); set_bvals(x_integer_t, 1); #endif // Basic types as per IEEE 1800-2017 35.5.6 e_byte(10 + n); e_byte_unsigned(20 + n); e_shortint(30 + n); e_shortint_unsigned(40 + n); e_int(50 + n); e_int_unsigned(60 + n); e_longint(70 + n); e_longint_unsigned(80 + n); #ifndef NO_TIME x_time[0].aval = 90 + n; x_time[1].aval = 0; e_time(x_time); #endif #ifndef NO_INTEGER x_integer[0].aval = 100 + n; e_integer(x_integer); #endif e_real(1.0 * n + 0.5); #ifndef NO_SHORTREAL e_shortreal(1.0f * n + 0.25f); #endif e_chandle((n % 2) ? reinterpret_cast(&e_chandle) : NULL); e_string((n % 2) ? "World" : "Hello"); e_bit(n % 2); e_logic(!(n % 2)); // Basic types via tyepdef e_byte_t(10 + 2 * n); e_byte_unsigned_t(20 + 2 * n); e_shortint_t(30 + 2 * n); e_shortint_unsigned_t(40 + 2 * n); e_int_t(50 + 2 * n); e_int_unsigned_t(60 + 2 * n); e_longint_t(70 + 2 * n); e_longint_unsigned_t(80 + 2 * n); #ifndef NO_TIME x_time_t[0].aval = 90 + 2 * n; x_time_t[1].aval = 0; e_time_t(x_time_t); #endif #ifndef NO_INTEGER x_integer_t[0].aval = 100 + 2 * n; e_integer_t(x_integer_t); #endif e_real_t(1.0 * (2 * n) + 0.5); #ifndef NO_SHORTREAL e_shortreal_t(1.0f * (2 * n) + 0.25f); #endif e_chandle_t((n % 2) ? NULL : reinterpret_cast(&e_chandle_t)); e_string_t((n % 2) ? "Hello" : "World"); e_bit_t(n % 2); e_logic_t(!(n % 2)); const int m = n == 0 ? 0 : n - 1; svBitVecVal b1[1]; svBitVecVal b2[2]; svBitVecVal b3[3]; svBitVecVal b4[4]; b3[0] = 0xffffffff; b4[0] = 0xffffffff; b4[1] = 0xffffffff; b4[2] = 0xffffffff; // 2-state packed arrays b1[0] = n % 2; e_array_2_state_1(b1); b1[0] = 0xffffffff >> n; e_array_2_state_32(b1); b2[1] = 1 >> n; b2[0] = 0xffffffff >> m; e_array_2_state_33(b2); b2[1] = 0xffffffff >> n; b2[0] = 0xffffffff; e_array_2_state_64(b2); b3[2] = 1 >> n; b3[1] = 0xffffffff >> m; e_array_2_state_65(b3); b4[3] = 0xffffffff >> n; e_array_2_state_128(b4); // 2-state packed structures b1[0] = n % 2; e_struct_2_state_1(b1); b1[0] = 0xffffffff >> n; e_struct_2_state_32(b1); b2[1] = 1 >> n; b2[0] = 0xffffffff >> m; e_struct_2_state_33(b2); b2[1] = 0xffffffff >> n; b2[0] = 0xffffffff; e_struct_2_state_64(b2); b3[2] = 1 >> n; b3[1] = 0xffffffff >> m; e_struct_2_state_65(b3); b4[3] = 0xffffffff >> n; e_struct_2_state_128(b4); // 2-state packed unions b1[0] = n % 2; e_union_2_state_1(b1); b1[0] = 0xffffffff >> n; e_union_2_state_32(b1); b2[1] = 1 >> n; b2[0] = 0xffffffff >> m; e_union_2_state_33(b2); b2[1] = 0xffffffff >> n; b2[0] = 0xffffffff; e_union_2_state_64(b2); b3[2] = 1 >> n; b3[1] = 0xffffffff >> m; e_union_2_state_65(b3); b4[3] = 0xffffffff >> n; e_union_2_state_128(b4); svLogicVecVal l1[1]; svLogicVecVal l2[2]; svLogicVecVal l3[3]; svLogicVecVal l4[4]; // bvals should be ignored, leave them un-initialized set_bvals(l1, 1); set_bvals(l2, 2); set_bvals(l3, 3); set_bvals(l4, 4); l3[0].aval = 0xffffffff; l4[0].aval = 0xffffffff; l4[1].aval = 0xffffffff; l4[2].aval = 0xffffffff; // 4-state packed arrays l1[0].aval = n % 2; e_array_4_state_1(l1); l1[0].aval = 0xffffffff >> n; e_array_4_state_32(l1); l2[1].aval = 1 >> n; l2[0].aval = 0xffffffff >> m; e_array_4_state_33(l2); l2[1].aval = 0xffffffff >> n; l2[0].aval = 0xffffffff; e_array_4_state_64(l2); l3[2].aval = 1 >> n; l3[1].aval = 0xffffffff >> m; e_array_4_state_65(l3); l4[3].aval = 0xffffffff >> n; e_array_4_state_128(l4); // 4-state packed structures l1[0].aval = n % 2; e_struct_4_state_1(l1); l1[0].aval = 0xffffffff >> n; e_struct_4_state_32(l1); l2[1].aval = 1 >> n; l2[0].aval = 0xffffffff >> m; e_struct_4_state_33(l2); l2[1].aval = 0xffffffff >> n; l2[0].aval = 0xffffffff; e_struct_4_state_64(l2); l3[2].aval = 1 >> n; l3[1].aval = 0xffffffff >> m; e_struct_4_state_65(l3); l4[3].aval = 0xffffffff >> n; e_struct_4_state_128(l4); // 4-state packed unions l1[0].aval = n % 2; e_union_4_state_1(l1); l1[0].aval = 0xffffffff >> n; e_union_4_state_32(l1); l2[1].aval = 1 >> n; l2[0].aval = 0xffffffff >> m; e_union_4_state_33(l2); l2[1].aval = 0xffffffff >> n; l2[0].aval = 0xffffffff; e_union_4_state_64(l2); l3[2].aval = 1 >> n; l3[1].aval = 0xffffffff >> m; e_union_4_state_65(l3); l4[3].aval = 0xffffffff >> n; e_union_4_state_128(l4); n++; }