@@ -3205,3 +3205,77 @@ bvt bv_utilst::verilog_bv_normal_bits(const bvt &src)
32053205
32063206 return even_bits;
32073207}
3208+
3209+ // / Symbolic implementation of popcount (count of 1 bits in a bit vector)
3210+ // / Based on the pop0 algorithm from Hacker's Delight
3211+ // / \param bv: The bit vector to count 1s in
3212+ // / \return A bit vector representing the count
3213+ bvt bv_utilst::popcount (const bvt &bv)
3214+ {
3215+ if (bv.empty ())
3216+ return bvt ();
3217+
3218+ // Determine the result width: log2(bv.size()) + 1
3219+ std::size_t result_width = address_bits (bv.size ());
3220+ if (result_width == 0 )
3221+ result_width = 1 ; // At least one bit for the result
3222+
3223+ // Start with the original bit vector
3224+ bvt x = bv;
3225+
3226+ // Apply the parallel bit counting algorithm from Hacker's Delight
3227+ // The algorithm works by summing adjacent bit groups of increasing sizes
3228+
3229+ // Iterate through the stages of the algorithm, doubling the field size each time
3230+ for (std::size_t stage = 0 ; stage < address_bits (x.size ()); stage++)
3231+ {
3232+ std::size_t shift_amount = 1 << stage; // 1, 2, 4, 8, 16, ...
3233+ std::size_t field_size = 2 * shift_amount; // 2, 4, 8, 16, 32, ...
3234+
3235+ // Skip if the bit vector is smaller than the field size
3236+ if (x.size () < field_size)
3237+ break ;
3238+
3239+ // Shift the bit vector
3240+ bvt x_shifted = shift (x, shiftt::SHIFT_LRIGHT, shift_amount);
3241+
3242+ // Create a mask with 'shift_amount' ones followed by 'shift_amount' zeros, repeated
3243+ bvt mask;
3244+ mask.reserve (x.size ());
3245+ for (std::size_t i = 0 ; i < x.size (); i++)
3246+ {
3247+ if ((i % field_size) < shift_amount)
3248+ mask.push_back (const_literal (true ));
3249+ else
3250+ mask.push_back (const_literal (false ));
3251+ }
3252+
3253+ // Apply the mask to both the original and shifted bit vectors
3254+ bvt masked_x = zeros (x.size ());
3255+ bvt masked_shifted = zeros (x.size ());
3256+
3257+ for (std::size_t i = 0 ; i < x.size (); i++)
3258+ {
3259+ masked_x[i] = prop.land (x[i], mask[i]);
3260+ masked_shifted[i] = prop.land (x_shifted[i], mask[i]);
3261+ }
3262+
3263+ // Add the masked vectors
3264+ x = add (masked_x, masked_shifted);
3265+ }
3266+
3267+ // Extract the result with the appropriate width
3268+ // The result is in the least significant bits of x
3269+ bvt result;
3270+ result.reserve (result_width);
3271+
3272+ for (std::size_t i = 0 ; i < result_width; i++)
3273+ {
3274+ if (i < x.size ())
3275+ result.push_back (x[i]);
3276+ else
3277+ result.push_back (const_literal (false ));
3278+ }
3279+
3280+ return result;
3281+ }
0 commit comments