Rework pipeline, add stall and flush signals
authorAnton Blanchard <anton@linux.ibm.com>
Tue, 3 Sep 2019 23:36:30 +0000 (09:36 +1000)
committerAnton Blanchard <anton@ozlabs.org>
Wed, 11 Sep 2019 03:23:45 +0000 (13:23 +1000)
This adds stall and flush signals to the pipeline.

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
common.vhdl
core.vhdl
decode1.vhdl
decode2.vhdl
execute1.vhdl
fetch1.vhdl
fetch2.vhdl

index c12f8b1c9465b5da96524160e84fe41dfd096f1d..b2edeaf18881c6603d96fcf234453e7af64665bd 100644 (file)
@@ -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;
 
index 01a96696f781ef758f96c032f3a7e2002539c77a..e29c519997bc3609fbe11455b784f59fab6bb7bc 100644 (file)
--- 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;
index ecedd91b283c0c76f105e2795f13e6cc5e8de6bd..735cf50abc0e6b8e321d92113741a5c46033e556 100644 (file)
@@ -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;
index f59f3402510a7a9b70c70b0d5260735189e6a81c..3e4b022d3b4c698c60691ae8b94894b1c2e9ad17 100644 (file)
@@ -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;
index e57dd4fc91f20d6d8184bc865ac638f244c73be0..d6076a96626dade7b96ac163c0886edd7c5c06ff 100644 (file)
@@ -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;
index 458805e269300515add6aaef0ed3ac04ecd17b84..14ef8e8d1fa28dc91a09b64acd7013f9c81e2d80 100644 (file)
@@ -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;
index 6f252c89ed81a29a5a30d80e4c5950e9e8f8770c..6ae72693cfe60fa0f72199450df51f68eb18e80b 100644 (file)
@@ -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;