-- 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;
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;
n := 10;
when SPR_HSPRG1 =>
n := 11;
- when SPR_XER =>
- n := 12;
when SPR_TAR =>
n := 13;
when others =>
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;
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)
);
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,
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,
d_out : out CrFileToDecode2Type;
w_in : in WritebackToCrFileType;
+ ctrl : in ctrl_t;
-- debug
sim_dump : in std_ulogic;
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;
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;
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);
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;
);
end generate;
- dbg_msr_out <= ctrl.msr;
+ dbg_ctrl_out <= ctrl;
log_rd_addr <= r.log_addr_spr;
a_in <= e_in.read_data1;
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;
"=" & 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 =>
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
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';
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