fetch1: Change the way predictions from the BTC are sent downstream
authorPaul Mackerras <paulus@ozlabs.org>
Sat, 20 Aug 2022 08:06:06 +0000 (18:06 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Sat, 1 Jul 2023 00:56:36 +0000 (10:56 +1000)
Instead of sending down the predicted taken/not-taken bits with the
target of the branch, we now send them down with the branch itself.
Previously icache adjusted for this by sending the prediction bits to
decode1 without a 1-clock delay while everything else had a 1-clock
delay.  Now icache keeps the prediction bits with the rest of the
attributes for the request.

Also fix a buglet in fetch1 where the first address sent out after
reset didn't have .req set.  Currently this doesn't cause a problem
because icache doesn't really look at .req.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
fetch1.vhdl
icache.vhdl

index 13f2a7f9c5011763c1548c4bd46c85063c25cd52..6803fb652d16223225a9df044844c9e711e44253 100644 (file)
@@ -41,7 +41,6 @@ architecture behaviour of fetch1 is
         mode_32bit: std_ulogic;
         rd_is_niap4: std_ulogic;
         predicted_taken: std_ulogic;
-        pred_not_taken: std_ulogic;
         predicted_nia: std_ulogic_vector(63 downto 0);
     end record;
     signal r, r_next : Fetch1ToIcacheType;
@@ -87,7 +86,6 @@ begin
                 r.pred_ntaken <= r_next.pred_ntaken;
                 r.nia <= r_next.nia;
                 r_int.predicted_taken <= r_next_int.predicted_taken;
-                r_int.pred_not_taken <= r_next_int.pred_not_taken;
                 r_int.predicted_nia <= r_next_int.predicted_nia;
                 r_int.rd_is_niap4 <= r_next_int.rd_is_niap4;
             end if;
@@ -155,7 +153,6 @@ begin
         v.predicted := '0';
         v.pred_ntaken := '0';
         v_int.predicted_taken := '0';
-        v_int.pred_not_taken := '0';
         v_int.rd_is_niap4 := '0';
 
        if rst = '1' then
@@ -185,10 +182,8 @@ begin
             end if;
         elsif r_int.predicted_taken = '1' then
             v.nia := r_int.predicted_nia;
-            v.predicted := '1';
-        else
+        elsif r.req = '1' then
             v_int.rd_is_niap4 := '1';
-            v.pred_ntaken := r_int.pred_not_taken;
             v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
             if r_int.mode_32bit = '1' then
                 v.nia(63 downto 32) := x"00000000";
@@ -198,7 +193,8 @@ begin
                 btc_rd_data(BTC_WIDTH - 3 downto BTC_TARGET_BITS)
                 = v.nia(BTC_TAG_BITS + BTC_ADDR_BITS + 1 downto BTC_ADDR_BITS + 2) then
                 v_int.predicted_taken := btc_rd_data(BTC_WIDTH - 1);
-                v_int.pred_not_taken := not btc_rd_data(BTC_WIDTH - 1);
+                v.predicted := btc_rd_data(BTC_WIDTH - 1);
+                v.pred_ntaken := not btc_rd_data(BTC_WIDTH - 1);
             end if;
         end if;
         v_int.predicted_nia := btc_rd_data(BTC_TARGET_BITS - 1 downto 0) & "00";
index 0467630e3379696db92475866cd63e37b073e8fe..6383726cf455a64c8e098fef9b3da61de68ef5f9 100644 (file)
@@ -192,6 +192,8 @@ architecture rtl of icache is
        hit_smark : std_ulogic;
        hit_valid : std_ulogic;
         big_endian: std_ulogic;
+        predicted  : std_ulogic;
+        pred_ntaken: std_ulogic;
 
        -- Cache miss state (reload state machine)
         state            : state_t;
@@ -629,8 +631,8 @@ begin
        i_out.stop_mark <= r.hit_smark;
         i_out.fetch_failed <= r.fetch_failed;
         i_out.big_endian <= r.big_endian;
-        i_out.next_predicted <= i_in.predicted;
-        i_out.next_pred_ntaken <= i_in.pred_ntaken;
+        i_out.next_predicted <= r.predicted;
+        i_out.next_pred_ntaken <= r.pred_ntaken;
 
        -- Stall fetch1 if we have a miss on cache or TLB or a protection fault
        stall_out <= not (is_hit and access_ok);
@@ -673,6 +675,8 @@ begin
                 r.hit_smark <= i_in.stop_mark;
                 r.hit_nia <= i_in.nia;
                 r.big_endian <= i_in.big_endian;
+                r.predicted <= i_in.predicted;
+                r.pred_ntaken <= i_in.pred_ntaken;
             end if;
             if i_out.valid = '1' then
                 assert not is_X(i_out.insn) severity failure;