From 204fedc63f7831e35cea09688b6e5249de8938da Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 29 Jun 2022 20:02:36 +1000 Subject: [PATCH] Move XER low bits out of register file 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 --- common.vhdl | 7 ++++--- core.vhdl | 7 ++++--- cr_file.vhdl | 10 ++++++++++ execute1.vhdl | 42 +++++++++++++++++++----------------------- register_file.vhdl | 1 - scripts/run_test.sh | 4 ++-- 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/common.vhdl b/common.vhdl index 14a8801..bab5aed 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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 => diff --git a/core.vhdl b/core.vhdl index b18f09a..070a1f1 100644 --- 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, diff --git a/cr_file.vhdl b/cr_file.vhdl index e9788cb..d1aedba 100644 --- a/cr_file.vhdl +++ b/cr_file.vhdl @@ -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; diff --git a/execute1.vhdl b/execute1.vhdl index 955a1da..b955b75 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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 diff --git a/register_file.vhdl b/register_file.vhdl index b5e7246..ab35855 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -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'; diff --git a/scripts/run_test.sh b/scripts/run_test.sh index 9fcb7ce..185c3a6 100755 --- a/scripts/run_test.sh +++ b/scripts/run_test.sh @@ -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