mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
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>
This commit is contained in:
parent
204fedc63f
commit
813e2317bf
25
common.vhdl
25
common.vhdl
@ -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;
|
||||
|
||||
38
decode1.vhdl
38
decode1.vhdl
@ -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);
|
||||
|
||||
|
||||
20
decode2.vhdl
20
decode2.vhdl
@ -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
|
||||
|
||||
957
execute1.vhdl
957
execute1.vhdl
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user