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