Pass mtspr/mfspr to MMU-related SPRs down to loadstore1

This arranges for some mfspr and mtspr to get sent to loadstore1
instead of being handled in execute1.  In particular, DAR and DSISR
are handled this way.  They are therefore "slow" SPRs.

While we're at it, fix the spelling of HEIR and remove mention of
DAR and DSISR from the comments in execute1.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/169/head
Paul Mackerras 4 years ago
parent 3340d8aa9f
commit 635e316f9b

@ -24,6 +24,8 @@ package common is
constant SPR_XER : spr_num_t := 1; constant SPR_XER : spr_num_t := 1;
constant SPR_LR : spr_num_t := 8; constant SPR_LR : spr_num_t := 8;
constant SPR_CTR : spr_num_t := 9; constant SPR_CTR : spr_num_t := 9;
constant SPR_DSISR : spr_num_t := 18;
constant SPR_DAR : spr_num_t := 19;
constant SPR_TB : spr_num_t := 268; constant SPR_TB : spr_num_t := 268;
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;
@ -214,7 +216,7 @@ package common is


type Execute1ToLoadstore1Type is record type Execute1ToLoadstore1Type is record
valid : std_ulogic; valid : std_ulogic;
op : insn_type_t; -- what ld/st op to do op : insn_type_t; -- what ld/st or m[tf]spr to do
addr1 : std_ulogic_vector(63 downto 0); addr1 : std_ulogic_vector(63 downto 0);
addr2 : std_ulogic_vector(63 downto 0); addr2 : std_ulogic_vector(63 downto 0);
data : std_ulogic_vector(63 downto 0); -- data to write, unused for read data : std_ulogic_vector(63 downto 0); -- data to write, unused for read
@ -228,10 +230,12 @@ package common is
xerc : xer_common_t; xerc : xer_common_t;
reserve : std_ulogic; -- set for larx/stcx. reserve : std_ulogic; -- set for larx/stcx.
rc : std_ulogic; -- set for stcx. rc : std_ulogic; -- set for stcx.
spr_num : spr_num_t; -- SPR number for mfspr/mtspr
end record; end record;
constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0', constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
sign_extend => '0', update => '0', xerc => xerc_init, sign_extend => '0', update => '0', xerc => xerc_init,
reserve => '0', rc => '0', others => (others => '0')); reserve => '0', rc => '0',
spr_num => 0, others => (others => '0'));


type Loadstore1ToDcacheType is record type Loadstore1ToDcacheType is record
valid : std_ulogic; valid : std_ulogic;

@ -363,6 +363,7 @@ begin
variable v : Decode1ToDecode2Type; variable v : Decode1ToDecode2Type;
variable majorop : major_opcode_t; variable majorop : major_opcode_t;
variable op_19_bits: std_ulogic_vector(2 downto 0); variable op_19_bits: std_ulogic_vector(2 downto 0);
variable sprn : spr_num_t;
begin begin
v := r; v := r;


@ -429,10 +430,17 @@ begin
end if; end if;
end if; end if;
elsif v.decode.insn_type = OP_MFSPR or v.decode.insn_type = OP_MTSPR then elsif v.decode.insn_type = OP_MFSPR or v.decode.insn_type = OP_MTSPR then
v.ispr1 := fast_spr_num(decode_spr_num(f_in.insn)); sprn := decode_spr_num(f_in.insn);
v.ispr1 := fast_spr_num(sprn);
-- Make slow SPRs single issue -- Make slow SPRs single issue
if is_fast_spr(v.ispr1) = '0' then if is_fast_spr(v.ispr1) = '0' then
v.decode.sgl_pipe := '1'; v.decode.sgl_pipe := '1';
-- send MMU-related SPRs to loadstore1
case sprn is
when SPR_DAR | SPR_DSISR =>
v.decode.unit := LDST;
when others =>
end case;
end if; end if;
elsif v.decode.insn_type = OP_RFID then elsif v.decode.insn_type = OP_RFID then
report "PPC RFID"; report "PPC RFID";

@ -463,7 +463,7 @@ begin


elsif irq_valid = '1' and e_in.valid = '1' then elsif irq_valid = '1' and e_in.valid = '1' then
-- we need two cycles to write srr0 and 1 -- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER -- will need more when we have to write HEIR
-- Don't deliver the interrupt until we have a valid instruction -- Don't deliver the interrupt until we have a valid instruction
-- coming in, so we have a valid NIA to put in SRR0. -- coming in, so we have a valid NIA to put in SRR0.
exception := '1'; exception := '1';
@ -494,13 +494,12 @@ begin


when OP_ILLEGAL => when OP_ILLEGAL =>
-- we need two cycles to write srr0 and 1 -- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER -- will need more when we have to write HEIR
illegal := '1'; illegal := '1';
when OP_SC => when OP_SC =>
-- check bit 1 of the instruction is 1 so we know this is sc; -- check bit 1 of the instruction is 1 so we know this is sc;
-- 0 would mean scv, so generate an illegal instruction interrupt -- 0 would mean scv, so generate an illegal instruction interrupt
-- we need two cycles to write srr0 and 1 -- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER
if e_in.insn(1) = '1' then if e_in.insn(1) = '1' then
exception := '1'; exception := '1';
exception_nextpc := '1'; exception_nextpc := '1';
@ -983,6 +982,7 @@ begin
lv.xerc := v.e.xerc; lv.xerc := v.e.xerc;
lv.reserve := e_in.reserve; lv.reserve := e_in.reserve;
lv.rc := e_in.rc; lv.rc := e_in.rc;
lv.spr_num := decode_spr_num(e_in.insn);
-- decode l*cix and st*cix instructions here -- decode l*cix and st*cix instructions here
if e_in.insn(31 downto 26) = "011111" and e_in.insn(10 downto 9) = "11" and if e_in.insn(31 downto 26) = "011111" and e_in.insn(10 downto 9) = "11" and
e_in.insn(5 downto 1) = "10101" then e_in.insn(5 downto 1) = "10101" then

@ -59,6 +59,8 @@ architecture behave of loadstore1 is
nc : std_ulogic; -- non-cacheable access nc : std_ulogic; -- non-cacheable access
state : state_t; state : state_t;
second_bytes : std_ulogic_vector(7 downto 0); second_bytes : std_ulogic_vector(7 downto 0);
dar : std_ulogic_vector(63 downto 0);
dsisr : std_ulogic_vector(31 downto 0);
end record; end record;


type byte_sel_t is array(0 to 7) of std_ulogic; type byte_sel_t is array(0 to 7) of std_ulogic;
@ -135,6 +137,9 @@ begin
variable use_second : byte_sel_t; variable use_second : byte_sel_t;
variable trim_ctl : trim_ctl_t; variable trim_ctl : trim_ctl_t;
variable negative : std_ulogic; variable negative : std_ulogic;
variable mfspr : std_ulogic;
variable sprn : std_ulogic_vector(9 downto 0);
variable sprval : std_ulogic_vector(63 downto 0);
begin begin
v := r; v := r;
req := '0'; req := '0';
@ -142,6 +147,8 @@ begin
done := '0'; done := '0';
byte_sel := (others => '0'); byte_sel := (others => '0');
addr := lsu_sum; addr := lsu_sum;
mfspr := '0';
sprval := (others => '0'); -- avoid inferred latches


write_enable := '0'; write_enable := '0';
do_update := '0'; do_update := '0';
@ -200,11 +207,38 @@ begin
if l_in.valid = '1' then if l_in.valid = '1' then
v.load := '0'; v.load := '0';
v.dcbz := '0'; v.dcbz := '0';
if l_in.op = OP_LOAD then case l_in.op is
when OP_STORE =>
req := '1';
when OP_LOAD =>
req := '1';
v.load := '1'; v.load := '1';
elsif l_in.op = OP_DCBZ then when OP_DCBZ =>
req := '1';
v.dcbz := '1'; v.dcbz := '1';
end if; when OP_MFSPR =>
done := '1';
mfspr := '1';
-- partial decode on SPR number should be adequate given
-- the restricted set that get sent down this path
sprn := std_ulogic_vector(to_unsigned(l_in.spr_num, 10));
if sprn(0) = '0' then
sprval := x"00000000" & r.dsisr;
else
sprval := r.dar;
end if;
when OP_MTSPR =>
done := '1';
sprn := std_ulogic_vector(to_unsigned(l_in.spr_num, 10));
if sprn(0) = '0' then
v.dsisr := l_in.data(31 downto 0);
else
v.dar := l_in.data;
end if;
when others =>
assert false report "unknown op sent to loadstore1";
end case;

v.addr := lsu_sum; v.addr := lsu_sum;
v.write_reg := l_in.write_reg; v.write_reg := l_in.write_reg;
v.length := l_in.length; v.length := l_in.length;
@ -246,12 +280,13 @@ begin
v.store_data(j + 7 downto j) := l_in.data(i * 8 + 7 downto i * 8); v.store_data(j + 7 downto j) := l_in.data(i * 8 + 7 downto i * 8);
end loop; end loop;


req := '1'; if req = '1' then
stall := '1'; stall := '1';
if long_sel(15 downto 8) = "00000000" then if long_sel(15 downto 8) = "00000000" then
v.state := LAST_ACK_WAIT; v.state := LAST_ACK_WAIT;
else else
v.state := SECOND_REQ; v.state := SECOND_REQ;
end if;
end if; end if;
end if; end if;


@ -308,7 +343,11 @@ begin
-- Multiplex either cache data to the destination GPR or -- Multiplex either cache data to the destination GPR or
-- the address for the rA update. -- the address for the rA update.
l_out.valid <= done; l_out.valid <= done;
if do_update = '1' then if mfspr = '1' then
l_out.write_enable <= '1';
l_out.write_reg <= l_in.write_reg;
l_out.write_data <= sprval;
elsif do_update = '1' then
l_out.write_enable <= '1'; l_out.write_enable <= '1';
l_out.write_reg <= r.update_reg; l_out.write_reg <= r.update_reg;
l_out.write_data <= r.addr; l_out.write_data <= r.addr;

Loading…
Cancel
Save