diff --git a/execute1.vhdl b/execute1.vhdl index 702744e..002bdac 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -11,361 +11,361 @@ use work.insn_helpers.all; use work.ppc_fx_insns.all; entity execute1 is - generic ( - SIM : boolean := false + generic ( + SIM : boolean := false ); - port ( - clk : in std_logic; + port ( + clk : in std_logic; - -- asynchronous - flush_out : out std_ulogic; + -- asynchronous + flush_out : out std_ulogic; - e_in : in Decode2ToExecute1Type; + e_in : in Decode2ToExecute1Type; - -- asynchronous - f_out : out Execute1ToFetch1Type; + -- asynchronous + f_out : out Execute1ToFetch1Type; - e_out : out Execute1ToWritebackType; + e_out : out Execute1ToWritebackType; - terminate_out : out std_ulogic + terminate_out : out std_ulogic ); end entity execute1; architecture behaviour of execute1 is - type reg_type is record - --f : Execute1ToFetch1Type; - e : Execute1ToWritebackType; - end record; + type reg_type is record + --f : Execute1ToFetch1Type; + e : Execute1ToWritebackType; + end record; - signal r, rin : reg_type; + signal r, rin : reg_type; - signal ctrl: ctrl_t := (carry => '0', others => (others => '0')); - signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0')); + signal ctrl: ctrl_t := (carry => '0', others => (others => '0')); + signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0')); - signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; - signal rotator_result: std_ulogic_vector(63 downto 0); - signal rotator_carry: std_ulogic; - signal logical_result: std_ulogic_vector(63 downto 0); - signal countzero_result: std_ulogic_vector(63 downto 0); + signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; + signal rotator_result: std_ulogic_vector(63 downto 0); + signal rotator_carry: std_ulogic; + signal logical_result: std_ulogic_vector(63 downto 0); + signal countzero_result: std_ulogic_vector(63 downto 0); - function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is - begin - case carry_sel is - when ZERO => - return '0'; - when CA => - return ca_in; - when ONE => - return '1'; - end case; - end; + function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is + begin + case carry_sel is + when ZERO => + return '0'; + when CA => + return ca_in; + when ONE => + return '1'; + end case; + end; begin - rotator_0: entity work.rotator - port map ( - rs => e_in.read_data3, - ra => e_in.read_data1, - shift => e_in.read_data2(6 downto 0), - insn => e_in.insn, - is_32bit => e_in.is_32bit, - right_shift => right_shift, - arith => e_in.is_signed, - clear_left => rot_clear_left, - clear_right => rot_clear_right, - result => rotator_result, - carry_out => rotator_carry - ); + rotator_0: entity work.rotator + port map ( + rs => e_in.read_data3, + ra => e_in.read_data1, + shift => e_in.read_data2(6 downto 0), + insn => e_in.insn, + is_32bit => e_in.is_32bit, + right_shift => right_shift, + arith => e_in.is_signed, + clear_left => rot_clear_left, + clear_right => rot_clear_right, + result => rotator_result, + carry_out => rotator_carry + ); - logical_0: entity work.logical - port map ( - rs => e_in.read_data3, - rb => e_in.read_data2, - op => e_in.insn_type, - invert_in => e_in.invert_a, - invert_out => e_in.invert_out, - result => logical_result - ); + logical_0: entity work.logical + port map ( + rs => e_in.read_data3, + rb => e_in.read_data2, + op => e_in.insn_type, + invert_in => e_in.invert_a, + invert_out => e_in.invert_out, + result => logical_result + ); - countzero_0: entity work.zero_counter - port map ( - rs => e_in.read_data3, - count_right => e_in.insn(10), - is_32bit => e_in.is_32bit, - result => countzero_result - ); + countzero_0: entity work.zero_counter + port map ( + rs => e_in.read_data3, + count_right => e_in.insn(10), + is_32bit => e_in.is_32bit, + result => countzero_result + ); - execute1_0: process(clk) - begin - if rising_edge(clk) then - r <= rin; - ctrl <= ctrl_tmp; - end if; - end process; + execute1_0: process(clk) + begin + if rising_edge(clk) then + r <= rin; + ctrl <= ctrl_tmp; + end if; + end process; - execute1_1: process(all) - variable v : reg_type; - variable a_inv : std_ulogic_vector(63 downto 0); - variable result : std_ulogic_vector(63 downto 0); - variable newcrf : std_ulogic_vector(3 downto 0); - variable result_with_carry : std_ulogic_vector(64 downto 0); - variable result_en : integer; - variable crnum : integer; - variable scrnum : integer; - variable lo, hi : integer; - variable sh, mb, me : std_ulogic_vector(5 downto 0); - variable sh32, mb32, me32 : 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 l : std_ulogic; - begin - result := (others => '0'); - result_with_carry := (others => '0'); - result_en := 0; - newcrf := (others => '0'); + execute1_1: process(all) + variable v : reg_type; + variable a_inv : std_ulogic_vector(63 downto 0); + variable result : std_ulogic_vector(63 downto 0); + variable newcrf : std_ulogic_vector(3 downto 0); + variable result_with_carry : std_ulogic_vector(64 downto 0); + variable result_en : integer; + variable crnum : integer; + variable scrnum : integer; + variable lo, hi : integer; + variable sh, mb, me : std_ulogic_vector(5 downto 0); + variable sh32, mb32, me32 : 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 l : std_ulogic; + begin + result := (others => '0'); + result_with_carry := (others => '0'); + result_en := 0; + newcrf := (others => '0'); - v := r; - v.e := Execute1ToWritebackInit; - --v.f := Execute1ToFetch1TypeInit; + v := r; + v.e := Execute1ToWritebackInit; + --v.f := Execute1ToFetch1TypeInit; - ctrl_tmp <= ctrl; - -- FIXME: run at 512MHz not core freq - ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); + ctrl_tmp <= ctrl; + -- FIXME: run at 512MHz not core freq + ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); - terminate_out <= '0'; - f_out <= Execute1ToFetch1TypeInit; + terminate_out <= '0'; + f_out <= Execute1ToFetch1TypeInit; - -- rotator control signals - right_shift <= '1' when e_in.insn_type = OP_SHR else '0'; - rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0'; - rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; + -- rotator control signals + right_shift <= '1' when e_in.insn_type = OP_SHR else '0'; + rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0'; + rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; - if e_in.valid = '1' then + if e_in.valid = '1' then - v.e.valid := '1'; - v.e.write_reg := e_in.write_reg; - v.e.write_len := x"8"; - v.e.sign_extend := '0'; + v.e.valid := '1'; + v.e.write_reg := e_in.write_reg; + v.e.write_len := x"8"; + v.e.sign_extend := '0'; - case_0: case e_in.insn_type is + case_0: case e_in.insn_type is - when OP_ILLEGAL => - terminate_out <= '1'; - report "illegal"; - when OP_NOP => - -- Do nothing - when OP_ADD => - if e_in.invert_a = '0' then - a_inv := e_in.read_data1; - else - a_inv := not e_in.read_data1; - end if; - result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry)); - result := result_with_carry(63 downto 0); - if e_in.output_carry then - ctrl_tmp.carry <= result_with_carry(64); - end if; - result_en := 1; - when OP_AND | OP_OR | OP_XOR => - result := logical_result; - result_en := 1; - when OP_B => - f_out.redirect <= '1'; - if (insn_aa(e_in.insn)) then - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); - else - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); - end if; - when OP_BC => - bo := insn_bo(e_in.insn); - bi := insn_bi(e_in.insn); - if bo(4-2) = '0' then - ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); - end if; - if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then - f_out.redirect <= '1'; - if (insn_aa(e_in.insn)) then - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); - else - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); - end if; - end if; - when OP_BCREG => - -- bits 10 and 6 distinguish between bclr, bcctr and bctar - bo := insn_bo(e_in.insn); - bi := insn_bi(e_in.insn); - if bo(4-2) = '0' and e_in.insn(10) = '0' then - ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); - end if; - if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then - f_out.redirect <= '1'; - if e_in.insn(10) = '0' then - f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00"; - else - f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00"; - end if; - end if; - when OP_CMPB => - result := ppc_cmpb(e_in.read_data3, e_in.read_data2); - result_en := 1; - when OP_CMP => - bf := insn_bf(e_in.insn); - l := insn_l(e_in.insn); - v.e.write_cr_enable := '1'; - 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) := ppc_cmp(l, e_in.read_data1, e_in.read_data2); - end loop; - when OP_CMPL => - bf := insn_bf(e_in.insn); - l := insn_l(e_in.insn); - v.e.write_cr_enable := '1'; - 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) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2); - end loop; - when OP_CNTZ => - result := countzero_result; - result_en := 1; - when OP_EXTS => - v.e.write_len := e_in.data_len; - v.e.sign_extend := '1'; - result := e_in.read_data3; - result_en := 1; - when OP_ISEL => - crnum := to_integer(unsigned(insn_bc(e_in.insn))); - if e_in.cr(31-crnum) = '1' then - result := e_in.read_data1; - else - result := e_in.read_data2; - end if; - result_en := 1; - when OP_MCRF => - bf := insn_bf(e_in.insn); - bfa := insn_bfa(e_in.insn); - v.e.write_cr_enable := '1'; - 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 := e_in.cr(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; - when OP_MFSPR => - if std_match(e_in.insn(20 downto 11), "0100100000") then - result := ctrl.ctr; - result_en := 1; - elsif std_match(e_in.insn(20 downto 11), "0100000000") then - result := ctrl.lr; - result_en := 1; - elsif std_match(e_in.insn(20 downto 11), "0110001000") then - result := ctrl.tb; - result_en := 1; - end if; - when OP_MFCR => - if e_in.insn(20) = '0' then - -- mfcr - result := x"00000000" & e_in.cr; - else - -- mfocrf - crnum := fxm_to_num(insn_fxm(e_in.insn)); - result := (others => '0'); - for i in 0 to 7 loop - lo := (7-i)*4; - hi := lo + 3; - if crnum = i then - result(hi downto lo) := e_in.cr(hi downto lo); - end if; - end loop; - end if; - result_en := 1; - when OP_MTCRF => - v.e.write_cr_enable := '1'; - 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 := e_in.read_data3(31 downto 0); - when OP_MTSPR => - if std_match(e_in.insn(20 downto 11), "0100100000") then - ctrl_tmp.ctr <= e_in.read_data3; - elsif std_match(e_in.insn(20 downto 11), "0100000000") then - ctrl_tmp.lr <= e_in.read_data3; - end if; - when OP_POPCNTB => - result := ppc_popcntb(e_in.read_data3); - result_en := 1; - when OP_POPCNTW => - result := ppc_popcntw(e_in.read_data3); - result_en := 1; - when OP_POPCNTD => - result := ppc_popcntd(e_in.read_data3); - result_en := 1; - when OP_PRTYD => - result := ppc_prtyd(e_in.read_data3); - result_en := 1; - when OP_PRTYW => - result := ppc_prtyw(e_in.read_data3); - result_en := 1; - when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR => - result := rotator_result; - if e_in.output_carry = '1' then - ctrl_tmp.carry <= rotator_carry; - end if; - result_en := 1; - when OP_SIM_CONFIG => - -- bit 0 was used to select the microwatt console, which - -- we no longer support. - if SIM = true then - result := x"0000000000000000"; - else - result := x"0000000000000000"; - end if; - result_en := 1; + when OP_ILLEGAL => + terminate_out <= '1'; + report "illegal"; + when OP_NOP => + -- Do nothing + when OP_ADD => + if e_in.invert_a = '0' then + a_inv := e_in.read_data1; + else + a_inv := not e_in.read_data1; + end if; + result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry)); + result := result_with_carry(63 downto 0); + if e_in.output_carry then + ctrl_tmp.carry <= result_with_carry(64); + end if; + result_en := 1; + when OP_AND | OP_OR | OP_XOR => + result := logical_result; + result_en := 1; + when OP_B => + f_out.redirect <= '1'; + if (insn_aa(e_in.insn)) then + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); + else + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); + end if; + when OP_BC => + bo := insn_bo(e_in.insn); + bi := insn_bi(e_in.insn); + if bo(4-2) = '0' then + ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); + end if; + if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then + f_out.redirect <= '1'; + if (insn_aa(e_in.insn)) then + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); + else + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); + end if; + end if; + when OP_BCREG => + -- bits 10 and 6 distinguish between bclr, bcctr and bctar + bo := insn_bo(e_in.insn); + bi := insn_bi(e_in.insn); + if bo(4-2) = '0' and e_in.insn(10) = '0' then + ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); + end if; + if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then + f_out.redirect <= '1'; + if e_in.insn(10) = '0' then + f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00"; + else + f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00"; + end if; + end if; + when OP_CMPB => + result := ppc_cmpb(e_in.read_data3, e_in.read_data2); + result_en := 1; + when OP_CMP => + bf := insn_bf(e_in.insn); + l := insn_l(e_in.insn); + v.e.write_cr_enable := '1'; + 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) := ppc_cmp(l, e_in.read_data1, e_in.read_data2); + end loop; + when OP_CMPL => + bf := insn_bf(e_in.insn); + l := insn_l(e_in.insn); + v.e.write_cr_enable := '1'; + 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) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2); + end loop; + when OP_CNTZ => + result := countzero_result; + result_en := 1; + when OP_EXTS => + v.e.write_len := e_in.data_len; + v.e.sign_extend := '1'; + result := e_in.read_data3; + result_en := 1; + when OP_ISEL => + crnum := to_integer(unsigned(insn_bc(e_in.insn))); + if e_in.cr(31-crnum) = '1' then + result := e_in.read_data1; + else + result := e_in.read_data2; + end if; + result_en := 1; + when OP_MCRF => + bf := insn_bf(e_in.insn); + bfa := insn_bfa(e_in.insn); + v.e.write_cr_enable := '1'; + 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 := e_in.cr(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; + when OP_MFSPR => + if std_match(e_in.insn(20 downto 11), "0100100000") then + result := ctrl.ctr; + result_en := 1; + elsif std_match(e_in.insn(20 downto 11), "0100000000") then + result := ctrl.lr; + result_en := 1; + elsif std_match(e_in.insn(20 downto 11), "0110001000") then + result := ctrl.tb; + result_en := 1; + end if; + when OP_MFCR => + if e_in.insn(20) = '0' then + -- mfcr + result := x"00000000" & e_in.cr; + else + -- mfocrf + crnum := fxm_to_num(insn_fxm(e_in.insn)); + result := (others => '0'); + for i in 0 to 7 loop + lo := (7-i)*4; + hi := lo + 3; + if crnum = i then + result(hi downto lo) := e_in.cr(hi downto lo); + end if; + end loop; + end if; + result_en := 1; + when OP_MTCRF => + v.e.write_cr_enable := '1'; + 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 := e_in.read_data3(31 downto 0); + when OP_MTSPR => + if std_match(e_in.insn(20 downto 11), "0100100000") then + ctrl_tmp.ctr <= e_in.read_data3; + elsif std_match(e_in.insn(20 downto 11), "0100000000") then + ctrl_tmp.lr <= e_in.read_data3; + end if; + when OP_POPCNTB => + result := ppc_popcntb(e_in.read_data3); + result_en := 1; + when OP_POPCNTW => + result := ppc_popcntw(e_in.read_data3); + result_en := 1; + when OP_POPCNTD => + result := ppc_popcntd(e_in.read_data3); + result_en := 1; + when OP_PRTYD => + result := ppc_prtyd(e_in.read_data3); + result_en := 1; + when OP_PRTYW => + result := ppc_prtyw(e_in.read_data3); + result_en := 1; + when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR => + result := rotator_result; + if e_in.output_carry = '1' then + ctrl_tmp.carry <= rotator_carry; + end if; + result_en := 1; + when OP_SIM_CONFIG => + -- bit 0 was used to select the microwatt console, which + -- we no longer support. + if SIM = true then + result := x"0000000000000000"; + else + result := x"0000000000000000"; + end if; + result_en := 1; - when OP_TDI => - -- Keep our test cases happy for now, ignore trap instructions - report "OP_TDI FIXME"; + when OP_TDI => + -- Keep our test cases happy for now, ignore trap instructions + report "OP_TDI FIXME"; - when others => - terminate_out <= '1'; - report "illegal"; - end case; + when others => + terminate_out <= '1'; + report "illegal"; + end case; - if e_in.lr = '1' then - ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4); - end if; + if e_in.lr = '1' then + ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4); + end if; - if result_en = 1 then - v.e.write_data := result; - v.e.write_enable := '1'; - v.e.rc := e_in.rc; - end if; - end if; + if result_en = 1 then + v.e.write_data := result; + v.e.write_enable := '1'; + v.e.rc := e_in.rc; + end if; + end if; - -- Update registers - rin <= v; + -- Update registers + rin <= v; - -- update outputs - --f_out <= r.f; - e_out <= r.e; - flush_out <= f_out.redirect; - end process; + -- update outputs + --f_out <= r.f; + e_out <= r.e; + flush_out <= f_out.redirect; + end process; end architecture behaviour;