mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-02 14:51:09 +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:
25
common.vhdl
25
common.vhdl
@@ -124,6 +124,23 @@ package common is
|
|||||||
end record;
|
end record;
|
||||||
constant xerc_init : xer_common_t := (others => '0');
|
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
|
-- FPSCR bit numbers
|
||||||
constant FPSCR_FX : integer := 63 - 32;
|
constant FPSCR_FX : integer := 63 - 32;
|
||||||
constant FPSCR_FEX : integer := 63 - 33;
|
constant FPSCR_FEX : integer := 63 - 33;
|
||||||
@@ -235,11 +252,13 @@ package common is
|
|||||||
decode: decode_rom_t;
|
decode: decode_rom_t;
|
||||||
br_pred: std_ulogic; -- Branch was predicted to be taken
|
br_pred: std_ulogic; -- Branch was predicted to be taken
|
||||||
big_endian: std_ulogic;
|
big_endian: std_ulogic;
|
||||||
|
spr_info : spr_id;
|
||||||
end record;
|
end record;
|
||||||
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
|
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
|
||||||
(valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
|
(valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
|
||||||
ispr1 => (others => '0'), ispr2 => (others => '0'), ispro => (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
|
type Decode1ToFetch1Type is record
|
||||||
redirect : std_ulogic;
|
redirect : std_ulogic;
|
||||||
@@ -299,6 +318,7 @@ package common is
|
|||||||
sub_select : std_ulogic_vector(2 downto 0); -- sub-result selection
|
sub_select : std_ulogic_vector(2 downto 0); -- sub-result selection
|
||||||
repeat : std_ulogic; -- set if instruction is cracked into two ops
|
repeat : std_ulogic; -- set if instruction is cracked into two ops
|
||||||
second : std_ulogic; -- set if this is the second op
|
second : std_ulogic; -- set if this is the second op
|
||||||
|
spr_select : spr_id;
|
||||||
end record;
|
end record;
|
||||||
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
||||||
(valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
|
(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'),
|
read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'),
|
||||||
cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'),
|
cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'),
|
||||||
result_sel => "000", sub_select => "000",
|
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
|
type MultiplyInputType is record
|
||||||
valid: std_ulogic;
|
valid: std_ulogic;
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ begin
|
|||||||
crs <= crs_updated;
|
crs <= crs_updated;
|
||||||
end if;
|
end if;
|
||||||
if w_in.write_xerc_enable = '1' then
|
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;
|
xerc <= xerc_updated;
|
||||||
end if;
|
end if;
|
||||||
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 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);
|
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
|
begin
|
||||||
decode1_0: process(clk)
|
decode1_0: process(clk)
|
||||||
begin
|
begin
|
||||||
@@ -586,6 +620,9 @@ begin
|
|||||||
majorop := unsigned(f_in.insn(31 downto 26));
|
majorop := unsigned(f_in.insn(31 downto 26));
|
||||||
v.decode := major_decode_rom_array(to_integer(majorop));
|
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
|
case to_integer(unsigned(majorop)) is
|
||||||
when 4 =>
|
when 4 =>
|
||||||
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
|
-- 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))));
|
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
|
-- 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.ispr1 := fast_spr_num(sprn);
|
||||||
v.ispro := 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_SHR => "010",
|
||||||
OP_EXTSWSLI => "010",
|
OP_EXTSWSLI => "010",
|
||||||
OP_MUL_L64 => "011", -- muldiv_result
|
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_MFSPR => "101", -- spr_result
|
||||||
OP_B => "110", -- next_nia
|
OP_B => "110", -- next_nia
|
||||||
OP_BC => "110",
|
OP_BC => "110",
|
||||||
@@ -440,6 +433,8 @@ begin
|
|||||||
decoded_reg_o.reg(0) := not r.repeat;
|
decoded_reg_o.reg(0) := not r.repeat;
|
||||||
end if;
|
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_enable <= decoded_reg_a.reg_valid and d_in.valid;
|
||||||
r_out.read1_reg <= decoded_reg_a.reg;
|
r_out.read1_reg <= decoded_reg_a.reg;
|
||||||
r_out.read2_enable <= decoded_reg_b.reg_valid and d_in.valid;
|
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
|
v.e.result_sel := "000"; -- select adder output
|
||||||
end if;
|
end if;
|
||||||
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.
|
-- See if any of the operands can get their value via the bypass path.
|
||||||
case gpr_a_bypass is
|
case gpr_a_bypass is
|
||||||
|
|||||||
957
execute1.vhdl
957
execute1.vhdl
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user