diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 983f19b4c..ec5ff4eb3 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -152,9 +152,11 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE; // PLIi // Base macros // Return true if data[bit] set; not 0/1 return, but 0/non-zero return. +// Arguments must not have side effects #define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit)) // Shift appropriate word by bit. Does not account for wrapping between two words +// Argument 'bit' must not have side effects #define VL_BITRSHIFT_W(data, bit) ((data)[VL_BITWORD_E(bit)] >> VL_BITBIT_E(bit)) // Create two 32-bit words from quadword @@ -758,6 +760,7 @@ static inline IData VL_ONEHOT0_W(int words, WDataInP const lwp) VL_PURE { static inline IData VL_CLOG2_I(IData lhs) VL_PURE { // There are faster algorithms, or fls GCC4 builtins, but rarely used + // In C++20 there will be std::bit_width(lhs) - 1 if (VL_UNLIKELY(!lhs)) return 0; --lhs; int shifts = 0; @@ -953,11 +956,19 @@ static inline void VL_NEGATE_INPLACE_W(int words, WDataOutP owp_lwp) VL_MT_SAFE // EMIT_RULE: VL_MUL: oclean=dirty; lclean==clean; rclean==clean; // EMIT_RULE: VL_DIV: oclean=dirty; lclean==clean; rclean==clean; // EMIT_RULE: VL_MODDIV: oclean=dirty; lclean==clean; rclean==clean; -#define VL_DIV_III(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) / (rhs)) -#define VL_DIV_QQQ(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) / (rhs)) +static inline IData VL_DIV_III(int lbits, IData lhs, IData rhs) { + return (rhs == 0) ? 0 : lhs / rhs; +} +static inline QData VL_DIV_QQQ(int lbits, QData lhs, QData rhs) { + return (rhs == 0) ? 0 : lhs / rhs; +} #define VL_DIV_WWW(lbits, owp, lwp, rwp) (_vl_moddiv_w(lbits, owp, lwp, rwp, 0)) -#define VL_MODDIV_III(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) % (rhs)) -#define VL_MODDIV_QQQ(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) % (rhs)) +static inline IData VL_MODDIV_III(int lbits, IData lhs, IData rhs) { + return (rhs == 0) ? 0 : lhs % rhs; +} +static inline QData VL_MODDIV_QQQ(int lbits, QData lhs, QData rhs) { + return (rhs == 0) ? 0 : lhs % rhs; +} #define VL_MODDIV_WWW(lbits, owp, lwp, rwp) (_vl_moddiv_w(lbits, owp, lwp, rwp, 1)) static inline WDataOutP VL_ADD_W(int words, WDataOutP owp, WDataInP const lwp, diff --git a/include/verilatedos.h b/include/verilatedos.h index 6a24ea36f..b86d7925a 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -321,6 +321,7 @@ extern "C" void __gcov_dump(); // Now that C++ requires these standard types the vl types are deprecated #include #include +#include #ifndef VL_NO_LEGACY using vluint8_t = uint8_t; ///< 8-bit unsigned type (backward compatibility) @@ -445,11 +446,14 @@ using ssize_t = uint32_t; ///< signed size_t; returned from read() #define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad /// Return mask for words with 1's where relevant bits are (0=all bits) +/// Arguments must not have side effects #define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) ? ((1U << ((nbits) & VL_SIZEBITS_I)) - 1) : ~0) /// Return mask for quads with 1's where relevant bits are (0=all bits) +/// Arguments must not have side effects #define VL_MASK_Q(nbits) \ (((nbits) & VL_SIZEBITS_Q) ? ((1ULL << ((nbits) & VL_SIZEBITS_Q)) - 1ULL) : ~0ULL) /// Return mask for EData with 1's where relevant bits are (0=all bits) +/// Arguments must not have side effects #define VL_MASK_E(nbits) VL_MASK_I(nbits) #define VL_EUL(n) VL_UL(n) // Make constant number EData sized @@ -471,8 +475,12 @@ using ssize_t = uint32_t; ///< signed size_t; returned from read() // #defines, to avoid requiring math.h on all compile runs #ifdef _MSC_VER -# define VL_TRUNC(n) (((n) < 0) ? std::ceil((n)) : std::floor((n))) -# define VL_ROUND(n) (((n) < 0) ? std::ceil((n)-0.5) : std::floor((n) + 0.5)) +static inline double VL_TRUNC(double n) { + return (n < 0) ? std::ceil(n) : std::floor(n); +} +static inline double VL_ROUND(double n) { + return (n < 0) ? std::ceil(n-0.5) : std::floor(n + 0.5); +} #else # define VL_TRUNC(n) std::trunc(n) # define VL_ROUND(n) std::round(n)