execute1: Restructure to separate out execution of side effects

We now have a record that represents the actions taken in executing an
instruction, and a process that computes that for the incoming
instruction.  We no longer have 'current' or 'r.cur_instr', instead
things like the destination register are put into r.e in the first
cycle of an instruction and not reinitialized in subsequent busy
cycles.

For mfspr and mtspr, we now decode "slow" SPR numbers (those SPRs that
are not stored in the register file) to a new "spr_selector" record
in decode1 (excluding those in the loadstore unit).  With this, the
result for mfspr is determined in the data path.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/379/head
Paul Mackerras 3 years ago
parent 204fedc63f
commit 813e2317bf

@ -124,6 +124,23 @@ package common is
end record;
constant xerc_init : xer_common_t := (others => '0');

subtype spr_selector is std_ulogic_vector(2 downto 0);
type spr_id is record
sel : spr_selector;
valid : std_ulogic;
ispmu : std_ulogic;
end record;
constant spr_id_init : spr_id := (sel => "000", others => '0');

constant SPRSEL_TB : spr_selector := 3x"0";
constant SPRSEL_TBU : spr_selector := 3x"1";
constant SPRSEL_DEC : spr_selector := 3x"2";
constant SPRSEL_PVR : spr_selector := 3x"3";
constant SPRSEL_LOGA : spr_selector := 3x"4";
constant SPRSEL_LOGD : spr_selector := 3x"5";
constant SPRSEL_CFAR : spr_selector := 3x"6";
constant SPRSEL_XER : spr_selector := 3x"7";

-- FPSCR bit numbers
constant FPSCR_FX : integer := 63 - 32;
constant FPSCR_FEX : integer := 63 - 33;
@ -235,11 +252,13 @@ package common is
decode: decode_rom_t;
br_pred: std_ulogic; -- Branch was predicted to be taken
big_endian: std_ulogic;
spr_info : spr_id;
end record;
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
(valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
ispr1 => (others => '0'), ispr2 => (others => '0'), ispro => (others => '0'),
decode => decode_rom_init, br_pred => '0', big_endian => '0');
decode => decode_rom_init, br_pred => '0', big_endian => '0',
spr_info => spr_id_init);

type Decode1ToFetch1Type is record
redirect : std_ulogic;
@ -299,6 +318,7 @@ package common is
sub_select : std_ulogic_vector(2 downto 0); -- sub-result selection
repeat : std_ulogic; -- set if instruction is cracked into two ops
second : std_ulogic; -- set if this is the second op
spr_select : spr_id;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
@ -311,7 +331,8 @@ package common is
read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'),
cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'),
result_sel => "000", sub_select => "000",
repeat => '0', second => '0', others => (others => '0'));
repeat => '0', second => '0', spr_select => spr_id_init,
others => (others => '0'));

type MultiplyInputType is record
valid: std_ulogic;

@ -66,7 +66,11 @@ begin
crs <= crs_updated;
end if;
if w_in.write_xerc_enable = '1' then
report "Writing XERC";
report "Writing XERC SO=" & std_ulogic'image(xerc_updated.so) &
" OV=" & std_ulogic'image(xerc_updated.ov) &
" CA=" & std_ulogic'image(xerc_updated.ca) &
" OV32=" & std_ulogic'image(xerc_updated.ov32) &
" CA32=" & std_ulogic'image(xerc_updated.ca32);
xerc <= xerc_updated;
end if;
end if;

@ -519,6 +519,40 @@ architecture behaviour of decode1 is
constant nop_instr : decode_rom_t := (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE);
constant fetch_fail_inst: decode_rom_t := (LDST, NONE, OP_FETCH_FAILED, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE);

function map_spr(sprn : spr_num_t) return spr_id is
variable i : spr_id;
begin
i.sel := "000";
i.valid := '1';
i.ispmu := '0';
case sprn is
when SPR_TB =>
i.sel := SPRSEL_TB;
when SPR_TBU =>
i.sel := SPRSEL_TBU;
when SPR_DEC =>
i.sel := SPRSEL_DEC;
when SPR_PVR =>
i.sel := SPRSEL_PVR;
when 724 => -- LOG_ADDR SPR
i.sel := SPRSEL_LOGA;
when 725 => -- LOG_DATA SPR
i.sel := SPRSEL_LOGD;
when SPR_UPMC1 | SPR_UPMC2 | SPR_UPMC3 | SPR_UPMC4 | SPR_UPMC5 | SPR_UPMC6 |
SPR_UMMCR0 | SPR_UMMCR1 | SPR_UMMCR2 | SPR_UMMCRA | SPR_USIER | SPR_USIAR | SPR_USDAR |
SPR_PMC1 | SPR_PMC2 | SPR_PMC3 | SPR_PMC4 | SPR_PMC5 | SPR_PMC6 |
SPR_MMCR0 | SPR_MMCR1 | SPR_MMCR2 | SPR_MMCRA | SPR_SIER | SPR_SIAR | SPR_SDAR =>
i.ispmu := '1';
when SPR_CFAR =>
i.sel := SPRSEL_CFAR;
when SPR_XER =>
i.sel := SPRSEL_XER;
when others =>
i.valid := '0';
end case;
return i;
end;

begin
decode1_0: process(clk)
begin
@ -586,6 +620,9 @@ begin
majorop := unsigned(f_in.insn(31 downto 26));
v.decode := major_decode_rom_array(to_integer(majorop));

sprn := decode_spr_num(f_in.insn);
v.spr_info := map_spr(sprn);

case to_integer(unsigned(majorop)) is
when 4 =>
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
@ -598,7 +635,6 @@ begin
v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1))));

-- Work out ispr1/ispro independent of v.decode since they seem to be critical path
sprn := decode_spr_num(f_in.insn);
v.ispr1 := fast_spr_num(sprn);
v.ispro := fast_spr_num(sprn);


@ -228,13 +228,6 @@ architecture behaviour of decode2 is
OP_SHR => "010",
OP_EXTSWSLI => "010",
OP_MUL_L64 => "011", -- muldiv_result
OP_MUL_H64 => "011",
OP_MUL_H32 => "011",
OP_DIV => "011",
OP_DIVE => "011",
OP_MOD => "011",
OP_CNTZ => "100", -- countbits_result
OP_POPCNT => "100",
OP_MFSPR => "101", -- spr_result
OP_B => "110", -- next_nia
OP_BC => "110",
@ -440,6 +433,8 @@ begin
decoded_reg_o.reg(0) := not r.repeat;
end if;

v.e.spr_select := d_in.spr_info;

r_out.read1_enable <= decoded_reg_a.reg_valid and d_in.valid;
r_out.read1_reg <= decoded_reg_a.reg;
r_out.read2_enable <= decoded_reg_b.reg_valid and d_in.valid;
@ -496,6 +491,17 @@ begin
v.e.result_sel := "000"; -- select adder output
end if;
end if;
if op = OP_MFSPR then
if is_fast_spr(d_in.ispr1) = '1' then
v.e.result_sel := "000"; -- adder_result, effectively a_in
elsif d_in.spr_info.valid = '0' then
-- Privileged mfspr to invalid/unimplemented SPR numbers
-- writes the contents of RT back to RT (i.e. it's a no-op)
v.e.result_sel := "001"; -- logical_result
elsif d_in.spr_info.ispmu = '1' then
v.e.result_sel := "100"; -- pmuspr_result
end if;
end if;

-- See if any of the operands can get their value via the bypass path.
case gpr_a_bypass is

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save