Separate issue control into its own unit

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
pull/100/head
Anton Blanchard 5 years ago committed by Anton Blanchard
parent 0a0fe03767
commit d5346d0abf

@ -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

@ -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;

@ -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

Loading…
Cancel
Save