mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-04 04:20:09 +00:00
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>
This commit is contained in:
@@ -243,6 +243,7 @@ package common is
|
||||
output_carry: std_ulogic;
|
||||
input_cr: std_ulogic;
|
||||
output_cr: std_ulogic;
|
||||
output_xer: std_ulogic;
|
||||
is_32bit: std_ulogic;
|
||||
is_signed: std_ulogic;
|
||||
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,
|
||||
write_reg_enable => '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',
|
||||
byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'),
|
||||
read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'),
|
||||
|
||||
41
decode2.vhdl
41
decode2.vhdl
@@ -208,22 +208,6 @@ architecture behaviour of decode2 is
|
||||
end case;
|
||||
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
|
||||
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_MFCR => "101",
|
||||
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"
|
||||
);
|
||||
|
||||
@@ -393,6 +383,22 @@ begin
|
||||
--v.e.input_cr := d_in.decode.input_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,
|
||||
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);
|
||||
@@ -465,9 +471,6 @@ begin
|
||||
v.e.write_reg := decoded_reg_o.reg;
|
||||
v.e.write_reg_enable := decoded_reg_o.reg_valid;
|
||||
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.invert_a := d_in.decode.invert_a;
|
||||
v.e.addm1 := '0';
|
||||
|
||||
186
execute1.vhdl
186
execute1.vhdl
@@ -119,10 +119,11 @@ architecture behaviour of execute1 is
|
||||
signal overflow_32 : 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 write_cr_mask : std_ulogic_vector(7 downto 0);
|
||||
signal write_cr_data : std_ulogic_vector(31 downto 0);
|
||||
|
||||
-- multiply signals
|
||||
signal x_to_multiply: MultiplyInputType;
|
||||
signal multiply_to_x: MultiplyOutputType;
|
||||
@@ -169,7 +170,6 @@ architecture behaviour of execute1 is
|
||||
begin
|
||||
e.xerc.ca32 := carry32;
|
||||
e.xerc.ca := carry;
|
||||
e.write_xerc_enable := '1';
|
||||
end;
|
||||
|
||||
procedure set_ov(e: inout Execute1ToWritebackType;
|
||||
@@ -181,7 +181,6 @@ architecture behaviour of execute1 is
|
||||
if ov = '1' then
|
||||
e.xerc.so := '1';
|
||||
end if;
|
||||
e.write_xerc_enable := '1';
|
||||
end;
|
||||
|
||||
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 setb_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 l : std_ulogic;
|
||||
variable zerohi, zerolo : std_ulogic;
|
||||
@@ -368,7 +366,16 @@ begin
|
||||
variable a_lt : std_ulogic;
|
||||
variable a_lt_lo : 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
|
||||
-- Main adder
|
||||
if e_in.invert_a = '0' then
|
||||
@@ -591,24 +598,77 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
|
||||
cmprb_result <= ppc_cmprb(a_in, b_in, insn_l(e_in.insn));
|
||||
cmpeqb_result <= ppc_cmpeqb(a_in, b_in);
|
||||
-- CR result mux
|
||||
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;
|
||||
|
||||
execute1_1: process(all)
|
||||
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 sh, mb, me : std_ulogic_vector(5 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 lv : Execute1ToLoadstore1Type;
|
||||
variable irq_valid : std_ulogic;
|
||||
@@ -625,7 +685,6 @@ begin
|
||||
variable f : Execute1ToFetch1Type;
|
||||
variable fv : Execute1ToFPUType;
|
||||
begin
|
||||
newcrf := (others => '0');
|
||||
is_branch := '0';
|
||||
is_direct_branch := '0';
|
||||
taken_branch := '0';
|
||||
@@ -800,27 +859,12 @@ begin
|
||||
else
|
||||
v.e.xerc.ov := carry_64;
|
||||
v.e.xerc.ov32 := carry_32;
|
||||
v.e.write_xerc_enable := '1';
|
||||
end if;
|
||||
end if;
|
||||
if e_in.oe = '1' then
|
||||
set_ov(v.e, overflow_64, overflow_32);
|
||||
end if;
|
||||
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 =>
|
||||
-- trap instructions (tw, twi, td, tdi)
|
||||
v.vector := 16#700#;
|
||||
@@ -833,19 +877,7 @@ begin
|
||||
end if;
|
||||
when OP_ADDG6S =>
|
||||
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 =>
|
||||
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 |
|
||||
OP_BPERM | OP_BCD =>
|
||||
|
||||
@@ -911,53 +943,8 @@ begin
|
||||
v.cntz_in_progress := '1';
|
||||
v.busy := '1';
|
||||
when OP_ISEL =>
|
||||
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_CROP =>
|
||||
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_MFMSR =>
|
||||
when OP_MFSPR =>
|
||||
@@ -1007,15 +994,6 @@ begin
|
||||
|
||||
when OP_MFCR =>
|
||||
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 =>
|
||||
if e_in.insn(16) = '1' then
|
||||
-- just update EE and RI
|
||||
@@ -1050,7 +1028,6 @@ begin
|
||||
v.e.xerc.ca := c_in(63-34);
|
||||
v.e.xerc.ov32 := c_in(63-44);
|
||||
v.e.xerc.ca32 := c_in(63-45);
|
||||
v.e.write_xerc_enable := '1';
|
||||
end if;
|
||||
else
|
||||
-- slow spr
|
||||
@@ -1170,7 +1147,6 @@ begin
|
||||
v.mul_finish := '1';
|
||||
v.busy := '1';
|
||||
else
|
||||
v.e.write_xerc_enable := current.oe;
|
||||
-- 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
|
||||
-- xerc if OE wasn't set.
|
||||
@@ -1190,7 +1166,6 @@ begin
|
||||
end if;
|
||||
elsif r.mul_finish = '1' then
|
||||
hold_wr_data := '1';
|
||||
v.e.write_xerc_enable := current.oe;
|
||||
v.e.xerc.ov := multiply_to_x.overflow;
|
||||
v.e.xerc.ov32 := multiply_to_x.overflow;
|
||||
if multiply_to_x.overflow = '1' then
|
||||
@@ -1268,8 +1243,11 @@ begin
|
||||
end if;
|
||||
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_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.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.tag <= current.instr_tag.tag;
|
||||
|
||||
Reference in New Issue
Block a user