mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-26 20:02:27 +00:00
core: Implement CFAR register
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>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user