Add GPR hazard detection
[microwatt.git] / control.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 entity control is
5 generic (
6 PIPELINE_DEPTH : natural := 2
7 );
8 port (
9 clk : in std_ulogic;
10 rst : in std_ulogic;
11
12 complete_in : in std_ulogic;
13 valid_in : in std_ulogic;
14 flush_in : in std_ulogic;
15 sgl_pipe_in : in std_ulogic;
16 stop_mark_in : in std_ulogic;
17
18 gpr_write_valid_in : in std_ulogic;
19 gpr_write_in : in std_ulogic_vector(4 downto 0);
20
21 gpr_a_read_valid_in : in std_ulogic;
22 gpr_a_read_in : in std_ulogic_vector(4 downto 0);
23
24 gpr_b_read_valid_in : in std_ulogic;
25 gpr_b_read_in : in std_ulogic_vector(4 downto 0);
26
27 gpr_c_read_valid_in : in std_ulogic;
28 gpr_c_read_in : in std_ulogic_vector(4 downto 0);
29
30 valid_out : out std_ulogic;
31 stall_out : out std_ulogic;
32 stopped_out : out std_ulogic
33 );
34 end entity control;
35
36 architecture rtl of control is
37 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
38
39 type reg_internal_type is record
40 state : state_type;
41 outstanding : integer range -1 to PIPELINE_DEPTH+2; -- XXX ?
42 end record;
43 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
44
45 signal r_int, rin_int : reg_internal_type := reg_internal_init;
46
47 signal stall_a_out, stall_b_out, stall_c_out : std_ulogic;
48
49 signal gpr_write_valid : std_ulogic := '0';
50 begin
51 gpr_hazard0: entity work.gpr_hazard
52 generic map (
53 PIPELINE_DEPTH => 2
54 )
55 port map (
56 clk => clk,
57
58 gpr_write_valid_in => gpr_write_valid,
59 gpr_write_in => gpr_write_in,
60 gpr_read_valid_in => gpr_a_read_valid_in,
61 gpr_read_in => gpr_a_read_in,
62
63 stall_out => stall_a_out
64 );
65
66 gpr_hazard1: entity work.gpr_hazard
67 generic map (
68 PIPELINE_DEPTH => 2
69 )
70 port map (
71 clk => clk,
72
73 gpr_write_valid_in => gpr_write_valid,
74 gpr_write_in => gpr_write_in,
75 gpr_read_valid_in => gpr_b_read_valid_in,
76 gpr_read_in => gpr_b_read_in,
77
78 stall_out => stall_b_out
79 );
80
81 gpr_hazard2: entity work.gpr_hazard
82 generic map (
83 PIPELINE_DEPTH => 2
84 )
85 port map (
86 clk => clk,
87
88 gpr_write_valid_in => gpr_write_valid,
89 gpr_write_in => gpr_write_in,
90 gpr_read_valid_in => gpr_c_read_valid_in,
91 gpr_read_in => gpr_c_read_in,
92
93 stall_out => stall_c_out
94 );
95
96 control0: process(clk)
97 begin
98 if rising_edge(clk) then
99 r_int <= rin_int;
100 end if;
101 end process;
102
103 control1 : process(all)
104 variable v_int : reg_internal_type;
105 variable valid_tmp : std_ulogic;
106 variable stall_tmp : std_ulogic;
107 begin
108 v_int := r_int;
109
110 -- asynchronous
111 valid_tmp := valid_in and not flush_in;
112 stall_tmp := '0';
113
114 if complete_in = '1' then
115 assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
116 v_int.outstanding := r_int.outstanding - 1;
117 end if;
118
119 -- Handle debugger stop
120 stopped_out <= '0';
121 if stop_mark_in = '1' and v_int.outstanding = 0 then
122 stopped_out <= '1';
123 end if;
124
125 -- state machine to handle instructions that must be single
126 -- through the pipeline.
127 case r_int.state is
128 when IDLE =>
129 if valid_tmp = '1' then
130 if (sgl_pipe_in = '1') then
131 if v_int.outstanding /= 0 then
132 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
133 stall_tmp := '1';
134 else
135 -- send insn out and wait on it to complete
136 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
137 end if;
138 else
139 -- let it go out if there are no GPR hazards
140 stall_tmp := stall_a_out or stall_b_out or stall_c_out;
141 end if;
142 end if;
143
144 when WAIT_FOR_PREV_TO_COMPLETE =>
145 if v_int.outstanding = 0 then
146 -- send insn out and wait on it to complete
147 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
148 else
149 stall_tmp := '1';
150 end if;
151
152 when WAIT_FOR_CURR_TO_COMPLETE =>
153 if v_int.outstanding = 0 then
154 v_int.state := IDLE;
155 -- XXX Don't replicate this
156 if valid_tmp = '1' then
157 if (sgl_pipe_in = '1') then
158 if v_int.outstanding /= 0 then
159 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
160 stall_tmp := '1';
161 else
162 -- send insn out and wait on it to complete
163 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
164 end if;
165 else
166 -- let it go out if there are no GPR hazards
167 stall_tmp := stall_a_out or stall_b_out or stall_c_out;
168 end if;
169 end if;
170 else
171 stall_tmp := '1';
172 end if;
173 end case;
174
175 if stall_tmp = '1' then
176 valid_tmp := '0';
177 end if;
178
179 if valid_tmp = '1' then
180 v_int.outstanding := v_int.outstanding + 1;
181 gpr_write_valid <= gpr_write_valid_in;
182 else
183 gpr_write_valid <= '0';
184 end if;
185
186 if rst = '1' then
187 v_int.state := IDLE;
188 v_int.outstanding := 0;
189 stall_tmp := '0';
190 end if;
191
192 -- update outputs
193 valid_out <= valid_tmp;
194 stall_out <= stall_tmp;
195
196 -- update registers
197 rin_int <= v_int;
198 end process;
199 end;