From d5346d0abf6fdae7ac55706c3be43984ff6df3a8 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 14 Oct 2019 12:40:23 +1100 Subject: [PATCH] Separate issue control into its own unit Signed-off-by: Anton Blanchard --- Makefile | 2 +- control.vhdl | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ decode2.vhdl | 111 +++++++++++++----------------------------------- microwatt.core | 1 + 4 files changed, 145 insertions(+), 82 deletions(-) create mode 100644 control.vhdl diff --git a/Makefile b/Makefile index 2694556..a895e5c 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ countzero.o: cr_file.o: common.o crhelpers.o: common.o decode1.o: common.o decode_types.o -decode2.o: decode_types.o common.o helpers.o insn_helpers.o +decode2.o: decode_types.o common.o helpers.o insn_helpers.o control.o decode_types.o: execute1.o: decode_types.o common.o helpers.o crhelpers.o insn_helpers.o ppc_fx_insns.o rotator.o logical.o countzero.o execute2.o: common.o crhelpers.o ppc_fx_insns.o diff --git a/control.vhdl b/control.vhdl new file mode 100644 index 0000000..35a7e17 --- /dev/null +++ b/control.vhdl @@ -0,0 +1,113 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity control is + generic ( + PIPELINE_DEPTH : natural := 2 + ); + port ( + clk : in std_ulogic; + rst : in std_ulogic; + + complete_in : in std_ulogic; + valid_in : in std_ulogic; + flush_in : in std_ulogic; + sgl_pipe_in : in std_ulogic; + stop_mark_in : in std_ulogic; + + valid_out : out std_ulogic; + stall_out : out std_ulogic; + stopped_out : out std_ulogic + ); +end entity control; + +architecture rtl of control is + 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 range -1 to PIPELINE_DEPTH+1; + end record; + constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0); + + signal r_int, rin_int : reg_internal_type := reg_internal_init; +begin + control0: process(clk) + begin + if rising_edge(clk) then + r_int <= rin_int; + end if; + end process; + + control1 : process(all) + variable v_int : reg_internal_type; + variable valid_tmp : std_ulogic; + begin + v_int := r_int; + + -- asynchronous + valid_tmp := valid_in and not flush_in; + stall_out <= '0'; + + if complete_in = '1' then + assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure; + v_int.outstanding := r_int.outstanding - 1; + end if; + + -- Handle debugger stop + stopped_out <= '0'; + if stop_mark_in = '1' and v_int.outstanding = 0 then + stopped_out <= '1'; + end if; + + -- state machine to handle instructions that must be single + -- through the pipeline. + case r_int.state is + when IDLE => + if (flush_in = '0') and (valid_tmp = '1') and (sgl_pipe_in = '1') then + if v_int.outstanding /= 0 then + v_int.state := WAIT_FOR_PREV_TO_COMPLETE; + valid_tmp := '0'; + stall_out <= '1'; + 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 + valid_tmp := '0'; + stall_out <= '1'; + end if; + + when WAIT_FOR_CURR_TO_COMPLETE => + if v_int.outstanding = 0 then + v_int.state := IDLE; + else + valid_tmp := '0'; + stall_out <= '1'; + end if; + end case; + + -- track outstanding instructions + if valid_tmp = '1' then + v_int.outstanding := v_int.outstanding + 1; + end if; + + if rst = '1' then + v_int.state := IDLE; + v_int.outstanding := 0; + stall_out <= '0'; + end if; + + -- update outputs + valid_out <= valid_tmp; + + -- update registers + rin_int <= v_int; + end process; +end; diff --git a/decode2.vhdl b/decode2.vhdl index 05819ee..3ba1079 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -36,13 +36,6 @@ entity decode2 is end entity decode2; architecture behaviour of decode2 is - 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 range -1 to 2; - end record; - type reg_type is record e : Decode2ToExecute1Type; m : Decode2ToMultiplyType; @@ -50,7 +43,6 @@ architecture behaviour of decode2 is l : Decode2ToLoadstore1Type; end record; - signal r_int, rin_int : reg_internal_type; signal r, rin : reg_type; type decode_input_reg_t is record @@ -134,18 +126,37 @@ architecture behaviour of decode2 is return '0'; end case; end; + + signal control_valid_in : std_ulogic; + signal control_valid_out : std_ulogic; + signal control_sgl_pipe : std_logic; begin + control_0: entity work.control + generic map ( + PIPELINE_DEPTH => 2 + ) + port map ( + clk => clk, + rst => rst, + + complete_in => complete_in, + valid_in => control_valid_in, + flush_in => flush_in, + sgl_pipe_in => control_sgl_pipe, + stop_mark_in => d_in.stop_mark, + + valid_out => control_valid_out, + stall_out => stall_out, + stopped_out => stopped_out + ); decode2_0: process(clk) begin if rising_edge(clk) then - assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure; - if rin.e.valid = '1' or rin.l.valid = '1' or rin.m.valid = '1' or rin.d.valid = '1' then report "execute " & to_hstring(rin.e.nia); end if; r <= rin; - r_int <= rin_int; end if; end process; @@ -157,17 +168,14 @@ begin 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 signed_division: std_ulogic; - variable is_valid : std_ulogic; begin v := r; - v_int := r_int; v.e := Decode2ToExecute1Init; v.l := Decode2ToLoadStore1Init; @@ -311,53 +319,9 @@ begin 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; - - -- Handle debugger stop - stopped_out <= '0'; - if d_in.stop_mark = '1' and v_int.outstanding = 0 then - stopped_out <= '1'; - end if; - - case v_int.state is - when IDLE => - if (flush_in = '0') and (is_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; + -- issue control + control_valid_in <= d_in.valid; + control_sgl_pipe <= d_in.decode.sgl_pipe; v.e.valid := '0'; v.m.valid := '0'; @@ -365,33 +329,19 @@ begin v.l.valid := '0'; case d_in.decode.unit is when ALU => - v.e.valid := is_valid; + v.e.valid := control_valid_out; when LDST => - v.l.valid := is_valid; + v.l.valid := control_valid_out; when MUL => - v.m.valid := is_valid; + v.m.valid := control_valid_out; when DIV => - v.d.valid := is_valid; + v.d.valid := control_valid_out; when NONE => - v.e.valid := is_valid; + v.e.valid := control_valid_out; v.e.insn_type := OP_ILLEGAL; end case; - if flush_in = '1' then - v.e.valid := '0'; - v.m.valid := '0'; - v.d.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' or v.d.valid = '1' then - v_int.outstanding := v_int.outstanding + 1; - end if; - if rst = '1' then - v_int.state := IDLE; - v_int.outstanding := 0; v.e := Decode2ToExecute1Init; v.l := Decode2ToLoadStore1Init; v.m := Decode2ToMultiplyInit; @@ -400,7 +350,6 @@ begin -- Update registers rin <= v; - rin_int <= v_int; -- Update outputs e_out <= r.e; diff --git a/microwatt.core b/microwatt.core index 2124896..5081453 100644 --- a/microwatt.core +++ b/microwatt.core @@ -20,6 +20,7 @@ filesets: - sim_console.vhdl - logical.vhdl - countzero.vhdl + - control.vhdl - execute1.vhdl - execute2.vhdl - loadstore1.vhdl