From 92a7152370f724628e24c3d1b63aa83103db733f Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 4 Sep 2019 09:36:30 +1000 Subject: [PATCH 1/8] Rework pipeline, add stall and flush signals This adds stall and flush signals to the pipeline. Signed-off-by: Anton Blanchard --- common.vhdl | 1 - core.vhdl | 45 +++--- decode1.vhdl | 440 ++++++++++++++++++++++++++------------------------ decode2.vhdl | 267 ++++++++++++++++++++---------- execute1.vhdl | 221 ++++++++++++++----------- fetch1.vhdl | 49 +++--- fetch2.vhdl | 139 +++++++++++++--- 7 files changed, 698 insertions(+), 464 deletions(-) diff --git a/common.vhdl b/common.vhdl index c12f8b1..b2edeaf 100644 --- a/common.vhdl +++ b/common.vhdl @@ -13,7 +13,6 @@ package common is end record; type Fetch1ToFetch2Type is record - valid: std_ulogic; nia: std_ulogic_vector(63 downto 0); end record; diff --git a/core.vhdl b/core.vhdl index 01a9669..e29c519 100644 --- a/core.vhdl +++ b/core.vhdl @@ -60,9 +60,15 @@ architecture behave of core is signal multiply_to_writeback: MultiplyToWritebackType; -- local signals - signal fetch_enable: std_ulogic := '0'; + signal fetch1_stall_in : std_ulogic; + signal fetch2_stall_in : std_ulogic; + signal fetch2_stall_out : std_ulogic; + signal decode1_stall_in : std_ulogic; + signal decode2_stall_out : std_ulogic; + + signal flush: std_ulogic; + signal complete: std_ulogic; - signal first_fetch: std_ulogic := '0'; signal terminate: std_ulogic; begin @@ -71,19 +77,27 @@ begin fetch1_0: entity work.fetch1 generic map (RESET_ADDRESS => (others => '0')) - port map (clk => clk, rst => rst, fetch_one_in => fetch_enable, + port map (clk => clk, rst => rst, stall_in => fetch1_stall_in, flush_in => flush, e_in => execute1_to_fetch1, f_out => fetch1_to_fetch2); + fetch1_stall_in <= fetch2_stall_out or decode2_stall_out; + fetch2_0: entity work.fetch2 - port map (clk => clk, wishbone_in => wishbone_insn_in, + port map (clk => clk, rst => rst, stall_in => fetch2_stall_in, + stall_out => fetch2_stall_out, flush_in => flush, wishbone_in => wishbone_insn_in, wishbone_out => wishbone_insn_out, f_in => fetch1_to_fetch2, f_out => fetch2_to_decode1); + fetch2_stall_in <= decode2_stall_out; + decode1_0: entity work.decode1 - port map (clk => clk, f_in => fetch2_to_decode1, d_out => decode1_to_decode2); + port map (clk => clk, rst => rst, stall_in => decode1_stall_in, flush_in => flush, f_in => fetch2_to_decode1, d_out => decode1_to_decode2); + + decode1_stall_in <= decode2_stall_out; decode2_0: entity work.decode2 - port map (clk => clk, d_in => decode1_to_decode2, e_out => decode2_to_execute1, + port map (clk => clk, rst => rst, stall_out => decode2_stall_out, flush_in => flush, + complete_in => complete, d_in => decode1_to_decode2, e_out => decode2_to_execute1, l_out => decode2_to_loadstore1, m_out => decode2_to_multiply, r_in => register_file_to_decode2, r_out => decode2_to_register_file, c_in => cr_file_to_decode2, c_out => decode2_to_cr_file); @@ -99,7 +113,7 @@ begin execute1_0: entity work.execute1 generic map (SIM => SIM) - port map (clk => clk, e_in => decode2_to_execute1, f_out => execute1_to_fetch1, + port map (clk => clk, flush_out => flush, e_in => decode2_to_execute1, f_out => execute1_to_fetch1, e_out => execute1_to_execute2, terminate_out => terminate); execute2_0: entity work.execute2 @@ -121,21 +135,4 @@ begin m_in => multiply_to_writeback, w_out => writeback_to_register_file, c_out => writeback_to_cr_file, complete_out => complete); - -- Only single issue until we add bypass support - single_issue_0: process(clk) - begin - if (rising_edge(clk)) then - if rst = '1' then - first_fetch <= '1'; - else - if first_fetch = '1' then - fetch_enable <= '1'; - first_fetch <= '0'; - else - fetch_enable <= complete; - end if; - end if; - end if; - end process single_issue_0; - end behave; diff --git a/decode1.vhdl b/decode1.vhdl index ecedd91..735cf50 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -8,15 +8,19 @@ use work.decode_types.all; entity decode1 is port ( - clk : in std_ulogic; + clk : in std_ulogic; + rst : in std_ulogic; - f_in : in Fetch2ToDecode1Type; - d_out : out Decode1ToDecode2Type + stall_in : in std_ulogic; + flush_in : in std_ulogic; + + f_in : in Fetch2ToDecode1Type; + d_out : out Decode1ToDecode2Type ); end entity decode1; architecture behaviour of decode1 is - signal f : Fetch2ToDecode1Type := Fetch2ToDecode1Init; + signal r, rin : Decode1ToDecode2Type; type decode_rom_array_t is array(ppc_insn_t) of decode_rom_t; @@ -230,610 +234,616 @@ begin decode1_0: process(clk) begin if rising_edge(clk) then - f <= f_in; + -- Output state remains unchanged on stall, unless we are flushing + if rst = '1' or flush_in = '1' or stall_in = '0' then + r <= rin; + end if; end if; end process; decode1_1: process(all) + variable v : Decode1ToDecode2Type; variable ppc_insn: ppc_insn_t; begin - d_out <= Decode1ToDecode2Init; + v := r; + + v.valid := f_in.valid; + ppc_insn := PPC_ILLEGAL; - d_out.valid <= f.valid; + if f_in.valid then + v.nia := f_in.nia; + v.insn := f_in.insn; - if f.valid then - d_out.nia <= f.nia; - d_out.insn <= f.insn; + report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia); - report "Decode insn " & to_hstring(f.insn); - if std_match(f.insn, "011111---------------0100001010-") then + if std_match(f_in.insn, "011111---------------0100001010-") then report "PPC_add"; ppc_insn := PPC_ADD; - elsif std_match(f.insn, "011111---------------0000001010-") then + elsif std_match(f_in.insn, "011111---------------0000001010-") then report "PPC_addc"; ppc_insn := PPC_ADDC; - elsif std_match(f.insn, "011111---------------0010001010-") then + elsif std_match(f_in.insn, "011111---------------0010001010-") then report "PPC_adde"; ppc_insn := PPC_ADDE; - elsif std_match(f.insn, "011111---------------0010101010-") then + elsif std_match(f_in.insn, "011111---------------0010101010-") then report "PPC_addex"; ppc_insn := PPC_ADDEX; - elsif std_match(f.insn, "001110--------------------------") then + elsif std_match(f_in.insn, "001110--------------------------") then report "PPC_addi"; ppc_insn := PPC_ADDI; - elsif std_match(f.insn, "001100--------------------------") then + elsif std_match(f_in.insn, "001100--------------------------") then report "PPC_addic"; ppc_insn := PPC_ADDIC; - elsif std_match(f.insn, "001101--------------------------") then + elsif std_match(f_in.insn, "001101--------------------------") then report "PPC_addic."; ppc_insn := PPC_ADDIC_RC; - elsif std_match(f.insn, "001111--------------------------") then + elsif std_match(f_in.insn, "001111--------------------------") then report "PPC_addis"; ppc_insn := PPC_ADDIS; - elsif std_match(f.insn, "011111---------------0011101010-") then + elsif std_match(f_in.insn, "011111---------------0011101010-") then report "PPC_addme"; ppc_insn := PPC_ADDME; - elsif std_match(f.insn, "010011--------------------00010-") then + elsif std_match(f_in.insn, "010011--------------------00010-") then report "PPC_addpcis"; ppc_insn := PPC_ADDPCIS; - elsif std_match(f.insn, "011111---------------0011001010-") then + elsif std_match(f_in.insn, "011111---------------0011001010-") then report "PPC_addze"; ppc_insn := PPC_ADDZE; - elsif std_match(f.insn, "011111---------------0000011100-") then + elsif std_match(f_in.insn, "011111---------------0000011100-") then report "PPC_and"; ppc_insn := PPC_AND; - elsif std_match(f.insn, "011111---------------0000111100-") then + elsif std_match(f_in.insn, "011111---------------0000111100-") then report "PPC_andc"; ppc_insn := PPC_ANDC; - elsif std_match(f.insn, "011100--------------------------") then + elsif std_match(f_in.insn, "011100--------------------------") then report "PPC_andi."; ppc_insn := PPC_ANDI_RC; - elsif std_match(f.insn, "011101--------------------------") then + elsif std_match(f_in.insn, "011101--------------------------") then report "PPC_andis."; ppc_insn := PPC_ANDIS_RC; - elsif std_match(f.insn, "000000---------------0100000000-") then + elsif std_match(f_in.insn, "000000---------------0100000000-") then report "PPC_attn"; ppc_insn := PPC_ATTN; - elsif std_match(f.insn, "010010------------------------0-") then + elsif std_match(f_in.insn, "010010------------------------0-") then report "PPC_b"; ppc_insn := PPC_B; - elsif std_match(f.insn, "010010------------------------1-") then + elsif std_match(f_in.insn, "010010------------------------1-") then report "PPC_ba"; ppc_insn := PPC_BA; - elsif std_match(f.insn, "010000------------------------0-") then + elsif std_match(f_in.insn, "010000------------------------0-") then report "PPC_bc"; ppc_insn := PPC_BC; - elsif std_match(f.insn, "010000------------------------10") then + elsif std_match(f_in.insn, "010000------------------------10") then report "PPC_bca"; ppc_insn := PPC_BCA; - elsif std_match(f.insn, "010011---------------1000010000-") then + elsif std_match(f_in.insn, "010011---------------1000010000-") then report "PPC_bcctr"; ppc_insn := PPC_BCCTR; - elsif std_match(f.insn, "010000------------------------11") then + elsif std_match(f_in.insn, "010000------------------------11") then report "PPC_bcla"; ppc_insn := PPC_BCLA; - elsif std_match(f.insn, "010011---------------0000010000-") then + elsif std_match(f_in.insn, "010011---------------0000010000-") then report "PPC_bclr"; ppc_insn := PPC_BCLR; - elsif std_match(f.insn, "010011---------------1000110000-") then + elsif std_match(f_in.insn, "010011---------------1000110000-") then report "PPC_bctar"; ppc_insn := PPC_BCTAR; - elsif std_match(f.insn, "011111---------------0011111100-") then + elsif std_match(f_in.insn, "011111---------------0011111100-") then report "PPC_bperm"; ppc_insn := PPC_BPERM; - elsif std_match(f.insn, "011111---------------0000000000-") then + elsif std_match(f_in.insn, "011111---------------0000000000-") then report "PPC_cmp"; ppc_insn := PPC_CMP; - elsif std_match(f.insn, "011111---------------0111111100-") then + elsif std_match(f_in.insn, "011111---------------0111111100-") then report "PPC_cmpb"; ppc_insn := PPC_CMPB; - elsif std_match(f.insn, "011111---------------0011100000-") then + elsif std_match(f_in.insn, "011111---------------0011100000-") then report "PPC_cmpeqb"; ppc_insn := PPC_CMPEQB; - elsif std_match(f.insn, "001011--------------------------") then + elsif std_match(f_in.insn, "001011--------------------------") then report "PPC_cmpi"; ppc_insn := PPC_CMPI; - elsif std_match(f.insn, "011111---------------0000100000-") then + elsif std_match(f_in.insn, "011111---------------0000100000-") then report "PPC_cmpl"; ppc_insn := PPC_CMPL; - elsif std_match(f.insn, "001010--------------------------") then + elsif std_match(f_in.insn, "001010--------------------------") then report "PPC_cmpli"; ppc_insn := PPC_CMPLI; - elsif std_match(f.insn, "011111---------------0011000000-") then + elsif std_match(f_in.insn, "011111---------------0011000000-") then report "PPC_cmprb"; ppc_insn := PPC_CMPRB; - elsif std_match(f.insn, "011111---------------0000111010-") then + elsif std_match(f_in.insn, "011111---------------0000111010-") then report "PPC_cntlzd"; ppc_insn := PPC_CNTLZD; - elsif std_match(f.insn, "011111---------------0000011010-") then + elsif std_match(f_in.insn, "011111---------------0000011010-") then report "PPC_cntlzw"; ppc_insn := PPC_CNTLZW; - elsif std_match(f.insn, "011111---------------1000111010-") then + elsif std_match(f_in.insn, "011111---------------1000111010-") then report "PPC_cnttzd"; ppc_insn := PPC_CNTTZD; - elsif std_match(f.insn, "011111---------------1000011010-") then + elsif std_match(f_in.insn, "011111---------------1000011010-") then report "PPC_cnttzw"; ppc_insn := PPC_CNTTZW; - elsif std_match(f.insn, "010011---------------0100000001-") then + elsif std_match(f_in.insn, "010011---------------0100000001-") then report "PPC_crand"; ppc_insn := PPC_CRAND; - elsif std_match(f.insn, "010011---------------0010000001-") then + elsif std_match(f_in.insn, "010011---------------0010000001-") then report "PPC_crandc"; ppc_insn := PPC_CRANDC; - elsif std_match(f.insn, "010011---------------0100100001-") then + elsif std_match(f_in.insn, "010011---------------0100100001-") then report "PPC_creqv"; ppc_insn := PPC_CREQV; - elsif std_match(f.insn, "010011---------------0011100001-") then + elsif std_match(f_in.insn, "010011---------------0011100001-") then report "PPC_crnand"; ppc_insn := PPC_CRNAND; - elsif std_match(f.insn, "010011---------------0000100001-") then + elsif std_match(f_in.insn, "010011---------------0000100001-") then report "PPC_crnor"; ppc_insn := PPC_CRNOR; - elsif std_match(f.insn, "010011---------------0111000001-") then + elsif std_match(f_in.insn, "010011---------------0111000001-") then report "PPC_cror"; ppc_insn := PPC_CROR; - elsif std_match(f.insn, "010011---------------0110100001-") then + elsif std_match(f_in.insn, "010011---------------0110100001-") then report "PPC_crorc"; ppc_insn := PPC_CRORC; - elsif std_match(f.insn, "010011---------------0011000001-") then + elsif std_match(f_in.insn, "010011---------------0011000001-") then report "PPC_crxor"; ppc_insn := PPC_CRXOR; - elsif std_match(f.insn, "011111---------------1011110011-") then + elsif std_match(f_in.insn, "011111---------------1011110011-") then report "PPC_darn"; ppc_insn := PPC_DARN; - elsif std_match(f.insn, "011111---------------0001010110-") then + elsif std_match(f_in.insn, "011111---------------0001010110-") then report "PPC_dcbf"; ppc_insn := PPC_DCBF; - elsif std_match(f.insn, "011111---------------0000110110-") then + elsif std_match(f_in.insn, "011111---------------0000110110-") then report "PPC_dcbst"; ppc_insn := PPC_DCBST; - elsif std_match(f.insn, "011111---------------0100010110-") then + elsif std_match(f_in.insn, "011111---------------0100010110-") then report "PPC_dcbt"; ppc_insn := PPC_DCBT; - elsif std_match(f.insn, "011111---------------0011110110-") then + elsif std_match(f_in.insn, "011111---------------0011110110-") then report "PPC_dcbtst"; ppc_insn := PPC_DCBTST; - elsif std_match(f.insn, "011111---------------1111110110-") then + elsif std_match(f_in.insn, "011111---------------1111110110-") then report "PPC_dcbz"; ppc_insn := PPC_DCBZ; - elsif std_match(f.insn, "011111---------------0111101001-") then + elsif std_match(f_in.insn, "011111---------------0111101001-") then report "PPC_divd"; ppc_insn := PPC_DIVD; - elsif std_match(f.insn, "011111---------------0110101001-") then + elsif std_match(f_in.insn, "011111---------------0110101001-") then report "PPC_divde"; ppc_insn := PPC_DIVDE; - elsif std_match(f.insn, "011111---------------0110001001-") then + elsif std_match(f_in.insn, "011111---------------0110001001-") then report "PPC_divdeu"; ppc_insn := PPC_DIVDEU; - elsif std_match(f.insn, "011111---------------0111001001-") then + elsif std_match(f_in.insn, "011111---------------0111001001-") then report "PPC_divdu"; ppc_insn := PPC_DIVDU; - elsif std_match(f.insn, "011111---------------0111101011-") then + elsif std_match(f_in.insn, "011111---------------0111101011-") then report "PPC_divw"; ppc_insn := PPC_DIVW; - elsif std_match(f.insn, "011111---------------0110101011-") then + elsif std_match(f_in.insn, "011111---------------0110101011-") then report "PPC_divwe"; ppc_insn := PPC_DIVWE; - elsif std_match(f.insn, "011111---------------0110001011-") then + elsif std_match(f_in.insn, "011111---------------0110001011-") then report "PPC_divweu"; ppc_insn := PPC_DIVWEU; - elsif std_match(f.insn, "011111---------------0111001011-") then + elsif std_match(f_in.insn, "011111---------------0111001011-") then report "PPC_divwu"; ppc_insn := PPC_DIVWU; - elsif std_match(f.insn, "011111---------------0100011100-") then + elsif std_match(f_in.insn, "011111---------------0100011100-") then report "PPC_eqv"; ppc_insn := PPC_EQV; - elsif std_match(f.insn, "011111---------------1110111010-") then + elsif std_match(f_in.insn, "011111---------------1110111010-") then report "PPC_extsb"; ppc_insn := PPC_EXTSB; - elsif std_match(f.insn, "011111---------------1110011010-") then + elsif std_match(f_in.insn, "011111---------------1110011010-") then report "PPC_extsh"; ppc_insn := PPC_EXTSH; - elsif std_match(f.insn, "011111---------------1111011010-") then + elsif std_match(f_in.insn, "011111---------------1111011010-") then report "PPC_extsw"; ppc_insn := PPC_EXTSW; - elsif std_match(f.insn, "011111---------------110111101--") then + elsif std_match(f_in.insn, "011111---------------110111101--") then report "PPC_extswsli"; ppc_insn := PPC_EXTSWSLI; - elsif std_match(f.insn, "011111---------------1111010110-") then + elsif std_match(f_in.insn, "011111---------------1111010110-") then report "PPC_icbi"; ppc_insn := PPC_ICBI; - elsif std_match(f.insn, "011111---------------0000010110-") then + elsif std_match(f_in.insn, "011111---------------0000010110-") then report "PPC_icbt"; ppc_insn := PPC_ICBT; - elsif std_match(f.insn, "011111--------------------01111-") then + elsif std_match(f_in.insn, "011111--------------------01111-") then report "PPC_isel"; ppc_insn := PPC_ISEL; - elsif std_match(f.insn, "010011---------------0010010110-") then + elsif std_match(f_in.insn, "010011---------------0010010110-") then report "PPC_isync"; ppc_insn := PPC_ISYNC; - elsif std_match(f.insn, "011111---------------0000110100-") then + elsif std_match(f_in.insn, "011111---------------0000110100-") then report "PPC_lbarx"; ppc_insn := PPC_LBARX; - elsif std_match(f.insn, "100010--------------------------") then + elsif std_match(f_in.insn, "100010--------------------------") then report "PPC_lbz"; ppc_insn := PPC_LBZ; - elsif std_match(f.insn, "100011--------------------------") then + elsif std_match(f_in.insn, "100011--------------------------") then report "PPC_lbzu"; ppc_insn := PPC_LBZU; - elsif std_match(f.insn, "011111---------------0001110111-") then + elsif std_match(f_in.insn, "011111---------------0001110111-") then report "PPC_lbzux"; ppc_insn := PPC_LBZUX; - elsif std_match(f.insn, "011111---------------0001010111-") then + elsif std_match(f_in.insn, "011111---------------0001010111-") then report "PPC_lbzx"; ppc_insn := PPC_LBZX; - elsif std_match(f.insn, "111010------------------------00") then + elsif std_match(f_in.insn, "111010------------------------00") then report "PPC_ld"; ppc_insn := PPC_LD; - elsif std_match(f.insn, "011111---------------0001010100-") then + elsif std_match(f_in.insn, "011111---------------0001010100-") then report "PPC_ldarx"; ppc_insn := PPC_LDARX; - elsif std_match(f.insn, "011111---------------1000010100-") then + elsif std_match(f_in.insn, "011111---------------1000010100-") then report "PPC_ldbrx"; ppc_insn := PPC_LDBRX; - elsif std_match(f.insn, "111010------------------------01") then + elsif std_match(f_in.insn, "111010------------------------01") then report "PPC_ldu"; ppc_insn := PPC_LDU; - elsif std_match(f.insn, "011111---------------0000110101-") then + elsif std_match(f_in.insn, "011111---------------0000110101-") then report "PPC_ldux"; ppc_insn := PPC_LDUX; - elsif std_match(f.insn, "011111---------------0000010101-") then + elsif std_match(f_in.insn, "011111---------------0000010101-") then report "PPC_ldx"; ppc_insn := PPC_LDX; - elsif std_match(f.insn, "101010--------------------------") then + elsif std_match(f_in.insn, "101010--------------------------") then report "PPC_lha"; ppc_insn := PPC_LHA; - elsif std_match(f.insn, "011111---------------0001110100-") then + elsif std_match(f_in.insn, "011111---------------0001110100-") then report "PPC_lharx"; ppc_insn := PPC_LHARX; - elsif std_match(f.insn, "101011--------------------------") then + elsif std_match(f_in.insn, "101011--------------------------") then report "PPC_lhau"; ppc_insn := PPC_LHAU; - elsif std_match(f.insn, "011111---------------0101110111-") then + elsif std_match(f_in.insn, "011111---------------0101110111-") then report "PPC_lhaux"; ppc_insn := PPC_LHAUX; - elsif std_match(f.insn, "011111---------------0101010111-") then + elsif std_match(f_in.insn, "011111---------------0101010111-") then report "PPC_lhax"; ppc_insn := PPC_LHAX; - elsif std_match(f.insn, "011111---------------1100010110-") then + elsif std_match(f_in.insn, "011111---------------1100010110-") then report "PPC_lhbrx"; ppc_insn := PPC_LHBRX; - elsif std_match(f.insn, "101000--------------------------") then + elsif std_match(f_in.insn, "101000--------------------------") then report "PPC_lhz"; ppc_insn := PPC_LHZ; - elsif std_match(f.insn, "101001--------------------------") then + elsif std_match(f_in.insn, "101001--------------------------") then report "PPC_lhzu"; ppc_insn := PPC_LHZU; - elsif std_match(f.insn, "011111---------------0100110111-") then + elsif std_match(f_in.insn, "011111---------------0100110111-") then report "PPC_lhzux"; ppc_insn := PPC_LHZUX; - elsif std_match(f.insn, "011111---------------0100010111-") then + elsif std_match(f_in.insn, "011111---------------0100010111-") then report "PPC_lhzx"; ppc_insn := PPC_LHZX; - elsif std_match(f.insn, "111010------------------------10") then + elsif std_match(f_in.insn, "111010------------------------10") then report "PPC_lwa"; ppc_insn := PPC_LWA; - elsif std_match(f.insn, "011111---------------0000010100-") then + elsif std_match(f_in.insn, "011111---------------0000010100-") then report "PPC_lwarx"; ppc_insn := PPC_LWARX; - elsif std_match(f.insn, "011111---------------0101110101-") then + elsif std_match(f_in.insn, "011111---------------0101110101-") then report "PPC_lwaux"; ppc_insn := PPC_LWAUX; - elsif std_match(f.insn, "011111---------------0101010101-") then + elsif std_match(f_in.insn, "011111---------------0101010101-") then report "PPC_lwax"; ppc_insn := PPC_LWAX; - elsif std_match(f.insn, "011111---------------1000010110-") then + elsif std_match(f_in.insn, "011111---------------1000010110-") then report "PPC_lwbrx"; ppc_insn := PPC_LWBRX; - elsif std_match(f.insn, "100000--------------------------") then + elsif std_match(f_in.insn, "100000--------------------------") then report "PPC_lwz"; ppc_insn := PPC_LWZ; - elsif std_match(f.insn, "100001--------------------------") then + elsif std_match(f_in.insn, "100001--------------------------") then report "PPC_lwzu"; ppc_insn := PPC_LWZU; - elsif std_match(f.insn, "011111---------------0000110111-") then + elsif std_match(f_in.insn, "011111---------------0000110111-") then report "PPC_lwzux"; ppc_insn := PPC_LWZUX; - elsif std_match(f.insn, "011111---------------0000010111-") then + elsif std_match(f_in.insn, "011111---------------0000010111-") then report "PPC_lwzx"; ppc_insn := PPC_LWZX; - elsif std_match(f.insn, "000100--------------------110000") then + elsif std_match(f_in.insn, "000100--------------------110000") then report "PPC_maddhd"; ppc_insn := PPC_MADDHD; - elsif std_match(f.insn, "000100--------------------110001") then + elsif std_match(f_in.insn, "000100--------------------110001") then report "PPC_maddhdu"; ppc_insn := PPC_MADDHDU; - elsif std_match(f.insn, "000100--------------------110011") then + elsif std_match(f_in.insn, "000100--------------------110011") then report "PPC_maddld"; ppc_insn := PPC_MADDLD; - elsif std_match(f.insn, "010011---------------0000000000-") then + elsif std_match(f_in.insn, "010011---------------0000000000-") then report "PPC_mcrf"; ppc_insn := PPC_MCRF; - elsif std_match(f.insn, "011111---------------1000000000-") then + elsif std_match(f_in.insn, "011111---------------1000000000-") then report "PPC_mcrxr"; ppc_insn := PPC_MCRXR; - elsif std_match(f.insn, "011111---------------1001000000-") then + elsif std_match(f_in.insn, "011111---------------1001000000-") then report "PPC_mcrxrx"; ppc_insn := PPC_MCRXRX; - elsif std_match(f.insn, "011111-----0---------0000010011-") then + elsif std_match(f_in.insn, "011111-----0---------0000010011-") then report "PPC_mfcr"; ppc_insn := PPC_MFCR; - elsif std_match(f.insn, "011111-----1---------0000010011-") then + elsif std_match(f_in.insn, "011111-----1---------0000010011-") then report "PPC_mfocrf"; ppc_insn := PPC_MFOCRF; -- Specific MF/MT SPR encodings first - elsif std_match(f.insn, "011111-----01001000000101010011-") then + elsif std_match(f_in.insn, "011111-----01001000000101010011-") then report "PPC_mfctr"; ppc_insn := PPC_MFCTR; - elsif std_match(f.insn, "011111-----01000000000101010011-") then + elsif std_match(f_in.insn, "011111-----01000000000101010011-") then report "PPC_mflr"; ppc_insn := PPC_MFLR; - elsif std_match(f.insn, "011111-----01100010000101010011-") then + elsif std_match(f_in.insn, "011111-----01100010000101010011-") then report "PPC_mftb"; ppc_insn := PPC_MFTB; - elsif std_match(f.insn, "011111-----01001000000111010011-") then + elsif std_match(f_in.insn, "011111-----01001000000111010011-") then report "PPC_mtctr"; ppc_insn := PPC_MTCTR; - elsif std_match(f.insn, "011111-----01000000000111010011-") then + elsif std_match(f_in.insn, "011111-----01000000000111010011-") then report "PPC_mtlr"; ppc_insn := PPC_MTLR; - elsif std_match(f.insn, "011111---------------0101010011-") then + elsif std_match(f_in.insn, "011111---------------0101010011-") then report "PPC_mfspr"; ppc_insn := PPC_MFSPR; - elsif std_match(f.insn, "011111---------------1100001001-") then + elsif std_match(f_in.insn, "011111---------------1100001001-") then report "PPC_modsd"; ppc_insn := PPC_MODSD; - elsif std_match(f.insn, "011111---------------1100001011-") then + elsif std_match(f_in.insn, "011111---------------1100001011-") then report "PPC_modsw"; ppc_insn := PPC_MODSW; - elsif std_match(f.insn, "011111---------------0100001001-") then + elsif std_match(f_in.insn, "011111---------------0100001001-") then report "PPC_modud"; ppc_insn := PPC_MODUD; - elsif std_match(f.insn, "011111---------------0100001011-") then + elsif std_match(f_in.insn, "011111---------------0100001011-") then report "PPC_moduw"; ppc_insn := PPC_MODUW; - elsif std_match(f.insn, "011111-----0---------0010010000-") then + elsif std_match(f_in.insn, "011111-----0---------0010010000-") then report "PPC_mtcrf"; ppc_insn := PPC_MTCRF; - elsif std_match(f.insn, "011111-----1---------0010010000-") then + elsif std_match(f_in.insn, "011111-----1---------0010010000-") then report "PPC_mtocrf"; ppc_insn := PPC_MTOCRF; - elsif std_match(f.insn, "011111---------------0111010011-") then + elsif std_match(f_in.insn, "011111---------------0111010011-") then report "PPC_mtspr"; ppc_insn := PPC_MTSPR; - elsif std_match(f.insn, "011111----------------001001001-") then + elsif std_match(f_in.insn, "011111----------------001001001-") then report "PPC_mulhd"; ppc_insn := PPC_MULHD; - elsif std_match(f.insn, "011111----------------000001001-") then + elsif std_match(f_in.insn, "011111----------------000001001-") then report "PPC_mulhdu"; ppc_insn := PPC_MULHDU; - elsif std_match(f.insn, "011111----------------001001011-") then + elsif std_match(f_in.insn, "011111----------------001001011-") then report "PPC_mulhw"; ppc_insn := PPC_MULHW; - elsif std_match(f.insn, "011111----------------000001011-") then + elsif std_match(f_in.insn, "011111----------------000001011-") then report "PPC_mulhwu"; ppc_insn := PPC_MULHWU; - elsif std_match(f.insn, "011111---------------0011101001-") then + elsif std_match(f_in.insn, "011111---------------0011101001-") then report "PPC_mulld"; ppc_insn := PPC_MULLD; - elsif std_match(f.insn, "000111--------------------------") then + elsif std_match(f_in.insn, "000111--------------------------") then report "PPC_mulli"; ppc_insn := PPC_MULLI; - elsif std_match(f.insn, "011111---------------0011101011-") then + elsif std_match(f_in.insn, "011111---------------0011101011-") then report "PPC_mullw"; ppc_insn := PPC_MULLW; - elsif std_match(f.insn, "011111---------------0111011100-") then + elsif std_match(f_in.insn, "011111---------------0111011100-") then report "PPC_nand"; ppc_insn := PPC_NAND; - elsif std_match(f.insn, "011111---------------0001101000-") then + elsif std_match(f_in.insn, "011111---------------0001101000-") then report "PPC_neg"; ppc_insn := PPC_NEG; - elsif std_match(f.insn, "011111---------------0001111100-") then + elsif std_match(f_in.insn, "011111---------------0001111100-") then report "PPC_nor"; ppc_insn := PPC_NOR; - elsif std_match(f.insn, "011111---------------0110111100-") then + elsif std_match(f_in.insn, "011111---------------0110111100-") then report "PPC_or"; ppc_insn := PPC_OR; - elsif std_match(f.insn, "011111---------------0110011100-") then + elsif std_match(f_in.insn, "011111---------------0110011100-") then report "PPC_orc"; ppc_insn := PPC_ORC; - elsif std_match(f.insn, "011000--------------------------") then + elsif std_match(f_in.insn, "011000--------------------------") then report "PPC_ori"; ppc_insn := PPC_ORI; - elsif std_match(f.insn, "011001--------------------------") then + elsif std_match(f_in.insn, "011001--------------------------") then report "PPC_oris"; ppc_insn := PPC_ORIS; - elsif std_match(f.insn, "011111---------------0001111010-") then + elsif std_match(f_in.insn, "011111---------------0001111010-") then report "PPC_popcntb"; ppc_insn := PPC_POPCNTB; - elsif std_match(f.insn, "011111---------------0111111010-") then + elsif std_match(f_in.insn, "011111---------------0111111010-") then report "PPC_popcntd"; ppc_insn := PPC_POPCNTD; - elsif std_match(f.insn, "011111---------------0101111010-") then + elsif std_match(f_in.insn, "011111---------------0101111010-") then report "PPC_popcntw"; ppc_insn := PPC_POPCNTW; - elsif std_match(f.insn, "011111---------------0010111010-") then + elsif std_match(f_in.insn, "011111---------------0010111010-") then report "PPC_prtyd"; ppc_insn := PPC_PRTYD; - elsif std_match(f.insn, "011111---------------0010011010-") then + elsif std_match(f_in.insn, "011111---------------0010011010-") then report "PPC_prtyw"; ppc_insn := PPC_PRTYW; - elsif std_match(f.insn, "011110---------------------1000-") then + elsif std_match(f_in.insn, "011110---------------------1000-") then report "PPC_rldcl"; ppc_insn := PPC_RLDCL; - elsif std_match(f.insn, "011110---------------------1001-") then + elsif std_match(f_in.insn, "011110---------------------1001-") then report "PPC_rldcr"; ppc_insn := PPC_RLDCR; - elsif std_match(f.insn, "011110---------------------010--") then + elsif std_match(f_in.insn, "011110---------------------010--") then report "PPC_rldic"; ppc_insn := PPC_RLDIC; - elsif std_match(f.insn, "011110---------------------000--") then + elsif std_match(f_in.insn, "011110---------------------000--") then report "PPC_rldicl"; ppc_insn := PPC_RLDICL; - elsif std_match(f.insn, "011110---------------------001--") then + elsif std_match(f_in.insn, "011110---------------------001--") then report "PPC_rldicr"; ppc_insn := PPC_RLDICR; - elsif std_match(f.insn, "011110---------------------011--") then + elsif std_match(f_in.insn, "011110---------------------011--") then report "PPC_rldimi"; ppc_insn := PPC_RLDIMI; - elsif std_match(f.insn, "010100--------------------------") then + elsif std_match(f_in.insn, "010100--------------------------") then report "PPC_rlwimi"; ppc_insn := PPC_RLWIMI; - elsif std_match(f.insn, "010101--------------------------") then + elsif std_match(f_in.insn, "010101--------------------------") then report "PPC_rlwinm"; ppc_insn := PPC_RLWINM; - elsif std_match(f.insn, "010111--------------------------") then + elsif std_match(f_in.insn, "010111--------------------------") then report "PPC_rlwnm"; ppc_insn := PPC_RLWNM; - elsif std_match(f.insn, "011111---------------0010000000-") then + elsif std_match(f_in.insn, "011111---------------0010000000-") then report "PPC_setb"; ppc_insn := PPC_SETB; - elsif std_match(f.insn, "011111---------------0000011011-") then + elsif std_match(f_in.insn, "011111---------------0000011011-") then report "PPC_sld"; ppc_insn := PPC_SLD; - elsif std_match(f.insn, "011111---------------0000011000-") then + elsif std_match(f_in.insn, "011111---------------0000011000-") then report "PPC_slw"; ppc_insn := PPC_SLW; - elsif std_match(f.insn, "011111---------------1100011010-") then + elsif std_match(f_in.insn, "011111---------------1100011010-") then report "PPC_srad"; ppc_insn := PPC_SRAD; - elsif std_match(f.insn, "011111---------------110011101--") then + elsif std_match(f_in.insn, "011111---------------110011101--") then report "PPC_sradi"; ppc_insn := PPC_SRADI; - elsif std_match(f.insn, "011111---------------1100011000-") then + elsif std_match(f_in.insn, "011111---------------1100011000-") then report "PPC_sraw"; ppc_insn := PPC_SRAW; - elsif std_match(f.insn, "011111---------------1100111000-") then + elsif std_match(f_in.insn, "011111---------------1100111000-") then report "PPC_srawi"; ppc_insn := PPC_SRAWI; - elsif std_match(f.insn, "011111---------------1000011011-") then + elsif std_match(f_in.insn, "011111---------------1000011011-") then report "PPC_srd"; ppc_insn := PPC_SRD; - elsif std_match(f.insn, "011111---------------1000011000-") then + elsif std_match(f_in.insn, "011111---------------1000011000-") then report "PPC_srw"; ppc_insn := PPC_SRW; - elsif std_match(f.insn, "100110--------------------------") then + elsif std_match(f_in.insn, "100110--------------------------") then report "PPC_stb"; ppc_insn := PPC_STB; - elsif std_match(f.insn, "011111---------------1010110110-") then + elsif std_match(f_in.insn, "011111---------------1010110110-") then report "PPC_stbcx"; ppc_insn := PPC_STBCX; - elsif std_match(f.insn, "100111--------------------------") then + elsif std_match(f_in.insn, "100111--------------------------") then report "PPC_stbu"; ppc_insn := PPC_STBU; - elsif std_match(f.insn, "011111---------------0011110111-") then + elsif std_match(f_in.insn, "011111---------------0011110111-") then report "PPC_stbux"; ppc_insn := PPC_STBUX; - elsif std_match(f.insn, "011111---------------0011010111-") then + elsif std_match(f_in.insn, "011111---------------0011010111-") then report "PPC_stbx"; ppc_insn := PPC_STBX; - elsif std_match(f.insn, "111110------------------------00") then + elsif std_match(f_in.insn, "111110------------------------00") then report "PPC_std"; ppc_insn := PPC_STD; - elsif std_match(f.insn, "011111---------------1010010100-") then + elsif std_match(f_in.insn, "011111---------------1010010100-") then report "PPC_stdbrx"; ppc_insn := PPC_STDBRX; - elsif std_match(f.insn, "011111---------------0011010110-") then + elsif std_match(f_in.insn, "011111---------------0011010110-") then report "PPC_stdcx"; ppc_insn := PPC_STDCX; - elsif std_match(f.insn, "111110------------------------01") then + elsif std_match(f_in.insn, "111110------------------------01") then report "PPC_stdu"; ppc_insn := PPC_STDU; - elsif std_match(f.insn, "011111---------------0010110101-") then + elsif std_match(f_in.insn, "011111---------------0010110101-") then report "PPC_stdux"; ppc_insn := PPC_STDUX; - elsif std_match(f.insn, "011111---------------0010010101-") then + elsif std_match(f_in.insn, "011111---------------0010010101-") then report "PPC_stdx"; ppc_insn := PPC_STDX; - elsif std_match(f.insn, "101100--------------------------") then + elsif std_match(f_in.insn, "101100--------------------------") then report "PPC_sth"; ppc_insn := PPC_STH; - elsif std_match(f.insn, "011111---------------1110010110-") then + elsif std_match(f_in.insn, "011111---------------1110010110-") then report "PPC_sthbrx"; ppc_insn := PPC_STHBRX; - elsif std_match(f.insn, "011111---------------1011010110-") then + elsif std_match(f_in.insn, "011111---------------1011010110-") then report "PPC_sthcx"; ppc_insn := PPC_STHCX; - elsif std_match(f.insn, "101101--------------------------") then + elsif std_match(f_in.insn, "101101--------------------------") then report "PPC_sthu"; ppc_insn := PPC_STHU; - elsif std_match(f.insn, "011111---------------0110110111-") then + elsif std_match(f_in.insn, "011111---------------0110110111-") then report "PPC_sthux"; ppc_insn := PPC_STHUX; - elsif std_match(f.insn, "011111---------------0110010111-") then + elsif std_match(f_in.insn, "011111---------------0110010111-") then report "PPC_sthx"; ppc_insn := PPC_STHX; - elsif std_match(f.insn, "100100--------------------------") then + elsif std_match(f_in.insn, "100100--------------------------") then report "PPC_stw"; ppc_insn := PPC_STW; - elsif std_match(f.insn, "011111---------------1010010110-") then + elsif std_match(f_in.insn, "011111---------------1010010110-") then report "PPC_stwbrx"; ppc_insn := PPC_STWBRX; - elsif std_match(f.insn, "011111---------------0010010110-") then + elsif std_match(f_in.insn, "011111---------------0010010110-") then report "PPC_stwcx"; ppc_insn := PPC_STWCX; - elsif std_match(f.insn, "100101--------------------------") then + elsif std_match(f_in.insn, "100101--------------------------") then report "PPC_stwu"; ppc_insn := PPC_STWU; - elsif std_match(f.insn, "011111---------------0010110111-") then + elsif std_match(f_in.insn, "011111---------------0010110111-") then report "PPC_stwux"; ppc_insn := PPC_STWUX; - elsif std_match(f.insn, "011111---------------0010010111-") then + elsif std_match(f_in.insn, "011111---------------0010010111-") then report "PPC_stwx"; ppc_insn := PPC_STWX; - elsif std_match(f.insn, "011111---------------0000101000-") then + elsif std_match(f_in.insn, "011111---------------0000101000-") then report "PPC_subf"; ppc_insn := PPC_SUBF; - elsif std_match(f.insn, "011111---------------0000001000-") then + elsif std_match(f_in.insn, "011111---------------0000001000-") then report "PPC_subfc"; ppc_insn := PPC_SUBFC; - elsif std_match(f.insn, "011111---------------0010001000-") then + elsif std_match(f_in.insn, "011111---------------0010001000-") then report "PPC_subfe"; ppc_insn := PPC_SUBFE; - elsif std_match(f.insn, "001000--------------------------") then + elsif std_match(f_in.insn, "001000--------------------------") then report "PPC_subfic"; ppc_insn := PPC_SUBFIC; - elsif std_match(f.insn, "011111---------------0011101000-") then + elsif std_match(f_in.insn, "011111---------------0011101000-") then report "PPC_subfme"; ppc_insn := PPC_SUBFME; - elsif std_match(f.insn, "011111---------------0011001000-") then + elsif std_match(f_in.insn, "011111---------------0011001000-") then report "PPC_subfze"; ppc_insn := PPC_SUBFZE; - elsif std_match(f.insn, "011111---------------1001010110-") then + elsif std_match(f_in.insn, "011111---------------1001010110-") then report "PPC_sync"; ppc_insn := PPC_SYNC; - elsif std_match(f.insn, "011111---------------0001000100-") then + elsif std_match(f_in.insn, "011111---------------0001000100-") then report "PPC_td"; ppc_insn := PPC_TD; - elsif std_match(f.insn, "000010--------------------------") then + elsif std_match(f_in.insn, "000010--------------------------") then report "PPC_tdi"; ppc_insn := PPC_TDI; - elsif std_match(f.insn, "011111---------------0000000100-") then + elsif std_match(f_in.insn, "011111---------------0000000100-") then report "PPC_tw"; ppc_insn := PPC_TW; - elsif std_match(f.insn, "000011--------------------------") then + elsif std_match(f_in.insn, "000011--------------------------") then report "PPC_twi"; ppc_insn := PPC_TWI; - elsif std_match(f.insn, "011111---------------0100111100-") then + elsif std_match(f_in.insn, "011111---------------0100111100-") then report "PPC_xor"; ppc_insn := PPC_XOR; - elsif std_match(f.insn, "011010--------------------------") then + elsif std_match(f_in.insn, "011010--------------------------") then report "PPC_xori"; ppc_insn := PPC_XORI; - elsif std_match(f.insn, "011011--------------------------") then + elsif std_match(f_in.insn, "011011--------------------------") then report "PPC_xoris"; ppc_insn := PPC_XORIS; - elsif std_match(f.insn, "000001---------------0000000000-") then + elsif std_match(f_in.insn, "000001---------------0000000000-") then report "PPC_SIM_READ"; ppc_insn := PPC_SIM_READ; - elsif std_match(f.insn, "000001---------------0000000001-") then + elsif std_match(f_in.insn, "000001---------------0000000001-") then report "PPC_SIM_POLL"; ppc_insn := PPC_SIM_POLL; - elsif std_match(f.insn, "000001---------------0000000010-") then + elsif std_match(f_in.insn, "000001---------------0000000010-") then report "PPC_SIM_WRITE"; ppc_insn := PPC_SIM_WRITE; - elsif std_match(f.insn, "000001---------------0000000011-") then + elsif std_match(f_in.insn, "000001---------------0000000011-") then report "PPC_SIM_CONFIG"; ppc_insn := PPC_SIM_CONFIG; else @@ -841,7 +851,21 @@ begin ppc_insn := PPC_ILLEGAL; end if; - d_out.decode <= decode_rom_array(ppc_insn); + v.decode := decode_rom_array(ppc_insn); + end if; + + if flush_in = '1' then + v.valid := '0'; + end if; + + if rst = '1' then + v := Decode1ToDecode2Init; end if; + + -- Update registers + rin <= v; + + -- Update outputs + d_out <= r; end process; end architecture behaviour; diff --git a/decode2.vhdl b/decode2.vhdl index f59f340..3e4b022 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -11,6 +11,12 @@ use work.insn_helpers.all; entity decode2 is port ( clk : in std_ulogic; + rst : in std_ulogic; + + complete_in : in std_ulogic; + stall_out : out std_ulogic; + + flush_in: in std_ulogic; d_in : in Decode1ToDecode2Type; @@ -27,7 +33,21 @@ entity decode2 is end entity decode2; architecture behaviour of decode2 is - signal d : Decode1ToDecode2Type; + type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE); + + type reg_internal_type is record + state : state_type; + outstanding : integer; + end record; + + type reg_type is record + e : Decode2ToExecute1Type; + m : Decode2ToMultiplyType; + l : Decode2ToLoadstore1Type; + end record; + + signal r_int, rin_int : reg_internal_type; + signal r, rin : reg_type; type decode_input_reg_t is record reg_valid : std_ulogic; @@ -168,138 +188,219 @@ begin decode2_0: process(clk) begin if rising_edge(clk) then - d <= d_in; + r <= rin; + r_int <= rin_int; end if; end process; - 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 + r_out.read1_reg <= insn_ra(d_in.insn) when (d_in.decode.input_reg_a = RA) else + insn_ra(d_in.insn) when d_in.decode.input_reg_a = RA_OR_ZERO else + insn_rs(d_in.insn) when d_in.decode.input_reg_a = RS else (others => '0'); - 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 + r_out.read2_reg <= insn_rb(d_in.insn) when d_in.decode.input_reg_b = RB else + insn_rs(d_in.insn) when d_in.decode.input_reg_b = RS else (others => '0'); - r_out.read3_reg <= insn_rs(d.insn) when d.decode.input_reg_c = RS else + r_out.read3_reg <= insn_rs(d_in.insn) when d_in.decode.input_reg_c = RS else (others => '0'); - c_out.read <= d.decode.input_cr; + c_out.read <= d_in.decode.input_cr; decode2_1: process(all) + variable v : reg_type; + variable v_int : reg_internal_type; 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; + variable is_valid : std_ulogic; begin - e_out <= Decode2ToExecute1Init; - l_out <= Decode2ToLoadStore1Init; - m_out <= Decode2ToMultiplyInit; + v := r; + v_int := r_int; + + v.e := Decode2ToExecute1Init; + v.l := Decode2ToLoadStore1Init; + v.m := Decode2ToMultiplyInit; mul_a := (others => '0'); mul_b := (others => '0'); - --e_out.input_cr <= d.decode.input_cr; - --m_out.input_cr <= d.decode.input_cr; - --e_out.output_cr <= d.decode.output_cr; + --v.e.input_cr := d_in.decode.input_cr; + --v.m.input_cr := d_in.decode.input_cr; + --v.e.output_cr := d_in.decode.output_cr; - 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); + decoded_reg_a := decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, r_in.read1_data); + decoded_reg_b := decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, r_in.read2_data); + decoded_reg_c := decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn, r_in.read3_data); r_out.read1_enable <= decoded_reg_a.reg_valid; r_out.read2_enable <= decoded_reg_b.reg_valid; r_out.read3_enable <= decoded_reg_c.reg_valid; - case d.decode.unit is - when ALU => - e_out.valid <= d.valid; - when LDST => - l_out.valid <= d.valid; - when MUL => - m_out.valid <= d.valid; - when NONE => - e_out.valid <= d.valid; - e_out.insn_type <= OP_ILLEGAL; - 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); + v.e.nia := d_in.nia; + v.e.insn_type := d_in.decode.insn_type; + v.e.read_reg1 := decoded_reg_a.reg; + v.e.read_data1 := decoded_reg_a.data; + v.e.read_reg2 := decoded_reg_b.reg; + v.e.read_data2 := decoded_reg_b.data; + v.e.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn); + v.e.rc := decode_rc(d_in.decode.rc, d_in.insn); + v.e.cr := c_in.read_cr_data; + v.e.input_carry := d_in.decode.input_carry; + v.e.output_carry := d_in.decode.output_carry; + if d_in.decode.lr then + v.e.lr := insn_lk(d_in.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); + v.e.const1 := decode_const_a(d_in.decode.const_a, d_in.insn); + v.e.const2 := decode_const_b(d_in.decode.const_b, d_in.insn); + v.e.const3 := decode_const_c(d_in.decode.const_c, d_in.insn); -- multiply unit - m_out.nia <= d.nia; - m_out.insn_type <= d.decode.insn_type; + v.m.nia := d_in.nia; + v.m.insn_type := d_in.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 - m_out.data1 <= (others => mul_a(31)); - m_out.data1(31 downto 0) <= mul_a(31 downto 0); - m_out.data2 <= (others => mul_b(31)); - m_out.data2(31 downto 0) <= mul_b(31 downto 0); + v.m.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn); + v.m.rc := decode_rc(d_in.decode.rc, d_in.insn); + + if d_in.decode.mul_32bit = '1' then + if d_in.decode.mul_signed = '1' then + v.m.data1 := (others => mul_a(31)); + v.m.data1(31 downto 0) := mul_a(31 downto 0); + v.m.data2 := (others => mul_b(31)); + v.m.data2(31 downto 0) := mul_b(31 downto 0); else - m_out.data1 <= '0' & x"00000000" & mul_a(31 downto 0); - m_out.data2 <= '0' & x"00000000" & mul_b(31 downto 0); + v.m.data1 := '0' & x"00000000" & mul_a(31 downto 0); + v.m.data2 := '0' & x"00000000" & mul_b(31 downto 0); end if; else - if d.decode.mul_signed = '1' then - m_out.data1 <= mul_a(63) & mul_a; - m_out.data2 <= mul_b(63) & mul_b; + if d_in.decode.mul_signed = '1' then + v.m.data1 := mul_a(63) & mul_a; + v.m.data2 := mul_b(63) & mul_b; else - m_out.data1 <= '0' & mul_a; - m_out.data2 <= '0' & mul_b; + v.m.data1 := '0' & mul_a; + v.m.data2 := '0' & mul_b; end if; end if; -- 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); - - if d.decode.insn_type = OP_LOAD then - l_out.load <= '1'; + v.l.nia := d_in.nia; + v.l.update_reg := decoded_reg_a.reg; + v.l.addr1 := decoded_reg_a.data; + v.l.addr2 := decoded_reg_b.data; + v.l.data := decoded_reg_c.data; + v.l.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn); + + if d_in.decode.insn_type = OP_LOAD then + v.l.load := '1'; else - l_out.load <= '0'; + v.l.load := '0'; end if; - case d.decode.length is + case d_in.decode.length is when is1B => - l_out.length <= "0001"; + v.l.length := "0001"; when is2B => - l_out.length <= "0010"; + v.l.length := "0010"; when is4B => - l_out.length <= "0100"; + v.l.length := "0100"; when is8B => - l_out.length <= "1000"; + v.l.length := "1000"; when NONE => - l_out.length <= "0000"; + v.l.length := "0000"; end case; - l_out.byte_reverse <= d.decode.byte_reverse; - l_out.sign_extend <= d.decode.sign_extend; - l_out.update <= d.decode.update; + v.l.byte_reverse := d_in.decode.byte_reverse; + v.l.sign_extend := d_in.decode.sign_extend; + v.l.update := d_in.decode.update; + + -- single issue + + if complete_in = '1' then + v_int.outstanding := v_int.outstanding - 1; + end if; + + -- state machine to handle instructions that must be single + -- through the pipeline. + stall_out <= '0'; + is_valid := d_in.valid; + case v_int.state is + when IDLE => + if (flush_in = '0') and (d_in.valid = '1') and (d_in.decode.sgl_pipe = '1') then + if v_int.outstanding /= 0 then + v_int.state := WAIT_FOR_PREV_TO_COMPLETE; + stall_out <= '1'; + is_valid := '0'; + else + -- send insn out and wait on it to complete + v_int.state := WAIT_FOR_CURR_TO_COMPLETE; + end if; + end if; + + when WAIT_FOR_PREV_TO_COMPLETE => + if v_int.outstanding = 0 then + -- send insn out and wait on it to complete + v_int.state := WAIT_FOR_CURR_TO_COMPLETE; + else + stall_out <= '1'; + is_valid := '0'; + end if; + + when WAIT_FOR_CURR_TO_COMPLETE => + if v_int.outstanding = 0 then + v_int.state := IDLE; + else + stall_out <= '1'; + is_valid := '0'; + end if; + end case; + + v.e.valid := '0'; + v.m.valid := '0'; + v.l.valid := '0'; + case d_in.decode.unit is + when ALU => + v.e.valid := is_valid; + when LDST => + v.l.valid := is_valid; + when MUL => + v.m.valid := is_valid; + when NONE => + v.e.valid := is_valid; + v.e.insn_type := OP_ILLEGAL; + end case; + + if flush_in = '1' then + v.e.valid := '0'; + v.m.valid := '0'; + v.l.valid := '0'; + end if; + + -- track outstanding instructions + if v.e.valid = '1' or v.l.valid = '1' or v.m.valid = '1' then + v_int.outstanding := v_int.outstanding + 1; + end if; + + assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure; + + if rst = '1' then + v_int.state := IDLE; + v_int.outstanding := 0; + v.e := Decode2ToExecute1Init; + v.l := Decode2ToLoadStore1Init; + v.m := Decode2ToMultiplyInit; + end if; + + -- Update registers + rin <= v; + rin_int <= v_int; + + -- Update outputs + e_out <= r.e; + l_out <= r.l; + m_out <= r.m; end process; end architecture behaviour; diff --git a/execute1.vhdl b/execute1.vhdl index e57dd4f..d6076a9 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -17,8 +17,14 @@ entity execute1 is port ( clk : in std_logic; + -- asynchronous + flush_out : out std_ulogic; + e_in : in Decode2ToExecute1Type; + + -- asynchronous f_out : out Execute1ToFetch1Type; + e_out : out Execute1ToExecute2Type; terminate_out : out std_ulogic @@ -26,19 +32,26 @@ entity execute1 is end entity execute1; architecture behaviour of execute1 is - signal e: Decode2ToExecute1Type := Decode2ToExecute1Init; + type reg_type is record + --f : Execute1ToFetch1Type; + e : Execute1ToExecute2Type; + end record; + + signal r, rin : reg_type; + signal ctrl: ctrl_t := (carry => '0', others => (others => '0')); signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0')); begin execute1_0: process(clk) begin if rising_edge(clk) then - e <= e_in; + r <= rin; ctrl <= ctrl_tmp; end if; end process; execute1_1: process(all) + variable v : reg_type; variable result : std_ulogic_vector(63 downto 0); variable result_with_carry : std_ulogic_vector(64 downto 0); variable result_en : integer; @@ -49,21 +62,26 @@ begin result_with_carry := (others => '0'); result_en := 0; - e_out <= Execute1ToExecute2Init; - f_out <= Execute1ToFetch1TypeInit; + v := r; + v.e := Execute1ToExecute2Init; + --v.f := Execute1ToFetch1TypeInit; + ctrl_tmp <= ctrl; -- FIXME: run at 512MHz not core freq ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); terminate_out <= '0'; + flush_out <= '0'; + f_out <= Execute1ToFetch1TypeInit; + + if e_in.valid = '1' then - if e.valid = '1' then - e_out.valid <= '1'; - e_out.write_reg <= e.write_reg; + v.e.valid := '1'; + v.e.write_reg := e_in.write_reg; - report "execute " & to_hstring(e.nia); + report "execute " & to_hstring(e_in.nia); - case_0: case e.insn_type is + case_0: case e_in.insn_type is when OP_ILLEGAL => terminate_out <= '1'; @@ -71,94 +89,98 @@ begin when OP_NOP => -- Do nothing when OP_ADD => - result := ppc_add(e.read_data1, e.read_data2); + result := ppc_add(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_ADDC => - result_with_carry := ppc_adde(e.read_data1, e.read_data2, ctrl.carry and e.input_carry); + result_with_carry := ppc_adde(e_in.read_data1, e_in.read_data2, ctrl.carry and e_in.input_carry); result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64) and e.output_carry; + ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry; result_en := 1; when OP_AND => - result := ppc_and(e.read_data1, e.read_data2); + result := ppc_and(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_ANDC => - result := ppc_andc(e.read_data1, e.read_data2); + result := ppc_andc(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_B => + flush_out <= '1'; f_out.redirect <= '1'; - f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2)); + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); when OP_BC => - if e.const1(4-2) = '0' then + if e_in.const1(4-2) = '0' then ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); end if; - if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then + if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then + flush_out <= '1'; f_out.redirect <= '1'; - f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2)); + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); end if; when OP_BCLR => - if e.const1(4-2) = '0' then + if e_in.const1(4-2) = '0' then ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); end if; - if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then + if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then + flush_out <= '1'; f_out.redirect <= '1'; f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00"; end if; when OP_BCCTR => - if ppc_bcctr_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr) = 1 then + if ppc_bcctr_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr) = 1 then + flush_out <= '1'; f_out.redirect <= '1'; f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00"; end if; when OP_CMPB => - result := ppc_cmpb(e.read_data1, e.read_data2); + result := ppc_cmpb(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_CMP => - e_out.write_cr_enable <= '1'; - crnum := to_integer(unsigned(e.const1(2 downto 0))); - e_out.write_cr_mask <= num_to_fxm(crnum); + v.e.write_cr_enable := '1'; + crnum := to_integer(unsigned(e_in.const1(2 downto 0))); + v.e.write_cr_mask := num_to_fxm(crnum); for i in 0 to 7 loop lo := i*4; hi := lo + 3; - e_out.write_cr_data(hi downto lo) <= ppc_cmp(e.const2(0), e.read_data1, e.read_data2); + v.e.write_cr_data(hi downto lo) := ppc_cmp(e_in.const2(0), e_in.read_data1, e_in.read_data2); end loop; when OP_CMPL => - e_out.write_cr_enable <= '1'; - crnum := to_integer(unsigned(e.const1(2 downto 0))); - e_out.write_cr_mask <= num_to_fxm(crnum); + v.e.write_cr_enable := '1'; + crnum := to_integer(unsigned(e_in.const1(2 downto 0))); + v.e.write_cr_mask := num_to_fxm(crnum); for i in 0 to 7 loop lo := i*4; hi := lo + 3; - e_out.write_cr_data(hi downto lo) <= ppc_cmpl(e.const2(0), e.read_data1, e.read_data2); + v.e.write_cr_data(hi downto lo) := ppc_cmpl(e_in.const2(0), e_in.read_data1, e_in.read_data2); end loop; when OP_CNTLZW => - result := ppc_cntlzw(e.read_data1); + result := ppc_cntlzw(e_in.read_data1); result_en := 1; when OP_CNTTZW => - result := ppc_cnttzw(e.read_data1); + result := ppc_cnttzw(e_in.read_data1); result_en := 1; when OP_CNTLZD => - result := ppc_cntlzd(e.read_data1); + result := ppc_cntlzd(e_in.read_data1); result_en := 1; when OP_CNTTZD => - result := ppc_cnttzd(e.read_data1); + result := ppc_cnttzd(e_in.read_data1); result_en := 1; when OP_EXTSB => - result := ppc_extsb(e.read_data1); + result := ppc_extsb(e_in.read_data1); result_en := 1; when OP_EXTSH => - result := ppc_extsh(e.read_data1); + result := ppc_extsh(e_in.read_data1); result_en := 1; when OP_EXTSW => - result := ppc_extsw(e.read_data1); + result := ppc_extsw(e_in.read_data1); result_en := 1; when OP_EQV => - result := ppc_eqv(e.read_data1, e.read_data2); + result := ppc_eqv(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_ISEL => - crnum := to_integer(unsigned(e.const1)); - if e.cr(31-crnum) = '1' then - result := e.read_data1; + crnum := to_integer(unsigned(e_in.const1)); + if e_in.cr(31-crnum) = '1' then + result := e_in.read_data1; else - result := e.read_data2; + result := e_in.read_data2; end if; result_en := 1; when OP_MFCTR => @@ -171,133 +193,133 @@ begin result := ctrl.tb; result_en := 1; when OP_MTCTR => - ctrl_tmp.ctr <= e.read_data1; + ctrl_tmp.ctr <= e_in.read_data1; when OP_MTLR => - ctrl_tmp.lr <= e.read_data1; + ctrl_tmp.lr <= e_in.read_data1; when OP_MFCR => - result := x"00000000" & e.cr; + result := x"00000000" & e_in.cr; result_en := 1; when OP_MFOCRF => - crnum := fxm_to_num(e.const1(7 downto 0)); + crnum := fxm_to_num(e_in.const1(7 downto 0)); result := (others => '0'); --- result((4*(7-crnum)+3) downto (4*(7-crnum))) := e.cr((4*(7-crnum)+3) downto (4*(7-crnum))); FIXME +-- result((4*(7-crnum)+3) downto (4*(7-crnum))) := e_in.cr((4*(7-crnum)+3) downto (4*(7-crnum))); FIXME for i in 0 to 7 loop lo := (7-i)*4; hi := lo + 3; if crnum = i then - result(hi downto lo) := e.cr(hi downto lo); + result(hi downto lo) := e_in.cr(hi downto lo); end if; end loop; result_en := 1; when OP_MTCRF => - e_out.write_cr_enable <= '1'; - e_out.write_cr_mask <= e.const1(7 downto 0); - e_out.write_cr_data <= e.read_data1(31 downto 0); + v.e.write_cr_enable := '1'; + v.e.write_cr_mask := e_in.const1(7 downto 0); + v.e.write_cr_data := e_in.read_data1(31 downto 0); when OP_MTOCRF => - e_out.write_cr_enable <= '1'; + v.e.write_cr_enable := '1'; -- We require one hot priority encoding here - crnum := fxm_to_num(e.const1(7 downto 0)); - e_out.write_cr_mask <= num_to_fxm(crnum); - e_out.write_cr_data <= e.read_data1(31 downto 0); + crnum := fxm_to_num(e_in.const1(7 downto 0)); + v.e.write_cr_mask := num_to_fxm(crnum); + v.e.write_cr_data := e_in.read_data1(31 downto 0); when OP_NAND => - result := ppc_nand(e.read_data1, e.read_data2); + result := ppc_nand(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_NEG => - result := ppc_neg(e.read_data1); + result := ppc_neg(e_in.read_data1); result_en := 1; when OP_NOR => - result := ppc_nor(e.read_data1, e.read_data2); + result := ppc_nor(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_OR => - result := ppc_or(e.read_data1, e.read_data2); + result := ppc_or(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_ORC => - result := ppc_orc(e.read_data1, e.read_data2); + result := ppc_orc(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_POPCNTB => - result := ppc_popcntb(e.read_data1); + result := ppc_popcntb(e_in.read_data1); result_en := 1; when OP_POPCNTW => - result := ppc_popcntw(e.read_data1); + result := ppc_popcntw(e_in.read_data1); result_en := 1; when OP_POPCNTD => - result := ppc_popcntd(e.read_data1); + result := ppc_popcntd(e_in.read_data1); result_en := 1; when OP_PRTYD => - result := ppc_prtyd(e.read_data1); + result := ppc_prtyd(e_in.read_data1); result_en := 1; when OP_PRTYW => - result := ppc_prtyw(e.read_data1); + result := ppc_prtyw(e_in.read_data1); result_en := 1; when OP_RLDCL => - result := ppc_rldcl(e.read_data1, e.read_data2, e.const2(5 downto 0)); + result := ppc_rldcl(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0)); result_en := 1; when OP_RLDCR => - result := ppc_rldcr(e.read_data1, e.read_data2, e.const2(5 downto 0)); + result := ppc_rldcr(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0)); result_en := 1; when OP_RLDICL => - result := ppc_rldicl(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0)); + result := ppc_rldicl(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); result_en := 1; when OP_RLDICR => - result := ppc_rldicr(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0)); + result := ppc_rldicr(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); result_en := 1; when OP_RLWNM => - result := ppc_rlwnm(e.read_data1, e.read_data2, e.const2(4 downto 0), e.const3(4 downto 0)); + result := ppc_rlwnm(e_in.read_data1, e_in.read_data2, e_in.const2(4 downto 0), e_in.const3(4 downto 0)); result_en := 1; when OP_RLWINM => - result := ppc_rlwinm(e.read_data1, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0)); + result := ppc_rlwinm(e_in.read_data1, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0)); result_en := 1; when OP_RLDIC => - result := ppc_rldic(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0)); + result := ppc_rldic(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); result_en := 1; when OP_RLDIMI => - result := ppc_rldimi(e.read_data1, e.read_data2, e.const1(5 downto 0), e.const2(5 downto 0)); + result := ppc_rldimi(e_in.read_data1, e_in.read_data2, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); result_en := 1; when OP_RLWIMI => - result := ppc_rlwimi(e.read_data1, e.read_data2, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0)); + result := ppc_rlwimi(e_in.read_data1, e_in.read_data2, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0)); result_en := 1; when OP_SLD => - result := ppc_sld(e.read_data1, e.read_data2); + result := ppc_sld(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_SLW => - result := ppc_slw(e.read_data1, e.read_data2); + result := ppc_slw(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_SRAW => - result_with_carry := ppc_sraw(e.read_data1, e.read_data2); + result_with_carry := ppc_sraw(e_in.read_data1, e_in.read_data2); result := result_with_carry(63 downto 0); ctrl_tmp.carry <= result_with_carry(64); result_en := 1; when OP_SRAWI => - result_with_carry := ppc_srawi(e.read_data1, e.const1(5 downto 0)); + result_with_carry := ppc_srawi(e_in.read_data1, e_in.const1(5 downto 0)); result := result_with_carry(63 downto 0); ctrl_tmp.carry <= result_with_carry(64); result_en := 1; when OP_SRAD => - result_with_carry := ppc_srad(e.read_data1, e.read_data2); + result_with_carry := ppc_srad(e_in.read_data1, e_in.read_data2); result := result_with_carry(63 downto 0); ctrl_tmp.carry <= result_with_carry(64); result_en := 1; when OP_SRADI => - result_with_carry := ppc_sradi(e.read_data1, e.const1(5 downto 0)); + result_with_carry := ppc_sradi(e_in.read_data1, e_in.const1(5 downto 0)); result := result_with_carry(63 downto 0); ctrl_tmp.carry <= result_with_carry(64); result_en := 1; when OP_SRD => - result := ppc_srd(e.read_data1, e.read_data2); + result := ppc_srd(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_SRW => - result := ppc_srw(e.read_data1, e.read_data2); + result := ppc_srw(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_SUBF => - result := ppc_subf(e.read_data1, e.read_data2); + result := ppc_subf(e_in.read_data1, e_in.read_data2); result_en := 1; when OP_SUBFC => - result_with_carry := ppc_subfe(e.read_data1, e.read_data2, ctrl.carry or not(e.input_carry)); + result_with_carry := ppc_subfe(e_in.read_data1, e_in.read_data2, ctrl.carry or not(e_in.input_carry)); result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64) and e.output_carry; + ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry; result_en := 1; when OP_XOR => - result := ppc_xor(e.read_data1, e.read_data2); + result := ppc_xor(e_in.read_data1, e_in.read_data2); result_en := 1; -- sim console @@ -319,7 +341,7 @@ begin end if; when OP_SIM_WRITE => if SIM = true then - sim_console_write(e.read_data1); + sim_console_write(e_in.read_data1); else terminate_out <= '1'; report "illegal"; @@ -338,7 +360,7 @@ begin when OP_DIVDU => if SIM = true then - result := ppc_divdu(e.read_data1, e.read_data2); + result := ppc_divdu(e_in.read_data1, e_in.read_data2); result_en := 1; else terminate_out <= '1'; @@ -346,7 +368,7 @@ begin end if; when OP_DIVD => if SIM = true then - result := ppc_divd(e.read_data1, e.read_data2); + result := ppc_divd(e_in.read_data1, e_in.read_data2); result_en := 1; else terminate_out <= '1'; @@ -354,7 +376,7 @@ begin end if; when OP_DIVWU => if SIM = true then - result := ppc_divwu(e.read_data1, e.read_data2); + result := ppc_divwu(e_in.read_data1, e_in.read_data2); result_en := 1; else terminate_out <= '1'; @@ -362,7 +384,7 @@ begin end if; when OP_DIVW => if SIM = true then - result := ppc_divw(e.read_data1, e.read_data2); + result := ppc_divw(e_in.read_data1, e_in.read_data2); result_en := 1; else terminate_out <= '1'; @@ -373,15 +395,22 @@ begin report "illegal"; end case; - if e.lr = '1' then - ctrl_tmp.lr <= std_ulogic_vector(unsigned(e.nia) + 4); + if e_in.lr = '1' then + ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4); end if; if result_en = 1 then - e_out.write_data <= result; - e_out.write_enable <= '1'; - e_out.rc <= e.rc; + 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 outputs + --f_out <= r.f; + e_out <= r.e; end process; end architecture behaviour; diff --git a/fetch1.vhdl b/fetch1.vhdl index 458805e..14ef8e8 100644 --- a/fetch1.vhdl +++ b/fetch1.vhdl @@ -14,7 +14,8 @@ entity fetch1 is rst : in std_ulogic; -- Control inputs: - fetch_one_in : in std_ulogic; + stall_in : in std_ulogic; + flush_in : in std_ulogic; -- redirect from execution unit e_in : in Execute1ToFetch1Type; @@ -25,54 +26,48 @@ entity fetch1 is end entity fetch1; architecture behaviour of fetch1 is - type reg_type is record - pc : std_ulogic_vector(63 downto 0); - fetch_one : std_ulogic; + type reg_internal_type is record + nia_next : std_ulogic_vector(63 downto 0); end record; - - signal r : reg_type; - signal rin : reg_type; + signal r_int, rin_int : reg_internal_type; + signal r, rin : Fetch1ToFetch2Type; begin regs : process(clk) begin if rising_edge(clk) then r <= rin; + r_int <= rin_int; end if; end process; comb : process(all) - variable v : reg_type; - variable fetch_valid : std_ulogic; - variable fetch_nia : std_ulogic_vector(63 downto 0); + variable v : Fetch1ToFetch2Type; + variable v_int : reg_internal_type; begin v := r; + v_int := r_int; - fetch_valid := '0'; - fetch_nia := (others => '0'); - - v.fetch_one := v.fetch_one or fetch_one_in; - - if e_in.redirect = '1' then - v.pc := e_in.redirect_nia; + if stall_in = '0' then + v.nia := r_int.nia_next; + v_int.nia_next := std_logic_vector(unsigned(r_int.nia_next) + 4); end if; - if v.fetch_one = '1' then - fetch_nia := v.pc; - fetch_valid := '1'; - v.pc := std_logic_vector(unsigned(v.pc) + 4); - - v.fetch_one := '0'; + if e_in.redirect = '1' then + v.nia := e_in.redirect_nia; + v_int.nia_next := std_logic_vector(unsigned(e_in.redirect_nia) + 4); end if; if rst = '1' then - v.pc := RESET_ADDRESS; - v.fetch_one := '0'; + v.nia := RESET_ADDRESS; + v_int.nia_next := std_logic_vector(unsigned(RESET_ADDRESS) + 4); end if; + -- Update registers rin <= v; + rin_int <= v_int; - f_out.valid <= fetch_valid; - f_out.nia <= fetch_nia; + -- Update outputs + f_out <= r; end process; end architecture behaviour; diff --git a/fetch2.vhdl b/fetch2.vhdl index 6f252c8..6ae7269 100644 --- a/fetch2.vhdl +++ b/fetch2.vhdl @@ -9,6 +9,12 @@ use work.wishbone_types.all; entity fetch2 is port( clk : in std_ulogic; + rst : in std_ulogic; + + stall_in : in std_ulogic; + stall_out : out std_ulogic; + + flush_in : in std_ulogic; -- instruction memory interface wishbone_in : in wishbone_slave_out; @@ -21,50 +27,133 @@ entity fetch2 is end entity fetch2; architecture behaviour of fetch2 is - type reg_type is record - valid : std_ulogic; - nia : std_ulogic_vector(63 downto 0); + type state_type is (IDLE, JUST_IDLE, WAIT_ACK, WAIT_ACK_THROWAWAY); + + type reg_internal_type is record + state : state_type; + nia : std_ulogic_vector(63 downto 0); + w : wishbone_master_out; + -- Trivial 64B cache + cache : std_ulogic_vector(63 downto 0); + tag : std_ulogic_vector(60 downto 0); + tag_valid : std_ulogic; end record; - signal f : Fetch1ToFetch2Type; - signal wishbone: wishbone_slave_out; - signal r : reg_type := (valid => '0', nia => (others => '0')); - signal rin : reg_type := (valid => '0', nia => (others => '0')); + function wishbone_fetch(nia : std_ulogic_vector(63 downto 0)) return wishbone_master_out is + variable w : wishbone_master_out; + begin + assert nia(2 downto 0) = "000"; + + w.adr := nia; + w.dat := (others => '0'); + w.cyc := '1'; + w.stb := '1'; + w.sel := "11111111"; + w.we := '0'; + + return w; + end; + + signal r, rin : Fetch2ToDecode1Type; + signal r_int, rin_int : reg_internal_type; begin regs : process(clk) begin if rising_edge(clk) then - wishbone <= wishbone_in; - f <= f_in; - r <= rin; + -- Output state remains unchanged on stall, unless we are flushing + if rst = '1' or flush_in = '1' or stall_in = '0' then + r <= rin; + end if; + r_int <= rin_int; end if; end process; comb : process(all) - variable v : reg_type; + variable v : Fetch2ToDecode1Type; + variable v_int : reg_internal_type; begin v := r; + v_int := r_int; + + v.valid := '0'; + v.nia := f_in.nia; + + case v_int.state is + when IDLE | JUST_IDLE => + v_int.state := IDLE; + + if (v_int.tag_valid = '1') and (v_int.tag = f_in.nia(63 downto 3)) then + v.valid := '1'; + if f_in.nia(2) = '0' then + v.insn := v_int.cache(31 downto 0); + else + v.insn := v_int.cache(63 downto 32); + end if; + else + v_int.state := WAIT_ACK; + v_int.nia := f_in.nia; + v_int.w := wishbone_fetch(f_in.nia(63 downto 3) & "000"); + end if; - if f.valid = '1' then - v.valid := '1'; - v.nia := f.nia; + when WAIT_ACK => + if wishbone_in.ack = '1' then + v_int.state := IDLE; + v_int.w := wishbone_master_out_init; + v_int.cache := wishbone_in.dat; + v_int.tag := v_int.nia(63 downto 3); + v_int.tag_valid := '1'; + + v.valid := '1'; + if v_int.nia(2) = '0' then + v.insn := v_int.cache(31 downto 0); + else + v.insn := v_int.cache(63 downto 32); + end if; + end if; + + when WAIT_ACK_THROWAWAY => + if wishbone_in.ack = '1' then + -- Should we put the returned data in the cache? We went to the + -- trouble of fetching it and it might be useful in the future + + v_int.w := wishbone_master_out_init; + + -- We need to stall fetch1 for one more cycle, so transition through JUST_IDLE + v_int.state := JUST_IDLE; + end if; + end case; + + stall_out <= '0'; + if v_int.state /= IDLE then + stall_out <= '1'; end if; - if v.valid = '1' and wishbone.ack = '1' then + if flush_in = '1' then v.valid := '0'; + + -- Throw away in flight data + if v_int.state = WAIT_ACK then + v_int.state := WAIT_ACK_THROWAWAY; + end if; end if; - rin <= v; + if rst = '1' then + v := Fetch2ToDecode1Init; - wishbone_out.adr <= v.nia(63 downto 3) & "000"; - wishbone_out.dat <= (others => '0'); - wishbone_out.cyc <= v.valid; - wishbone_out.stb <= v.valid; - wishbone_out.sel <= "00001111" when v.nia(2) = '0' else "11110000"; - wishbone_out.we <= '0'; + v_int.state := IDLE; + v_int.nia := (others => '0'); + v_int.w := wishbone_master_out_init; + v_int.cache := (others => '0'); + v_int.tag := (others => '0'); + v_int.tag_valid := '0'; + end if; + + -- Update registers + rin_int <= v_int; + rin <= v; - f_out.valid <= wishbone.ack; - f_out.nia <= v.nia; - f_out.insn <= wishbone.dat(31 downto 0) when v.nia(2) = '0' else wishbone.dat(63 downto 32); + -- Update outputs + f_out <= r; + wishbone_out <= r_int.w; end process; end architecture behaviour; From a8f8c54b770750cf0978e2348996a46650dd3c5a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Sep 2019 15:02:18 +1000 Subject: [PATCH 2/8] Move debug execute output into decode2 This covers all units, and we avoid double printing. Signed-off-by: Anton Blanchard --- decode2.vhdl | 9 +++++++++ execute1.vhdl | 2 -- loadstore1.vhdl | 5 ----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/decode2.vhdl b/decode2.vhdl index 3e4b022..3aff41e 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -188,6 +188,15 @@ begin decode2_0: process(clk) begin if rising_edge(clk) then + if rin.e.valid = '1' then + report "execute " & to_hstring(rin.e.nia); + end if; + if rin.l.valid = '1' then + report "execute " & to_hstring(rin.e.nia); + end if; + if rin.m.valid = '1' then + report "execute " & to_hstring(rin.e.nia); + end if; r <= rin; r_int <= rin_int; end if; diff --git a/execute1.vhdl b/execute1.vhdl index d6076a9..cbb4049 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -79,8 +79,6 @@ begin v.e.valid := '1'; v.e.write_reg := e_in.write_reg; - report "execute " & to_hstring(e_in.nia); - case_0: case e_in.insn_type is when OP_ILLEGAL => diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 20b2f9a..bf006d9 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -28,11 +28,6 @@ begin begin if rising_edge(clk) then l <= l_in; - - if l_in.valid = '1' then - report "execute " & to_hstring(l_in.nia); - end if; - end if; end process; From 819f8200905fa4ab7b6eafef8cb42606d6982bd9 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Sep 2019 15:39:50 +1000 Subject: [PATCH 3/8] Register outputs on loadstore1 Signed-off-by: Anton Blanchard --- loadstore1.vhdl | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/loadstore1.vhdl b/loadstore1.vhdl index bf006d9..f35b64d 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -13,36 +13,46 @@ entity loadstore1 is clk : in std_ulogic; l_in : in Decode2ToLoadstore1Type; + l_out : out Loadstore1ToLoadstore2Type ); end loadstore1; architecture behave of loadstore1 is - signal l : Decode2ToLoadstore1Type; + signal r, rin : Loadstore1ToLoadstore2Type; signal lsu_sum : std_ulogic_vector(63 downto 0); begin -- Calculate the address in the first cycle - lsu_sum <= std_ulogic_vector(unsigned(l.addr1) + unsigned(l.addr2)) when l.valid = '1' else (others => '0'); + lsu_sum <= std_ulogic_vector(unsigned(l_in.addr1) + unsigned(l_in.addr2)) when l_in.valid = '1' else (others => '0'); loadstore1_0: process(clk) begin if rising_edge(clk) then - l <= l_in; + r <= rin; end if; end process; loadstore1_1: process(all) + variable v : Loadstore1ToLoadstore2Type; begin - l_out.valid <= l.valid; - l_out.load <= l.load; - l_out.data <= l.data; - l_out.write_reg <= l.write_reg; - l_out.length <= l.length; - l_out.byte_reverse <= l.byte_reverse; - l_out.sign_extend <= l.sign_extend; - l_out.update <= l.update; - l_out.update_reg <= l.update_reg; - - l_out.addr <= lsu_sum; + v := r; + + v.valid := l_in.valid; + v.load := l_in.load; + v.data := l_in.data; + v.write_reg := l_in.write_reg; + v.length := l_in.length; + v.byte_reverse := l_in.byte_reverse; + v.sign_extend := l_in.sign_extend; + v.update := l_in.update; + v.update_reg := l_in.update_reg; + + v.addr := lsu_sum; + + -- Update registers + rin <= v; + + -- Update outputs + l_out <= v; end process; end; From c7aa683ba8aa40eda15131c49e272187588fce4c Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Sep 2019 15:40:20 +1000 Subject: [PATCH 4/8] Register outputs on execute2 Signed-off-by: Anton Blanchard --- execute2.vhdl | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/execute2.vhdl b/execute2.vhdl index 851e58f..c7cf61e 100644 --- a/execute2.vhdl +++ b/execute2.vhdl @@ -20,29 +20,38 @@ entity execute2 is end execute2; architecture behave of execute2 is - signal e: Execute1ToExecute2Type; + signal r, rin : Execute2ToWritebackType; begin execute2_0: process(clk) begin - if (rising_edge(clk)) then - e <= e_in; + if rising_edge(clk) then + r <= rin; end if; end process; execute2_1: process(all) + variable v : Execute2ToWritebackType; begin - e_out.valid <= e.valid; - e_out.write_enable <= e.write_enable; - e_out.write_reg <= e.write_reg; - e_out.write_data <= e.write_data; - e_out.write_cr_enable <= e.write_cr_enable; - e_out.write_cr_mask <= e.write_cr_mask; - e_out.write_cr_data <= e.write_cr_data; - - if e.valid = '1' and e.rc = '1' then - e_out.write_cr_enable <= '1'; - e_out.write_cr_mask <= num_to_fxm(0); - e_out.write_cr_data <= ppc_cmpi('1', e.write_data, x"0000") & x"0000000"; + v := rin; + + v.valid := e_in.valid; + v.write_enable := e_in.write_enable; + v.write_reg := e_in.write_reg; + v.write_data := e_in.write_data; + v.write_cr_enable := e_in.write_cr_enable; + v.write_cr_mask := e_in.write_cr_mask; + v.write_cr_data := e_in.write_cr_data; + + if e_in.valid = '1' and e_in.rc = '1' then + v.write_cr_enable := '1'; + v.write_cr_mask := num_to_fxm(0); + v.write_cr_data := ppc_cmpi('1', e_in.write_data, x"0000") & x"0000000"; end if; + + -- Update registers + rin <= v; + + -- Update outputs + e_out <= v; end process; end; From 9fe8d211eba24eb92273c03f098be2ccc1517565 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Sep 2019 16:04:39 +1000 Subject: [PATCH 5/8] Register outputs on writeback Signed-off-by: Anton Blanchard --- writeback.vhdl | 101 +++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/writeback.vhdl b/writeback.vhdl index 5a6bbe4..d37c4b1 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -21,74 +21,91 @@ entity writeback is end entity writeback; architecture behaviour of writeback is - signal e : Execute2ToWritebackType; - signal l : Loadstore2ToWritebackType; - signal m : MultiplyToWritebackType; - signal w_tmp : WritebackToRegisterFileType; - signal c_tmp : WritebackToCrFileType; + type reg_internal_type is record + complete : std_ulogic; + end record; + type reg_type is record + w : WritebackToRegisterFileType; + c : WritebackToCrFileType; + end record; + signal r, rin : reg_type; + signal r_int, rin_int : reg_internal_type; begin writeback_0: process(clk) begin if rising_edge(clk) then - e <= e_in; - l <= l_in; - m <= m_in; + r <= rin; + r_int <= rin_int; end if; end process; - w_out <= w_tmp; - c_out <= c_tmp; - - complete_out <= '1' when e.valid or l.valid or m.valid else '0'; - writeback_1: process(all) variable x: std_ulogic_vector(0 downto 0); variable y: std_ulogic_vector(0 downto 0); variable z: std_ulogic_vector(0 downto 0); + variable v : reg_type; + variable v_int : reg_internal_type; begin - x := "" & e.valid; - y := "" & l.valid; - z := "" & m.valid; + v := r; + v_int := r_int; + + x := "" & e_in.valid; + y := "" & l_in.valid; + z := "" & m_in.valid; assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) + to_integer(unsigned(z))) <= 1; - x := "" & e.write_enable; - y := "" & l.write_enable; - z := "" & m.write_reg_enable; + x := "" & e_in.write_enable; + y := "" & l_in.write_enable; + z := "" & m_in.write_reg_enable; assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) + to_integer(unsigned(z))) <= 1; - assert not(e.write_cr_enable = '1' and m.write_cr_enable = '1'); + assert not(e_in.write_cr_enable = '1' and m_in.write_cr_enable = '1'); - w_tmp <= WritebackToRegisterFileInit; - c_tmp <= WritebackToCrFileInit; + v.w := WritebackToRegisterFileInit; + v.c := WritebackToCrFileInit; - if e.write_enable = '1' then - w_tmp.write_reg <= e.write_reg; - w_tmp.write_data <= e.write_data; - w_tmp.write_enable <= '1'; + v_int.complete := '0'; + if e_in.valid = '1' or l_in.valid = '1' or m_in.valid = '1' then + v_int.complete := '1'; end if; - if e.write_cr_enable = '1' then - c_tmp.write_cr_enable <= '1'; - c_tmp.write_cr_mask <= e.write_cr_mask; - c_tmp.write_cr_data <= e.write_cr_data; + if e_in.write_enable = '1' then + v.w.write_reg := e_in.write_reg; + v.w.write_data := e_in.write_data; + v.w.write_enable := '1'; end if; - if l.write_enable = '1' then - w_tmp.write_reg <= l.write_reg; - w_tmp.write_data <= l.write_data; - w_tmp.write_enable <= '1'; + if e_in.write_cr_enable = '1' then + v.c.write_cr_enable := '1'; + v.c.write_cr_mask := e_in.write_cr_mask; + v.c.write_cr_data := e_in.write_cr_data; end if; - if m.write_reg_enable = '1' then - w_tmp.write_enable <= '1'; - w_tmp.write_reg <= m.write_reg_nr; - w_tmp.write_data <= m.write_reg_data; + if l_in.write_enable = '1' then + v.w.write_reg := l_in.write_reg; + v.w.write_data := l_in.write_data; + v.w.write_enable := '1'; end if; - if m.write_cr_enable = '1' then - c_tmp.write_cr_enable <= '1'; - c_tmp.write_cr_mask <= m.write_cr_mask; - c_tmp.write_cr_data <= m.write_cr_data; + if m_in.write_reg_enable = '1' then + v.w.write_enable := '1'; + v.w.write_reg := m_in.write_reg_nr; + v.w.write_data := m_in.write_reg_data; end if; + + if m_in.write_cr_enable = '1' then + v.c.write_cr_enable := '1'; + v.c.write_cr_mask := m_in.write_cr_mask; + v.c.write_cr_data := m_in.write_cr_data; + end if; + + -- Update registers + rin <= v; + rin_int <= v_int; + + -- Update outputs + complete_out <= r_int.complete; + w_out <= r.w; + c_out <= r.c; end process; end; From 68533c4cfb4d91dff51c7d015d66ec22d5215714 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Sep 2019 16:22:58 +1000 Subject: [PATCH 6/8] Reduce multiply to 2 cycles We want all non load/store ops to take 2 cycles to make tracking write back easier. Signed-off-by: Anton Blanchard --- multiply.vhdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multiply.vhdl b/multiply.vhdl index 4d9637f..9aa4316 100644 --- a/multiply.vhdl +++ b/multiply.vhdl @@ -10,7 +10,7 @@ use work.crhelpers.all; entity multiply is generic ( - PIPELINE_DEPTH : natural := 6 + PIPELINE_DEPTH : natural := 2 ); port ( clk : in std_logic; From a2df2a10a22966c1820da7ba9ea769d11d2046e2 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 11 Sep 2019 07:16:56 +1000 Subject: [PATCH 7/8] Remove sim console We can force all existing code to use the UART console by passing 0 in bit zero of the sim config register. Signed-off-by: Anton Blanchard --- decode1.vhdl | 12 ------------ decode_types.vhdl | 5 ++--- execute1.vhdl | 28 +++------------------------- 3 files changed, 5 insertions(+), 40 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 735cf50..38d31dd 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -222,9 +222,6 @@ architecture behaviour of decode1 is PPC_XOR => (ALU, OP_XOR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), PPC_XORI => (ALU, OP_XOR, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), PPC_XORIS => (ALU, OP_XOR, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_SIM_READ => (ALU, OP_SIM_READ, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_SIM_POLL => (ALU, OP_SIM_POLL, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_SIM_WRITE => (ALU, OP_SIM_WRITE, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), PPC_SIM_CONFIG => (ALU, OP_SIM_CONFIG,NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), others => decode_rom_init @@ -834,15 +831,6 @@ begin elsif std_match(f_in.insn, "011011--------------------------") then report "PPC_xoris"; ppc_insn := PPC_XORIS; - elsif std_match(f_in.insn, "000001---------------0000000000-") then - report "PPC_SIM_READ"; - ppc_insn := PPC_SIM_READ; - elsif std_match(f_in.insn, "000001---------------0000000001-") then - report "PPC_SIM_POLL"; - ppc_insn := PPC_SIM_POLL; - elsif std_match(f_in.insn, "000001---------------0000000010-") then - report "PPC_SIM_WRITE"; - ppc_insn := PPC_SIM_WRITE; elsif std_match(f_in.insn, "000001---------------0000000011-") then report "PPC_SIM_CONFIG"; ppc_insn := PPC_SIM_CONFIG; diff --git a/decode_types.vhdl b/decode_types.vhdl index 1797641..faf1305 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -37,7 +37,7 @@ package decode_types is PPC_STWCX, PPC_STWU, PPC_STWUX, PPC_STWX, PPC_SUBF, PPC_SUBFC, PPC_SUBFE, PPC_SUBFIC, PPC_SUBFME, PPC_SUBFZE, PPC_SYNC, PPC_TD, PPC_TDI, PPC_TW, PPC_TWI, PPC_XOR, PPC_XORI, PPC_XORIS, - PPC_SIM_READ, PPC_SIM_POLL, PPC_SIM_WRITE, PPC_SIM_CONFIG); + PPC_SIM_CONFIG); type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, OP_ADDC, OP_ADDEX, OP_ADDME, OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BA, OP_BC, @@ -59,8 +59,7 @@ package decode_types is OP_RLDIMI, OP_RLWIMI, OP_RLWINM, OP_RLWNM, OP_SETB, OP_SLD, OP_SLW, OP_SRAD, OP_SRADI, OP_SRAW, OP_SRAWI, OP_SRD, OP_SRW, OP_SUBF, OP_SUBFC, OP_SUBFME, OP_SYNC, OP_TD, OP_TDI, OP_TW, - OP_TWI, OP_XOR, OP_SIM_READ, OP_SIM_POLL, OP_SIM_WRITE, - OP_SIM_CONFIG); + OP_TWI, OP_XOR, OP_SIM_CONFIG); type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RS); type input_reg_b_t is (NONE, RB, RS, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS); diff --git a/execute1.vhdl b/execute1.vhdl index cbb4049..b29bc0d 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -320,33 +320,11 @@ begin result := ppc_xor(e_in.read_data1, e_in.read_data2); result_en := 1; - -- sim console - when OP_SIM_READ => - if SIM = true then - sim_console_read(result); - result_en := 1; - else - terminate_out <= '1'; - report "illegal"; - end if; - when OP_SIM_POLL => - if SIM = true then - sim_console_poll(result); - result_en := 1; - else - terminate_out <= '1'; - report "illegal"; - end if; - when OP_SIM_WRITE => - if SIM = true then - sim_console_write(e_in.read_data1); - else - terminate_out <= '1'; - report "illegal"; - end if; when OP_SIM_CONFIG => + -- bit 0 was used to select the microwatt console, which + -- we no longer support. if SIM = true then - result := x"0000000000000001"; + result := x"0000000000000000"; else result := x"0000000000000000"; end if; From 4528ef2b43ca01b221fe938b17956e9e0a2b2c00 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 11 Sep 2019 07:55:35 +1000 Subject: [PATCH 8/8] Reformat core.vhdl --- core.vhdl | 313 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 191 insertions(+), 122 deletions(-) diff --git a/core.vhdl b/core.vhdl index e29c519..87401f0 100644 --- a/core.vhdl +++ b/core.vhdl @@ -7,132 +7,201 @@ use work.common.all; use work.wishbone_types.all; entity core is - generic ( - SIM : boolean := false - ); - port ( - clk : in std_logic; - rst : in std_logic; - - wishbone_insn_in : in wishbone_slave_out; - wishbone_insn_out : out wishbone_master_out; - - wishbone_data_in : in wishbone_slave_out; - wishbone_data_out : out wishbone_master_out; - - -- Added for debug, ghdl doesn't support external names unfortunately - registers : out regfile; - terminate_out : out std_ulogic - ); + generic ( + SIM : boolean := false + ); + port ( + clk : in std_logic; + rst : in std_logic; + + wishbone_insn_in : in wishbone_slave_out; + wishbone_insn_out : out wishbone_master_out; + + wishbone_data_in : in wishbone_slave_out; + wishbone_data_out : out wishbone_master_out; + + -- Added for debug, ghdl doesn't support external names unfortunately + registers : out regfile; + terminate_out : out std_ulogic + ); end core; architecture behave of core is - -- fetch signals - signal fetch1_to_fetch2: Fetch1ToFetch2Type; - signal fetch2_to_decode1: Fetch2ToDecode1Type; - - -- decode signals - signal decode1_to_decode2: Decode1ToDecode2Type; - signal decode2_to_execute1: Decode2ToExecute1Type; - - -- register file signals - signal register_file_to_decode2: RegisterFileToDecode2Type; - signal decode2_to_register_file: Decode2ToRegisterFileType; - signal writeback_to_register_file: WritebackToRegisterFileType; - - -- CR file signals - signal decode2_to_cr_file: Decode2ToCrFileType; - signal cr_file_to_decode2: CrFileToDecode2Type; - signal writeback_to_cr_file: WritebackToCrFileType; - - -- execute signals - signal execute1_to_execute2: Execute1ToExecute2Type; - signal execute2_to_writeback: Execute2ToWritebackType; - signal execute1_to_fetch1: Execute1ToFetch1Type; - - -- load store signals - signal decode2_to_loadstore1: Decode2ToLoadstore1Type; - signal loadstore1_to_loadstore2: Loadstore1ToLoadstore2Type; - signal loadstore2_to_writeback: Loadstore2ToWritebackType; - - -- multiply signals - signal decode2_to_multiply: Decode2ToMultiplyType; - signal multiply_to_writeback: MultiplyToWritebackType; - - -- local signals - signal fetch1_stall_in : std_ulogic; - signal fetch2_stall_in : std_ulogic; - signal fetch2_stall_out : std_ulogic; - signal decode1_stall_in : std_ulogic; - signal decode2_stall_out : std_ulogic; - - signal flush: std_ulogic; - - signal complete: std_ulogic; - - signal terminate: std_ulogic; + -- fetch signals + signal fetch1_to_fetch2: Fetch1ToFetch2Type; + signal fetch2_to_decode1: Fetch2ToDecode1Type; + + -- decode signals + signal decode1_to_decode2: Decode1ToDecode2Type; + signal decode2_to_execute1: Decode2ToExecute1Type; + + -- register file signals + signal register_file_to_decode2: RegisterFileToDecode2Type; + signal decode2_to_register_file: Decode2ToRegisterFileType; + signal writeback_to_register_file: WritebackToRegisterFileType; + + -- CR file signals + signal decode2_to_cr_file: Decode2ToCrFileType; + signal cr_file_to_decode2: CrFileToDecode2Type; + signal writeback_to_cr_file: WritebackToCrFileType; + + -- execute signals + signal execute1_to_execute2: Execute1ToExecute2Type; + signal execute2_to_writeback: Execute2ToWritebackType; + signal execute1_to_fetch1: Execute1ToFetch1Type; + + -- load store signals + signal decode2_to_loadstore1: Decode2ToLoadstore1Type; + signal loadstore1_to_loadstore2: Loadstore1ToLoadstore2Type; + signal loadstore2_to_writeback: Loadstore2ToWritebackType; + + -- multiply signals + signal decode2_to_multiply: Decode2ToMultiplyType; + signal multiply_to_writeback: MultiplyToWritebackType; + + -- local signals + signal fetch1_stall_in : std_ulogic; + signal fetch2_stall_in : std_ulogic; + signal fetch2_stall_out : std_ulogic; + signal decode1_stall_in : std_ulogic; + signal decode2_stall_out : std_ulogic; + + signal flush: std_ulogic; + + signal complete: std_ulogic; + + signal terminate: std_ulogic; begin - terminate_out <= terminate; - - fetch1_0: entity work.fetch1 - generic map (RESET_ADDRESS => (others => '0')) - port map (clk => clk, rst => rst, stall_in => fetch1_stall_in, flush_in => flush, - e_in => execute1_to_fetch1, f_out => fetch1_to_fetch2); - - fetch1_stall_in <= fetch2_stall_out or decode2_stall_out; - - fetch2_0: entity work.fetch2 - port map (clk => clk, rst => rst, stall_in => fetch2_stall_in, - stall_out => fetch2_stall_out, flush_in => flush, wishbone_in => wishbone_insn_in, - wishbone_out => wishbone_insn_out, f_in => fetch1_to_fetch2, - f_out => fetch2_to_decode1); - - fetch2_stall_in <= decode2_stall_out; - - decode1_0: entity work.decode1 - port map (clk => clk, rst => rst, stall_in => decode1_stall_in, flush_in => flush, f_in => fetch2_to_decode1, d_out => decode1_to_decode2); - - decode1_stall_in <= decode2_stall_out; - - decode2_0: entity work.decode2 - port map (clk => clk, rst => rst, stall_out => decode2_stall_out, flush_in => flush, - complete_in => complete, d_in => decode1_to_decode2, e_out => decode2_to_execute1, - l_out => decode2_to_loadstore1, m_out => decode2_to_multiply, - r_in => register_file_to_decode2, r_out => decode2_to_register_file, - c_in => cr_file_to_decode2, c_out => decode2_to_cr_file); - - register_file_0: entity work.register_file - port map (clk => clk, d_in => decode2_to_register_file, - d_out => register_file_to_decode2, w_in => writeback_to_register_file, - registers_out => registers); - - cr_file_0: entity work.cr_file - port map (clk => clk, d_in => decode2_to_cr_file, d_out => cr_file_to_decode2, - w_in => writeback_to_cr_file); - - execute1_0: entity work.execute1 - generic map (SIM => SIM) - port map (clk => clk, flush_out => flush, e_in => decode2_to_execute1, f_out => execute1_to_fetch1, - e_out => execute1_to_execute2, terminate_out => terminate); - - execute2_0: entity work.execute2 - port map (clk => clk, e_in => execute1_to_execute2, e_out => execute2_to_writeback); - - loadstore1_0: entity work.loadstore1 - port map (clk => clk, l_in => decode2_to_loadstore1, l_out => loadstore1_to_loadstore2); - - loadstore2_0: entity work.loadstore2 - port map (clk => clk, l_in => loadstore1_to_loadstore2, - w_out => loadstore2_to_writeback, m_in => wishbone_data_in, - m_out => wishbone_data_out); - - multiply_0: entity work.multiply - port map (clk => clk, m_in => decode2_to_multiply, m_out => multiply_to_writeback); - - writeback_0: entity work.writeback - port map (clk => clk, e_in => execute2_to_writeback, l_in => loadstore2_to_writeback, - m_in => multiply_to_writeback, w_out => writeback_to_register_file, - c_out => writeback_to_cr_file, complete_out => complete); + terminate_out <= terminate; + + fetch1_0: entity work.fetch1 + generic map ( + RESET_ADDRESS => (others => '0') + ) + port map ( + clk => clk, + rst => rst, + stall_in => fetch1_stall_in, + flush_in => flush, + e_in => execute1_to_fetch1, + f_out => fetch1_to_fetch2 + ); + + fetch1_stall_in <= fetch2_stall_out or decode2_stall_out; + + fetch2_0: entity work.fetch2 + port map ( + clk => clk, + rst => rst, + stall_in => fetch2_stall_in, + stall_out => fetch2_stall_out, + flush_in => flush, + wishbone_in => wishbone_insn_in, + wishbone_out => wishbone_insn_out, + f_in => fetch1_to_fetch2, + f_out => fetch2_to_decode1 + ); + + fetch2_stall_in <= decode2_stall_out; + + decode1_0: entity work.decode1 + port map ( + clk => clk, + rst => rst, + stall_in => decode1_stall_in, + flush_in => flush, + f_in => fetch2_to_decode1, + d_out => decode1_to_decode2 + ); + + decode1_stall_in <= decode2_stall_out; + + decode2_0: entity work.decode2 + port map ( + clk => clk, + rst => rst, + stall_out => decode2_stall_out, + flush_in => flush, + complete_in => complete, + d_in => decode1_to_decode2, + e_out => decode2_to_execute1, + l_out => decode2_to_loadstore1, + m_out => decode2_to_multiply, + r_in => register_file_to_decode2, + r_out => decode2_to_register_file, + c_in => cr_file_to_decode2, + c_out => decode2_to_cr_file + ); + + register_file_0: entity work.register_file + port map ( + clk => clk, + d_in => decode2_to_register_file, + d_out => register_file_to_decode2, + w_in => writeback_to_register_file, + registers_out => registers); + + cr_file_0: entity work.cr_file + port map ( + clk => clk, + d_in => decode2_to_cr_file, + d_out => cr_file_to_decode2, + w_in => writeback_to_cr_file + ); + + execute1_0: entity work.execute1 + generic map ( + SIM => SIM + ) + port map ( + clk => clk, + flush_out => flush, + e_in => decode2_to_execute1, + f_out => execute1_to_fetch1, + e_out => execute1_to_execute2, + terminate_out => terminate + ); + + execute2_0: entity work.execute2 + port map ( + clk => clk, + e_in => execute1_to_execute2, + e_out => execute2_to_writeback + ); + + loadstore1_0: entity work.loadstore1 + port map ( + clk => clk, + l_in => decode2_to_loadstore1, + l_out => loadstore1_to_loadstore2 + ); + + loadstore2_0: entity work.loadstore2 + port map ( + clk => clk, + l_in => loadstore1_to_loadstore2, + w_out => loadstore2_to_writeback, + m_in => wishbone_data_in, + m_out => wishbone_data_out + ); + + multiply_0: entity work.multiply + port map ( + clk => clk, + m_in => decode2_to_multiply, + m_out => multiply_to_writeback + ); + + writeback_0: entity work.writeback + port map ( + clk => clk, + e_in => execute2_to_writeback, + l_in => loadstore2_to_writeback, + m_in => multiply_to_writeback, + w_out => writeback_to_register_file, + c_out => writeback_to_cr_file, + complete_out => complete + ); end behave;