use work.decode_types.all;
use work.common.all;
use work.helpers.all;
+use work.insn_helpers.all;
entity decode2 is
port (
architecture behaviour of decode2 is
signal d : Decode1ToDecode2Type;
- alias insn_rs : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
- alias insn_rt : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
- alias insn_ra : std_ulogic_vector(4 downto 0) is d.insn(20 downto 16);
- alias insn_rb : std_ulogic_vector(4 downto 0) is d.insn(15 downto 11);
- alias insn_si : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
- alias insn_ui : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
- alias insn_l : std_ulogic is d.insn(21);
- alias insn_sh32 : std_ulogic_vector(4 downto 0) is d.insn(15 downto 11);
- alias insn_mb32 : std_ulogic_vector(4 downto 0) is d.insn(10 downto 6);
- alias insn_me32 : std_ulogic_vector(4 downto 0) is d.insn(5 downto 1);
- alias insn_li : std_ulogic_vector(23 downto 0) is d.insn(25 downto 2);
- alias insn_lk : std_ulogic is d.insn(0);
- alias insn_rc : std_ulogic is d.insn(0);
- alias insn_bd : std_ulogic_vector(13 downto 0) is d.insn(15 downto 2);
- alias insn_bf : std_ulogic_vector(2 downto 0) is d.insn(25 downto 23);
- alias insn_fxm : std_ulogic_vector(7 downto 0) is d.insn(19 downto 12);
- alias insn_bo : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
- alias insn_bi : std_ulogic_vector(4 downto 0) is d.insn(20 downto 16);
- alias insn_bh : std_ulogic_vector(1 downto 0) is d.insn(12 downto 11);
- alias insn_d : std_ulogic_vector(15 downto 0) is d.insn(15 downto 0);
- alias insn_ds : std_ulogic_vector(13 downto 0) is d.insn(15 downto 2);
- alias insn_to : std_ulogic_vector(4 downto 0) is d.insn(25 downto 21);
- alias insn_bc : std_ulogic_vector(4 downto 0) is d.insn(10 downto 6);
-
- -- can't use an alias for these
- signal insn_sh : std_ulogic_vector(5 downto 0);
- signal insn_me : std_ulogic_vector(5 downto 0);
- signal insn_mb : std_ulogic_vector(5 downto 0);
+ type decode_input_reg_t is record
+ reg_valid : std_ulogic;
+ reg : std_ulogic_vector(4 downto 0);
+ data : std_ulogic_vector(63 downto 0);
+ end record;
+
+ function decode_input_reg_a (t : input_reg_a_t; insn_in : std_ulogic_vector(31 downto 0);
+ reg_data : std_ulogic_vector(63 downto 0)) return decode_input_reg_t is
+ begin
+ case t is
+ when RA =>
+ return ('1', insn_ra(insn_in), reg_data);
+ when RA_OR_ZERO =>
+ return ('1', insn_ra(insn_in), ra_or_zero(reg_data, insn_ra(insn_in)));
+ when RS =>
+ return ('1', insn_rs(insn_in), reg_data);
+ when NONE =>
+ return ('0', (others => '0'), (others => '0'));
+ end case;
+ end;
+
+ function decode_input_reg_b (t : input_reg_b_t; insn_in : std_ulogic_vector(31 downto 0);
+ reg_data : std_ulogic_vector(63 downto 0)) return decode_input_reg_t is
+ begin
+ case t is
+ when RB =>
+ return ('1', insn_rb(insn_in), reg_data);
+ when RS =>
+ return ('1', insn_rs(insn_in), reg_data);
+ when CONST_UI =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_ui(insn_in)), 64)));
+ when CONST_SI =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_si(insn_in)), 64)));
+ when CONST_SI_HI =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_si(insn_in)) & x"0000", 64)));
+ when CONST_UI_HI =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_si(insn_in)) & x"0000", 64)));
+ when CONST_LI =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_li(insn_in)) & "00", 64)));
+ when CONST_BD =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_bd(insn_in)) & "00", 64)));
+ when CONST_DS =>
+ return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_ds(insn_in)) & "00", 64)));
+ when NONE =>
+ return ('0', (others => '0'), (others => '0'));
+ end case;
+ end;
+
+ function decode_input_reg_c (t : input_reg_c_t; insn_in : std_ulogic_vector(31 downto 0);
+ reg_data : std_ulogic_vector(63 downto 0)) return decode_input_reg_t is
+ begin
+ case t is
+ when RS =>
+ return ('1', insn_rs(insn_in), reg_data);
+ when NONE =>
+ return ('0', (others => '0'), (others => '0'));
+ end case;
+ end;
+
+ function decode_output_reg (t : output_reg_a_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
+ begin
+ case t is
+ when RT =>
+ return insn_rt(insn_in);
+ when RA =>
+ return insn_ra(insn_in);
+ when NONE =>
+ return "00000";
+ end case;
+ end;
+
+ function decode_const_a (t : constant_a_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
+ begin
+ case t is
+ when SH =>
+ return "00" & insn_sh(insn_in);
+ when SH32 =>
+ return "000" & insn_sh32(insn_in);
+ when FXM =>
+ return insn_fxm(insn_in);
+ when BO =>
+ return "000" & insn_bo(insn_in);
+ when BF =>
+ return "00000" & insn_bf(insn_in);
+ when TOO =>
+ return "000" & insn_to(insn_in);
+ when BC =>
+ return "000" & insn_bc(insn_in);
+ when NONE =>
+ return "00000000";
+ end case;
+ end;
+
+ function decode_const_b (t : constant_b_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
+ begin
+ case t is
+ when MB =>
+ return insn_mb(insn_in);
+ when ME =>
+ return insn_me(insn_in);
+ when MB32 =>
+ return "0" & insn_mb32(insn_in);
+ when BI =>
+ return "0" & insn_bi(insn_in);
+ when L =>
+ return "00000" & insn_l(insn_in);
+ when NONE =>
+ return "000000";
+ end case;
+ end;
+
+ function decode_const_c (t : constant_c_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
+ begin
+ case t is
+ when ME32 =>
+ return insn_me32(insn_in);
+ when BH =>
+ return "000" & insn_bh(insn_in);
+ when NONE =>
+ return "00000";
+ end case;
+ end;
+
+ function decode_rc (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is
+ begin
+ case t is
+ when RC =>
+ return insn_rc(insn_in);
+ when ONE =>
+ return '1';
+ when NONE =>
+ return '0';
+ end case;
+ end;
begin
- insn_sh <= d.insn(1) & d.insn(15 downto 11);
- insn_me <= d.insn(5) & d.insn(10 downto 6);
- insn_mb <= d.insn(5) & d.insn(10 downto 6);
decode2_0: process(clk)
begin
end if;
end process;
- r_out.read1_reg <= insn_ra when (d.decode.input_reg_a = RA) else
- insn_ra when d.decode.input_reg_a = RA_OR_ZERO else
- insn_rs when d.decode.input_reg_a = RS else
+ r_out.read1_reg <= insn_ra(d.insn) when (d.decode.input_reg_a = RA) else
+ insn_ra(d.insn) when d.decode.input_reg_a = RA_OR_ZERO else
+ insn_rs(d.insn) when d.decode.input_reg_a = RS else
(others => '0');
- r_out.read2_reg <= insn_rb when d.decode.input_reg_b = RB else
- insn_rs when d.decode.input_reg_b = RS else
+ r_out.read2_reg <= insn_rb(d.insn) when d.decode.input_reg_b = RB else
+ insn_rs(d.insn) when d.decode.input_reg_b = RS else
(others => '0');
- r_out.read3_reg <= insn_rs when d.decode.input_reg_c = RS else
+ r_out.read3_reg <= insn_rs(d.insn) when d.decode.input_reg_c = RS else
(others => '0');
decode2_1: process(all)
variable mul_a : std_ulogic_vector(63 downto 0);
variable mul_b : std_ulogic_vector(63 downto 0);
+ variable decoded_reg_a : decode_input_reg_t;
+ variable decoded_reg_b : decode_input_reg_t;
+ variable decoded_reg_c : decode_input_reg_t;
begin
e_out <= Decode2ToExecute1Init;
l_out <= Decode2ToLoadStore1Init;
mul_a := (others => '0');
mul_b := (others => '0');
- e_out.nia <= d.nia;
- l_out.nia <= d.nia;
- m_out.nia <= d.nia;
-
--e_out.input_cr <= d.decode.input_cr;
--m_out.input_cr <= d.decode.input_cr;
--e_out.output_cr <= d.decode.output_cr;
- e_out.cr <= c_in.read_cr_data;
-
- e_out.input_carry <= d.decode.input_carry;
- e_out.output_carry <= d.decode.output_carry;
-
- if d.decode.lr then
- e_out.lr <= insn_lk;
- end if;
-
- -- XXX This is getting too complicated. Use variables and assign to each unit later
+ decoded_reg_a := decode_input_reg_a (d.decode.input_reg_a, d.insn, r_in.read1_data);
+ decoded_reg_b := decode_input_reg_b (d.decode.input_reg_b, d.insn, r_in.read2_data);
+ decoded_reg_c := decode_input_reg_c (d.decode.input_reg_c, d.insn, r_in.read3_data);
case d.decode.unit is
when ALU =>
- e_out.insn_type <= d.decode.insn_type;
e_out.valid <= d.valid;
when LDST =>
l_out.valid <= d.valid;
when MUL =>
- m_out.insn_type <= d.decode.insn_type;
m_out.valid <= d.valid;
when NONE =>
- e_out.insn_type <= OP_ILLEGAL;
e_out.valid <= d.valid;
+ e_out.insn_type <= OP_ILLEGAL;
end case;
- -- required for bypassing
- case d.decode.input_reg_a is
- when RA =>
- e_out.read_reg1 <= insn_ra;
- l_out.update_reg <= insn_ra;
- when RA_OR_ZERO =>
- e_out.read_reg1 <= insn_ra;
- l_out.update_reg <= insn_ra;
- when RS =>
- e_out.read_reg1 <= insn_rs;
- when NONE =>
- e_out.read_reg1 <= (others => '0');
- l_out.update_reg <= (others => '0');
- end case;
-
- -- required for bypassing
- case d.decode.input_reg_b is
- when RB =>
- e_out.read_reg2 <= insn_rb;
- when RS =>
- e_out.read_reg2 <= insn_rs;
- when others =>
- e_out.read_reg2 <= (others => '0');
- end case;
-
- -- required for bypassing
- --case d.decode.input_reg_c is
- --when RS =>
- --e_out.read_reg3 <= insn_rs;
- --when NONE =>
- --e_out.read_reg3 <= (others => '0');
- --end case;
-
- case d.decode.input_reg_a is
- when RA =>
- e_out.read_data1 <= r_in.read1_data;
- mul_a := r_in.read1_data;
- l_out.addr1 <= r_in.read1_data;
- when RA_OR_ZERO =>
- e_out.read_data1 <= ra_or_zero(r_in.read1_data, insn_ra);
- l_out.addr1 <= ra_or_zero(r_in.read1_data, insn_ra);
- when RS =>
- e_out.read_data1 <= r_in.read1_data;
- when NONE =>
- e_out.read_data1 <= (others => '0');
- mul_a := (others => '0');
- end case;
-
- case d.decode.input_reg_b is
- when RB =>
- e_out.read_data2 <= r_in.read2_data;
- mul_b := r_in.read2_data;
- l_out.addr2 <= r_in.read2_data;
- when RS =>
- e_out.read_data2 <= r_in.read2_data;
- when CONST_UI =>
- e_out.read_data2 <= std_ulogic_vector(resize(unsigned(insn_ui), 64));
- when CONST_SI =>
- e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_si), 64));
- l_out.addr2 <= std_ulogic_vector(resize(signed(insn_si), 64));
- mul_b := std_ulogic_vector(resize(signed(insn_si), 64));
- when CONST_SI_HI =>
- e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_si) & x"0000", 64));
- when CONST_UI_HI =>
- e_out.read_data2 <= std_ulogic_vector(resize(unsigned(insn_si) & x"0000", 64));
- when CONST_LI =>
- e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_li) & "00", 64));
- when CONST_BD =>
- e_out.read_data2 <= std_ulogic_vector(resize(signed(insn_bd) & "00", 64));
- when CONST_DS =>
- l_out.addr2 <= std_ulogic_vector(resize(signed(insn_ds) & "00", 64));
- when NONE =>
- e_out.read_data2 <= (others => '0');
- l_out.addr2 <= (others => '0');
- mul_b := (others => '0');
- end case;
+ -- execute unit
+ e_out.nia <= d.nia;
+ e_out.insn_type <= d.decode.insn_type;
+ e_out.read_reg1 <= decoded_reg_a.reg;
+ e_out.read_data1 <= decoded_reg_a.data;
+ e_out.read_reg2 <= decoded_reg_b.reg;
+ e_out.read_data2 <= decoded_reg_b.data;
+ e_out.write_reg <= decode_output_reg(d.decode.output_reg_a, d.insn);
+ e_out.rc <= decode_rc(d.decode.rc, d.insn);
+ e_out.cr <= c_in.read_cr_data;
+ e_out.input_carry <= d.decode.input_carry;
+ e_out.output_carry <= d.decode.output_carry;
+ if d.decode.lr then
+ e_out.lr <= insn_lk(d.insn);
+ end if;
+ e_out.const1 <= decode_const_a(d.decode.const_a, d.insn);
+ e_out.const2 <= decode_const_b(d.decode.const_b, d.insn);
+ e_out.const3 <= decode_const_c(d.decode.const_c, d.insn);
- case d.decode.input_reg_c is
- when RS =>
- l_out.data <= r_in.read3_data;
- when NONE =>
- l_out.data <= (others => '0');
- end case;
+ -- multiply unit
+ m_out.nia <= d.nia;
+ m_out.insn_type <= d.decode.insn_type;
+ mul_a := decoded_reg_a.data;
+ mul_b := decoded_reg_b.data;
+ m_out.write_reg <= decode_output_reg(d.decode.output_reg_a, d.insn);
+ m_out.rc <= decode_rc(d.decode.rc, d.insn);
if d.decode.mul_32bit = '1' then
if d.decode.mul_signed = '1' then
end if;
end if;
- case d.decode.const_a is
- when SH =>
- e_out.const1(insn_sh'range) <= insn_sh;
- when SH32 =>
- e_out.const1(insn_sh32'range) <= insn_sh32;
- when FXM =>
- e_out.const1(insn_fxm'range) <= insn_fxm;
- when BO =>
- e_out.const1(insn_bo'range)<= insn_bo;
- when BF =>
- e_out.const1(insn_bf'range)<= insn_bf;
- when TOO =>
- e_out.const1(insn_to'range)<= insn_to;
- when BC =>
- e_out.const1(insn_bc'range)<= insn_bc;
- when NONE =>
- e_out.const1 <= (others => '0');
- end case;
-
- case d.decode.const_b is
- when MB =>
- e_out.const2(insn_mb'range) <= insn_mb;
- when ME =>
- e_out.const2(insn_me'range) <= insn_me;
- when MB32 =>
- e_out.const2(insn_mb32'range) <= insn_mb32;
- when BI =>
- e_out.const2(insn_bi'range) <= insn_bi;
- when L =>
- e_out.const2(0) <= insn_l;
- when NONE =>
- e_out.const2 <= (others => '0');
- end case;
-
- case d.decode.const_c is
- when ME32 =>
- e_out.const3(insn_me32'range) <= insn_me32;
- when BH =>
- e_out.const3(insn_bh'range) <= insn_bh;
- when NONE =>
- e_out.const3 <= (others => '0');
- end case;
-
- case d.decode.output_reg_a is
- when RT =>
- e_out.write_reg <= insn_rt;
- l_out.write_reg <= insn_rt;
- m_out.write_reg <= insn_rt;
- when RA =>
- e_out.write_reg <= insn_ra;
- l_out.write_reg <= insn_ra;
- when NONE =>
- e_out.write_reg <= (others => '0');
- l_out.write_reg <= (others => '0');
- m_out.write_reg <= (others => '0');
- end case;
-
- case d.decode.rc is
- when RC =>
- e_out.rc <= insn_rc;
- m_out.rc <= insn_rc;
- when ONE =>
- e_out.rc <= '1';
- m_out.rc <= '1';
- when NONE =>
- e_out.rc <= '0';
- m_out.rc <= '0';
- end case;
+ -- load/store unit
+ l_out.nia <= d.nia;
+ l_out.update_reg <= decoded_reg_a.reg;
+ l_out.addr1 <= decoded_reg_a.data;
+ l_out.addr2 <= decoded_reg_b.data;
+ l_out.data <= decoded_reg_c.data;
+ l_out.write_reg <= decode_output_reg(d.decode.output_reg_a, d.insn);
- -- load/store specific signals
if d.decode.insn_type = OP_LOAD then
l_out.load <= '1';
else
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+
+package insn_helpers is
+ function insn_rs (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_rt (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_ra (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_rb (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_si (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_ui (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_l (insn_in : std_ulogic_vector) return std_ulogic;
+ function insn_sh32 (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_mb32 (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_me32 (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_li (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_lk (insn_in : std_ulogic_vector) return std_ulogic;
+ function insn_rc (insn_in : std_ulogic_vector) return std_ulogic;
+ function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_bh (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_d (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_ds (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_to (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_bc (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_sh (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_me (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_mb (insn_in : std_ulogic_vector) return std_ulogic_vector;
+end package insn_helpers;
+
+package body insn_helpers is
+ function insn_rs (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 21);
+ end;
+
+ function insn_rt (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 21);
+ end;
+
+ function insn_ra (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(20 downto 16);
+ end;
+
+ function insn_rb (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 11);
+ end;
+
+ function insn_si (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 0);
+ end;
+
+ function insn_ui (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 0);
+ end;
+
+ function insn_l (insn_in : std_ulogic_vector) return std_ulogic is
+ begin
+ return insn_in(21);
+ end;
+
+ function insn_sh32 (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 11);
+ end;
+
+ function insn_mb32 (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(10 downto 6);
+ end;
+
+ function insn_me32 (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(5 downto 1);
+ end;
+
+ function insn_li (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 2);
+ end;
+
+ function insn_lk (insn_in : std_ulogic_vector) return std_ulogic is
+ begin
+ return insn_in(0);
+ end;
+
+ function insn_rc (insn_in : std_ulogic_vector) return std_ulogic is
+ begin
+ return insn_in(0);
+ end;
+
+ function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 2);
+ end;
+
+ function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 23);
+ end;
+
+ function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(19 downto 12);
+ end;
+
+ function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 21);
+ end;
+
+ function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(20 downto 16);
+ end;
+
+ function insn_bh (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(12 downto 11);
+ end;
+
+ function insn_d (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 0);
+ end;
+
+ function insn_ds (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(15 downto 2);
+ end;
+
+ function insn_to (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(25 downto 21);
+ end;
+
+ function insn_bc (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(10 downto 6);
+ end;
+
+ function insn_sh (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(1) & insn_in(15 downto 11);
+ end;
+
+ function insn_me (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(5) & insn_in(10 downto 6);
+ end;
+
+ function insn_mb (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(5) & insn_in(10 downto 6);
+ end;
+end package body insn_helpers;