@@ -3205,3 +3205,77 @@ bvt bv_utilst::verilog_bv_normal_bits(const bvt &src)
3205
3205
3206
3206
return even_bits;
3207
3207
}
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