execute1: Move CR result to data path process

Also work out in decode2 whether the instruction sets the XER common
bits.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/269/head
Paul Mackerras 4 years ago
parent d6ac43251a
commit 4fd8d9509c

@ -243,6 +243,7 @@ package common is
output_carry: std_ulogic; output_carry: std_ulogic;
input_cr: std_ulogic; input_cr: std_ulogic;
output_cr: std_ulogic; output_cr: std_ulogic;
output_xer: std_ulogic;
is_32bit: std_ulogic; is_32bit: std_ulogic;
is_signed: std_ulogic; is_signed: std_ulogic;
insn: std_ulogic_vector(31 downto 0); insn: std_ulogic_vector(31 downto 0);
@ -261,7 +262,8 @@ package common is
(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,
write_reg_enable => '0', write_reg_enable => '0',
lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0', lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0',
invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0', invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0',
output_cr => '0', output_xer => '0',
is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0', is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0',
byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'), byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'),
read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'), read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'),

@ -208,22 +208,6 @@ architecture behaviour of decode2 is
end case; end case;
end; end;


-- For now, use "rc" in the decode table to decide whether oe exists.
-- This is not entirely correct architecturally: For mulhd and
-- mulhdu, the OE field is reserved. It remains to be seen what an
-- actual POWER9 does if we set it on those instructions, for now we
-- test that further down when assigning to the multiplier oe input.
--
function decode_oe (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is
begin
case t is
when RC =>
return insn_oe(insn_in);
when OTHERS =>
return '0';
end case;
end;

-- control signals that are derived from insn_type -- control signals that are derived from insn_type
type mux_select_array_t is array(insn_type_t) of std_ulogic_vector(2 downto 0); type mux_select_array_t is array(insn_type_t) of std_ulogic_vector(2 downto 0);


@ -277,6 +261,12 @@ architecture behaviour of decode2 is
OP_MFMSR => "100", OP_MFMSR => "100",
OP_MFCR => "101", OP_MFCR => "101",
OP_SETB => "110", OP_SETB => "110",
OP_CMP => "000", -- cr_result
OP_CMPRB => "001",
OP_CMPEQB => "010",
OP_CROP => "011",
OP_MCRXRX => "100",
OP_MTCRF => "101",
others => "000" others => "000"
); );


@ -393,6 +383,22 @@ begin
--v.e.input_cr := d_in.decode.input_cr; --v.e.input_cr := d_in.decode.input_cr;
v.e.output_cr := d_in.decode.output_cr; v.e.output_cr := d_in.decode.output_cr;


-- Work out whether XER common bits are set
v.e.output_xer := d_in.decode.output_carry;
case d_in.decode.insn_type is
when OP_ADD | OP_MUL_L64 | OP_DIV | OP_DIVE =>
-- OE field is valid in OP_ADD/OP_MUL_L64 with major opcode 31 only
if d_in.insn(31 downto 26) = "011111" and insn_oe(d_in.insn) = '1' then
v.e.oe := '1';
v.e.output_xer := '1';
end if;
when OP_MTSPR =>
if decode_spr_num(d_in.insn) = SPR_XER then
v.e.output_xer := '1';
end if;
when others =>
end case;

decoded_reg_a := decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, r_in.read1_data, d_in.ispr1, decoded_reg_a := decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, r_in.read1_data, d_in.ispr1,
d_in.nia); d_in.nia);
decoded_reg_b := decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, r_in.read2_data, d_in.ispr2); decoded_reg_b := decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, r_in.read2_data, d_in.ispr2);
@ -465,9 +471,6 @@ begin
v.e.write_reg := decoded_reg_o.reg; v.e.write_reg := decoded_reg_o.reg;
v.e.write_reg_enable := decoded_reg_o.reg_valid; v.e.write_reg_enable := decoded_reg_o.reg_valid;
v.e.rc := decode_rc(d_in.decode.rc, d_in.insn); v.e.rc := decode_rc(d_in.decode.rc, d_in.insn);
if not (d_in.decode.insn_type = OP_MUL_H32 or d_in.decode.insn_type = OP_MUL_H64) then
v.e.oe := decode_oe(d_in.decode.rc, d_in.insn);
end if;
v.e.xerc := c_in.read_xerc_data; v.e.xerc := c_in.read_xerc_data;
v.e.invert_a := d_in.decode.invert_a; v.e.invert_a := d_in.decode.invert_a;
v.e.addm1 := '0'; v.e.addm1 := '0';

@ -119,10 +119,11 @@ architecture behaviour of execute1 is
signal overflow_32 : std_ulogic; signal overflow_32 : std_ulogic;
signal overflow_64 : std_ulogic; signal overflow_64 : std_ulogic;


signal cmprb_result : std_ulogic_vector(3 downto 0);
signal cmpeqb_result : std_ulogic_vector(3 downto 0);
signal trapval : std_ulogic_vector(4 downto 0); signal trapval : std_ulogic_vector(4 downto 0);


signal write_cr_mask : std_ulogic_vector(7 downto 0);
signal write_cr_data : std_ulogic_vector(31 downto 0);

-- multiply signals -- multiply signals
signal x_to_multiply: MultiplyInputType; signal x_to_multiply: MultiplyInputType;
signal multiply_to_x: MultiplyOutputType; signal multiply_to_x: MultiplyOutputType;
@ -169,7 +170,6 @@ architecture behaviour of execute1 is
begin begin
e.xerc.ca32 := carry32; e.xerc.ca32 := carry32;
e.xerc.ca := carry; e.xerc.ca := carry;
e.write_xerc_enable := '1';
end; end;


procedure set_ov(e: inout Execute1ToWritebackType; procedure set_ov(e: inout Execute1ToWritebackType;
@ -181,7 +181,6 @@ architecture behaviour of execute1 is
if ov = '1' then if ov = '1' then
e.xerc.so := '1'; e.xerc.so := '1';
end if; end if;
e.write_xerc_enable := '1';
end; end;


function calc_ov(msb_a : std_ulogic; msb_b: std_ulogic; function calc_ov(msb_a : std_ulogic; msb_b: std_ulogic;
@ -360,7 +359,6 @@ begin
variable darn : std_ulogic_vector(63 downto 0); variable darn : std_ulogic_vector(63 downto 0);
variable setb_result : std_ulogic_vector(63 downto 0); variable setb_result : std_ulogic_vector(63 downto 0);
variable mfcr_result : std_ulogic_vector(63 downto 0); variable mfcr_result : std_ulogic_vector(63 downto 0);
variable crnum : crnum_t;
variable lo, hi : integer; variable lo, hi : integer;
variable l : std_ulogic; variable l : std_ulogic;
variable zerohi, zerolo : std_ulogic; variable zerohi, zerolo : std_ulogic;
@ -368,7 +366,16 @@ begin
variable a_lt : std_ulogic; variable a_lt : std_ulogic;
variable a_lt_lo : std_ulogic; variable a_lt_lo : std_ulogic;
variable a_lt_hi : std_ulogic; variable a_lt_hi : std_ulogic;
variable bfa : std_ulogic_vector(2 downto 0); variable newcrf : std_ulogic_vector(3 downto 0);
variable bf, bfa : std_ulogic_vector(2 downto 0);
variable crnum : crnum_t;
variable scrnum : crnum_t;
variable cr_operands : std_ulogic_vector(1 downto 0);
variable crresult : std_ulogic;
variable bt, ba, bb : std_ulogic_vector(4 downto 0);
variable btnum : integer range 0 to 3;
variable banum, bbnum : integer range 0 to 31;
variable j : integer;
begin begin
-- Main adder -- Main adder
if e_in.invert_a = '0' then if e_in.invert_a = '0' then
@ -591,24 +598,77 @@ begin
end if; end if;
end if; end if;


cmprb_result <= ppc_cmprb(a_in, b_in, insn_l(e_in.insn)); -- CR result mux
cmpeqb_result <= ppc_cmpeqb(a_in, b_in); bf := insn_bf(e_in.insn);
crnum := to_integer(unsigned(bf));
newcrf := (others => '0');
case current.sub_select is
when "000" =>
-- CMP and CMPL instructions
if e_in.is_signed = '1' then
newcrf := trapval(4 downto 2) & xerc_in.so;
else
newcrf := trapval(1 downto 0) & trapval(2) & xerc_in.so;
end if;
when "001" =>
newcrf := ppc_cmprb(a_in, b_in, insn_l(e_in.insn));
when "010" =>
newcrf := ppc_cmpeqb(a_in, b_in);
when "011" =>
if current.insn(1) = '1' then
-- CR logical instructions
j := (7 - crnum) * 4;
newcrf := cr_in(j + 3 downto j);
bt := insn_bt(e_in.insn);
ba := insn_ba(e_in.insn);
bb := insn_bb(e_in.insn);
btnum := 3 - to_integer(unsigned(bt(1 downto 0)));
banum := 31 - to_integer(unsigned(ba));
bbnum := 31 - to_integer(unsigned(bb));
-- Bits 6-9 of the instruction word give the truth table
-- of the requested logical operation
cr_operands := cr_in(banum) & cr_in(bbnum);
crresult := e_in.insn(6 + to_integer(unsigned(cr_operands)));
for i in 0 to 3 loop
if i = btnum then
newcrf(i) := crresult;
end if;
end loop;
else
-- MCRF
bfa := insn_bfa(e_in.insn);
scrnum := to_integer(unsigned(bfa));
j := (7 - scrnum) * 4;
newcrf := cr_in(j + 3 downto j);
end if;
when "100" =>
-- MCRXRX
newcrf := xerc_in.ov & xerc_in.ca & xerc_in.ov32 & xerc_in.ca32;
when others =>
end case;
if current.insn_type = OP_MTCRF then
if e_in.insn(20) = '0' then
-- mtcrf
write_cr_mask <= insn_fxm(e_in.insn);
else
-- mtocrf: We require one hot priority encoding here
crnum := fxm_to_num(insn_fxm(e_in.insn));
write_cr_mask <= num_to_fxm(crnum);
end if;
write_cr_data <= c_in(31 downto 0);
else
write_cr_mask <= num_to_fxm(crnum);
write_cr_data <= newcrf & newcrf & newcrf & newcrf &
newcrf & newcrf & newcrf & newcrf;
end if;

end process; end process;


execute1_1: process(all) execute1_1: process(all)
variable v : reg_type; variable v : reg_type;
variable newcrf : std_ulogic_vector(3 downto 0);
variable crnum : crnum_t;
variable scrnum : crnum_t;
variable lo, hi : integer; variable lo, hi : integer;
variable sh, mb, me : std_ulogic_vector(5 downto 0); variable sh, mb, me : std_ulogic_vector(5 downto 0);
variable bo, bi : std_ulogic_vector(4 downto 0); variable bo, bi : std_ulogic_vector(4 downto 0);
variable bf, bfa : std_ulogic_vector(2 downto 0);
variable cr_op : std_ulogic_vector(9 downto 0);
variable cr_operands : std_ulogic_vector(1 downto 0);
variable bt, ba, bb : std_ulogic_vector(4 downto 0);
variable btnum, banum, bbnum : integer range 0 to 31;
variable crresult : std_ulogic;
variable overflow : std_ulogic; variable overflow : std_ulogic;
variable lv : Execute1ToLoadstore1Type; variable lv : Execute1ToLoadstore1Type;
variable irq_valid : std_ulogic; variable irq_valid : std_ulogic;
@ -625,7 +685,6 @@ begin
variable f : Execute1ToFetch1Type; variable f : Execute1ToFetch1Type;
variable fv : Execute1ToFPUType; variable fv : Execute1ToFPUType;
begin begin
newcrf := (others => '0');
is_branch := '0'; is_branch := '0';
is_direct_branch := '0'; is_direct_branch := '0';
taken_branch := '0'; taken_branch := '0';
@ -800,27 +859,12 @@ begin
else else
v.e.xerc.ov := carry_64; v.e.xerc.ov := carry_64;
v.e.xerc.ov32 := carry_32; v.e.xerc.ov32 := carry_32;
v.e.write_xerc_enable := '1';
end if; end if;
end if; end if;
if e_in.oe = '1' then if e_in.oe = '1' then
set_ov(v.e, overflow_64, overflow_32); set_ov(v.e, overflow_64, overflow_32);
end if; end if;
when OP_CMP => when OP_CMP =>
-- CMP and CMPL instructions
if e_in.is_signed = '1' then
newcrf := trapval(4 downto 2) & xerc_in.so;
else
newcrf := trapval(1 downto 0) & trapval(2) & xerc_in.so;
end if;
bf := insn_bf(e_in.insn);
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
for i in 0 to 7 loop
lo := i*4;
hi := lo + 3;
v.e.write_cr_data(hi downto lo) := newcrf;
end loop;
when OP_TRAP => when OP_TRAP =>
-- trap instructions (tw, twi, td, tdi) -- trap instructions (tw, twi, td, tdi)
v.vector := 16#700#; v.vector := 16#700#;
@ -833,19 +877,7 @@ begin
end if; end if;
when OP_ADDG6S => when OP_ADDG6S =>
when OP_CMPRB => when OP_CMPRB =>
newcrf := cmprb_result;
bf := insn_bf(e_in.insn);
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
newcrf & newcrf & newcrf & newcrf;
when OP_CMPEQB => when OP_CMPEQB =>
newcrf := cmpeqb_result;
bf := insn_bf(e_in.insn);
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
newcrf & newcrf & newcrf & newcrf;
when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS | when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS |
OP_BPERM | OP_BCD => OP_BPERM | OP_BCD =>


@ -912,52 +944,7 @@ begin
v.busy := '1'; v.busy := '1';
when OP_ISEL => when OP_ISEL =>
when OP_CROP => when OP_CROP =>
cr_op := insn_cr(e_in.insn);
if cr_op(0) = '0' then -- MCRF
bf := insn_bf(e_in.insn);
bfa := insn_bfa(e_in.insn);
crnum := to_integer(unsigned(bf));
scrnum := to_integer(unsigned(bfa));
v.e.write_cr_mask := num_to_fxm(crnum);
for i in 0 to 7 loop
lo := (7-i)*4;
hi := lo + 3;
if i = scrnum then
newcrf := cr_in(hi downto lo);
end if;
end loop;
for i in 0 to 7 loop
lo := i*4;
hi := lo + 3;
v.e.write_cr_data(hi downto lo) := newcrf;
end loop;
else
bt := insn_bt(e_in.insn);
ba := insn_ba(e_in.insn);
bb := insn_bb(e_in.insn);
btnum := 31 - to_integer(unsigned(bt));
banum := 31 - to_integer(unsigned(ba));
bbnum := 31 - to_integer(unsigned(bb));
-- Bits 5-8 of cr_op give the truth table of the requested
-- logical operation
cr_operands := cr_in(banum) & cr_in(bbnum);
crresult := cr_op(5 + to_integer(unsigned(cr_operands)));
v.e.write_cr_mask := num_to_fxm((31-btnum) / 4);
for i in 0 to 31 loop
if i = btnum then
v.e.write_cr_data(i) := crresult;
else
v.e.write_cr_data(i) := cr_in(i);
end if;
end loop;
end if;
when OP_MCRXRX => when OP_MCRXRX =>
newcrf := xerc_in.ov & xerc_in.ca & xerc_in.ov32 & xerc_in.ca32;
bf := insn_bf(e_in.insn);
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
newcrf & newcrf & newcrf & newcrf;
when OP_DARN => when OP_DARN =>
when OP_MFMSR => when OP_MFMSR =>
when OP_MFSPR => when OP_MFSPR =>
@ -1007,15 +994,6 @@ begin


when OP_MFCR => when OP_MFCR =>
when OP_MTCRF => when OP_MTCRF =>
if e_in.insn(20) = '0' then
-- mtcrf
v.e.write_cr_mask := insn_fxm(e_in.insn);
else
-- mtocrf: We require one hot priority encoding here
crnum := fxm_to_num(insn_fxm(e_in.insn));
v.e.write_cr_mask := num_to_fxm(crnum);
end if;
v.e.write_cr_data := c_in(31 downto 0);
when OP_MTMSRD => when OP_MTMSRD =>
if e_in.insn(16) = '1' then if e_in.insn(16) = '1' then
-- just update EE and RI -- just update EE and RI
@ -1050,7 +1028,6 @@ begin
v.e.xerc.ca := c_in(63-34); v.e.xerc.ca := c_in(63-34);
v.e.xerc.ov32 := c_in(63-44); v.e.xerc.ov32 := c_in(63-44);
v.e.xerc.ca32 := c_in(63-45); v.e.xerc.ca32 := c_in(63-45);
v.e.write_xerc_enable := '1';
end if; end if;
else else
-- slow spr -- slow spr
@ -1170,7 +1147,6 @@ begin
v.mul_finish := '1'; v.mul_finish := '1';
v.busy := '1'; v.busy := '1';
else else
v.e.write_xerc_enable := current.oe;
-- We must test oe because the RC update code in writeback -- We must test oe because the RC update code in writeback
-- will use the xerc value to set CR0:SO so we must not clobber -- will use the xerc value to set CR0:SO so we must not clobber
-- xerc if OE wasn't set. -- xerc if OE wasn't set.
@ -1190,7 +1166,6 @@ begin
end if; end if;
elsif r.mul_finish = '1' then elsif r.mul_finish = '1' then
hold_wr_data := '1'; hold_wr_data := '1';
v.e.write_xerc_enable := current.oe;
v.e.xerc.ov := multiply_to_x.overflow; v.e.xerc.ov := multiply_to_x.overflow;
v.e.xerc.ov32 := multiply_to_x.overflow; v.e.xerc.ov32 := multiply_to_x.overflow;
if multiply_to_x.overflow = '1' then if multiply_to_x.overflow = '1' then
@ -1268,8 +1243,11 @@ begin
end if; end if;
v.e.write_reg := current.write_reg; v.e.write_reg := current.write_reg;
v.e.write_enable := current.write_reg_enable and v.e.valid and not exception; v.e.write_enable := current.write_reg_enable and v.e.valid and not exception;
v.e.write_cr_enable := current.output_cr and v.e.valid and not exception;
v.e.rc := current.rc and v.e.valid and not exception; v.e.rc := current.rc and v.e.valid and not exception;
v.e.write_cr_data := write_cr_data;
v.e.write_cr_mask := write_cr_mask;
v.e.write_cr_enable := current.output_cr and v.e.valid and not exception;
v.e.write_xerc_enable := current.output_xer and v.e.valid and not exception;


bypass_data.tag.valid <= current.instr_tag.valid and current.write_reg_enable and v.e.valid; bypass_data.tag.valid <= current.instr_tag.valid and current.write_reg_enable and v.e.valid;
bypass_data.tag.tag <= current.instr_tag.tag; bypass_data.tag.tag <= current.instr_tag.tag;

Loading…
Cancel
Save