Move XER low bits out of register file
authorPaul Mackerras <paulus@ozlabs.org>
Wed, 29 Jun 2022 10:02:36 +0000 (20:02 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Wed, 29 Jun 2022 10:02:36 +0000 (20:02 +1000)
Besides the overflow and status carry bits, XER has 18 bits which need
to retain the value written by mtxer (in case software wants to
emulate the move-assist instructions (lswi, lswx, stswi, stswx).
Until now these bits (and others) have been stored in the GPR file as
a "fast" SPR, but this causes complications because XER is not really
a fast SPR.

Instead, we now store these 18 bits in the 'ctrl' signal, which exists
in execute1.  This will enable us to simplify the data path in future,
and has the added bonus that with a little bit of plumbing, we can get
the full XER value printed when dumping registers at the end of a
simulation.

Therefore this changes scripts/run_test.sh to remove the greps which
exclude XER from the comparison of actual and expected register
results.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
common.vhdl
core.vhdl
cr_file.vhdl
execute1.vhdl
register_file.vhdl
scripts/run_test.sh

index 14a8801d7e84fd930c5b12557aa0226bad59658e..bab5aedc7721c5347246440e3341bcf58e5bccf0 100644 (file)
@@ -114,7 +114,7 @@ package common is
 
     -- The XER is split: the common bits (CA, OV, SO, OV32 and CA32) are
     -- in the CR file as a kind of CR extension (with a separate write
-    -- control). The rest is stored as a fast SPR.
+    -- control). The rest is stored in ctrl_t (effectively in execute1).
     type xer_common_t is record
        ca : std_ulogic;
        ca32 : std_ulogic;
@@ -192,7 +192,10 @@ package common is
        dec: std_ulogic_vector(63 downto 0);
        msr: std_ulogic_vector(63 downto 0);
         cfar: std_ulogic_vector(63 downto 0);
+        xer_low: std_ulogic_vector(17 downto 0);
     end record;
+    constant ctrl_t_init : ctrl_t :=
+        (xer_low => 18x"0", others => (others => '0'));
 
     type Fetch1ToIcacheType is record
        req: std_ulogic;
@@ -739,8 +742,6 @@ package body common is
            n := 10;
        when SPR_HSPRG1 =>
            n := 11;
-       when SPR_XER =>
-           n := 12;
        when SPR_TAR =>
            n := 13;
        when others =>
index b18f09afc174163ddb8376280722c5ca7af863fe..070a1f1f667316f95bd8ebe3c8037b58b9bdc244 100644 (file)
--- a/core.vhdl
+++ b/core.vhdl
@@ -145,7 +145,7 @@ architecture behave of core is
     signal dbg_gpr_addr : gspr_index_t;
     signal dbg_gpr_data : std_ulogic_vector(63 downto 0);
 
-    signal msr : std_ulogic_vector(63 downto 0);
+    signal ctrl_debug : ctrl_t;
 
     -- PMU event bus
     signal icache_events    : IcacheEventType;
@@ -333,6 +333,7 @@ begin
             d_out => cr_file_to_decode2,
             w_in => writeback_to_cr_file,
             sim_dump => sim_cr_dump,
+            ctrl => ctrl_debug,
             log_out => log_data(183 downto 171)
             );
 
@@ -359,7 +360,7 @@ begin
             bypass_data => execute1_bypass,
             bypass_cr_data => execute1_cr_bypass,
            icache_inval => ex1_icache_inval,
-            dbg_msr_out => msr,
+            dbg_ctrl_out => ctrl_debug,
             wb_events => writeback_events,
             ls_events => loadstore_events,
             dc_events => dcache_events,
@@ -482,7 +483,7 @@ begin
            terminate => terminate,
            core_stopped => dbg_core_is_stopped,
            nia => fetch1_to_icache.nia,
-            msr => msr,
+            msr => ctrl_debug.msr,
             dbg_gpr_req => dbg_gpr_req,
             dbg_gpr_ack => dbg_gpr_ack,
             dbg_gpr_addr => dbg_gpr_addr,
index e9788cb29ef07f9023550127f0a19d7e689a8a81..d1aedbae3f25195e0f504d558b3eb838042d7e24 100644 (file)
@@ -18,6 +18,7 @@ entity cr_file is
         d_out : out CrFileToDecode2Type;
 
         w_in  : in WritebackToCrFileType;
+        ctrl  : in ctrl_t;
 
         -- debug
         sim_dump : in std_ulogic;
@@ -84,9 +85,18 @@ begin
 
     sim_dump_test: if SIM generate
         dump_cr: process(all)
+            variable xer : std_ulogic_vector(31 downto 0);
         begin
             if sim_dump = '1' then
                 report "CR 00000000" & to_hstring(crs);
+                xer := (others => '0');
+                xer(31) := xerc.so;
+                xer(30) := xerc.ov;
+                xer(29) := xerc.ca;
+                xer(19) := xerc.ov32;
+                xer(18) := xerc.ca32;
+                xer(17 downto 0) := ctrl.xer_low;
+                report "XER 00000000" & to_hstring(xer);
                 assert false report "end of test" severity failure;
             end if;
         end process;
index 955a1da79d99ca76adbc15bc73362aaabc9da107..b955b752f2fdd0f7a493ae03867bb177d8c96c85 100644 (file)
@@ -41,7 +41,7 @@ entity execute1 is
         bypass_data : out bypass_data_t;
         bypass_cr_data : out cr_bypass_data_t;
 
-        dbg_msr_out : out std_ulogic_vector(63 downto 0);
+        dbg_ctrl_out : out ctrl_t;
 
        icache_inval : out std_ulogic;
        terminate_out : out std_ulogic;
@@ -99,8 +99,8 @@ architecture behaviour of execute1 is
     signal mshort_p : std_ulogic_vector(31 downto 0) := (others => '0');
 
     signal valid_in : std_ulogic;
-    signal ctrl: ctrl_t;
-    signal ctrl_tmp: ctrl_t;
+    signal ctrl: ctrl_t := ctrl_t_init;
+    signal ctrl_tmp: ctrl_t := ctrl_t_init;
     signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
     signal rot_sign_ext: std_ulogic;
     signal rotator_result: std_ulogic_vector(63 downto 0);
@@ -249,6 +249,13 @@ architecture behaviour of execute1 is
         return x(n - 1) = '1';
     end;
 
+    function assemble_xer(xerc: xer_common_t; xer_low: std_ulogic_vector)
+        return std_ulogic_vector is
+    begin
+        return 32x"0" & xerc.so & xerc.ov & xerc.ca & "000000000" &
+            xerc.ov32 & xerc.ca32 & xer_low(17 downto 0);
+    end;
+
     -- Tell vivado to keep the hierarchy for the random module so that the
     -- net names in the xdc file match.
     attribute keep_hierarchy : string;
@@ -336,7 +343,7 @@ begin
             );
     end generate;
 
-    dbg_msr_out <= ctrl.msr;
+    dbg_ctrl_out <= ctrl;
     log_rd_addr <= r.log_addr_spr;
 
     a_in <= e_in.read_data1;
@@ -402,9 +409,7 @@ begin
        if rising_edge(clk) then
             if rst = '1' then
                 r <= reg_type_init;
-                ctrl.tb <= (others => '0');
-                ctrl.dec <= (others => '0');
-                ctrl.cfar <= (others => '0');
+                ctrl <= ctrl_t_init;
                 ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
             else
                 r <= rin;
@@ -1043,19 +1048,11 @@ begin
                    "=" & to_hstring(a_in);
                if is_fast_spr(e_in.read_reg1) = '1' then
                    spr_val := a_in;
-                    if decode_spr_num(e_in.insn) = SPR_XER then
-                       -- bits 0:31 and 35:43 are treated as reserved and return 0s when read using mfxer
-                       spr_val(63 downto 32) := (others => '0');
-                       spr_val(63-32) := xerc_in.so;
-                       spr_val(63-33) := xerc_in.ov;
-                       spr_val(63-34) := xerc_in.ca;
-                       spr_val(63-35 downto 63-43) := "000000000";
-                       spr_val(63-44) := xerc_in.ov32;
-                       spr_val(63-45) := xerc_in.ca32;
-                    end if;
                else
                     spr_val := c_in;
                     case decode_spr_num(e_in.insn) is
+                    when SPR_XER =>
+                        spr_val := assemble_xer(xerc_in, ctrl.xer_low);
                    when SPR_TB =>
                        spr_val := ctrl.tb;
                    when SPR_TBU =>
@@ -1118,17 +1115,16 @@ begin
            when OP_MTSPR =>
                report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
                    "=" & to_hstring(c_in);
-               if is_fast_spr(e_in.write_reg) then
-                   if decode_spr_num(e_in.insn) = SPR_XER then
+               if is_fast_spr(e_in.write_reg) = '0' then
+                   -- slow spr
+                   case decode_spr_num(e_in.insn) is
+                    when SPR_XER =>
                        v.e.xerc.so := c_in(63-32);
                        v.e.xerc.ov := c_in(63-33);
                        v.e.xerc.ca := c_in(63-34);
                        v.e.xerc.ov32 := c_in(63-44);
                        v.e.xerc.ca32 := c_in(63-45);
-                   end if;
-               else
-                   -- slow spr
-                   case decode_spr_num(e_in.insn) is
+                        ctrl_tmp.xer_low <= c_in(17 downto 0);
                    when SPR_DEC =>
                        ctrl_tmp.dec <= c_in;
                     when 724 =>     -- LOG_ADDR SPR
index b5e7246ac0bcc75f95c09c3f5a5cca2798c39668..ab358552b445b3341661818567fddc8156e0114d 100644 (file)
@@ -143,7 +143,6 @@ begin
 
                 report "LR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_LR)))));
                 report "CTR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_CTR)))));
-                report "XER " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_XER)))));
                 sim_dump_done <= '1';
             else
                 sim_dump_done <= '0';
index 9fcb7ce3c06f92325aa7bd1b37b1c71dca94c6bc..185c3a634ce285ae00ec579869fcfd292ad90fd8 100755 (executable)
@@ -21,9 +21,9 @@ cd $TMPDIR
 
 cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin
 
-${MICROWATT_DIR}/core_tb | sed 's/.*: //' | egrep '^(GPR[0-9]|LR |CTR |XER |CR [0-9])' | sort | grep -v GPR31 | grep -v XER > test.out || true
+${MICROWATT_DIR}/core_tb | sed 's/.*: //' | egrep '^(GPR[0-9]|LR |CTR |XER |CR [0-9])' | sort | grep -v GPR31 > test.out || true
 
-grep -v "^$" ${MICROWATT_DIR}/tests/${TEST}.out | sort | grep -v GPR31 | grep -v XER > exp.out
+grep -v "^$" ${MICROWATT_DIR}/tests/${TEST}.out | sort | grep -v GPR31 > exp.out
 
 cp test.out /tmp
 cp exp.out /tmp