From ca3b5fbe995d9afd0a62c2b46dfbe796415c7a72 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 30 Dec 2023 15:31:58 -0500 Subject: [PATCH] Add verilated asserts that VL_MULS_MAX_WORDS does not overflow (#4781). No functional change intended. --- include/verilated.cpp | 12 +++++++++--- include/verilated_funcs.h | 27 +++++++++++++++------------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index 4c372be79..4037cdb20 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -444,6 +444,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData const int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm const int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm + VL_DEBUG_IFDEF(assert(uw <= VL_MULS_MAX_WORDS);); + VL_DEBUG_IFDEF(assert(vw <= VL_MULS_MAX_WORDS);); if (vw == 1) { // Single divisor word breaks rest of algorithm uint64_t k = 0; @@ -542,6 +544,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp, const WDataInP rwp) VL_MT_SAFE { // obits==lbits, rbits can be different + const int owords = VL_WORDS_I(obits); + VL_DEBUG_IFDEF(assert(owords <= VL_MULS_MAX_WORDS);); owp[0] = 1; for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0; // cppcheck-has-bug-suppress variableScope @@ -553,11 +557,11 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lw for (int bit = 0; bit < rbits; bit++) { if (bit > 0) { // power = power*power VL_ASSIGN_W(obits, lastpowstore, powstore); - VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore); + VL_MUL_W(owords, powstore, lastpowstore, lastpowstore); } if (VL_BITISSET_W(rwp, bit)) { // out *= power VL_ASSIGN_W(obits, lastoutstore, owp); - VL_MUL_W(VL_WORDS_I(obits), owp, lastoutstore, powstore); + VL_MUL_W(owords, owp, lastoutstore, powstore); } } return owp; @@ -653,8 +657,10 @@ double VL_ITOR_D_W(int lbits, const WDataInP lwp) VL_PURE { } double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_MT_SAFE { if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp); + const int words = VL_WORDS_I(lbits); + VL_DEBUG_IFDEF(assert(words <= VL_MULS_MAX_WORDS);); uint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here - VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp); + VL_NEGATE_W(words, pos, lwp); _vl_clean_inplace_w(lbits, pos); return -VL_ITOR_D_W(lbits, pos); } diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 23b261f53..ad1ae5dcb 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -1032,6 +1032,7 @@ static inline QData VL_MULS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE { static inline WDataOutP VL_MULS_WWW(int lbits, WDataOutP owp, WDataInP const lwp, WDataInP const rwp) VL_MT_SAFE { const int words = VL_WORDS_I(lbits); + VL_DEBUG_IFDEF(assert(words <= VL_MULS_MAX_WORDS);); // cppcheck-suppress variableScope WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here // cppcheck-suppress variableScope @@ -1102,21 +1103,22 @@ static inline QData VL_MODDIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE { static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP const lwp, WDataInP const rwp) VL_MT_SAFE { - const int words = VL_WORDS_I(lbits); - const EData lsign = VL_SIGN_E(lbits, lwp[words - 1]); - const EData rsign = VL_SIGN_E(lbits, rwp[words - 1]); + const int lwords = VL_WORDS_I(lbits); + const EData lsign = VL_SIGN_E(lbits, lwp[lwords - 1]); + const EData rsign = VL_SIGN_E(lbits, rwp[lwords - 1]); + VL_DEBUG_IFDEF(assert(lwords <= VL_MULS_MAX_WORDS);); // cppcheck-suppress variableScope WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here // cppcheck-suppress variableScope WData rwstore[VL_MULS_MAX_WORDS]; WDataInP ltup = lwp; WDataInP rtup = rwp; - if (lsign) ltup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); - if (rsign) rtup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); + if (lsign) ltup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, lwstore, lwp)); + if (rsign) rtup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, rwstore, rwp)); if ((lsign && !rsign) || (!lsign && rsign)) { WData qNoSign[VL_MULS_MAX_WORDS]; VL_DIV_WWW(lbits, qNoSign, ltup, rtup); - _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign)); + _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, owp, qNoSign)); return owp; } else { return VL_DIV_WWW(lbits, owp, ltup, rtup); @@ -1124,21 +1126,22 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP const lwp } static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp, WDataInP const lwp, WDataInP const rwp) VL_MT_SAFE { - const int words = VL_WORDS_I(lbits); - const EData lsign = VL_SIGN_E(lbits, lwp[words - 1]); - const EData rsign = VL_SIGN_E(lbits, rwp[words - 1]); + const int lwords = VL_WORDS_I(lbits); + const EData lsign = VL_SIGN_E(lbits, lwp[lwords - 1]); + const EData rsign = VL_SIGN_E(lbits, rwp[lwords - 1]); + VL_DEBUG_IFDEF(assert(lwords <= VL_MULS_MAX_WORDS);); // cppcheck-suppress variableScope WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here // cppcheck-suppress variableScope WData rwstore[VL_MULS_MAX_WORDS]; WDataInP ltup = lwp; WDataInP rtup = rwp; - if (lsign) ltup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); - if (rsign) rtup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); + if (lsign) ltup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, lwstore, lwp)); + if (rsign) rtup = _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, rwstore, rwp)); if (lsign) { // Only dividend sign matters for modulus WData qNoSign[VL_MULS_MAX_WORDS]; VL_MODDIV_WWW(lbits, qNoSign, ltup, rtup); - _vl_clean_inplace_w(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign)); + _vl_clean_inplace_w(lbits, VL_NEGATE_W(lwords, owp, qNoSign)); return owp; } else { return VL_MODDIV_WWW(lbits, owp, ltup, rtup);