core: Restore bypass path from execute1
[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 EX1_BYPASS : boolean := true;
10 PIPELINE_DEPTH : natural := 2
11 );
12 port (
13 clk : in std_ulogic;
14 rst : in std_ulogic;
15
16 complete_in : in instr_tag_t;
17 valid_in : in std_ulogic;
18 repeated : in std_ulogic;
19 flush_in : in std_ulogic;
20 busy_in : in std_ulogic;
21 deferred : in std_ulogic;
22 sgl_pipe_in : in std_ulogic;
23 stop_mark_in : in std_ulogic;
24
25 gpr_write_valid_in : in std_ulogic;
26 gpr_write_in : in gspr_index_t;
27
28 gpr_a_read_valid_in : in std_ulogic;
29 gpr_a_read_in : in gspr_index_t;
30
31 gpr_b_read_valid_in : in std_ulogic;
32 gpr_b_read_in : in gspr_index_t;
33
34 gpr_c_read_valid_in : in std_ulogic;
35 gpr_c_read_in : in gspr_index_t;
36
37 execute_next_tag : in instr_tag_t;
38
39 cr_read_in : in std_ulogic;
40 cr_write_in : in std_ulogic;
41 cr_bypassable : in std_ulogic;
42
43 valid_out : out std_ulogic;
44 stall_out : out std_ulogic;
45 stopped_out : out std_ulogic;
46
47 gpr_bypass_a : out std_ulogic;
48 gpr_bypass_b : out std_ulogic;
49 gpr_bypass_c : out std_ulogic;
50 cr_bypass : out std_ulogic;
51
52 instr_tag_out : out instr_tag_t
53 );
54 end entity control;
55
56 architecture rtl of control is
57 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
58
59 type reg_internal_type is record
60 state : state_type;
61 outstanding : integer range -1 to PIPELINE_DEPTH+2;
62 end record;
63 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
64
65 signal r_int, rin_int : reg_internal_type := reg_internal_init;
66
67 signal stall_a_out : std_ulogic;
68 signal stall_b_out : std_ulogic;
69 signal stall_c_out : std_ulogic;
70 signal cr_stall_out : std_ulogic;
71
72 signal gpr_write_valid : std_ulogic := '0';
73 signal cr_write_valid : std_ulogic := '0';
74
75 type tag_register is record
76 wr_gpr : std_ulogic;
77 reg : gspr_index_t;
78 recent : std_ulogic;
79 end record;
80
81 type tag_regs_array is array(tag_number_t) of tag_register;
82 signal tag_regs : tag_regs_array;
83
84 signal instr_tag : instr_tag_t;
85
86 signal gpr_tag_stall : std_ulogic;
87
88 signal curr_tag : tag_number_t;
89 signal next_tag : tag_number_t;
90
91 begin
92 cr_hazard0: entity work.cr_hazard
93 generic map (
94 PIPELINE_DEPTH => PIPELINE_DEPTH
95 )
96 port map (
97 clk => clk,
98 busy_in => busy_in,
99 deferred => deferred,
100 complete_in => complete_in.valid,
101 flush_in => flush_in,
102 issuing => valid_out,
103
104 cr_read_in => cr_read_in,
105 cr_write_in => cr_write_valid,
106 bypassable => cr_bypassable,
107
108 stall_out => cr_stall_out,
109 use_bypass => cr_bypass
110 );
111
112 control0: process(clk)
113 begin
114 if rising_edge(clk) then
115 assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1)
116 report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure;
117 r_int <= rin_int;
118 for i in tag_number_t loop
119 if rst = '1' or flush_in = '1' then
120 tag_regs(i).wr_gpr <= '0';
121 else
122 if complete_in.valid = '1' and i = complete_in.tag then
123 tag_regs(i).wr_gpr <= '0';
124 report "tag " & integer'image(i) & " not valid";
125 end if;
126 if gpr_write_valid = '1' and tag_regs(i).reg = gpr_write_in then
127 tag_regs(i).recent <= '0';
128 if tag_regs(i).recent = '1' and tag_regs(i).wr_gpr = '1' then
129 report "tag " & integer'image(i) & " not recent";
130 end if;
131 end if;
132 if instr_tag.valid = '1' and i = instr_tag.tag then
133 tag_regs(i).wr_gpr <= gpr_write_valid;
134 tag_regs(i).reg <= gpr_write_in;
135 tag_regs(i).recent <= gpr_write_valid;
136 if gpr_write_valid = '1' then
137 report "tag " & integer'image(i) & " valid for gpr " & to_hstring(gpr_write_in);
138 end if;
139 end if;
140 end if;
141 end loop;
142 if rst = '1' then
143 curr_tag <= 0;
144 else
145 curr_tag <= next_tag;
146 end if;
147 end if;
148 end process;
149
150 control_hazards : process(all)
151 variable gpr_stall : std_ulogic;
152 variable tag_a : instr_tag_t;
153 variable tag_b : instr_tag_t;
154 variable tag_c : instr_tag_t;
155 variable tag_s : instr_tag_t;
156 variable tag_t : instr_tag_t;
157 variable incr_tag : tag_number_t;
158 variable byp_a : std_ulogic;
159 variable byp_b : std_ulogic;
160 variable byp_c : std_ulogic;
161 begin
162 tag_a := instr_tag_init;
163 for i in tag_number_t loop
164 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
165 tag_a.valid := gpr_a_read_valid_in;
166 tag_a.tag := i;
167 end if;
168 end loop;
169 if tag_match(tag_a, complete_in) then
170 tag_a.valid := '0';
171 end if;
172 tag_b := instr_tag_init;
173 for i in tag_number_t loop
174 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then
175 tag_b.valid := gpr_b_read_valid_in;
176 tag_b.tag := i;
177 end if;
178 end loop;
179 if tag_match(tag_b, complete_in) then
180 tag_b.valid := '0';
181 end if;
182 tag_c := instr_tag_init;
183 for i in tag_number_t loop
184 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
185 tag_c.valid := gpr_c_read_valid_in;
186 tag_c.tag := i;
187 end if;
188 end loop;
189 if tag_match(tag_c, complete_in) then
190 tag_c.valid := '0';
191 end if;
192
193 byp_a := '0';
194 if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
195 byp_a := '1';
196 end if;
197 byp_b := '0';
198 if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then
199 byp_b := '1';
200 end if;
201 byp_c := '0';
202 if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then
203 byp_c := '1';
204 end if;
205
206 gpr_bypass_a <= byp_a;
207 gpr_bypass_b <= byp_b;
208 gpr_bypass_c <= byp_c;
209
210 gpr_tag_stall <= (tag_a.valid and not byp_a) or
211 (tag_b.valid and not byp_b) or
212 (tag_c.valid and not byp_c);
213
214 incr_tag := curr_tag;
215 instr_tag.tag <= curr_tag;
216 instr_tag.valid <= valid_out and not deferred;
217 if instr_tag.valid = '1' then
218 incr_tag := (curr_tag + 1) mod TAG_COUNT;
219 end if;
220 next_tag <= incr_tag;
221 instr_tag_out <= instr_tag;
222 end process;
223
224 control1 : process(all)
225 variable v_int : reg_internal_type;
226 variable valid_tmp : std_ulogic;
227 variable stall_tmp : std_ulogic;
228 begin
229 v_int := r_int;
230
231 -- asynchronous
232 valid_tmp := valid_in and not flush_in;
233 stall_tmp := '0';
234
235 if flush_in = '1' then
236 -- expect to see complete_in next cycle
237 v_int.outstanding := 1;
238 elsif complete_in.valid = '1' then
239 v_int.outstanding := r_int.outstanding - 1;
240 end if;
241
242 if rst = '1' then
243 v_int := reg_internal_init;
244 valid_tmp := '0';
245 end if;
246
247 -- Handle debugger stop
248 stopped_out <= '0';
249 if stop_mark_in = '1' and v_int.outstanding = 0 then
250 stopped_out <= '1';
251 end if;
252
253 -- state machine to handle instructions that must be single
254 -- through the pipeline.
255 case r_int.state is
256 when IDLE =>
257 if valid_tmp = '1' then
258 if (sgl_pipe_in = '1') then
259 if v_int.outstanding /= 0 then
260 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
261 stall_tmp := '1';
262 else
263 -- send insn out and wait on it to complete
264 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
265 end if;
266 else
267 -- let it go out if there are no GPR or CR hazards
268 stall_tmp := gpr_tag_stall or cr_stall_out;
269 end if;
270 end if;
271
272 when WAIT_FOR_PREV_TO_COMPLETE =>
273 if v_int.outstanding = 0 then
274 -- send insn out and wait on it to complete
275 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
276 else
277 stall_tmp := '1';
278 end if;
279
280 when WAIT_FOR_CURR_TO_COMPLETE =>
281 if v_int.outstanding = 0 then
282 v_int.state := IDLE;
283 -- XXX Don't replicate this
284 if valid_tmp = '1' then
285 if (sgl_pipe_in = '1') then
286 if v_int.outstanding /= 0 then
287 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
288 stall_tmp := '1';
289 else
290 -- send insn out and wait on it to complete
291 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
292 end if;
293 else
294 -- let it go out if there are no GPR or CR hazards
295 stall_tmp := gpr_tag_stall or cr_stall_out;
296 end if;
297 end if;
298 else
299 stall_tmp := '1';
300 end if;
301 end case;
302
303 if stall_tmp = '1' then
304 valid_tmp := '0';
305 end if;
306
307 gpr_write_valid <= gpr_write_valid_in and valid_tmp;
308 cr_write_valid <= cr_write_in and valid_tmp;
309
310 if valid_tmp = '1' and deferred = '0' then
311 v_int.outstanding := v_int.outstanding + 1;
312 end if;
313
314 -- update outputs
315 valid_out <= valid_tmp;
316 stall_out <= stall_tmp or deferred;
317
318 -- update registers
319 rin_int <= v_int;
320 end process;
321 end;