// -*- mode: C++; c-file-style: "cc-mode" -*- // // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2022 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 #include VM_PREFIX_INCLUDE VM_PREFIX* tb = nullptr; bool pass = true; double sc_time_stamp() { return 0; } void compare_signals(const sc_signal>& ls, const sc_signal>& rs) { if (ls.read() != rs.read()) { pass &= false; VL_PRINTF("%%Error: Data mismatch in signals %s and %s\n", ls.name(), rs.name()); } } void compareWls(int obits, WDataInP const lwp, WDataInP const rwp) { const int words = VL_WORDS_I(obits); bool same = true; for (int i = 0; (i < (words - 1)); ++i) { if (lwp[i] != rwp[i]) { same = false; } } if ((lwp[words - 1] & VL_MASK_E(obits)) != (rwp[words - 1] & VL_MASK_E(obits))) { same = false; } if (!same) { pass &= false; VL_PRINTF("%%Error: There is a difference in VlWide variable %d bits wide\n", obits); } } // old macro which is correct but has MT issue with range #define VL_ASSIGN_SBW_MT_ISSUE(obits, svar, rwp) \ { \ sc_biguint<(obits)> _butemp; \ for (int i = 0; i < VL_WORDS_I(obits); ++i) { \ int msb = ((i + 1) * VL_IDATASIZE) - 1; \ msb = (msb >= (obits)) ? ((obits)-1) : msb; \ _butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \ } \ (svar).write(_butemp); \ } #ifdef SYSTEMC_VERSION int sc_main(int, char**) #else int main() #endif { Verilated::debug(0); tb = new VM_PREFIX("tb"); VlWide<8> /*255:0*/ input_var; VlWide<8> /*255:0*/ out_var; // msb is always set to F not to be false positive on checking equality input_var.m_storage[0] = 0xF2341234; input_var.m_storage[1] = 0xFEADBEEF; input_var.m_storage[2] = 0xF5A5A5A5; input_var.m_storage[3] = 0xF1B2C3D4; input_var.m_storage[4] = 0xFFFFFFFF; input_var.m_storage[5] = 0xFAAABBBB; input_var.m_storage[6] = 0xF000AAAA; input_var.m_storage[7] = 0xF0101010; #ifdef SYSTEMC_VERSION // clang-format off sc_signal> SC_NAMED(i_29_s), SC_NAMED(i_29_old_s), SC_NAMED(o_29_s), SC_NAMED(o_29_old_s), SC_NAMED(i_30_s), SC_NAMED(i_30_old_s), SC_NAMED(o_30_s), SC_NAMED(o_30_old_s), SC_NAMED(i_31_s), SC_NAMED(i_31_old_s), SC_NAMED(o_31_s), SC_NAMED(o_31_old_s), SC_NAMED(i_32_s), SC_NAMED(i_32_old_s), SC_NAMED(o_32_s), SC_NAMED(o_32_old_s), SC_NAMED(i_59_s), SC_NAMED(i_59_old_s), SC_NAMED(o_59_s), SC_NAMED(o_59_old_s), SC_NAMED(i_60_s), SC_NAMED(i_60_old_s), SC_NAMED(o_60_s), SC_NAMED(o_60_old_s), SC_NAMED(i_62_s), SC_NAMED(i_62_old_s), SC_NAMED(o_62_s), SC_NAMED(o_62_old_s), SC_NAMED(i_64_s), SC_NAMED(i_64_old_s), SC_NAMED(o_64_s), SC_NAMED(o_64_old_s), SC_NAMED(i_119_s), SC_NAMED(i_119_old_s), SC_NAMED(o_119_s), SC_NAMED(o_119_old_s), SC_NAMED(i_120_s), SC_NAMED(i_120_old_s), SC_NAMED(o_120_s), SC_NAMED(o_120_old_s), SC_NAMED(i_121_s), SC_NAMED(i_121_old_s), SC_NAMED(o_121_s), SC_NAMED(o_121_old_s), SC_NAMED(i_127_s), SC_NAMED(i_127_old_s), SC_NAMED(o_127_s), SC_NAMED(o_127_old_s), SC_NAMED(i_128_s), SC_NAMED(i_128_old_s), SC_NAMED(o_128_s), SC_NAMED(o_128_old_s), SC_NAMED(i_255_s), SC_NAMED(i_255_old_s), SC_NAMED(o_255_s), SC_NAMED(o_255_old_s), SC_NAMED(i_256_s), SC_NAMED(i_256_old_s), SC_NAMED(o_256_s), SC_NAMED(o_256_old_s); tb->i_29(i_29_s); tb->i_29_old(i_29_old_s); tb->o_29(o_29_s); tb->o_29_old(o_29_old_s); tb->i_30(i_30_s); tb->i_30_old(i_30_old_s); tb->o_30(o_30_s); tb->o_30_old(o_30_old_s); tb->i_31(i_31_s); tb->i_31_old(i_31_old_s); tb->o_31(o_31_s); tb->o_31_old(o_31_old_s); tb->i_32(i_32_s); tb->i_32_old(i_32_old_s); tb->o_32(o_32_s); tb->o_32_old(o_32_old_s); tb->i_59(i_59_s); tb->i_59_old(i_59_old_s); tb->o_59(o_59_s); tb->o_59_old(o_59_old_s); tb->i_60(i_60_s); tb->i_60_old(i_60_old_s); tb->o_60(o_60_s); tb->o_60_old(o_60_old_s); tb->i_62(i_62_s); tb->i_62_old(i_62_old_s); tb->o_62(o_62_s); tb->o_62_old(o_62_old_s); tb->i_64(i_64_s); tb->i_64_old(i_64_old_s); tb->o_64(o_64_s); tb->o_64_old(o_64_old_s); tb->i_119(i_119_s); tb->i_119_old(i_119_old_s); tb->o_119(o_119_s); tb->o_119_old(o_119_old_s); tb->i_120(i_120_s); tb->i_120_old(i_120_old_s); tb->o_120(o_120_s); tb->o_120_old(o_120_old_s); tb->i_121(i_121_s); tb->i_121_old(i_121_old_s); tb->o_121(o_121_s); tb->o_121_old(o_121_old_s); tb->i_127(i_127_s); tb->i_127_old(i_127_old_s); tb->o_127(o_127_s); tb->o_127_old(o_127_old_s); tb->i_128(i_128_s); tb->i_128_old(i_128_old_s); tb->o_128(o_128_s); tb->o_128_old(o_128_old_s); tb->i_255(i_255_s); tb->i_255_old(i_255_old_s); tb->o_255(o_255_s); tb->o_255_old(o_255_old_s); tb->i_256(i_256_s); tb->i_256_old(i_256_old_s); tb->o_256(o_256_s); tb->o_256_old(o_256_old_s); // clang-format on #endif // clang-format off #ifdef SYSTEMC_VERSION sc_start(1, SC_NS); #else tb->eval(); #endif // This testcase is testing multi-thread safe VL_ASSIGN_SBW and VL_ASSIGN_WSB macros. // Testbench is assigning different number of bits from VlWide input_var variable to different inputs. // Values around multiple of 30 (i.e. BITS_PER_DIGIT defined in SystemC sc_nbdefs.h) are tested with the special care, since // it is the value by which the data_ptr of sc_biguint underlying data type is increased by (and not expected 32, as width of uint32_t). // Correctness of the output is compared against the 'old' macro, which is correct but has multi-threaded issue since it's using range function. // Second part is testing VL_ASSIGN_WSB in a reverse way, it is reading signals from the previous test, // and comparing the output with (fraction) of VlWide input_var variable. // clang-format on VL_ASSIGN_SBW(29, i_29_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(29, i_29_old_s, input_var); VL_ASSIGN_SBW(30, i_30_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(30, i_30_old_s, input_var); VL_ASSIGN_SBW(31, i_31_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(31, i_31_old_s, input_var); VL_ASSIGN_SBW(32, i_32_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(32, i_32_old_s, input_var); VL_ASSIGN_SBW(59, i_59_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(59, i_59_old_s, input_var); VL_ASSIGN_SBW(60, i_60_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(60, i_60_old_s, input_var); VL_ASSIGN_SBW(62, i_62_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(62, i_62_old_s, input_var); VL_ASSIGN_SBW(64, i_64_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(64, i_64_old_s, input_var); VL_ASSIGN_SBW(119, i_119_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(119, i_119_old_s, input_var); VL_ASSIGN_SBW(120, i_120_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(120, i_120_old_s, input_var); VL_ASSIGN_SBW(121, i_121_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(121, i_121_old_s, input_var); VL_ASSIGN_SBW(127, i_127_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(127, i_127_old_s, input_var); VL_ASSIGN_SBW(128, i_128_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(128, i_128_old_s, input_var); VL_ASSIGN_SBW(255, i_255_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(255, i_255_old_s, input_var); VL_ASSIGN_SBW(256, i_256_s, input_var); VL_ASSIGN_SBW_MT_ISSUE(256, i_256_old_s, input_var); #ifdef SYSTEMC_VERSION sc_start(1, SC_NS); #else tb->eval(); #endif compare_signals(o_29_s, o_29_old_s); compare_signals(o_30_s, o_30_old_s); compare_signals(o_31_s, o_31_old_s); compare_signals(o_32_s, o_32_old_s); compare_signals(o_59_s, o_59_old_s); compare_signals(o_60_s, o_60_old_s); compare_signals(o_62_s, o_62_old_s); compare_signals(o_64_s, o_64_old_s); compare_signals(o_119_s, o_119_old_s); compare_signals(o_120_s, o_120_old_s); compare_signals(o_121_s, o_121_old_s); compare_signals(o_127_s, o_127_old_s); compare_signals(o_128_s, o_128_old_s); compare_signals(o_255_s, o_255_old_s); compare_signals(o_256_s, o_256_old_s); //////////////////////////////// VL_ASSIGN_WSB(29, out_var, o_29_s); compareWls(29, input_var.data(), out_var.data()); VL_ASSIGN_WSB(30, out_var, o_30_s); compareWls(30, input_var.data(), out_var.data()); VL_ASSIGN_WSB(31, out_var, o_31_s); compareWls(31, input_var.data(), out_var.data()); VL_ASSIGN_WSB(32, out_var, o_32_s); compareWls(32, input_var.data(), out_var.data()); VL_ASSIGN_WSB(59, out_var, o_59_s); compareWls(59, input_var.data(), out_var.data()); VL_ASSIGN_WSB(60, out_var, o_60_s); compareWls(60, input_var.data(), out_var.data()); VL_ASSIGN_WSB(62, out_var, o_62_s); compareWls(62, input_var.data(), out_var.data()); VL_ASSIGN_WSB(64, out_var, o_64_s); compareWls(64, input_var.data(), out_var.data()); VL_ASSIGN_WSB(119, out_var, o_119_s); compareWls(119, input_var.data(), out_var.data()); VL_ASSIGN_WSB(120, out_var, o_120_s); compareWls(120, input_var.data(), out_var.data()); VL_ASSIGN_WSB(121, out_var, o_121_s); compareWls(121, input_var.data(), out_var.data()); VL_ASSIGN_WSB(127, out_var, o_127_s); compareWls(127, input_var.data(), out_var.data()); VL_ASSIGN_WSB(128, out_var, o_128_s); compareWls(128, input_var.data(), out_var.data()); VL_ASSIGN_WSB(255, out_var, o_255_s); compareWls(255, input_var.data(), out_var.data()); VL_ASSIGN_WSB(256, out_var, o_256_s); compareWls(256, input_var.data(), out_var.data()); tb->final(); VL_DO_DANGLING(delete tb, tb); if (pass) { VL_PRINTF("*-* All Finished *-*\n"); } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from test\n"); } return 0; }