core: Use a busy signal rather than a stall
[microwatt.git] / control.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 library work;
5 use work.common.all;
6
7 entity control is
8 generic (
9 PIPELINE_DEPTH : natural := 2
10 );
11 port (
12 clk : in std_ulogic;
13 rst : in std_ulogic;
14
15 complete_in : in std_ulogic;
16 valid_in : in std_ulogic;
17 flush_in : in std_ulogic;
18 busy_in : in std_ulogic;
19 deferred : in std_ulogic;
20 sgl_pipe_in : in std_ulogic;
21 stop_mark_in : in std_ulogic;
22
23 gpr_write_valid_in : in std_ulogic;
24 gpr_write_in : in gspr_index_t;
25 gpr_bypassable : in std_ulogic;
26
27 update_gpr_write_valid : in std_ulogic;
28 update_gpr_write_reg : in gspr_index_t;
29
30 gpr_a_read_valid_in : in std_ulogic;
31 gpr_a_read_in : in gspr_index_t;
32
33 gpr_b_read_valid_in : in std_ulogic;
34 gpr_b_read_in : in gspr_index_t;
35
36 gpr_c_read_valid_in : in std_ulogic;
37 gpr_c_read_in : in gpr_index_t;
38
39 cr_read_in : in std_ulogic;
40 cr_write_in : in std_ulogic;
41
42 valid_out : out std_ulogic;
43 stall_out : out std_ulogic;
44 stopped_out : out std_ulogic;
45
46 gpr_bypass_a : out std_ulogic;
47 gpr_bypass_b : out std_ulogic;
48 gpr_bypass_c : out std_ulogic
49 );
50 end entity control;
51
52 architecture rtl of control is
53 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
54
55 type reg_internal_type is record
56 state : state_type;
57 outstanding : integer range -1 to PIPELINE_DEPTH+2;
58 end record;
59 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
60
61 signal r_int, rin_int : reg_internal_type := reg_internal_init;
62
63 signal stall_a_out : std_ulogic;
64 signal stall_b_out : std_ulogic;
65 signal stall_c_out : std_ulogic;
66 signal cr_stall_out : std_ulogic;
67
68 signal gpr_write_valid : std_ulogic := '0';
69 signal cr_write_valid : std_ulogic := '0';
70
71 signal gpr_c_read_in_fmt : std_ulogic_vector(5 downto 0);
72 begin
73 gpr_hazard0: entity work.gpr_hazard
74 generic map (
75 PIPELINE_DEPTH => PIPELINE_DEPTH
76 )
77 port map (
78 clk => clk,
79 busy_in => busy_in,
80 deferred => deferred,
81 complete_in => complete_in,
82 flush_in => flush_in,
83 issuing => valid_out,
84
85 gpr_write_valid_in => gpr_write_valid,
86 gpr_write_in => gpr_write_in,
87 bypass_avail => gpr_bypassable,
88 gpr_read_valid_in => gpr_a_read_valid_in,
89 gpr_read_in => gpr_a_read_in,
90
91 ugpr_write_valid => update_gpr_write_valid,
92 ugpr_write_reg => update_gpr_write_reg,
93
94 stall_out => stall_a_out,
95 use_bypass => gpr_bypass_a
96 );
97
98 gpr_hazard1: entity work.gpr_hazard
99 generic map (
100 PIPELINE_DEPTH => PIPELINE_DEPTH
101 )
102 port map (
103 clk => clk,
104 busy_in => busy_in,
105 deferred => deferred,
106 complete_in => complete_in,
107 flush_in => flush_in,
108 issuing => valid_out,
109
110 gpr_write_valid_in => gpr_write_valid,
111 gpr_write_in => gpr_write_in,
112 bypass_avail => gpr_bypassable,
113 gpr_read_valid_in => gpr_b_read_valid_in,
114 gpr_read_in => gpr_b_read_in,
115
116 ugpr_write_valid => update_gpr_write_valid,
117 ugpr_write_reg => update_gpr_write_reg,
118
119 stall_out => stall_b_out,
120 use_bypass => gpr_bypass_b
121 );
122
123 gpr_c_read_in_fmt <= "0" & gpr_c_read_in;
124
125 gpr_hazard2: entity work.gpr_hazard
126 generic map (
127 PIPELINE_DEPTH => PIPELINE_DEPTH
128 )
129 port map (
130 clk => clk,
131 busy_in => busy_in,
132 deferred => deferred,
133 complete_in => complete_in,
134 flush_in => flush_in,
135 issuing => valid_out,
136
137 gpr_write_valid_in => gpr_write_valid,
138 gpr_write_in => gpr_write_in,
139 bypass_avail => gpr_bypassable,
140 gpr_read_valid_in => gpr_c_read_valid_in,
141 gpr_read_in => gpr_c_read_in_fmt,
142
143 ugpr_write_valid => update_gpr_write_valid,
144 ugpr_write_reg => update_gpr_write_reg,
145
146 stall_out => stall_c_out,
147 use_bypass => gpr_bypass_c
148 );
149
150 cr_hazard0: entity work.cr_hazard
151 generic map (
152 PIPELINE_DEPTH => PIPELINE_DEPTH
153 )
154 port map (
155 clk => clk,
156 busy_in => busy_in,
157 deferred => deferred,
158 complete_in => complete_in,
159 flush_in => flush_in,
160 issuing => valid_out,
161
162 cr_read_in => cr_read_in,
163 cr_write_in => cr_write_valid,
164
165 stall_out => cr_stall_out
166 );
167
168 control0: process(clk)
169 begin
170 if rising_edge(clk) then
171 assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1)
172 report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure;
173 r_int <= rin_int;
174 end if;
175 end process;
176
177 control1 : process(all)
178 variable v_int : reg_internal_type;
179 variable valid_tmp : std_ulogic;
180 variable stall_tmp : std_ulogic;
181 begin
182 v_int := r_int;
183
184 -- asynchronous
185 valid_tmp := valid_in and not flush_in;
186 stall_tmp := '0';
187
188 if flush_in = '1' then
189 -- expect to see complete_in next cycle
190 v_int.outstanding := 1;
191 elsif complete_in = '1' then
192 v_int.outstanding := r_int.outstanding - 1;
193 end if;
194
195 if rst = '1' then
196 v_int := reg_internal_init;
197 valid_tmp := '0';
198 end if;
199
200 -- Handle debugger stop
201 stopped_out <= '0';
202 if stop_mark_in = '1' and v_int.outstanding = 0 then
203 stopped_out <= '1';
204 end if;
205
206 -- state machine to handle instructions that must be single
207 -- through the pipeline.
208 case r_int.state is
209 when IDLE =>
210 if valid_tmp = '1' then
211 if (sgl_pipe_in = '1') then
212 if v_int.outstanding /= 0 then
213 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
214 stall_tmp := '1';
215 else
216 -- send insn out and wait on it to complete
217 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
218 end if;
219 else
220 -- let it go out if there are no GPR hazards
221 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
222 end if;
223 end if;
224
225 when WAIT_FOR_PREV_TO_COMPLETE =>
226 if v_int.outstanding = 0 then
227 -- send insn out and wait on it to complete
228 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
229 else
230 stall_tmp := '1';
231 end if;
232
233 when WAIT_FOR_CURR_TO_COMPLETE =>
234 if v_int.outstanding = 0 then
235 v_int.state := IDLE;
236 -- XXX Don't replicate this
237 if valid_tmp = '1' then
238 if (sgl_pipe_in = '1') then
239 if v_int.outstanding /= 0 then
240 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
241 stall_tmp := '1';
242 else
243 -- send insn out and wait on it to complete
244 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
245 end if;
246 else
247 -- let it go out if there are no GPR hazards
248 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
249 end if;
250 end if;
251 else
252 stall_tmp := '1';
253 end if;
254 end case;
255
256 if stall_tmp = '1' then
257 valid_tmp := '0';
258 end if;
259
260 if valid_tmp = '1' then
261 if deferred = '0' then
262 v_int.outstanding := v_int.outstanding + 1;
263 end if;
264 gpr_write_valid <= gpr_write_valid_in;
265 cr_write_valid <= cr_write_in;
266 else
267 gpr_write_valid <= '0';
268 cr_write_valid <= '0';
269 end if;
270
271 -- update outputs
272 valid_out <= valid_tmp;
273 stall_out <= stall_tmp or deferred;
274
275 -- update registers
276 rin_int <= v_int;
277 end process;
278 end;