Add Tercel PHY reset synchronization
[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 := 3
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 execute_next_cr_tag : in instr_tag_t;
39
40 cr_read_in : in std_ulogic;
41 cr_write_in : 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 gpr_write_valid : std_ulogic := '0';
68 signal cr_write_valid : std_ulogic := '0';
69
70 type tag_register is record
71 wr_gpr : std_ulogic;
72 reg : gspr_index_t;
73 recent : std_ulogic;
74 wr_cr : std_ulogic;
75 end record;
76
77 type tag_regs_array is array(tag_number_t) of tag_register;
78 signal tag_regs : tag_regs_array;
79
80 signal instr_tag : instr_tag_t;
81
82 signal gpr_tag_stall : std_ulogic;
83 signal cr_tag_stall : std_ulogic;
84
85 signal curr_tag : tag_number_t;
86 signal next_tag : tag_number_t;
87
88 signal curr_cr_tag : tag_number_t;
89
90 begin
91 control0: process(clk)
92 begin
93 if rising_edge(clk) then
94 assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1)
95 report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure;
96 r_int <= rin_int;
97 for i in tag_number_t loop
98 if rst = '1' or flush_in = '1' then
99 tag_regs(i).wr_gpr <= '0';
100 tag_regs(i).wr_cr <= '0';
101 else
102 if complete_in.valid = '1' and i = complete_in.tag then
103 tag_regs(i).wr_gpr <= '0';
104 tag_regs(i).wr_cr <= '0';
105 report "tag " & integer'image(i) & " not valid";
106 end if;
107 if gpr_write_valid = '1' and tag_regs(i).reg = gpr_write_in then
108 tag_regs(i).recent <= '0';
109 if tag_regs(i).recent = '1' and tag_regs(i).wr_gpr = '1' then
110 report "tag " & integer'image(i) & " not recent";
111 end if;
112 end if;
113 if instr_tag.valid = '1' and i = instr_tag.tag then
114 tag_regs(i).wr_gpr <= gpr_write_valid;
115 tag_regs(i).reg <= gpr_write_in;
116 tag_regs(i).recent <= gpr_write_valid;
117 tag_regs(i).wr_cr <= cr_write_valid;
118 if gpr_write_valid = '1' then
119 report "tag " & integer'image(i) & " valid for gpr " & to_hstring(gpr_write_in);
120 end if;
121 end if;
122 end if;
123 end loop;
124 if rst = '1' then
125 curr_tag <= 0;
126 curr_cr_tag <= 0;
127 else
128 curr_tag <= next_tag;
129 if cr_write_valid = '1' then
130 curr_cr_tag <= instr_tag.tag;
131 end if;
132 end if;
133 end if;
134 end process;
135
136 control_hazards : process(all)
137 variable gpr_stall : std_ulogic;
138 variable tag_a : instr_tag_t;
139 variable tag_b : instr_tag_t;
140 variable tag_c : instr_tag_t;
141 variable tag_s : instr_tag_t;
142 variable tag_t : instr_tag_t;
143 variable incr_tag : tag_number_t;
144 variable byp_a : std_ulogic;
145 variable byp_b : std_ulogic;
146 variable byp_c : std_ulogic;
147 variable tag_cr : instr_tag_t;
148 variable byp_cr : std_ulogic;
149 begin
150 tag_a := instr_tag_init;
151 for i in tag_number_t loop
152 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
153 tag_a.valid := gpr_a_read_valid_in;
154 tag_a.tag := i;
155 end if;
156 end loop;
157 if tag_match(tag_a, complete_in) then
158 tag_a.valid := '0';
159 end if;
160 tag_b := instr_tag_init;
161 for i in tag_number_t loop
162 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then
163 tag_b.valid := gpr_b_read_valid_in;
164 tag_b.tag := i;
165 end if;
166 end loop;
167 if tag_match(tag_b, complete_in) then
168 tag_b.valid := '0';
169 end if;
170 tag_c := instr_tag_init;
171 for i in tag_number_t loop
172 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
173 tag_c.valid := gpr_c_read_valid_in;
174 tag_c.tag := i;
175 end if;
176 end loop;
177 if tag_match(tag_c, complete_in) then
178 tag_c.valid := '0';
179 end if;
180
181 byp_a := '0';
182 if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
183 byp_a := '1';
184 end if;
185 byp_b := '0';
186 if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then
187 byp_b := '1';
188 end if;
189 byp_c := '0';
190 if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then
191 byp_c := '1';
192 end if;
193
194 gpr_bypass_a <= byp_a;
195 gpr_bypass_b <= byp_b;
196 gpr_bypass_c <= byp_c;
197
198 gpr_tag_stall <= (tag_a.valid and not byp_a) or
199 (tag_b.valid and not byp_b) or
200 (tag_c.valid and not byp_c);
201
202 incr_tag := curr_tag;
203 instr_tag.tag <= curr_tag;
204 instr_tag.valid <= valid_out and not deferred;
205 if instr_tag.valid = '1' then
206 incr_tag := (curr_tag + 1) mod TAG_COUNT;
207 end if;
208 next_tag <= incr_tag;
209 instr_tag_out <= instr_tag;
210
211 -- CR hazards
212 tag_cr.tag := curr_cr_tag;
213 tag_cr.valid := cr_read_in and tag_regs(curr_cr_tag).wr_cr;
214 if tag_match(tag_cr, complete_in) then
215 tag_cr.valid := '0';
216 end if;
217 byp_cr := '0';
218 if EX1_BYPASS and tag_match(execute_next_cr_tag, tag_cr) then
219 byp_cr := '1';
220 end if;
221
222 cr_bypass <= byp_cr;
223 cr_tag_stall <= tag_cr.valid and not byp_cr;
224 end process;
225
226 control1 : process(all)
227 variable v_int : reg_internal_type;
228 variable valid_tmp : std_ulogic;
229 variable stall_tmp : std_ulogic;
230 begin
231 v_int := r_int;
232
233 -- asynchronous
234 valid_tmp := valid_in and not flush_in;
235 stall_tmp := '0';
236
237 if flush_in = '1' then
238 v_int.outstanding := 0;
239 elsif complete_in.valid = '1' then
240 v_int.outstanding := r_int.outstanding - 1;
241 end if;
242 if r_int.outstanding >= PIPELINE_DEPTH + 1 then
243 valid_tmp := '0';
244 stall_tmp := '1';
245 end if;
246
247 if rst = '1' then
248 v_int := reg_internal_init;
249 valid_tmp := '0';
250 end if;
251
252 -- Handle debugger stop
253 stopped_out <= '0';
254 if stop_mark_in = '1' and v_int.outstanding = 0 then
255 stopped_out <= '1';
256 end if;
257
258 -- state machine to handle instructions that must be single
259 -- through the pipeline.
260 case r_int.state is
261 when IDLE =>
262 if valid_tmp = '1' then
263 if (sgl_pipe_in = '1') then
264 if v_int.outstanding /= 0 then
265 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
266 stall_tmp := '1';
267 else
268 -- send insn out and wait on it to complete
269 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
270 end if;
271 else
272 -- let it go out if there are no GPR or CR hazards
273 stall_tmp := gpr_tag_stall or cr_tag_stall;
274 end if;
275 end if;
276
277 when WAIT_FOR_PREV_TO_COMPLETE =>
278 if v_int.outstanding = 0 then
279 -- send insn out and wait on it to complete
280 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
281 else
282 stall_tmp := '1';
283 end if;
284
285 when WAIT_FOR_CURR_TO_COMPLETE =>
286 if v_int.outstanding = 0 then
287 v_int.state := IDLE;
288 -- XXX Don't replicate this
289 if valid_tmp = '1' then
290 if (sgl_pipe_in = '1') then
291 if v_int.outstanding /= 0 then
292 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
293 stall_tmp := '1';
294 else
295 -- send insn out and wait on it to complete
296 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
297 end if;
298 else
299 -- let it go out if there are no GPR or CR hazards
300 stall_tmp := gpr_tag_stall or cr_tag_stall;
301 end if;
302 end if;
303 else
304 stall_tmp := '1';
305 end if;
306 end case;
307
308 if stall_tmp = '1' then
309 valid_tmp := '0';
310 end if;
311
312 gpr_write_valid <= gpr_write_valid_in and valid_tmp;
313 cr_write_valid <= cr_write_in and valid_tmp;
314
315 if valid_tmp = '1' and deferred = '0' then
316 v_int.outstanding := v_int.outstanding + 1;
317 end if;
318
319 -- update outputs
320 valid_out <= valid_tmp;
321 stall_out <= stall_tmp or deferred;
322
323 -- update registers
324 rin_int <= v_int;
325 end process;
326 end;