FPU: Implement fmrgew and fmrgow and add tests for them
[microwatt.git] / fpu.vhdl
1 -- Floating-point unit for Microwatt
2
3 library ieee;
4 use ieee.std_logic_1164.all;
5 use ieee.numeric_std.all;
6
7 library work;
8 use work.insn_helpers.all;
9 use work.decode_types.all;
10 use work.crhelpers.all;
11 use work.helpers.all;
12 use work.common.all;
13
14 entity fpu is
15 port (
16 clk : in std_ulogic;
17 rst : in std_ulogic;
18
19 e_in : in Execute1toFPUType;
20 e_out : out FPUToExecute1Type;
21
22 w_out : out FPUToWritebackType
23 );
24 end entity fpu;
25
26 architecture behaviour of fpu is
27 type fp_number_class is (ZERO, FINITE, INFINITY, NAN);
28
29 constant EXP_BITS : natural := 13;
30
31 type fpu_reg_type is record
32 class : fp_number_class;
33 negative : std_ulogic;
34 exponent : signed(EXP_BITS-1 downto 0); -- unbiased
35 mantissa : std_ulogic_vector(63 downto 0); -- 10.54 format
36 end record;
37
38 type state_t is (IDLE,
39 DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF,
40 DO_FMR, DO_FMRG,
41 DO_FCFID, DO_FCTI,
42 DO_FRSP, DO_FRI,
43 FRI_1,
44 INT_SHIFT, INT_ROUND, INT_ISHIFT,
45 INT_FINAL, INT_CHECK, INT_OFLOW,
46 FINISH, NORMALIZE,
47 ROUND_UFLOW, ROUND_OFLOW,
48 ROUNDING, ROUNDING_2, ROUNDING_3,
49 DENORM);
50
51 type reg_type is record
52 state : state_t;
53 busy : std_ulogic;
54 instr_done : std_ulogic;
55 do_intr : std_ulogic;
56 op : insn_type_t;
57 insn : std_ulogic_vector(31 downto 0);
58 dest_fpr : gspr_index_t;
59 fe_mode : std_ulogic;
60 rc : std_ulogic;
61 is_cmp : std_ulogic;
62 single_prec : std_ulogic;
63 fpscr : std_ulogic_vector(31 downto 0);
64 a : fpu_reg_type;
65 b : fpu_reg_type;
66 r : std_ulogic_vector(63 downto 0); -- 10.54 format
67 x : std_ulogic;
68 result_sign : std_ulogic;
69 result_class : fp_number_class;
70 result_exp : signed(EXP_BITS-1 downto 0);
71 shift : signed(EXP_BITS-1 downto 0);
72 writing_back : std_ulogic;
73 int_result : std_ulogic;
74 cr_result : std_ulogic_vector(3 downto 0);
75 cr_mask : std_ulogic_vector(7 downto 0);
76 old_exc : std_ulogic_vector(4 downto 0);
77 update_fprf : std_ulogic;
78 quieten_nan : std_ulogic;
79 tiny : std_ulogic;
80 denorm : std_ulogic;
81 round_mode : std_ulogic_vector(2 downto 0);
82 end record;
83
84 signal r, rin : reg_type;
85
86 signal fp_result : std_ulogic_vector(63 downto 0);
87 signal opsel_a : std_ulogic_vector(1 downto 0);
88 signal opsel_b : std_ulogic_vector(1 downto 0);
89 signal opsel_r : std_ulogic_vector(1 downto 0);
90 signal opsel_ainv : std_ulogic;
91 signal opsel_amask : std_ulogic;
92 signal in_a : std_ulogic_vector(63 downto 0);
93 signal in_b : std_ulogic_vector(63 downto 0);
94 signal result : std_ulogic_vector(63 downto 0);
95 signal carry_in : std_ulogic;
96 signal lost_bits : std_ulogic;
97 signal r_hi_nz : std_ulogic;
98 signal r_lo_nz : std_ulogic;
99 signal misc_sel : std_ulogic_vector(3 downto 0);
100
101 -- opsel values
102 constant AIN_R : std_ulogic_vector(1 downto 0) := "00";
103 constant AIN_A : std_ulogic_vector(1 downto 0) := "01";
104 constant AIN_B : std_ulogic_vector(1 downto 0) := "10";
105
106 constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00";
107 constant BIN_R : std_ulogic_vector(1 downto 0) := "01";
108 constant BIN_MASK : std_ulogic_vector(1 downto 0) := "10";
109
110 constant RES_SUM : std_ulogic_vector(1 downto 0) := "00";
111 constant RES_SHIFT : std_ulogic_vector(1 downto 0) := "01";
112 constant RES_MISC : std_ulogic_vector(1 downto 0) := "11";
113
114 -- Left and right shifter with 120 bit input and 64 bit output.
115 -- Shifts inp left by shift bits and returns the upper 64 bits of
116 -- the result. The shift parameter is interpreted as a signed
117 -- number in the range -64..63, with negative values indicating
118 -- right shifts.
119 function shifter_64(inp: std_ulogic_vector(119 downto 0);
120 shift: std_ulogic_vector(6 downto 0))
121 return std_ulogic_vector is
122 variable s1 : std_ulogic_vector(94 downto 0);
123 variable s2 : std_ulogic_vector(70 downto 0);
124 variable result : std_ulogic_vector(63 downto 0);
125 begin
126 case shift(6 downto 5) is
127 when "00" =>
128 s1 := inp(119 downto 25);
129 when "01" =>
130 s1 := inp(87 downto 0) & "0000000";
131 when "10" =>
132 s1 := x"0000000000000000" & inp(119 downto 89);
133 when others =>
134 s1 := x"00000000" & inp(119 downto 57);
135 end case;
136 case shift(4 downto 3) is
137 when "00" =>
138 s2 := s1(94 downto 24);
139 when "01" =>
140 s2 := s1(86 downto 16);
141 when "10" =>
142 s2 := s1(78 downto 8);
143 when others =>
144 s2 := s1(70 downto 0);
145 end case;
146 case shift(2 downto 0) is
147 when "000" =>
148 result := s2(70 downto 7);
149 when "001" =>
150 result := s2(69 downto 6);
151 when "010" =>
152 result := s2(68 downto 5);
153 when "011" =>
154 result := s2(67 downto 4);
155 when "100" =>
156 result := s2(66 downto 3);
157 when "101" =>
158 result := s2(65 downto 2);
159 when "110" =>
160 result := s2(64 downto 1);
161 when others =>
162 result := s2(63 downto 0);
163 end case;
164 return result;
165 end;
166
167 -- Generate a mask with 0-bits on the left and 1-bits on the right which
168 -- selects the bits will be lost in doing a right shift. The shift
169 -- parameter is the bottom 6 bits of a negative shift count,
170 -- indicating a right shift.
171 function right_mask(shift: unsigned(5 downto 0)) return std_ulogic_vector is
172 variable result: std_ulogic_vector(63 downto 0);
173 begin
174 result := (others => '0');
175 for i in 0 to 63 loop
176 if i >= shift then
177 result(63 - i) := '1';
178 end if;
179 end loop;
180 return result;
181 end;
182
183 -- Split a DP floating-point number into components and work out its class.
184 -- If is_int = 1, the input is considered an integer
185 function decode_dp(fpr: std_ulogic_vector(63 downto 0); is_int: std_ulogic) return fpu_reg_type is
186 variable r : fpu_reg_type;
187 variable exp_nz : std_ulogic;
188 variable exp_ao : std_ulogic;
189 variable frac_nz : std_ulogic;
190 variable cls : std_ulogic_vector(2 downto 0);
191 begin
192 r.negative := fpr(63);
193 exp_nz := or (fpr(62 downto 52));
194 exp_ao := and (fpr(62 downto 52));
195 frac_nz := or (fpr(51 downto 0));
196 if is_int = '0' then
197 r.exponent := signed(resize(unsigned(fpr(62 downto 52)), EXP_BITS)) - to_signed(1023, EXP_BITS);
198 if exp_nz = '0' then
199 r.exponent := to_signed(-1022, EXP_BITS);
200 end if;
201 r.mantissa := "000000000" & exp_nz & fpr(51 downto 0) & "00";
202 cls := exp_ao & exp_nz & frac_nz;
203 case cls is
204 when "000" => r.class := ZERO;
205 when "001" => r.class := FINITE; -- denormalized
206 when "010" => r.class := FINITE;
207 when "011" => r.class := FINITE;
208 when "110" => r.class := INFINITY;
209 when others => r.class := NAN;
210 end case;
211 else
212 r.mantissa := fpr;
213 r.exponent := (others => '0');
214 if (fpr(63) or exp_nz or frac_nz) = '1' then
215 r.class := FINITE;
216 else
217 r.class := ZERO;
218 end if;
219 end if;
220 return r;
221 end;
222
223 -- Construct a DP floating-point result from components
224 function pack_dp(sign: std_ulogic; class: fp_number_class; exp: signed(EXP_BITS-1 downto 0);
225 mantissa: std_ulogic_vector; single_prec: std_ulogic; quieten_nan: std_ulogic)
226 return std_ulogic_vector is
227 variable result : std_ulogic_vector(63 downto 0);
228 begin
229 result := (others => '0');
230 result(63) := sign;
231 case class is
232 when ZERO =>
233 when FINITE =>
234 if mantissa(54) = '1' then
235 -- normalized number
236 result(62 downto 52) := std_ulogic_vector(resize(exp, 11) + 1023);
237 end if;
238 result(51 downto 29) := mantissa(53 downto 31);
239 if single_prec = '0' then
240 result(28 downto 0) := mantissa(30 downto 2);
241 end if;
242 when INFINITY =>
243 result(62 downto 52) := "11111111111";
244 when NAN =>
245 result(62 downto 52) := "11111111111";
246 result(51) := quieten_nan or mantissa(53);
247 result(50 downto 29) := mantissa(52 downto 31);
248 if single_prec = '0' then
249 result(28 downto 0) := mantissa(30 downto 2);
250 end if;
251 end case;
252 return result;
253 end;
254
255 -- Determine whether to increment when rounding
256 -- Returns rounding_inc & inexact
257 -- Assumes x includes the bottom 29 bits of the mantissa already
258 -- if single_prec = 1 (usually arranged by setting set_x = 1 earlier).
259 function fp_rounding(mantissa: std_ulogic_vector(63 downto 0); x: std_ulogic;
260 single_prec: std_ulogic; rn: std_ulogic_vector(2 downto 0);
261 sign: std_ulogic)
262 return std_ulogic_vector is
263 variable grx : std_ulogic_vector(2 downto 0);
264 variable ret : std_ulogic_vector(1 downto 0);
265 variable lsb : std_ulogic;
266 begin
267 if single_prec = '0' then
268 grx := mantissa(1 downto 0) & x;
269 lsb := mantissa(2);
270 else
271 grx := mantissa(30 downto 29) & x;
272 lsb := mantissa(31);
273 end if;
274 ret(1) := '0';
275 ret(0) := or (grx);
276 case rn(1 downto 0) is
277 when "00" => -- round to nearest
278 if grx = "100" and rn(2) = '0' then
279 ret(1) := lsb; -- tie, round to even
280 else
281 ret(1) := grx(2);
282 end if;
283 when "01" => -- round towards zero
284 when others => -- round towards +/- inf
285 if rn(0) = sign then
286 -- round towards greater magnitude
287 ret(1) := ret(0);
288 end if;
289 end case;
290 return ret;
291 end;
292
293 -- Determine result flags to write into the FPSCR
294 function result_flags(sign: std_ulogic; class: fp_number_class; unitbit: std_ulogic)
295 return std_ulogic_vector is
296 begin
297 case class is
298 when ZERO =>
299 return sign & "0010";
300 when FINITE =>
301 return (not unitbit) & sign & (not sign) & "00";
302 when INFINITY =>
303 return '0' & sign & (not sign) & "01";
304 when NAN =>
305 return "10001";
306 end case;
307 end;
308
309 begin
310 fpu_0: process(clk)
311 begin
312 if rising_edge(clk) then
313 if rst = '1' then
314 r.state <= IDLE;
315 r.busy <= '0';
316 r.instr_done <= '0';
317 r.do_intr <= '0';
318 r.fpscr <= (others => '0');
319 r.writing_back <= '0';
320 else
321 assert not (r.state /= IDLE and e_in.valid = '1') severity failure;
322 r <= rin;
323 end if;
324 end if;
325 end process;
326
327 e_out.busy <= r.busy;
328 e_out.exception <= r.fpscr(FPSCR_FEX);
329 e_out.interrupt <= r.do_intr;
330
331 w_out.valid <= r.instr_done and not r.do_intr;
332 w_out.write_enable <= r.writing_back;
333 w_out.write_reg <= r.dest_fpr;
334 w_out.write_data <= fp_result;
335 w_out.write_cr_enable <= r.instr_done and (r.rc or r.is_cmp);
336 w_out.write_cr_mask <= r.cr_mask;
337 w_out.write_cr_data <= r.cr_result & r.cr_result & r.cr_result & r.cr_result &
338 r.cr_result & r.cr_result & r.cr_result & r.cr_result;
339
340 fpu_1: process(all)
341 variable v : reg_type;
342 variable adec : fpu_reg_type;
343 variable bdec : fpu_reg_type;
344 variable fpscr_mask : std_ulogic_vector(31 downto 0);
345 variable illegal : std_ulogic;
346 variable j, k : integer;
347 variable flm : std_ulogic_vector(7 downto 0);
348 variable int_input : std_ulogic;
349 variable mask : std_ulogic_vector(63 downto 0);
350 variable in_a0 : std_ulogic_vector(63 downto 0);
351 variable in_b0 : std_ulogic_vector(63 downto 0);
352 variable misc : std_ulogic_vector(63 downto 0);
353 variable shift_res : std_ulogic_vector(63 downto 0);
354 variable round : std_ulogic_vector(1 downto 0);
355 variable update_fx : std_ulogic;
356 variable arith_done : std_ulogic;
357 variable invalid : std_ulogic;
358 variable mant_nz : std_ulogic;
359 variable min_exp : signed(EXP_BITS-1 downto 0);
360 variable max_exp : signed(EXP_BITS-1 downto 0);
361 variable bias_exp : signed(EXP_BITS-1 downto 0);
362 variable new_exp : signed(EXP_BITS-1 downto 0);
363 variable exp_tiny : std_ulogic;
364 variable exp_huge : std_ulogic;
365 variable renormalize : std_ulogic;
366 variable clz : std_ulogic_vector(5 downto 0);
367 variable set_x : std_ulogic;
368 variable mshift : signed(EXP_BITS-1 downto 0);
369 variable need_check : std_ulogic;
370 variable msb : std_ulogic;
371 begin
372 v := r;
373 illegal := '0';
374 v.busy := '0';
375 int_input := '0';
376
377 -- capture incoming instruction
378 if e_in.valid = '1' then
379 v.insn := e_in.insn;
380 v.op := e_in.op;
381 v.fe_mode := or (e_in.fe_mode);
382 v.dest_fpr := e_in.frt;
383 v.single_prec := e_in.single;
384 v.int_result := '0';
385 v.rc := e_in.rc;
386 v.is_cmp := e_in.out_cr;
387 if e_in.out_cr = '0' then
388 v.cr_mask := num_to_fxm(1);
389 else
390 v.cr_mask := num_to_fxm(to_integer(unsigned(insn_bf(e_in.insn))));
391 end if;
392 int_input := '0';
393 if e_in.op = OP_FPOP_I then
394 int_input := '1';
395 end if;
396 v.quieten_nan := '1';
397 v.tiny := '0';
398 v.denorm := '0';
399 v.round_mode := '0' & r.fpscr(FPSCR_RN+1 downto FPSCR_RN);
400 adec := decode_dp(e_in.fra, int_input);
401 bdec := decode_dp(e_in.frb, int_input);
402 v.a := adec;
403 v.b := bdec;
404 end if;
405
406 r_hi_nz <= or (r.r(55 downto 31));
407 r_lo_nz <= or (r.r(30 downto 2));
408
409 if r.single_prec = '0' then
410 max_exp := to_signed(1023, EXP_BITS);
411 min_exp := to_signed(-1022, EXP_BITS);
412 bias_exp := to_signed(1536, EXP_BITS);
413 else
414 max_exp := to_signed(127, EXP_BITS);
415 min_exp := to_signed(-126, EXP_BITS);
416 bias_exp := to_signed(192, EXP_BITS);
417 end if;
418 new_exp := r.result_exp - r.shift;
419 exp_tiny := '0';
420 exp_huge := '0';
421 if new_exp < min_exp then
422 exp_tiny := '1';
423 end if;
424 if new_exp > max_exp then
425 exp_huge := '1';
426 end if;
427
428 v.writing_back := '0';
429 v.instr_done := '0';
430 v.update_fprf := '0';
431 v.shift := to_signed(0, EXP_BITS);
432 opsel_a <= AIN_R;
433 opsel_ainv <= '0';
434 opsel_amask <= '0';
435 opsel_b <= BIN_ZERO;
436 opsel_r <= RES_SUM;
437 carry_in <= '0';
438 misc_sel <= "0000";
439 fpscr_mask := (others => '1');
440 update_fx := '0';
441 arith_done := '0';
442 invalid := '0';
443 renormalize := '0';
444 set_x := '0';
445
446 case r.state is
447 when IDLE =>
448 if e_in.valid = '1' then
449 case e_in.insn(5 downto 1) is
450 when "00000" =>
451 v.state := DO_MCRFS;
452 when "00110" =>
453 if e_in.insn(10) = '0' then
454 if e_in.insn(8) = '0' then
455 v.state := DO_MTFSB;
456 else
457 v.state := DO_MTFSFI;
458 end if;
459 else
460 v.state := DO_FMRG;
461 end if;
462 when "00111" =>
463 if e_in.insn(8) = '0' then
464 v.state := DO_MFFS;
465 else
466 v.state := DO_MTFSF;
467 end if;
468 when "01000" =>
469 if e_in.insn(9 downto 8) /= "11" then
470 v.state := DO_FMR;
471 else
472 v.state := DO_FRI;
473 end if;
474 when "01100" =>
475 v.state := DO_FRSP;
476 when "01110" =>
477 if int_input = '1' then
478 -- fcfid[u][s]
479 v.state := DO_FCFID;
480 else
481 v.state := DO_FCTI;
482 end if;
483 when "01111" =>
484 v.round_mode := "001";
485 v.state := DO_FCTI;
486 when others =>
487 illegal := '1';
488 end case;
489 end if;
490 v.x := '0';
491 v.old_exc := r.fpscr(FPSCR_VX downto FPSCR_XX);
492
493 when DO_MCRFS =>
494 j := to_integer(unsigned(insn_bfa(r.insn)));
495 for i in 0 to 7 loop
496 if i = j then
497 k := (7 - i) * 4;
498 v.cr_result := r.fpscr(k + 3 downto k);
499 fpscr_mask(k + 3 downto k) := "0000";
500 end if;
501 end loop;
502 v.fpscr := r.fpscr and (fpscr_mask or x"6007F8FF");
503 v.instr_done := '1';
504 v.state := IDLE;
505
506 when DO_MTFSB =>
507 -- mtfsb{0,1}
508 j := to_integer(unsigned(insn_bt(r.insn)));
509 for i in 0 to 31 loop
510 if i = j then
511 v.fpscr(31 - i) := r.insn(6);
512 end if;
513 end loop;
514 v.instr_done := '1';
515 v.state := IDLE;
516
517 when DO_MTFSFI =>
518 -- mtfsfi
519 j := to_integer(unsigned(insn_bf(r.insn)));
520 if r.insn(16) = '0' then
521 for i in 0 to 7 loop
522 if i = j then
523 k := (7 - i) * 4;
524 v.fpscr(k + 3 downto k) := insn_u(r.insn);
525 end if;
526 end loop;
527 end if;
528 v.instr_done := '1';
529 v.state := IDLE;
530
531 when DO_FMRG =>
532 -- fmrgew, fmrgow
533 opsel_r <= RES_MISC;
534 misc_sel <= "01" & r.insn(8) & '0';
535 v.int_result := '1';
536 v.writing_back := '1';
537 v.instr_done := '1';
538 v.state := IDLE;
539
540 when DO_MFFS =>
541 v.int_result := '1';
542 v.writing_back := '1';
543 opsel_r <= RES_MISC;
544 case r.insn(20 downto 16) is
545 when "00000" =>
546 -- mffs
547 when "00001" =>
548 -- mffsce
549 v.fpscr(FPSCR_VE downto FPSCR_XE) := "00000";
550 when "10100" | "10101" =>
551 -- mffscdrn[i] (but we don't implement DRN)
552 fpscr_mask := x"000000FF";
553 when "10110" =>
554 -- mffscrn
555 fpscr_mask := x"000000FF";
556 v.fpscr(FPSCR_RN+1 downto FPSCR_RN) :=
557 r.b.mantissa(FPSCR_RN+1 downto FPSCR_RN);
558 when "10111" =>
559 -- mffscrni
560 fpscr_mask := x"000000FF";
561 v.fpscr(FPSCR_RN+1 downto FPSCR_RN) := r.insn(12 downto 11);
562 when "11000" =>
563 -- mffsl
564 fpscr_mask := x"0007F0FF";
565 when others =>
566 illegal := '1';
567 end case;
568 v.instr_done := '1';
569 v.state := IDLE;
570
571 when DO_MTFSF =>
572 if r.insn(25) = '1' then
573 flm := x"FF";
574 elsif r.insn(16) = '1' then
575 flm := x"00";
576 else
577 flm := r.insn(24 downto 17);
578 end if;
579 for i in 0 to 7 loop
580 k := i * 4;
581 if flm(i) = '1' then
582 v.fpscr(k + 3 downto k) := r.b.mantissa(k + 3 downto k);
583 end if;
584 end loop;
585 v.instr_done := '1';
586 v.state := IDLE;
587
588 when DO_FMR =>
589 opsel_a <= AIN_B;
590 v.result_class := r.b.class;
591 v.result_exp := r.b.exponent;
592 v.quieten_nan := '0';
593 if r.insn(9) = '1' then
594 v.result_sign := '0'; -- fabs
595 elsif r.insn(8) = '1' then
596 v.result_sign := '1'; -- fnabs
597 elsif r.insn(7) = '1' then
598 v.result_sign := r.b.negative; -- fmr
599 elsif r.insn(6) = '1' then
600 v.result_sign := not r.b.negative; -- fneg
601 else
602 v.result_sign := r.a.negative; -- fcpsgn
603 end if;
604 v.writing_back := '1';
605 v.instr_done := '1';
606 v.state := IDLE;
607
608 when DO_FRI => -- fri[nzpm]
609 opsel_a <= AIN_B;
610 v.result_class := r.b.class;
611 v.result_sign := r.b.negative;
612 v.result_exp := r.b.exponent;
613 v.fpscr(FPSCR_FR) := '0';
614 v.fpscr(FPSCR_FI) := '0';
615 if r.b.class = NAN and r.b.mantissa(53) = '0' then
616 -- Signalling NAN
617 v.fpscr(FPSCR_VXSNAN) := '1';
618 invalid := '1';
619 end if;
620 if r.b.class = FINITE then
621 if r.b.exponent >= to_signed(52, EXP_BITS) then
622 -- integer already, no rounding required
623 arith_done := '1';
624 else
625 v.shift := r.b.exponent - to_signed(52, EXP_BITS);
626 v.state := FRI_1;
627 v.round_mode := '1' & r.insn(7 downto 6);
628 end if;
629 else
630 arith_done := '1';
631 end if;
632
633 when DO_FRSP =>
634 opsel_a <= AIN_B;
635 v.result_class := r.b.class;
636 v.result_sign := r.b.negative;
637 v.result_exp := r.b.exponent;
638 v.fpscr(FPSCR_FR) := '0';
639 v.fpscr(FPSCR_FI) := '0';
640 if r.b.class = NAN and r.b.mantissa(53) = '0' then
641 -- Signalling NAN
642 v.fpscr(FPSCR_VXSNAN) := '1';
643 invalid := '1';
644 end if;
645 set_x := '1';
646 if r.b.class = FINITE then
647 if r.b.exponent < to_signed(-126, EXP_BITS) then
648 v.shift := r.b.exponent - to_signed(-126, EXP_BITS);
649 v.state := ROUND_UFLOW;
650 elsif r.b.exponent > to_signed(127, EXP_BITS) then
651 v.state := ROUND_OFLOW;
652 else
653 v.shift := to_signed(-2, EXP_BITS);
654 v.state := ROUNDING;
655 end if;
656 else
657 arith_done := '1';
658 end if;
659
660 when DO_FCTI =>
661 -- instr bit 9: 1=dword 0=word
662 -- instr bit 8: 1=unsigned 0=signed
663 -- instr bit 1: 1=round to zero 0=use fpscr[RN]
664 opsel_a <= AIN_B;
665 v.result_class := r.b.class;
666 v.result_sign := r.b.negative;
667 v.result_exp := r.b.exponent;
668 v.fpscr(FPSCR_FR) := '0';
669 v.fpscr(FPSCR_FI) := '0';
670 if r.b.class = NAN and r.b.mantissa(53) = '0' then
671 -- Signalling NAN
672 v.fpscr(FPSCR_VXSNAN) := '1';
673 invalid := '1';
674 end if;
675
676 v.int_result := '1';
677 case r.b.class is
678 when ZERO =>
679 arith_done := '1';
680 when FINITE =>
681 if r.b.exponent >= to_signed(64, EXP_BITS) or
682 (r.insn(9) = '0' and r.b.exponent >= to_signed(32, EXP_BITS)) then
683 v.state := INT_OFLOW;
684 elsif r.b.exponent >= to_signed(52, EXP_BITS) then
685 -- integer already, no rounding required,
686 -- shift into final position
687 v.shift := r.b.exponent - to_signed(54, EXP_BITS);
688 if r.insn(8) = '1' and r.b.negative = '1' then
689 v.state := INT_OFLOW;
690 else
691 v.state := INT_ISHIFT;
692 end if;
693 else
694 v.shift := r.b.exponent - to_signed(52, EXP_BITS);
695 v.state := INT_SHIFT;
696 end if;
697 when INFINITY | NAN =>
698 v.state := INT_OFLOW;
699 end case;
700
701 when DO_FCFID =>
702 v.result_sign := '0';
703 opsel_a <= AIN_B;
704 if r.insn(8) = '0' and r.b.negative = '1' then
705 -- fcfid[s] with negative operand, set R = -B
706 opsel_ainv <= '1';
707 carry_in <= '1';
708 v.result_sign := '1';
709 end if;
710 v.result_class := r.b.class;
711 v.result_exp := to_signed(54, EXP_BITS);
712 v.fpscr(FPSCR_FR) := '0';
713 v.fpscr(FPSCR_FI) := '0';
714 if r.b.class = ZERO then
715 arith_done := '1';
716 else
717 v.state := FINISH;
718 end if;
719
720 when INT_SHIFT =>
721 opsel_r <= RES_SHIFT;
722 set_x := '1';
723 v.state := INT_ROUND;
724 v.shift := to_signed(-2, EXP_BITS);
725
726 when INT_ROUND =>
727 opsel_r <= RES_SHIFT;
728 round := fp_rounding(r.r, r.x, '0', r.round_mode, r.result_sign);
729 v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
730 -- Check for negative values that don't round to 0 for fcti*u*
731 if r.insn(8) = '1' and r.result_sign = '1' and
732 (r_hi_nz or r_lo_nz or v.fpscr(FPSCR_FR)) = '1' then
733 v.state := INT_OFLOW;
734 else
735 v.state := INT_FINAL;
736 end if;
737
738 when INT_ISHIFT =>
739 opsel_r <= RES_SHIFT;
740 v.state := INT_FINAL;
741
742 when INT_FINAL =>
743 -- Negate if necessary, and increment for rounding if needed
744 opsel_ainv <= r.result_sign;
745 carry_in <= r.fpscr(FPSCR_FR) xor r.result_sign;
746 -- Check for possible overflows
747 case r.insn(9 downto 8) is
748 when "00" => -- fctiw[z]
749 need_check := r.r(31) or (r.r(30) and not r.result_sign);
750 when "01" => -- fctiwu[z]
751 need_check := r.r(31);
752 when "10" => -- fctid[z]
753 need_check := r.r(63) or (r.r(62) and not r.result_sign);
754 when others => -- fctidu[z]
755 need_check := r.r(63);
756 end case;
757 if need_check = '1' then
758 v.state := INT_CHECK;
759 else
760 if r.fpscr(FPSCR_FI) = '1' then
761 v.fpscr(FPSCR_XX) := '1';
762 end if;
763 arith_done := '1';
764 end if;
765
766 when INT_CHECK =>
767 if r.insn(9) = '0' then
768 msb := r.r(31);
769 else
770 msb := r.r(63);
771 end if;
772 misc_sel <= '1' & r.insn(9 downto 8) & r.result_sign;
773 if (r.insn(8) = '0' and msb /= r.result_sign) or
774 (r.insn(8) = '1' and msb /= '1') then
775 opsel_r <= RES_MISC;
776 v.fpscr(FPSCR_VXCVI) := '1';
777 invalid := '1';
778 else
779 if r.fpscr(FPSCR_FI) = '1' then
780 v.fpscr(FPSCR_XX) := '1';
781 end if;
782 end if;
783 arith_done := '1';
784
785 when INT_OFLOW =>
786 opsel_r <= RES_MISC;
787 misc_sel <= '1' & r.insn(9 downto 8) & r.result_sign;
788 if r.b.class = NAN then
789 misc_sel(0) <= '1';
790 end if;
791 v.fpscr(FPSCR_VXCVI) := '1';
792 invalid := '1';
793 arith_done := '1';
794
795 when FRI_1 =>
796 opsel_r <= RES_SHIFT;
797 set_x := '1';
798 v.shift := to_signed(-2, EXP_BITS);
799 v.state := ROUNDING;
800
801 when FINISH =>
802 if r.r(63 downto 54) /= "0000000001" then
803 renormalize := '1';
804 v.state := NORMALIZE;
805 else
806 set_x := '1';
807 if exp_tiny = '1' then
808 v.shift := new_exp - min_exp;
809 v.state := ROUND_UFLOW;
810 elsif exp_huge = '1' then
811 v.state := ROUND_OFLOW;
812 else
813 v.shift := to_signed(-2, EXP_BITS);
814 v.state := ROUNDING;
815 end if;
816 end if;
817
818 when NORMALIZE =>
819 -- Shift so we have 9 leading zeroes (we know R is non-zero)
820 opsel_r <= RES_SHIFT;
821 set_x := '1';
822 if exp_tiny = '1' then
823 v.shift := new_exp - min_exp;
824 v.state := ROUND_UFLOW;
825 elsif exp_huge = '1' then
826 v.state := ROUND_OFLOW;
827 else
828 v.shift := to_signed(-2, EXP_BITS);
829 v.state := ROUNDING;
830 end if;
831
832 when ROUND_UFLOW =>
833 v.tiny := '1';
834 if r.fpscr(FPSCR_UE) = '0' then
835 -- disabled underflow exception case
836 -- have to denormalize before rounding
837 opsel_r <= RES_SHIFT;
838 set_x := '1';
839 v.shift := to_signed(-2, EXP_BITS);
840 v.state := ROUNDING;
841 else
842 -- enabled underflow exception case
843 -- if denormalized, have to normalize before rounding
844 v.fpscr(FPSCR_UX) := '1';
845 v.result_exp := r.result_exp + bias_exp;
846 if r.r(54) = '0' then
847 renormalize := '1';
848 v.state := NORMALIZE;
849 else
850 v.shift := to_signed(-2, EXP_BITS);
851 v.state := ROUNDING;
852 end if;
853 end if;
854
855 when ROUND_OFLOW =>
856 v.fpscr(FPSCR_OX) := '1';
857 if r.fpscr(FPSCR_OE) = '0' then
858 -- disabled overflow exception
859 -- result depends on rounding mode
860 v.fpscr(FPSCR_XX) := '1';
861 v.fpscr(FPSCR_FI) := '1';
862 if r.round_mode(1 downto 0) = "00" or
863 (r.round_mode(1) = '1' and r.round_mode(0) = r.result_sign) then
864 v.result_class := INFINITY;
865 v.fpscr(FPSCR_FR) := '1';
866 else
867 v.fpscr(FPSCR_FR) := '0';
868 end if;
869 -- construct largest representable number
870 v.result_exp := max_exp;
871 opsel_r <= RES_MISC;
872 misc_sel <= "001" & r.single_prec;
873 arith_done := '1';
874 else
875 -- enabled overflow exception
876 v.result_exp := r.result_exp - bias_exp;
877 v.shift := to_signed(-2, EXP_BITS);
878 v.state := ROUNDING;
879 end if;
880
881 when ROUNDING =>
882 opsel_amask <= '1';
883 round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign);
884 v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
885 if round(1) = '1' then
886 -- set mask to increment the LSB for the precision
887 opsel_b <= BIN_MASK;
888 carry_in <= '1';
889 v.shift := to_signed(-1, EXP_BITS);
890 v.state := ROUNDING_2;
891 else
892 if r.r(54) = '0' then
893 -- result after masking could be zero, or could be a
894 -- denormalized result that needs to be renormalized
895 renormalize := '1';
896 v.state := ROUNDING_3;
897 else
898 arith_done := '1';
899 end if;
900 end if;
901 if round(0) = '1' then
902 v.fpscr(FPSCR_XX) := '1';
903 if r.tiny = '1' then
904 v.fpscr(FPSCR_UX) := '1';
905 end if;
906 end if;
907
908 when ROUNDING_2 =>
909 -- Check for overflow during rounding
910 v.x := '0';
911 if r.r(55) = '1' then
912 opsel_r <= RES_SHIFT;
913 if exp_huge = '1' then
914 v.state := ROUND_OFLOW;
915 else
916 arith_done := '1';
917 end if;
918 elsif r.r(54) = '0' then
919 -- Do CLZ so we can renormalize the result
920 renormalize := '1';
921 v.state := ROUNDING_3;
922 else
923 arith_done := '1';
924 end if;
925
926 when ROUNDING_3 =>
927 mant_nz := r_hi_nz or (r_lo_nz and not r.single_prec);
928 if mant_nz = '0' then
929 v.result_class := ZERO;
930 arith_done := '1';
931 else
932 -- Renormalize result after rounding
933 opsel_r <= RES_SHIFT;
934 v.denorm := exp_tiny;
935 v.shift := new_exp - to_signed(-1022, EXP_BITS);
936 if new_exp < to_signed(-1022, EXP_BITS) then
937 v.state := DENORM;
938 else
939 arith_done := '1';
940 end if;
941 end if;
942
943 when DENORM =>
944 opsel_r <= RES_SHIFT;
945 arith_done := '1';
946
947 end case;
948
949 if arith_done = '1' then
950 -- Enabled invalid exception doesn't write result or FPRF
951 if (invalid and r.fpscr(FPSCR_VE)) = '0' then
952 v.writing_back := '1';
953 v.update_fprf := '1';
954 end if;
955 v.instr_done := '1';
956 v.state := IDLE;
957 update_fx := '1';
958 end if;
959
960 -- Data path.
961 -- This has A and B input multiplexers, an adder, a shifter,
962 -- count-leading-zeroes logic, and a result mux.
963 if r.single_prec = '1' then
964 mshift := r.shift + to_signed(-29, EXP_BITS);
965 else
966 mshift := r.shift;
967 end if;
968 if mshift < to_signed(-64, EXP_BITS) then
969 mask := (others => '1');
970 elsif mshift >= to_signed(0, EXP_BITS) then
971 mask := (others => '0');
972 else
973 mask := right_mask(unsigned(mshift(5 downto 0)));
974 end if;
975 case opsel_a is
976 when AIN_R =>
977 in_a0 := r.r;
978 when AIN_A =>
979 in_a0 := r.a.mantissa;
980 when others =>
981 in_a0 := r.b.mantissa;
982 end case;
983 if (or (mask and in_a0)) = '1' and set_x = '1' then
984 v.x := '1';
985 end if;
986 if opsel_ainv = '1' then
987 in_a0 := not in_a0;
988 end if;
989 if opsel_amask = '1' then
990 in_a0 := in_a0 and not mask;
991 end if;
992 in_a <= in_a0;
993 case opsel_b is
994 when BIN_ZERO =>
995 in_b0 := (others => '0');
996 when BIN_R =>
997 in_b0 := r.r;
998 when BIN_MASK =>
999 in_b0 := mask;
1000 when others =>
1001 in_b0 := (others => '0');
1002 end case;
1003 in_b <= in_b0;
1004 if r.shift >= to_signed(-64, EXP_BITS) and r.shift <= to_signed(63, EXP_BITS) then
1005 shift_res := shifter_64(r.r & x"00000000000000",
1006 std_ulogic_vector(r.shift(6 downto 0)));
1007 else
1008 shift_res := (others => '0');
1009 end if;
1010 case opsel_r is
1011 when RES_SUM =>
1012 result <= std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
1013 when RES_SHIFT =>
1014 result <= shift_res;
1015 when others =>
1016 case misc_sel is
1017 when "0000" =>
1018 misc := x"00000000" & (r.fpscr and fpscr_mask);
1019 when "0010" =>
1020 -- mantissa of max representable DP number
1021 misc := x"007ffffffffffffc";
1022 when "0011" =>
1023 -- mantissa of max representable SP number
1024 misc := x"007fffff80000000";
1025 when "0100" =>
1026 -- fmrgow result
1027 misc := r.a.mantissa(31 downto 0) & r.b.mantissa(31 downto 0);
1028 when "0110" =>
1029 -- fmrgew result
1030 misc := r.a.mantissa(63 downto 32) & r.b.mantissa(63 downto 32);
1031 when "1000" =>
1032 -- max positive result for fctiw[z]
1033 misc := x"000000007fffffff";
1034 when "1001" =>
1035 -- max negative result for fctiw[z]
1036 misc := x"ffffffff80000000";
1037 when "1010" =>
1038 -- max positive result for fctiwu[z]
1039 misc := x"00000000ffffffff";
1040 when "1011" =>
1041 -- max negative result for fctiwu[z]
1042 misc := x"0000000000000000";
1043 when "1100" =>
1044 -- max positive result for fctid[z]
1045 misc := x"7fffffffffffffff";
1046 when "1101" =>
1047 -- max negative result for fctid[z]
1048 misc := x"8000000000000000";
1049 when "1110" =>
1050 -- max positive result for fctidu[z]
1051 misc := x"ffffffffffffffff";
1052 when "1111" =>
1053 -- max negative result for fctidu[z]
1054 misc := x"0000000000000000";
1055 when others =>
1056 misc := x"0000000000000000";
1057 end case;
1058 result <= misc;
1059 end case;
1060 v.r := result;
1061
1062 if opsel_r = RES_SHIFT then
1063 v.result_exp := new_exp;
1064 end if;
1065
1066 if renormalize = '1' then
1067 clz := count_left_zeroes(r.r);
1068 v.shift := resize(signed('0' & clz) - 9, EXP_BITS);
1069 end if;
1070
1071 if r.int_result = '1' then
1072 fp_result <= r.r;
1073 else
1074 fp_result <= pack_dp(r.result_sign, r.result_class, r.result_exp, r.r,
1075 r.single_prec, r.quieten_nan);
1076 end if;
1077 if r.update_fprf = '1' then
1078 v.fpscr(FPSCR_C downto FPSCR_FU) := result_flags(r.result_sign, r.result_class,
1079 r.r(54) and not r.denorm);
1080 end if;
1081
1082 v.fpscr(FPSCR_VX) := (or (v.fpscr(FPSCR_VXSNAN downto FPSCR_VXVC))) or
1083 (or (v.fpscr(FPSCR_VXSOFT downto FPSCR_VXCVI)));
1084 v.fpscr(FPSCR_FEX) := or (v.fpscr(FPSCR_VX downto FPSCR_XX) and
1085 v.fpscr(FPSCR_VE downto FPSCR_XE));
1086 if update_fx = '1' and
1087 (v.fpscr(FPSCR_VX downto FPSCR_XX) and not r.old_exc) /= "00000" then
1088 v.fpscr(FPSCR_FX) := '1';
1089 end if;
1090 if r.rc = '1' then
1091 v.cr_result := v.fpscr(FPSCR_FX downto FPSCR_OX);
1092 end if;
1093
1094 if illegal = '1' then
1095 v.instr_done := '0';
1096 v.do_intr := '0';
1097 v.writing_back := '0';
1098 v.busy := '0';
1099 v.state := IDLE;
1100 else
1101 v.do_intr := v.instr_done and v.fpscr(FPSCR_FEX) and r.fe_mode;
1102 if v.state /= IDLE or v.do_intr = '1' then
1103 v.busy := '1';
1104 end if;
1105 end if;
1106
1107 rin <= v;
1108 e_out.illegal <= illegal;
1109 end process;
1110
1111 end architecture behaviour;