ignore /abc.history
[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 flush_in : in std_ulogic;
19 deferred : in std_ulogic;
20 serialize : 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
26 gpr_a_read_valid_in : in std_ulogic;
27 gpr_a_read_in : in gspr_index_t;
28
29 gpr_b_read_valid_in : in std_ulogic;
30 gpr_b_read_in : in gspr_index_t;
31
32 gpr_c_read_valid_in : in std_ulogic;
33 gpr_c_read_in : in gspr_index_t;
34
35 execute_next_tag : in instr_tag_t;
36 execute_next_cr_tag : in instr_tag_t;
37 execute2_next_tag : in instr_tag_t;
38 execute2_next_cr_tag : in instr_tag_t;
39
40 cr_read_in : in std_ulogic;
41 cr_write_in : in std_ulogic;
42 ov_read_in : in std_ulogic;
43 ov_write_in : in std_ulogic;
44
45 valid_out : out std_ulogic;
46 stopped_out : out std_ulogic;
47
48 gpr_bypass_a : out std_ulogic_vector(1 downto 0);
49 gpr_bypass_b : out std_ulogic_vector(1 downto 0);
50 gpr_bypass_c : out std_ulogic_vector(1 downto 0);
51 cr_bypass : out std_ulogic_vector(1 downto 0);
52
53 instr_tag_out : out instr_tag_t
54 );
55 end entity control;
56
57 architecture rtl of control is
58 signal gpr_write_valid : std_ulogic;
59 signal cr_write_valid : std_ulogic;
60 signal ov_write_valid : std_ulogic;
61
62 type tag_register is record
63 wr_gpr : std_ulogic;
64 reg : gspr_index_t;
65 recent : std_ulogic;
66 wr_cr : std_ulogic;
67 wr_ov : std_ulogic;
68 valid : std_ulogic;
69 end record;
70
71 type tag_regs_array is array(tag_number_t) of tag_register;
72 signal tag_regs : tag_regs_array;
73
74 signal instr_tag : instr_tag_t;
75
76 signal gpr_tag_stall : std_ulogic;
77 signal cr_tag_stall : std_ulogic;
78 signal ov_tag_stall : std_ulogic;
79 signal serial_stall : std_ulogic;
80
81 signal curr_tag : tag_number_t;
82 signal next_tag : tag_number_t;
83
84 signal curr_cr_tag : tag_number_t;
85 signal curr_ov_tag : tag_number_t;
86 signal prev_tag : tag_number_t;
87
88 begin
89 control0: process(clk)
90 begin
91 if rising_edge(clk) then
92 for i in tag_number_t loop
93 if rst = '1' or flush_in = '1' then
94 tag_regs(i).wr_gpr <= '0';
95 tag_regs(i).wr_cr <= '0';
96 tag_regs(i).wr_ov <= '0';
97 tag_regs(i).valid <= '0';
98 else
99 if complete_in.valid = '1' and i = complete_in.tag then
100 assert tag_regs(i).valid = '1' report "spurious completion" severity failure;
101 tag_regs(i).wr_gpr <= '0';
102 tag_regs(i).wr_cr <= '0';
103 tag_regs(i).wr_ov <= '0';
104 tag_regs(i).valid <= '0';
105 report "tag " & integer'image(i) & " not valid";
106 end if;
107 if instr_tag.valid = '1' and gpr_write_valid = '1' and
108 tag_regs(i).reg = gpr_write_in then
109 tag_regs(i).recent <= '0';
110 if tag_regs(i).recent = '1' and tag_regs(i).wr_gpr = '1' then
111 report "tag " & integer'image(i) & " not recent";
112 end if;
113 end if;
114 if instr_tag.valid = '1' and i = instr_tag.tag then
115 tag_regs(i).wr_gpr <= gpr_write_valid;
116 tag_regs(i).reg <= gpr_write_in;
117 tag_regs(i).recent <= gpr_write_valid;
118 tag_regs(i).wr_cr <= cr_write_valid;
119 tag_regs(i).wr_ov <= ov_write_valid;
120 tag_regs(i).valid <= '1';
121 if gpr_write_valid = '1' then
122 report "tag " & integer'image(i) & " valid for gpr " & to_hstring(gpr_write_in);
123 end if;
124 end if;
125 end if;
126 end loop;
127 if rst = '1' then
128 curr_tag <= 0;
129 curr_cr_tag <= 0;
130 curr_ov_tag <= 0;
131 prev_tag <= 0;
132 else
133 curr_tag <= next_tag;
134 if instr_tag.valid = '1' and cr_write_valid = '1' then
135 curr_cr_tag <= instr_tag.tag;
136 end if;
137 if instr_tag.valid = '1' and ov_write_valid = '1' then
138 curr_ov_tag <= instr_tag.tag;
139 end if;
140 if valid_out = '1' then
141 prev_tag <= instr_tag.tag;
142 end if;
143 end if;
144 end if;
145 end process;
146
147 control_hazards : process(all)
148 variable gpr_stall : std_ulogic;
149 variable tag_a : instr_tag_t;
150 variable tag_b : instr_tag_t;
151 variable tag_c : instr_tag_t;
152 variable tag_s : instr_tag_t;
153 variable tag_t : instr_tag_t;
154 variable incr_tag : tag_number_t;
155 variable byp_a : std_ulogic_vector(1 downto 0);
156 variable byp_b : std_ulogic_vector(1 downto 0);
157 variable byp_c : std_ulogic_vector(1 downto 0);
158 variable tag_cr : instr_tag_t;
159 variable byp_cr : std_ulogic_vector(1 downto 0);
160 variable tag_ov : instr_tag_t;
161 variable tag_prev : instr_tag_t;
162 begin
163 tag_a := instr_tag_init;
164 for i in tag_number_t loop
165 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
166 tag_a.valid := gpr_a_read_valid_in;
167 tag_a.tag := i;
168 end if;
169 end loop;
170 tag_b := 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_b_read_in then
173 tag_b.valid := gpr_b_read_valid_in;
174 tag_b.tag := i;
175 end if;
176 end loop;
177 tag_c := instr_tag_init;
178 for i in tag_number_t loop
179 if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
180 tag_c.valid := gpr_c_read_valid_in;
181 tag_c.tag := i;
182 end if;
183 end loop;
184
185 byp_a := "00";
186 if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
187 byp_a := "01";
188 elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_a) then
189 byp_a := "10";
190 elsif tag_match(complete_in, tag_a) then
191 byp_a := "11";
192 end if;
193 byp_b := "00";
194 if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then
195 byp_b := "01";
196 elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then
197 byp_b := "10";
198 elsif tag_match(complete_in, tag_b) then
199 byp_b := "11";
200 end if;
201 byp_c := "00";
202 if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then
203 byp_c := "01";
204 elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then
205 byp_c := "10";
206 elsif tag_match(complete_in, tag_c) then
207 byp_c := "11";
208 end if;
209
210 gpr_bypass_a <= byp_a;
211 gpr_bypass_b <= byp_b;
212 gpr_bypass_c <= byp_c;
213
214 gpr_tag_stall <= (tag_a.valid and not (or (byp_a))) or
215 (tag_b.valid and not (or (byp_b))) or
216 (tag_c.valid and not (or (byp_c)));
217
218 incr_tag := curr_tag;
219 instr_tag.tag <= curr_tag;
220 instr_tag.valid <= valid_out and not deferred;
221 if instr_tag.valid = '1' then
222 incr_tag := (curr_tag + 1) mod TAG_COUNT;
223 end if;
224 next_tag <= incr_tag;
225 instr_tag_out <= instr_tag;
226
227 -- CR hazards
228 tag_cr.tag := curr_cr_tag;
229 tag_cr.valid := cr_read_in and tag_regs(curr_cr_tag).wr_cr;
230 if tag_match(tag_cr, complete_in) then
231 tag_cr.valid := '0';
232 end if;
233 byp_cr := "00";
234 if EX1_BYPASS and tag_match(execute_next_cr_tag, tag_cr) then
235 byp_cr := "10";
236 elsif EX1_BYPASS and tag_match(execute2_next_cr_tag, tag_cr) then
237 byp_cr := "11";
238 end if;
239
240 cr_bypass <= byp_cr;
241 cr_tag_stall <= tag_cr.valid and not byp_cr(1);
242
243 -- OV hazards
244 tag_ov.tag := curr_ov_tag;
245 tag_ov.valid := ov_read_in and tag_regs(curr_ov_tag).wr_ov;
246 if tag_match(tag_ov, complete_in) then
247 tag_ov.valid := '0';
248 end if;
249 ov_tag_stall <= tag_ov.valid;
250
251 tag_prev.tag := prev_tag;
252 tag_prev.valid := tag_regs(prev_tag).valid;
253 if tag_match(tag_prev, complete_in) then
254 tag_prev.valid := '0';
255 end if;
256 serial_stall <= tag_prev.valid;
257 end process;
258
259 control1 : process(all)
260 variable valid_tmp : std_ulogic;
261 begin
262 -- asynchronous
263 valid_tmp := valid_in and not flush_in;
264
265 if rst = '1' then
266 gpr_write_valid <= '0';
267 cr_write_valid <= '0';
268 valid_tmp := '0';
269 end if;
270
271 -- Handle debugger stop
272 stopped_out <= stop_mark_in and not serial_stall;
273
274 -- Don't let it go out if there are GPR or CR hazards
275 -- or we are waiting for the previous instruction to complete
276 if (gpr_tag_stall or cr_tag_stall or ov_tag_stall or
277 (serialize and serial_stall)) = '1' then
278 valid_tmp := '0';
279 end if;
280
281 gpr_write_valid <= gpr_write_valid_in and valid_tmp;
282 cr_write_valid <= cr_write_in and valid_tmp;
283 ov_write_valid <= ov_write_in and valid_tmp;
284
285 -- update outputs
286 valid_out <= valid_tmp;
287 end process;
288 end;