mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-15 20:26:20 +00:00
Merge pull request #100 from antonblanchard/gpr-hazard-5-a
Separate issue control into its own unit
This commit is contained in:
2
Makefile
2
Makefile
@@ -23,7 +23,7 @@ countzero_tb.o: common.o glibc_random.o 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
|
||||
|
||||
113
control.vhdl
Normal file
113
control.vhdl
Normal file
@@ -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;
|
||||
111
decode2.vhdl
111
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;
|
||||
|
||||
@@ -20,6 +20,7 @@ filesets:
|
||||
- sim_console.vhdl
|
||||
- logical.vhdl
|
||||
- countzero.vhdl
|
||||
- control.vhdl
|
||||
- execute1.vhdl
|
||||
- execute2.vhdl
|
||||
- loadstore1.vhdl
|
||||
|
||||
Reference in New Issue
Block a user