From 77e13f522a0555721d312f610b743adae96cc2e8 Mon Sep 17 00:00:00 2001 From: Qi Xuesong <1411979083@qq.com> Date: Wed, 16 Jul 2025 20:44:48 +0800 Subject: [PATCH 1/2] [bitmanip] Remove redundant logic --- rtl/ibex_alu.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/ibex_alu.sv b/rtl/ibex_alu.sv index 563f571cf4..b0e907a01f 100644 --- a/rtl/ibex_alu.sv +++ b/rtl/ibex_alu.sv @@ -458,7 +458,7 @@ module ibex_alu #( always_comb begin unique case (1'b1) zbe_op: bitcnt_bits = operand_b_i; - bitcnt_cz: bitcnt_bits = bitcnt_bit_mask & ~bitcnt_mask_op; // clz / ctz + bitcnt_cz: bitcnt_bits = bitcnt_bit_mask; // clz / ctz default: bitcnt_bits = operand_a_i; // cpop endcase end From a754dbca8fe0683991146053703948dee0bc3a67 Mon Sep 17 00:00:00 2001 From: Qi Xuesong <1411979083@qq.com> Date: Mon, 21 Jul 2025 22:43:08 +0800 Subject: [PATCH 2/2] [bitmanip] Remove redundant logic in converting clz/ctz to cpop --- rtl/ibex_alu.sv | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/rtl/ibex_alu.sv b/rtl/ibex_alu.sv index b0e907a01f..afbbcfbc94 100644 --- a/rtl/ibex_alu.sv +++ b/rtl/ibex_alu.sv @@ -437,28 +437,23 @@ module ibex_alu #( assign bitcnt_cz = bitcnt_ctz | bitcnt_clz; assign bitcnt_result = bitcnt_partial[31]; - // Bit-mask generation for clz and ctz: - // The bit mask is generated by spreading the lowest-order set bit in the operand to all - // higher order bits. The resulting mask is inverted to cover the lowest order zeros. In order - // to create the bit mask for leading zeros, the input operand needs to be reversed. - assign bitcnt_mask_op = bitcnt_clz ? operand_a_rev : operand_a_i; + // Bitcnt_bits generation for clz and ctz: + // The operand of ctz can be divided into 3 parts: the don't-care bits in the high-order bits, + // the lowest-order set bit, and the trailing zeros. Bitcnt_bit_mask is obtained by subtracting 1 + // from bitcnt_mask_op, which clears the lowest-order set bit and sets all the trailing zeros to 1. + // Then, bitcnt_bit_mask & ~bitcnt_mask_op clears the don't-care bits. + // At this point, counting the number of 1s gives the number of trailing zeros. + // In order to create the bit mask for leading zeros, the input operand needs to be reversed. - always_comb begin - bitcnt_bit_mask = bitcnt_mask_op; - bitcnt_bit_mask |= bitcnt_bit_mask << 1; - bitcnt_bit_mask |= bitcnt_bit_mask << 2; - bitcnt_bit_mask |= bitcnt_bit_mask << 4; - bitcnt_bit_mask |= bitcnt_bit_mask << 8; - bitcnt_bit_mask |= bitcnt_bit_mask << 16; - bitcnt_bit_mask = ~bitcnt_bit_mask; - end + assign bitcnt_mask_op = bitcnt_clz ? operand_a_rev : operand_a_i; + assign bitcnt_bit_mask = bitcnt_mask_op - 32'h1; assign zbe_op = (operator_i == ALU_BCOMPRESS) | (operator_i == ALU_BDECOMPRESS); always_comb begin unique case (1'b1) zbe_op: bitcnt_bits = operand_b_i; - bitcnt_cz: bitcnt_bits = bitcnt_bit_mask; // clz / ctz + bitcnt_cz: bitcnt_bits = bitcnt_bit_mask & ~bitcnt_mask_op; // clz / ctz default: bitcnt_bits = operand_a_i; // cpop endcase end