Allow a full make check on Travis
[microwatt.git] / execute1.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.decode_types.all;
7 use work.common.all;
8 use work.helpers.all;
9 use work.crhelpers.all;
10 use work.ppc_fx_insns.all;
11 use work.sim_console.all;
12
13 entity execute1 is
14 generic (
15 SIM : boolean := false
16 );
17 port (
18 clk : in std_logic;
19
20 e_in : in Decode2ToExecute1Type;
21 f_out : out Execute1ToFetch1Type;
22 e_out : out Execute1ToExecute2Type;
23
24 terminate_out : out std_ulogic
25 );
26 end entity execute1;
27
28 architecture behaviour of execute1 is
29 signal e: Decode2ToExecute1Type := Decode2ToExecute1Init;
30 signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
31 signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
32 begin
33 execute1_0: process(clk)
34 begin
35 if rising_edge(clk) then
36 e <= e_in;
37 ctrl <= ctrl_tmp;
38 end if;
39 end process;
40
41 execute1_1: process(all)
42 variable result : std_ulogic_vector(63 downto 0);
43 variable result_with_carry : std_ulogic_vector(64 downto 0);
44 variable result_en : integer;
45 variable crnum : integer;
46 variable lo, hi : integer;
47 begin
48 result := (others => '0');
49 result_with_carry := (others => '0');
50 result_en := 0;
51
52 e_out <= Execute1ToExecute2Init;
53 f_out <= Execute1ToFetch1TypeInit;
54 ctrl_tmp <= ctrl;
55 -- FIXME: run at 512MHz not core freq
56 ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
57
58 terminate_out <= '0';
59
60 if e.valid = '1' then
61 e_out.valid <= '1';
62 e_out.write_reg <= e.write_reg;
63
64 report "execute " & to_hstring(e.nia);
65
66 case_0: case e.insn_type is
67
68 when OP_ILLEGAL =>
69 terminate_out <= '1';
70 report "illegal";
71 when OP_NOP =>
72 -- Do nothing
73 when OP_ADD =>
74 result := ppc_add(e.read_data1, e.read_data2);
75 result_en := 1;
76 when OP_ADDC =>
77 result_with_carry := ppc_adde(e.read_data1, e.read_data2, ctrl.carry and e.input_carry);
78 result := result_with_carry(63 downto 0);
79 ctrl_tmp.carry <= result_with_carry(64) and e.output_carry;
80 result_en := 1;
81 when OP_AND =>
82 result := ppc_and(e.read_data1, e.read_data2);
83 result_en := 1;
84 when OP_ANDC =>
85 result := ppc_andc(e.read_data1, e.read_data2);
86 result_en := 1;
87 when OP_B =>
88 f_out.redirect <= '1';
89 f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2));
90 when OP_BC =>
91 if e.const1(4-2) = '0' then
92 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
93 end if;
94 if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then
95 f_out.redirect <= '1';
96 f_out.redirect_nia <= std_ulogic_vector(signed(e.nia) + signed(e.read_data2));
97 end if;
98 when OP_BCLR =>
99 if e.const1(4-2) = '0' then
100 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
101 end if;
102 if ppc_bc_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr, ctrl.ctr) = 1 then
103 f_out.redirect <= '1';
104 f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
105 end if;
106 when OP_BCCTR =>
107 if ppc_bcctr_taken(e.const1(4 downto 0), e.const2(4 downto 0), e.cr) = 1 then
108 f_out.redirect <= '1';
109 f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
110 end if;
111 when OP_CMPB =>
112 result := ppc_cmpb(e.read_data1, e.read_data2);
113 result_en := 1;
114 when OP_CMP =>
115 e_out.write_cr_enable <= '1';
116 crnum := to_integer(unsigned(e.const1(2 downto 0)));
117 e_out.write_cr_mask <= num_to_fxm(crnum);
118 for i in 0 to 7 loop
119 lo := i*4;
120 hi := lo + 3;
121 e_out.write_cr_data(hi downto lo) <= ppc_cmp(e.const2(0), e.read_data1, e.read_data2);
122 end loop;
123 when OP_CMPL =>
124 e_out.write_cr_enable <= '1';
125 crnum := to_integer(unsigned(e.const1(2 downto 0)));
126 e_out.write_cr_mask <= num_to_fxm(crnum);
127 for i in 0 to 7 loop
128 lo := i*4;
129 hi := lo + 3;
130 e_out.write_cr_data(hi downto lo) <= ppc_cmpl(e.const2(0), e.read_data1, e.read_data2);
131 end loop;
132 when OP_CNTLZW =>
133 result := ppc_cntlzw(e.read_data1);
134 result_en := 1;
135 when OP_CNTTZW =>
136 result := ppc_cnttzw(e.read_data1);
137 result_en := 1;
138 when OP_CNTLZD =>
139 result := ppc_cntlzd(e.read_data1);
140 result_en := 1;
141 when OP_CNTTZD =>
142 result := ppc_cnttzd(e.read_data1);
143 result_en := 1;
144 when OP_EXTSB =>
145 result := ppc_extsb(e.read_data1);
146 result_en := 1;
147 when OP_EXTSH =>
148 result := ppc_extsh(e.read_data1);
149 result_en := 1;
150 when OP_EXTSW =>
151 result := ppc_extsw(e.read_data1);
152 result_en := 1;
153 when OP_EQV =>
154 result := ppc_eqv(e.read_data1, e.read_data2);
155 result_en := 1;
156 when OP_ISEL =>
157 crnum := to_integer(unsigned(e.const1));
158 if e.cr(31-crnum) = '1' then
159 result := e.read_data1;
160 else
161 result := e.read_data2;
162 end if;
163 result_en := 1;
164 when OP_MFCTR =>
165 result := ctrl.ctr;
166 result_en := 1;
167 when OP_MFLR =>
168 result := ctrl.lr;
169 result_en := 1;
170 when OP_MFTB =>
171 result := ctrl.tb;
172 result_en := 1;
173 when OP_MTCTR =>
174 ctrl_tmp.ctr <= e.read_data1;
175 when OP_MTLR =>
176 ctrl_tmp.lr <= e.read_data1;
177 when OP_MFCR =>
178 result := x"00000000" & e.cr;
179 result_en := 1;
180 when OP_MFOCRF =>
181 crnum := fxm_to_num(e.const1(7 downto 0));
182 result := (others => '0');
183 -- result((4*(7-crnum)+3) downto (4*(7-crnum))) := e.cr((4*(7-crnum)+3) downto (4*(7-crnum))); FIXME
184 for i in 0 to 7 loop
185 lo := (7-i)*4;
186 hi := lo + 3;
187 if crnum = i then
188 result(hi downto lo) := e.cr(hi downto lo);
189 end if;
190 end loop;
191 result_en := 1;
192 when OP_MTCRF =>
193 e_out.write_cr_enable <= '1';
194 e_out.write_cr_mask <= e.const1(7 downto 0);
195 e_out.write_cr_data <= e.read_data1(31 downto 0);
196 when OP_MTOCRF =>
197 e_out.write_cr_enable <= '1';
198 -- We require one hot priority encoding here
199 crnum := fxm_to_num(e.const1(7 downto 0));
200 e_out.write_cr_mask <= num_to_fxm(crnum);
201 e_out.write_cr_data <= e.read_data1(31 downto 0);
202 when OP_NAND =>
203 result := ppc_nand(e.read_data1, e.read_data2);
204 result_en := 1;
205 when OP_NEG =>
206 result := ppc_neg(e.read_data1);
207 result_en := 1;
208 when OP_NOR =>
209 result := ppc_nor(e.read_data1, e.read_data2);
210 result_en := 1;
211 when OP_OR =>
212 result := ppc_or(e.read_data1, e.read_data2);
213 result_en := 1;
214 when OP_ORC =>
215 result := ppc_orc(e.read_data1, e.read_data2);
216 result_en := 1;
217 when OP_POPCNTB =>
218 result := ppc_popcntb(e.read_data1);
219 result_en := 1;
220 when OP_POPCNTW =>
221 result := ppc_popcntw(e.read_data1);
222 result_en := 1;
223 when OP_POPCNTD =>
224 result := ppc_popcntd(e.read_data1);
225 result_en := 1;
226 when OP_PRTYD =>
227 result := ppc_prtyd(e.read_data1);
228 result_en := 1;
229 when OP_PRTYW =>
230 result := ppc_prtyw(e.read_data1);
231 result_en := 1;
232 when OP_RLDCL =>
233 result := ppc_rldcl(e.read_data1, e.read_data2, e.const2(5 downto 0));
234 result_en := 1;
235 when OP_RLDCR =>
236 result := ppc_rldcr(e.read_data1, e.read_data2, e.const2(5 downto 0));
237 result_en := 1;
238 when OP_RLDICL =>
239 result := ppc_rldicl(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
240 result_en := 1;
241 when OP_RLDICR =>
242 result := ppc_rldicr(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
243 result_en := 1;
244 when OP_RLWNM =>
245 result := ppc_rlwnm(e.read_data1, e.read_data2, e.const2(4 downto 0), e.const3(4 downto 0));
246 result_en := 1;
247 when OP_RLWINM =>
248 result := ppc_rlwinm(e.read_data1, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0));
249 result_en := 1;
250 when OP_RLDIC =>
251 result := ppc_rldic(e.read_data1, e.const1(5 downto 0), e.const2(5 downto 0));
252 result_en := 1;
253 when OP_RLDIMI =>
254 result := ppc_rldimi(e.read_data1, e.read_data2, e.const1(5 downto 0), e.const2(5 downto 0));
255 result_en := 1;
256 when OP_RLWIMI =>
257 result := ppc_rlwimi(e.read_data1, e.read_data2, e.const1(4 downto 0), e.const2(4 downto 0), e.const3(4 downto 0));
258 result_en := 1;
259 when OP_SLD =>
260 result := ppc_sld(e.read_data1, e.read_data2);
261 result_en := 1;
262 when OP_SLW =>
263 result := ppc_slw(e.read_data1, e.read_data2);
264 result_en := 1;
265 when OP_SRAW =>
266 result_with_carry := ppc_sraw(e.read_data1, e.read_data2);
267 result := result_with_carry(63 downto 0);
268 ctrl_tmp.carry <= result_with_carry(64);
269 result_en := 1;
270 when OP_SRAWI =>
271 result_with_carry := ppc_srawi(e.read_data1, e.const1(5 downto 0));
272 result := result_with_carry(63 downto 0);
273 ctrl_tmp.carry <= result_with_carry(64);
274 result_en := 1;
275 when OP_SRAD =>
276 result_with_carry := ppc_srad(e.read_data1, e.read_data2);
277 result := result_with_carry(63 downto 0);
278 ctrl_tmp.carry <= result_with_carry(64);
279 result_en := 1;
280 when OP_SRADI =>
281 result_with_carry := ppc_sradi(e.read_data1, e.const1(5 downto 0));
282 result := result_with_carry(63 downto 0);
283 ctrl_tmp.carry <= result_with_carry(64);
284 result_en := 1;
285 when OP_SRD =>
286 result := ppc_srd(e.read_data1, e.read_data2);
287 result_en := 1;
288 when OP_SRW =>
289 result := ppc_srw(e.read_data1, e.read_data2);
290 result_en := 1;
291 when OP_SUBF =>
292 result := ppc_subf(e.read_data1, e.read_data2);
293 result_en := 1;
294 when OP_SUBFC =>
295 result_with_carry := ppc_subfe(e.read_data1, e.read_data2, ctrl.carry or not(e.input_carry));
296 result := result_with_carry(63 downto 0);
297 ctrl_tmp.carry <= result_with_carry(64) and e.output_carry;
298 result_en := 1;
299 when OP_XOR =>
300 result := ppc_xor(e.read_data1, e.read_data2);
301 result_en := 1;
302
303 -- sim console
304 when OP_SIM_READ =>
305 if SIM = true then
306 sim_console_read(result);
307 result_en := 1;
308 else
309 terminate_out <= '1';
310 report "illegal";
311 end if;
312 when OP_SIM_POLL =>
313 if SIM = true then
314 sim_console_poll(result);
315 result_en := 1;
316 else
317 terminate_out <= '1';
318 report "illegal";
319 end if;
320 when OP_SIM_WRITE =>
321 if SIM = true then
322 sim_console_write(e.read_data1);
323 else
324 terminate_out <= '1';
325 report "illegal";
326 end if;
327 when OP_SIM_CONFIG =>
328 if SIM = true then
329 result := x"0000000000000001";
330 else
331 result := x"0000000000000000";
332 end if;
333 result_en := 1;
334
335 when OP_TDI =>
336 -- Keep our test cases happy for now, ignore trap instructions
337 report "OP_TDI FIXME";
338
339 when OP_DIVDU =>
340 if SIM = true then
341 result := ppc_divdu(e.read_data1, e.read_data2);
342 result_en := 1;
343 else
344 terminate_out <= '1';
345 report "illegal";
346 end if;
347 when OP_DIVD =>
348 if SIM = true then
349 result := ppc_divd(e.read_data1, e.read_data2);
350 result_en := 1;
351 else
352 terminate_out <= '1';
353 report "illegal";
354 end if;
355 when OP_DIVWU =>
356 if SIM = true then
357 result := ppc_divwu(e.read_data1, e.read_data2);
358 result_en := 1;
359 else
360 terminate_out <= '1';
361 report "illegal";
362 end if;
363 when OP_DIVW =>
364 if SIM = true then
365 result := ppc_divw(e.read_data1, e.read_data2);
366 result_en := 1;
367 else
368 terminate_out <= '1';
369 report "illegal";
370 end if;
371 when others =>
372 terminate_out <= '1';
373 report "illegal";
374 end case;
375
376 if e.lr = '1' then
377 ctrl_tmp.lr <= std_ulogic_vector(unsigned(e.nia) + 4);
378 end if;
379
380 if result_en = 1 then
381 e_out.write_data <= result;
382 e_out.write_enable <= '1';
383 e_out.rc <= e.rc;
384 end if;
385 end if;
386 end process;
387 end architecture behaviour;