decode1: Avoid overriding fields of v.decode in decode1

In the cases where we need to override the values from the decode ROMs,
we now do that overriding after the clock edge (eating into decode2's
cycle) rather than before.  This helps timing a little.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/244/head
Paul Mackerras 4 years ago
parent da4be71bd3
commit 6a80825e70

@ -31,6 +31,21 @@ architecture behaviour of decode1 is
signal r, rin : Decode1ToDecode2Type; signal r, rin : Decode1ToDecode2Type;
signal s : Decode1ToDecode2Type; signal s : Decode1ToDecode2Type;


constant illegal_inst : decode_rom_t :=
(NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');

type reg_internal_t is record
override : std_ulogic;
override_decode: decode_rom_t;
override_unit: std_ulogic;
force_single: std_ulogic;
end record;
constant reg_internal_t_init : reg_internal_t :=
(override => '0', override_decode => illegal_inst, override_unit => '0', force_single => '0');

signal ri, ri_in : reg_internal_t;
signal si : reg_internal_t;

subtype major_opcode_t is unsigned(5 downto 0); subtype major_opcode_t is unsigned(5 downto 0);
type major_rom_array_t is array(0 to 63) of decode_rom_t; type major_rom_array_t is array(0 to 63) of decode_rom_t;
type minor_valid_array_t is array(0 to 1023) of std_ulogic; type minor_valid_array_t is array(0 to 1023) of std_ulogic;
@ -41,9 +56,6 @@ architecture behaviour of decode1 is
type op_31_subop_array_t is array(0 to 1023) of decode_rom_t; type op_31_subop_array_t is array(0 to 1023) of decode_rom_t;
type minor_rom_array_2_t is array(0 to 3) of decode_rom_t; type minor_rom_array_2_t is array(0 to 3) of decode_rom_t;


constant illegal_inst : decode_rom_t :=
(ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1');

constant major_decode_rom_array : major_rom_array_t := ( constant major_decode_rom_array : major_rom_array_t := (
-- unit internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl -- unit internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl
-- op in out A out in out len ext pipe -- op in out A out in out len ext pipe
@ -107,25 +119,21 @@ architecture behaviour of decode1 is


-- indexed by bits 10..1 of instruction word -- indexed by bits 10..1 of instruction word
constant decode_op_19_valid : minor_valid_array_t := ( constant decode_op_19_valid : minor_valid_array_t := (
-- addpcis, 5 upper bits are part of constant 2#0001000000# to 2#0001011111# => '1', -- addpcis, 5 upper bits are part of constant
2#0000000010# => '1', 2#0000100010# => '1', 2#0001000010# => '1', 2#0001100010# => '1', 2#0010000010# => '1', 2#0010100010# => '1', 2#0011000010# => '1', 2#0011100010# => '1',
2#0100000010# => '1', 2#0100100010# => '1', 2#0101000010# => '1', 2#0101100010# => '1', 2#0110000010# => '1', 2#0110100010# => '1', 2#0111000010# => '1', 2#0111100010# => '1',
2#1000000010# => '1', 2#1000100010# => '1', 2#1001000010# => '1', 2#1001100010# => '1', 2#1010000010# => '1', 2#1010100010# => '1', 2#1011000010# => '1', 2#1011100010# => '1',
2#1100000010# => '1', 2#1100100010# => '1', 2#1101000010# => '1', 2#1101100010# => '1', 2#1110000010# => '1', 2#1110100010# => '1', 2#1111000010# => '1', 2#1111100010# => '1',
2#1000010000# => '1', -- bcctr 2#1000010000# => '1', -- bcctr
2#0000010000# => '1', -- bclr 2#1000000000# => '1', -- bclr
2#1000110000# => '1', -- bctar 2#1000010001# => '1', -- bctar
2#0100000001# => '1', -- crand 2#0000101000# => '1', -- crand
2#0010000001# => '1', -- crandc 2#0000100100# => '1', -- crandc
2#0100100001# => '1', -- creqv 2#0000101001# => '1', -- creqv
2#0011100001# => '1', -- crnand 2#0000100111# => '1', -- crnand
2#0000100001# => '1', -- crnor 2#0000100001# => '1', -- crnor
2#0111000001# => '1', -- cror 2#0000101110# => '1', -- cror
2#0110100001# => '1', -- crorc 2#0000101101# => '1', -- crorc
2#0011000001# => '1', -- crxor 2#0000100110# => '1', -- crxor
2#0010010110# => '1', -- isync 2#1011000100# => '1', -- isync
2#0000000000# => '1', -- mcrf 2#0000000000# => '1', -- mcrf
2#0000010010# => '1', -- rfid 2#1001000000# => '1', -- rfid
others => '0' others => '0'
); );


@ -401,19 +409,24 @@ begin
if rst = '1' then if rst = '1' then
r <= Decode1ToDecode2Init; r <= Decode1ToDecode2Init;
s <= Decode1ToDecode2Init; s <= Decode1ToDecode2Init;
ri <= reg_internal_t_init;
si <= reg_internal_t_init;
elsif flush_in = '1' then elsif flush_in = '1' then
r.valid <= '0'; r.valid <= '0';
s.valid <= '0'; s.valid <= '0';
elsif s.valid = '1' then elsif s.valid = '1' then
if stall_in = '0' then if stall_in = '0' then
r <= s; r <= s;
ri <= si;
s.valid <= '0'; s.valid <= '0';
end if; end if;
else else
s <= rin; s <= rin;
si <= ri_in;
s.valid <= rin.valid and r.valid and stall_in; s.valid <= rin.valid and r.valid and stall_in;
if r.valid = '0' or stall_in = '0' then if r.valid = '0' or stall_in = '0' then
r <= rin; r <= rin;
ri <= ri_in;
end if; end if;
end if; end if;
end if; end if;
@ -422,6 +435,7 @@ begin


decode1_1: process(all) decode1_1: process(all)
variable v : Decode1ToDecode2Type; variable v : Decode1ToDecode2Type;
variable vi : reg_internal_t;
variable f : Decode1ToFetch1Type; variable f : Decode1ToFetch1Type;
variable majorop : major_opcode_t; variable majorop : major_opcode_t;
variable minor4op : std_ulogic_vector(10 downto 0); variable minor4op : std_ulogic_vector(10 downto 0);
@ -432,37 +446,30 @@ begin
variable br_offset : signed(23 downto 0); variable br_offset : signed(23 downto 0);
begin begin
v := Decode1ToDecode2Init; v := Decode1ToDecode2Init;
vi := reg_internal_t_init;


v.valid := f_in.valid; v.valid := f_in.valid;
v.nia := f_in.nia; v.nia := f_in.nia;
v.insn := f_in.insn; v.insn := f_in.insn;
v.stop_mark := f_in.stop_mark; v.stop_mark := f_in.stop_mark;
v.ispr1 := (others => '0');
v.ispr2 := (others => '0');


if f_in.valid = '1' then if f_in.valid = '1' then
report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia); report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia);
end if; end if;


br_offset := (others => '0');

majorop := unsigned(f_in.insn(31 downto 26)); majorop := unsigned(f_in.insn(31 downto 26));
if f_in.fetch_failed = '1' then v.decode := major_decode_rom_array(to_integer(majorop));
v.valid := '1';
-- Only send down a single OP_FETCH_FAILED
if r.decode.insn_type = OP_FETCH_FAILED then
v.valid := '0';
end if;
v.decode := fetch_fail_inst;


elsif majorop = "000100" then case to_integer(unsigned(majorop)) is
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*)
minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6); minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6);
if decode_op_4_valid(to_integer(unsigned(minor4op))) = '1' then vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op)));
v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0)))); v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0))));
else
v.decode := illegal_inst;
end if;


elsif majorop = "011111" then when 31 =>
-- major opcode 31, lots of things -- major opcode 31, lots of things
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))));


@ -474,32 +481,35 @@ begin
-- mfspr or mtspr -- mfspr or mtspr
-- 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'; vi.force_single := '1';
-- send MMU-related SPRs to loadstore1 -- send MMU-related SPRs to loadstore1
case sprn is case sprn is
when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PRTBL => when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PRTBL =>
v.decode.unit := LDST; vi.override_decode.unit := LDST;
vi.override_unit := '1';
when others => when others =>
end case; end case;
end if; end if;
end if; end if;


elsif majorop = "010000" then when 16 =>
-- CTR may be needed as input to bc -- CTR may be needed as input to bc
v.decode := major_decode_rom_array(to_integer(majorop));
if f_in.insn(23) = '0' then if f_in.insn(23) = '0' then
v.ispr1 := fast_spr_num(SPR_CTR); v.ispr1 := fast_spr_num(SPR_CTR);
end if; end if;
-- Predict backward branches as taken, forward as untaken
v.br_pred := f_in.insn(15);
br_offset := resize(signed(f_in.insn(15 downto 2)), 24);


elsif majorop = "010011" then when 18 =>
if decode_op_19_valid(to_integer(unsigned(f_in.insn(10 downto 1)))) = '0' then -- Unconditional branches are always taken
report "op 19 illegal subcode"; v.br_pred := '1';
v.decode := illegal_inst; br_offset := signed(f_in.insn(25 downto 2));
else
op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2); when 19 =>
v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits))); vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6))));
report "op 19 sub " & to_hstring(op_19_bits); op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2);
end if; v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits)));


-- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path -- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path
if f_in.insn(2) = '0' then if f_in.insn(2) = '0' then
@ -523,36 +533,39 @@ begin
v.ispr2 := fast_spr_num(SPR_SRR0); v.ispr2 := fast_spr_num(SPR_SRR0);
end if; end if;


elsif majorop = "011110" then when 30 =>
v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1))));


elsif majorop = "111010" then when 48 =>
-- ori, special-case the standard NOP
if std_match(f_in.insn, "01100000000000000000000000000000") then
report "PPC_nop";
vi.override := '1';
vi.override_decode := nop_instr;
end if;

when 58 =>
v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0)))); v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0))));


elsif majorop = "111110" then when 62 =>
v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0)))); v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0))));


elsif std_match(f_in.insn, "01100000000000000000000000000000") then when others =>
report "PPC_nop"; end case;
v.decode := nop_instr;


else if f_in.fetch_failed = '1' then
v.decode := major_decode_rom_array(to_integer(majorop)); v.valid := '1';
vi.override := '1';
vi.override_decode := fetch_fail_inst;
-- Only send down a single OP_FETCH_FAILED
if ri.override = '1' and ri.override_decode.insn_type = OP_FETCH_FAILED then
v.valid := '0';
end if;
end if; end if;


-- Branch predictor -- Branch predictor
-- Note bclr, bcctr and bctar are predicted not taken as we have no -- Note bclr, bcctr and bctar are predicted not taken as we have no
-- count cache or link stack. -- count cache or link stack.
br_offset := (others => '0');
if majorop = 18 then
-- Unconditional branches are always taken
v.br_pred := '1';
br_offset := signed(f_in.insn(25 downto 2));
elsif majorop = 16 then
-- Predict backward branches as taken, forward as untaken
v.br_pred := f_in.insn(15);
br_offset := resize(signed(f_in.insn(15 downto 2)), 24);
end if;
br_nia := f_in.nia(63 downto 2); br_nia := f_in.nia(63 downto 2);
if f_in.insn(1) = '1' then if f_in.insn(1) = '1' then
br_nia := (others => '0'); br_nia := (others => '0');
@ -563,9 +576,18 @@ begin


-- Update registers -- Update registers
rin <= v; rin <= v;
ri_in <= vi;


-- Update outputs -- Update outputs
d_out <= r; d_out <= r;
if ri.override = '1' then
d_out.decode <= ri.override_decode;
elsif ri.override_unit = '1' then
d_out.decode.unit <= ri.override_decode.unit;
end if;
if ri.force_single = '1' then
d_out.decode.sgl_pipe <= '1';
end if;
f_out <= f; f_out <= f;
flush_out <= f.redirect; flush_out <= f.redirect;
end process; end process;

@ -403,9 +403,6 @@ begin
end if; end if;


v.e.valid := control_valid_out; v.e.valid := control_valid_out;
if d_in.decode.unit = NONE then
v.e.insn_type := OP_ILLEGAL;
end if;


if rst = '1' or flush_in = '1' then if rst = '1' or flush_in = '1' then
v.e := Decode2ToExecute1Init; v.e := Decode2ToExecute1Init;

@ -1044,6 +1044,8 @@ begin
-- instruction for other units, i.e. LDST -- instruction for other units, i.e. LDST
if e_in.unit = LDST then if e_in.unit = LDST then
lv.valid := '1'; lv.valid := '1';
elsif e_in.unit = NONE then
illegal := '1';
end if; end if;


elsif r.f.redirect = '1' then elsif r.f.redirect = '1' then

Loading…
Cancel
Save