core: Implement CFAR register
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 15 Jun 2020 07:45:55 +0000 (17:45 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Mon, 29 Jun 2020 23:07:41 +0000 (09:07 +1000)
This implements the CFAR SPR as a slow SPR stored in 'ctrl'.  Taken
branches and rfid update it to the address of the branch or rfid
instruction.

To simplify the logic, this makes rfid use the branch logic to
generate its redirect (requiring SRR0 to come in to execute1 on
the B input and SRR1 on the A input), and the masking of the bottom
2 bits of NIA is moved to fetch1.

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

index d376ac36a273eca1cd4f279415cdb5bcf563fa56..15c5c2aba14563191bef86caba031299863bd000 100644 (file)
@@ -31,6 +31,7 @@ package common is
     constant SPR_DEC    : spr_num_t := 22;
     constant SPR_SRR0   : spr_num_t := 26;
     constant SPR_SRR1   : spr_num_t := 27;
+    constant SPR_CFAR   : spr_num_t := 28;
     constant SPR_HSRR0  : spr_num_t := 314;
     constant SPR_HSRR1  : spr_num_t := 315;
     constant SPR_SPRG0  : spr_num_t := 272;
@@ -94,6 +95,7 @@ package common is
        tb: std_ulogic_vector(63 downto 0);
        dec: std_ulogic_vector(63 downto 0);
        msr: std_ulogic_vector(63 downto 0);
+        cfar: std_ulogic_vector(63 downto 0);
        irq_state : irq_state_t;
        irq_nia: std_ulogic_vector(63 downto 0);
        srr1: std_ulogic_vector(63 downto 0);
index 2060e64947ccb5a2cec950b260d28b81d376eea2..d215e7e7a44e810aa4e69729f5d2c06263020b6d 100644 (file)
@@ -473,8 +473,8 @@ begin
                 end if;
             else
                 -- Could be OP_RFID
-                v.ispr1 := fast_spr_num(SPR_SRR0);
-                v.ispr2 := fast_spr_num(SPR_SRR1);
+                v.ispr1 := fast_spr_num(SPR_SRR1);
+                v.ispr2 := fast_spr_num(SPR_SRR0);
             end if;
 
         elsif majorop = "011110" then
index c585f781c6e5e8cc3c89c64dd51edc98fdb62287..0da059aee9b7d5c30910de2e7c44370cfb9261a9 100644 (file)
@@ -652,26 +652,27 @@ begin
                    result_en := '1';
                    v.e.write_reg := fast_spr_num(SPR_CTR);
                end if;
-               if ppc_bc_taken(bo, bi, e_in.cr, a_in) = '1' then
-                   f_out.redirect <= '1';
-                   f_out.redirect_nia <= b_in(63 downto 2) & "00";
-               end if;
+                is_branch := '1';
+               taken_branch := ppc_bc_taken(bo, bi, e_in.cr, a_in);
+                abs_branch := '1';
 
            when OP_RFID =>
-               f_out.redirect <= '1';
-                f_out.virt_mode <= b_in(MSR_IR) or b_in(MSR_PR);
-                f_out.priv_mode <= not b_in(MSR_PR);
-               f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
+                f_out.virt_mode <= a_in(MSR_IR) or a_in(MSR_PR);
+                f_out.priv_mode <= not a_in(MSR_PR);
                 -- Can't use msr_copy here because the partial function MSR
                 -- bits should be left unchanged, not zeroed.
-                ctrl_tmp.msr(63 downto 31) <= b_in(63 downto 31);
-                ctrl_tmp.msr(26 downto 22) <= b_in(26 downto 22);
-                ctrl_tmp.msr(15 downto 0)  <= b_in(15 downto 0);
-                if b_in(MSR_PR) = '1' then
+                ctrl_tmp.msr(63 downto 31) <= a_in(63 downto 31);
+                ctrl_tmp.msr(26 downto 22) <= a_in(26 downto 22);
+                ctrl_tmp.msr(15 downto 0)  <= a_in(15 downto 0);
+                if a_in(MSR_PR) = '1' then
                     ctrl_tmp.msr(MSR_EE) <= '1';
                     ctrl_tmp.msr(MSR_IR) <= '1';
                     ctrl_tmp.msr(MSR_DR) <= '1';
                 end if;
+                -- mark this as a branch so CFAR gets updated
+                is_branch := '1';
+                taken_branch := '1';
+                abs_branch := '1';
 
             when OP_CNTZ =>
                 v.e.valid := '0';
@@ -757,6 +758,8 @@ begin
                        spr_val(31 downto 0)  := ctrl.tb(63 downto 32);
                    when SPR_DEC =>
                        spr_val := ctrl.dec;
+                    when SPR_CFAR =>
+                        spr_val := ctrl.cfar;
                     when 724 =>     -- LOG_ADDR SPR
                         spr_val := log_wr_addr & r.log_addr_spr;
                     when 725 =>     -- LOG_DATA SPR
@@ -879,9 +882,9 @@ begin
            v.e.rc := e_in.rc and valid_in;
 
             -- Mispredicted branches cause a redirect
-            if is_branch = '1' and taken_branch /= e_in.br_pred then
-                f_out.redirect <= '1';
+            if is_branch = '1' then
                 if taken_branch = '1' then
+                    ctrl_tmp.cfar <= e_in.nia;
                     if abs_branch = '1' then
                         f_out.redirect_nia <= b_in;
                     else
@@ -890,6 +893,9 @@ begin
                 else
                     f_out.redirect_nia <= next_nia;
                 end if;
+                if taken_branch /= e_in.br_pred then
+                    f_out.redirect <= '1';
+                end if;
             end if;
 
            -- Update LR on the next cycle after a branch link
index 0d9c6f73f3133f07255bfc24795fba1ce8b356ed..a56f33dad12e304b7c0dfa9da99cbbd822814a84 100644 (file)
@@ -83,11 +83,11 @@ begin
             v.priv_mode := '1';
            v_int.stop_state := RUNNING;
        elsif e_in.redirect = '1' then
-           v.nia := e_in.redirect_nia;
+           v.nia := e_in.redirect_nia(63 downto 2) & "00";
             v.virt_mode := e_in.virt_mode;
             v.priv_mode := e_in.priv_mode;
         elsif d_in.redirect = '1' then
-            v.nia := d_in.redirect_nia;
+            v.nia := d_in.redirect_nia(63 downto 2) & "00";
        elsif stall_in = '0' then
 
            -- For debug stop/step to work properly we need a little bit of