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