Use alternative count-leading-zeroes algorithm in the FPU and LSU
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 21 Feb 2022 01:06:11 +0000 (12:06 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Mon, 21 Feb 2022 01:29:08 +0000 (12:29 +1100)
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
countbits.vhdl
helpers.vhdl

index ab5be2a75f9e8f5bf6289dd5ea547fc0bc00a98d..b16baa0dda47f7eb965c1aae4820e517d1f19741 100644 (file)
@@ -46,25 +46,6 @@ architecture behaviour of bit_counter is
     signal pc32     : sixbit2;
     signal popcnt   : std_ulogic_vector(63 downto 0);
 
-    function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector is
-        variable p: std_ulogic_vector(nbits - 1 downto 0);
-        variable stride: natural;
-        variable b: std_ulogic;
-        variable k: natural;
-    begin
-        stride := 2;
-        for i in 0 to nbits - 1 loop
-            b := '0';
-            for j in 0 to (2**nbits / stride) - 1 loop
-                k := j * stride;
-                b := b or (v(k + stride - 1) and not v(k + (stride/2) - 1));
-            end loop;
-            p(i) := b;
-            stride := stride * 2;
-        end loop;
-        return p;
-    end function;
-
 begin
     countzero_r: process(clk)
     begin
index 834e3863dd871f8b7129581937391a108464512c..654c113553cd97a814bfa82813072627de2f35b5 100644 (file)
@@ -28,6 +28,7 @@ package helpers is
 
     function bit_reverse(a: std_ulogic_vector) return std_ulogic_vector;
     function bit_number(a: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
+    function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector;
     function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector;
 end package helpers;
 
@@ -247,16 +248,44 @@ package body helpers is
         return ret;
     end;
 
+    -- Assuming the input 'v' is a value of the form 1...10...0,
+    -- the output is the bit number of the rightmost 1 bit in v.
+    -- If v is zero, the result is zero.
+    function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector is
+        variable p: std_ulogic_vector(nbits - 1 downto 0);
+        variable stride: natural;
+        variable b: std_ulogic;
+        variable k: natural;
+    begin
+        stride := 2;
+        for i in 0 to nbits - 1 loop
+            b := '0';
+            for j in 0 to (2**nbits / stride) - 1 loop
+                k := j * stride;
+                b := b or (v(k + stride - 1) and not v(k + (stride/2) - 1));
+            end loop;
+            p(i) := b;
+            stride := stride * 2;
+        end loop;
+        return p;
+    end function;
+
     -- Count leading zeroes operation
     -- Assumes the value passed in is not zero (if it is, zero is returned)
     function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector is
         variable rev: std_ulogic_vector(val'left downto val'right);
         variable sum: std_ulogic_vector(val'left downto val'right);
         variable onehot: std_ulogic_vector(val'left downto val'right);
+        variable edge: std_ulogic_vector(val'left downto val'right);
+        variable bn, bn_e, bn_o: std_ulogic_vector(5 downto 0);
     begin
         rev := bit_reverse(val);
         sum := std_ulogic_vector(- signed(rev));
         onehot := sum and rev;
-        return bit_number(std_ulogic_vector(resize(unsigned(onehot), 64)));
+        edge := sum or rev;
+        bn_e := edgelocation(std_ulogic_vector(resize(signed(edge), 64)), 6);
+        bn_o := bit_number(std_ulogic_vector(resize(unsigned(onehot), 64)));
+        bn := bn_e(5 downto 2) & bn_o(1 downto 0);
+        return bn;
     end;
 end package body helpers;