FPU: Implement floating convert from integer instructions
[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,
41 DO_FCFID,
42 FINISH, NORMALIZE,
43 ROUND_UFLOW, ROUND_OFLOW,
44 ROUNDING, ROUNDING_2, ROUNDING_3,
45 DENORM);
46
47 type reg_type is record
48 state : state_t;
49 busy : std_ulogic;
50 instr_done : std_ulogic;
51 do_intr : std_ulogic;
52 op : insn_type_t;
53 insn : std_ulogic_vector(31 downto 0);
54 dest_fpr : gspr_index_t;
55 fe_mode : std_ulogic;
56 rc : std_ulogic;
57 is_cmp : std_ulogic;
58 single_prec : std_ulogic;
59 fpscr : std_ulogic_vector(31 downto 0);
60 a : fpu_reg_type;
61 b : fpu_reg_type;
62 r : std_ulogic_vector(63 downto 0); -- 10.54 format
63 x : std_ulogic;
64 result_sign : std_ulogic;
65 result_class : fp_number_class;
66 result_exp : signed(EXP_BITS-1 downto 0);
67 shift : signed(EXP_BITS-1 downto 0);
68 writing_back : std_ulogic;
69 int_result : std_ulogic;
70 cr_result : std_ulogic_vector(3 downto 0);
71 cr_mask : std_ulogic_vector(7 downto 0);
72 old_exc : std_ulogic_vector(4 downto 0);
73 update_fprf : std_ulogic;
74 tiny : std_ulogic;
75 denorm : std_ulogic;
76 round_mode : std_ulogic_vector(2 downto 0);
77 end record;
78
79 signal r, rin : reg_type;
80
81 signal fp_result : std_ulogic_vector(63 downto 0);
82 signal opsel_a : std_ulogic_vector(1 downto 0);
83 signal opsel_b : std_ulogic_vector(1 downto 0);
84 signal opsel_r : std_ulogic_vector(1 downto 0);
85 signal opsel_ainv : std_ulogic;
86 signal opsel_amask : std_ulogic;
87 signal in_a : std_ulogic_vector(63 downto 0);
88 signal in_b : std_ulogic_vector(63 downto 0);
89 signal result : std_ulogic_vector(63 downto 0);
90 signal carry_in : std_ulogic;
91 signal lost_bits : std_ulogic;
92 signal r_hi_nz : std_ulogic;
93 signal r_lo_nz : std_ulogic;
94 signal misc_sel : std_ulogic_vector(3 downto 0);
95
96 -- opsel values
97 constant AIN_R : std_ulogic_vector(1 downto 0) := "00";
98 constant AIN_A : std_ulogic_vector(1 downto 0) := "01";
99 constant AIN_B : std_ulogic_vector(1 downto 0) := "10";
100
101 constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00";
102 constant BIN_R : std_ulogic_vector(1 downto 0) := "01";
103 constant BIN_MASK : std_ulogic_vector(1 downto 0) := "10";
104
105 constant RES_SUM : std_ulogic_vector(1 downto 0) := "00";
106 constant RES_SHIFT : std_ulogic_vector(1 downto 0) := "01";
107 constant RES_MISC : std_ulogic_vector(1 downto 0) := "11";
108
109 -- Left and right shifter with 120 bit input and 64 bit output.
110 -- Shifts inp left by shift bits and returns the upper 64 bits of
111 -- the result. The shift parameter is interpreted as a signed
112 -- number in the range -64..63, with negative values indicating
113 -- right shifts.
114 function shifter_64(inp: std_ulogic_vector(119 downto 0);
115 shift: std_ulogic_vector(6 downto 0))
116 return std_ulogic_vector is
117 variable s1 : std_ulogic_vector(94 downto 0);
118 variable s2 : std_ulogic_vector(70 downto 0);
119 variable result : std_ulogic_vector(63 downto 0);
120 begin
121 case shift(6 downto 5) is
122 when "00" =>
123 s1 := inp(119 downto 25);
124 when "01" =>
125 s1 := inp(87 downto 0) & "0000000";
126 when "10" =>
127 s1 := x"0000000000000000" & inp(119 downto 89);
128 when others =>
129 s1 := x"00000000" & inp(119 downto 57);
130 end case;
131 case shift(4 downto 3) is
132 when "00" =>
133 s2 := s1(94 downto 24);
134 when "01" =>
135 s2 := s1(86 downto 16);
136 when "10" =>
137 s2 := s1(78 downto 8);
138 when others =>
139 s2 := s1(70 downto 0);
140 end case;
141 case shift(2 downto 0) is
142 when "000" =>
143 result := s2(70 downto 7);
144 when "001" =>
145 result := s2(69 downto 6);
146 when "010" =>
147 result := s2(68 downto 5);
148 when "011" =>
149 result := s2(67 downto 4);
150 when "100" =>
151 result := s2(66 downto 3);
152 when "101" =>
153 result := s2(65 downto 2);
154 when "110" =>
155 result := s2(64 downto 1);
156 when others =>
157 result := s2(63 downto 0);
158 end case;
159 return result;
160 end;
161
162 -- Generate a mask with 0-bits on the left and 1-bits on the right which
163 -- selects the bits will be lost in doing a right shift. The shift
164 -- parameter is the bottom 6 bits of a negative shift count,
165 -- indicating a right shift.
166 function right_mask(shift: unsigned(5 downto 0)) return std_ulogic_vector is
167 variable result: std_ulogic_vector(63 downto 0);
168 begin
169 result := (others => '0');
170 for i in 0 to 63 loop
171 if i >= shift then
172 result(63 - i) := '1';
173 end if;
174 end loop;
175 return result;
176 end;
177
178 -- Split a DP floating-point number into components and work out its class.
179 -- If is_int = 1, the input is considered an integer
180 function decode_dp(fpr: std_ulogic_vector(63 downto 0); is_int: std_ulogic) return fpu_reg_type is
181 variable r : fpu_reg_type;
182 variable exp_nz : std_ulogic;
183 variable exp_ao : std_ulogic;
184 variable frac_nz : std_ulogic;
185 variable cls : std_ulogic_vector(2 downto 0);
186 begin
187 r.negative := fpr(63);
188 exp_nz := or (fpr(62 downto 52));
189 exp_ao := and (fpr(62 downto 52));
190 frac_nz := or (fpr(51 downto 0));
191 if is_int = '0' then
192 r.exponent := signed(resize(unsigned(fpr(62 downto 52)), EXP_BITS)) - to_signed(1023, EXP_BITS);
193 if exp_nz = '0' then
194 r.exponent := to_signed(-1022, EXP_BITS);
195 end if;
196 r.mantissa := "000000000" & exp_nz & fpr(51 downto 0) & "00";
197 cls := exp_ao & exp_nz & frac_nz;
198 case cls is
199 when "000" => r.class := ZERO;
200 when "001" => r.class := FINITE; -- denormalized
201 when "010" => r.class := FINITE;
202 when "011" => r.class := FINITE;
203 when "110" => r.class := INFINITY;
204 when others => r.class := NAN;
205 end case;
206 else
207 r.mantissa := fpr;
208 r.exponent := (others => '0');
209 if (fpr(63) or exp_nz or frac_nz) = '1' then
210 r.class := FINITE;
211 else
212 r.class := ZERO;
213 end if;
214 end if;
215 return r;
216 end;
217
218 -- Construct a DP floating-point result from components
219 function pack_dp(sign: std_ulogic; class: fp_number_class; exp: signed(EXP_BITS-1 downto 0);
220 mantissa: std_ulogic_vector; single_prec: std_ulogic)
221 return std_ulogic_vector is
222 variable result : std_ulogic_vector(63 downto 0);
223 begin
224 result := (others => '0');
225 result(63) := sign;
226 case class is
227 when ZERO =>
228 when FINITE =>
229 if mantissa(54) = '1' then
230 -- normalized number
231 result(62 downto 52) := std_ulogic_vector(resize(exp, 11) + 1023);
232 end if;
233 result(51 downto 29) := mantissa(53 downto 31);
234 if single_prec = '0' then
235 result(28 downto 0) := mantissa(30 downto 2);
236 end if;
237 when INFINITY =>
238 result(62 downto 52) := "11111111111";
239 when NAN =>
240 result(62 downto 52) := "11111111111";
241 result(51 downto 29) := mantissa(53 downto 31);
242 if single_prec = '0' then
243 result(28 downto 0) := mantissa(30 downto 2);
244 end if;
245 end case;
246 return result;
247 end;
248
249 -- Determine whether to increment when rounding
250 -- Returns rounding_inc & inexact
251 -- Assumes x includes the bottom 29 bits of the mantissa already
252 -- if single_prec = 1 (usually arranged by setting set_x = 1 earlier).
253 function fp_rounding(mantissa: std_ulogic_vector(63 downto 0); x: std_ulogic;
254 single_prec: std_ulogic; rn: std_ulogic_vector(2 downto 0);
255 sign: std_ulogic)
256 return std_ulogic_vector is
257 variable grx : std_ulogic_vector(2 downto 0);
258 variable ret : std_ulogic_vector(1 downto 0);
259 variable lsb : std_ulogic;
260 begin
261 if single_prec = '0' then
262 grx := mantissa(1 downto 0) & x;
263 lsb := mantissa(2);
264 else
265 grx := mantissa(30 downto 29) & x;
266 lsb := mantissa(31);
267 end if;
268 ret(1) := '0';
269 ret(0) := or (grx);
270 case rn(1 downto 0) is
271 when "00" => -- round to nearest
272 if grx = "100" and rn(2) = '0' then
273 ret(1) := lsb; -- tie, round to even
274 else
275 ret(1) := grx(2);
276 end if;
277 when "01" => -- round towards zero
278 when others => -- round towards +/- inf
279 if rn(0) = sign then
280 -- round towards greater magnitude
281 ret(1) := ret(0);
282 end if;
283 end case;
284 return ret;
285 end;
286
287 -- Determine result flags to write into the FPSCR
288 function result_flags(sign: std_ulogic; class: fp_number_class; unitbit: std_ulogic)
289 return std_ulogic_vector is
290 begin
291 case class is
292 when ZERO =>
293 return sign & "0010";
294 when FINITE =>
295 return (not unitbit) & sign & (not sign) & "00";
296 when INFINITY =>
297 return '0' & sign & (not sign) & "01";
298 when NAN =>
299 return "10001";
300 end case;
301 end;
302
303 begin
304 fpu_0: process(clk)
305 begin
306 if rising_edge(clk) then
307 if rst = '1' then
308 r.state <= IDLE;
309 r.busy <= '0';
310 r.instr_done <= '0';
311 r.do_intr <= '0';
312 r.fpscr <= (others => '0');
313 r.writing_back <= '0';
314 else
315 assert not (r.state /= IDLE and e_in.valid = '1') severity failure;
316 r <= rin;
317 end if;
318 end if;
319 end process;
320
321 e_out.busy <= r.busy;
322 e_out.exception <= r.fpscr(FPSCR_FEX);
323 e_out.interrupt <= r.do_intr;
324
325 w_out.valid <= r.instr_done and not r.do_intr;
326 w_out.write_enable <= r.writing_back;
327 w_out.write_reg <= r.dest_fpr;
328 w_out.write_data <= fp_result;
329 w_out.write_cr_enable <= r.instr_done and (r.rc or r.is_cmp);
330 w_out.write_cr_mask <= r.cr_mask;
331 w_out.write_cr_data <= r.cr_result & r.cr_result & r.cr_result & r.cr_result &
332 r.cr_result & r.cr_result & r.cr_result & r.cr_result;
333
334 fpu_1: process(all)
335 variable v : reg_type;
336 variable adec : fpu_reg_type;
337 variable bdec : fpu_reg_type;
338 variable fpscr_mask : std_ulogic_vector(31 downto 0);
339 variable illegal : std_ulogic;
340 variable j, k : integer;
341 variable flm : std_ulogic_vector(7 downto 0);
342 variable int_input : std_ulogic;
343 variable mask : std_ulogic_vector(63 downto 0);
344 variable in_a0 : std_ulogic_vector(63 downto 0);
345 variable in_b0 : std_ulogic_vector(63 downto 0);
346 variable misc : std_ulogic_vector(63 downto 0);
347 variable shift_res : std_ulogic_vector(63 downto 0);
348 variable round : std_ulogic_vector(1 downto 0);
349 variable update_fx : std_ulogic;
350 variable arith_done : std_ulogic;
351 variable mant_nz : std_ulogic;
352 variable min_exp : signed(EXP_BITS-1 downto 0);
353 variable max_exp : signed(EXP_BITS-1 downto 0);
354 variable bias_exp : signed(EXP_BITS-1 downto 0);
355 variable new_exp : signed(EXP_BITS-1 downto 0);
356 variable exp_tiny : std_ulogic;
357 variable exp_huge : std_ulogic;
358 variable renormalize : std_ulogic;
359 variable clz : std_ulogic_vector(5 downto 0);
360 variable set_x : std_ulogic;
361 variable mshift : signed(EXP_BITS-1 downto 0);
362 begin
363 v := r;
364 illegal := '0';
365 v.busy := '0';
366 int_input := '0';
367
368 -- capture incoming instruction
369 if e_in.valid = '1' then
370 v.insn := e_in.insn;
371 v.op := e_in.op;
372 v.fe_mode := or (e_in.fe_mode);
373 v.dest_fpr := e_in.frt;
374 v.single_prec := e_in.single;
375 v.int_result := '0';
376 v.rc := e_in.rc;
377 v.is_cmp := e_in.out_cr;
378 if e_in.out_cr = '0' then
379 v.cr_mask := num_to_fxm(1);
380 else
381 v.cr_mask := num_to_fxm(to_integer(unsigned(insn_bf(e_in.insn))));
382 end if;
383 int_input := '0';
384 if e_in.op = OP_FPOP_I then
385 int_input := '1';
386 end if;
387 v.tiny := '0';
388 v.denorm := '0';
389 v.round_mode := '0' & r.fpscr(FPSCR_RN+1 downto FPSCR_RN);
390 adec := decode_dp(e_in.fra, int_input);
391 bdec := decode_dp(e_in.frb, int_input);
392 v.a := adec;
393 v.b := bdec;
394 end if;
395
396 r_hi_nz <= or (r.r(55 downto 31));
397 r_lo_nz <= or (r.r(30 downto 2));
398
399 if r.single_prec = '0' then
400 max_exp := to_signed(1023, EXP_BITS);
401 min_exp := to_signed(-1022, EXP_BITS);
402 bias_exp := to_signed(1536, EXP_BITS);
403 else
404 max_exp := to_signed(127, EXP_BITS);
405 min_exp := to_signed(-126, EXP_BITS);
406 bias_exp := to_signed(192, EXP_BITS);
407 end if;
408 new_exp := r.result_exp - r.shift;
409 exp_tiny := '0';
410 exp_huge := '0';
411 if new_exp < min_exp then
412 exp_tiny := '1';
413 end if;
414 if new_exp > max_exp then
415 exp_huge := '1';
416 end if;
417
418 v.writing_back := '0';
419 v.instr_done := '0';
420 v.update_fprf := '0';
421 v.shift := to_signed(0, EXP_BITS);
422 opsel_a <= AIN_R;
423 opsel_ainv <= '0';
424 opsel_amask <= '0';
425 opsel_b <= BIN_ZERO;
426 opsel_r <= RES_SUM;
427 carry_in <= '0';
428 misc_sel <= "0000";
429 fpscr_mask := (others => '1');
430 update_fx := '0';
431 arith_done := '0';
432 renormalize := '0';
433 set_x := '0';
434
435 case r.state is
436 when IDLE =>
437 if e_in.valid = '1' then
438 case e_in.insn(5 downto 1) is
439 when "00000" =>
440 v.state := DO_MCRFS;
441 when "00110" =>
442 if e_in.insn(8) = '0' then
443 v.state := DO_MTFSB;
444 else
445 v.state := DO_MTFSFI;
446 end if;
447 when "00111" =>
448 if e_in.insn(8) = '0' then
449 v.state := DO_MFFS;
450 else
451 v.state := DO_MTFSF;
452 end if;
453 when "01000" =>
454 v.state := DO_FMR;
455 when "01110" =>
456 -- fcfid[u][s]
457 v.state := DO_FCFID;
458 when others =>
459 illegal := '1';
460 end case;
461 end if;
462 v.x := '0';
463 v.old_exc := r.fpscr(FPSCR_VX downto FPSCR_XX);
464
465 when DO_MCRFS =>
466 j := to_integer(unsigned(insn_bfa(r.insn)));
467 for i in 0 to 7 loop
468 if i = j then
469 k := (7 - i) * 4;
470 v.cr_result := r.fpscr(k + 3 downto k);
471 fpscr_mask(k + 3 downto k) := "0000";
472 end if;
473 end loop;
474 v.fpscr := r.fpscr and (fpscr_mask or x"6007F8FF");
475 v.instr_done := '1';
476 v.state := IDLE;
477
478 when DO_MTFSB =>
479 -- mtfsb{0,1}
480 j := to_integer(unsigned(insn_bt(r.insn)));
481 for i in 0 to 31 loop
482 if i = j then
483 v.fpscr(31 - i) := r.insn(6);
484 end if;
485 end loop;
486 v.instr_done := '1';
487 v.state := IDLE;
488
489 when DO_MTFSFI =>
490 -- mtfsfi
491 j := to_integer(unsigned(insn_bf(r.insn)));
492 if r.insn(16) = '0' then
493 for i in 0 to 7 loop
494 if i = j then
495 k := (7 - i) * 4;
496 v.fpscr(k + 3 downto k) := insn_u(r.insn);
497 end if;
498 end loop;
499 end if;
500 v.instr_done := '1';
501 v.state := IDLE;
502
503 when DO_MFFS =>
504 v.int_result := '1';
505 v.writing_back := '1';
506 opsel_r <= RES_MISC;
507 case r.insn(20 downto 16) is
508 when "00000" =>
509 -- mffs
510 when "00001" =>
511 -- mffsce
512 v.fpscr(FPSCR_VE downto FPSCR_XE) := "00000";
513 when "10100" | "10101" =>
514 -- mffscdrn[i] (but we don't implement DRN)
515 fpscr_mask := x"000000FF";
516 when "10110" =>
517 -- mffscrn
518 fpscr_mask := x"000000FF";
519 v.fpscr(FPSCR_RN+1 downto FPSCR_RN) :=
520 r.b.mantissa(FPSCR_RN+1 downto FPSCR_RN);
521 when "10111" =>
522 -- mffscrni
523 fpscr_mask := x"000000FF";
524 v.fpscr(FPSCR_RN+1 downto FPSCR_RN) := r.insn(12 downto 11);
525 when "11000" =>
526 -- mffsl
527 fpscr_mask := x"0007F0FF";
528 when others =>
529 illegal := '1';
530 end case;
531 v.instr_done := '1';
532 v.state := IDLE;
533
534 when DO_MTFSF =>
535 if r.insn(25) = '1' then
536 flm := x"FF";
537 elsif r.insn(16) = '1' then
538 flm := x"00";
539 else
540 flm := r.insn(24 downto 17);
541 end if;
542 for i in 0 to 7 loop
543 k := i * 4;
544 if flm(i) = '1' then
545 v.fpscr(k + 3 downto k) := r.b.mantissa(k + 3 downto k);
546 end if;
547 end loop;
548 v.instr_done := '1';
549 v.state := IDLE;
550
551 when DO_FMR =>
552 opsel_a <= AIN_B;
553 v.result_class := r.b.class;
554 v.result_exp := r.b.exponent;
555 if r.insn(9) = '1' then
556 v.result_sign := '0'; -- fabs
557 elsif r.insn(8) = '1' then
558 v.result_sign := '1'; -- fnabs
559 elsif r.insn(7) = '1' then
560 v.result_sign := r.b.negative; -- fmr
561 elsif r.insn(6) = '1' then
562 v.result_sign := not r.b.negative; -- fneg
563 else
564 v.result_sign := r.a.negative; -- fcpsgn
565 end if;
566 v.writing_back := '1';
567 v.instr_done := '1';
568 v.state := IDLE;
569
570 when DO_FCFID =>
571 v.result_sign := '0';
572 opsel_a <= AIN_B;
573 if r.insn(8) = '0' and r.b.negative = '1' then
574 -- fcfid[s] with negative operand, set R = -B
575 opsel_ainv <= '1';
576 carry_in <= '1';
577 v.result_sign := '1';
578 end if;
579 v.result_class := r.b.class;
580 v.result_exp := to_signed(54, EXP_BITS);
581 v.fpscr(FPSCR_FR) := '0';
582 v.fpscr(FPSCR_FI) := '0';
583 if r.b.class = ZERO then
584 arith_done := '1';
585 else
586 v.state := FINISH;
587 end if;
588
589 when FINISH =>
590 if r.r(63 downto 54) /= "0000000001" then
591 renormalize := '1';
592 v.state := NORMALIZE;
593 else
594 set_x := '1';
595 if exp_tiny = '1' then
596 v.shift := new_exp - min_exp;
597 v.state := ROUND_UFLOW;
598 elsif exp_huge = '1' then
599 v.state := ROUND_OFLOW;
600 else
601 v.shift := to_signed(-2, EXP_BITS);
602 v.state := ROUNDING;
603 end if;
604 end if;
605
606 when NORMALIZE =>
607 -- Shift so we have 9 leading zeroes (we know R is non-zero)
608 opsel_r <= RES_SHIFT;
609 set_x := '1';
610 if exp_tiny = '1' then
611 v.shift := new_exp - min_exp;
612 v.state := ROUND_UFLOW;
613 elsif exp_huge = '1' then
614 v.state := ROUND_OFLOW;
615 else
616 v.shift := to_signed(-2, EXP_BITS);
617 v.state := ROUNDING;
618 end if;
619
620 when ROUND_UFLOW =>
621 v.tiny := '1';
622 if r.fpscr(FPSCR_UE) = '0' then
623 -- disabled underflow exception case
624 -- have to denormalize before rounding
625 opsel_r <= RES_SHIFT;
626 set_x := '1';
627 v.shift := to_signed(-2, EXP_BITS);
628 v.state := ROUNDING;
629 else
630 -- enabled underflow exception case
631 -- if denormalized, have to normalize before rounding
632 v.fpscr(FPSCR_UX) := '1';
633 v.result_exp := r.result_exp + bias_exp;
634 if r.r(54) = '0' then
635 renormalize := '1';
636 v.state := NORMALIZE;
637 else
638 v.shift := to_signed(-2, EXP_BITS);
639 v.state := ROUNDING;
640 end if;
641 end if;
642
643 when ROUND_OFLOW =>
644 v.fpscr(FPSCR_OX) := '1';
645 if r.fpscr(FPSCR_OE) = '0' then
646 -- disabled overflow exception
647 -- result depends on rounding mode
648 v.fpscr(FPSCR_XX) := '1';
649 v.fpscr(FPSCR_FI) := '1';
650 if r.round_mode(1 downto 0) = "00" or
651 (r.round_mode(1) = '1' and r.round_mode(0) = r.result_sign) then
652 v.result_class := INFINITY;
653 v.fpscr(FPSCR_FR) := '1';
654 else
655 v.fpscr(FPSCR_FR) := '0';
656 end if;
657 -- construct largest representable number
658 v.result_exp := max_exp;
659 opsel_r <= RES_MISC;
660 misc_sel <= "001" & r.single_prec;
661 arith_done := '1';
662 else
663 -- enabled overflow exception
664 v.result_exp := r.result_exp - bias_exp;
665 v.shift := to_signed(-2, EXP_BITS);
666 v.state := ROUNDING;
667 end if;
668
669 when ROUNDING =>
670 opsel_amask <= '1';
671 round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign);
672 v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
673 if round(1) = '1' then
674 -- set mask to increment the LSB for the precision
675 opsel_b <= BIN_MASK;
676 carry_in <= '1';
677 v.shift := to_signed(-1, EXP_BITS);
678 v.state := ROUNDING_2;
679 else
680 if r.r(54) = '0' then
681 -- result after masking could be zero, or could be a
682 -- denormalized result that needs to be renormalized
683 renormalize := '1';
684 v.state := ROUNDING_3;
685 else
686 arith_done := '1';
687 end if;
688 end if;
689 if round(0) = '1' then
690 v.fpscr(FPSCR_XX) := '1';
691 if r.tiny = '1' then
692 v.fpscr(FPSCR_UX) := '1';
693 end if;
694 end if;
695
696 when ROUNDING_2 =>
697 -- Check for overflow during rounding
698 v.x := '0';
699 if r.r(55) = '1' then
700 opsel_r <= RES_SHIFT;
701 if exp_huge = '1' then
702 v.state := ROUND_OFLOW;
703 else
704 arith_done := '1';
705 end if;
706 elsif r.r(54) = '0' then
707 -- Do CLZ so we can renormalize the result
708 renormalize := '1';
709 v.state := ROUNDING_3;
710 else
711 arith_done := '1';
712 end if;
713
714 when ROUNDING_3 =>
715 mant_nz := r_hi_nz or (r_lo_nz and not r.single_prec);
716 if mant_nz = '0' then
717 v.result_class := ZERO;
718 arith_done := '1';
719 else
720 -- Renormalize result after rounding
721 opsel_r <= RES_SHIFT;
722 v.denorm := exp_tiny;
723 v.shift := new_exp - to_signed(-1022, EXP_BITS);
724 if new_exp < to_signed(-1022, EXP_BITS) then
725 v.state := DENORM;
726 else
727 arith_done := '1';
728 end if;
729 end if;
730
731 when DENORM =>
732 opsel_r <= RES_SHIFT;
733 arith_done := '1';
734
735 end case;
736
737 if arith_done = '1' then
738 v.writing_back := '1';
739 v.update_fprf := '1';
740 v.instr_done := '1';
741 v.state := IDLE;
742 update_fx := '1';
743 end if;
744
745 -- Data path.
746 -- This has A and B input multiplexers, an adder, a shifter,
747 -- count-leading-zeroes logic, and a result mux.
748 if r.single_prec = '1' then
749 mshift := r.shift + to_signed(-29, EXP_BITS);
750 else
751 mshift := r.shift;
752 end if;
753 if mshift < to_signed(-64, EXP_BITS) then
754 mask := (others => '1');
755 elsif mshift >= to_signed(0, EXP_BITS) then
756 mask := (others => '0');
757 else
758 mask := right_mask(unsigned(mshift(5 downto 0)));
759 end if;
760 case opsel_a is
761 when AIN_R =>
762 in_a0 := r.r;
763 when AIN_A =>
764 in_a0 := r.a.mantissa;
765 when others =>
766 in_a0 := r.b.mantissa;
767 end case;
768 if (or (mask and in_a0)) = '1' and set_x = '1' then
769 v.x := '1';
770 end if;
771 if opsel_ainv = '1' then
772 in_a0 := not in_a0;
773 end if;
774 if opsel_amask = '1' then
775 in_a0 := in_a0 and not mask;
776 end if;
777 in_a <= in_a0;
778 case opsel_b is
779 when BIN_ZERO =>
780 in_b0 := (others => '0');
781 when BIN_R =>
782 in_b0 := r.r;
783 when BIN_MASK =>
784 in_b0 := mask;
785 when others =>
786 in_b0 := (others => '0');
787 end case;
788 in_b <= in_b0;
789 if r.shift >= to_signed(-64, EXP_BITS) and r.shift <= to_signed(63, EXP_BITS) then
790 shift_res := shifter_64(r.r & x"00000000000000",
791 std_ulogic_vector(r.shift(6 downto 0)));
792 else
793 shift_res := (others => '0');
794 end if;
795 case opsel_r is
796 when RES_SUM =>
797 result <= std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
798 when RES_SHIFT =>
799 result <= shift_res;
800 when others =>
801 case misc_sel is
802 when "0000" =>
803 misc := x"00000000" & (r.fpscr and fpscr_mask);
804 when "0010" =>
805 -- mantissa of max representable DP number
806 misc := x"007ffffffffffffc";
807 when "0011" =>
808 -- mantissa of max representable SP number
809 misc := x"007fffff80000000";
810 when others =>
811 misc := x"0000000000000000";
812 end case;
813 result <= misc;
814 end case;
815 v.r := result;
816
817 if opsel_r = RES_SHIFT then
818 v.result_exp := new_exp;
819 end if;
820
821 if renormalize = '1' then
822 clz := count_left_zeroes(r.r);
823 v.shift := resize(signed('0' & clz) - 9, EXP_BITS);
824 end if;
825
826 if r.int_result = '1' then
827 fp_result <= r.r;
828 else
829 fp_result <= pack_dp(r.result_sign, r.result_class, r.result_exp, r.r,
830 r.single_prec);
831 end if;
832 if r.update_fprf = '1' then
833 v.fpscr(FPSCR_C downto FPSCR_FU) := result_flags(r.result_sign, r.result_class,
834 r.r(54) and not r.denorm);
835 end if;
836
837 v.fpscr(FPSCR_VX) := (or (v.fpscr(FPSCR_VXSNAN downto FPSCR_VXVC))) or
838 (or (v.fpscr(FPSCR_VXSOFT downto FPSCR_VXCVI)));
839 v.fpscr(FPSCR_FEX) := or (v.fpscr(FPSCR_VX downto FPSCR_XX) and
840 v.fpscr(FPSCR_VE downto FPSCR_XE));
841 if update_fx = '1' and
842 (v.fpscr(FPSCR_VX downto FPSCR_XX) and not r.old_exc) /= "00000" then
843 v.fpscr(FPSCR_FX) := '1';
844 end if;
845 if r.rc = '1' then
846 v.cr_result := v.fpscr(FPSCR_FX downto FPSCR_OX);
847 end if;
848
849 if illegal = '1' then
850 v.instr_done := '0';
851 v.do_intr := '0';
852 v.writing_back := '0';
853 v.busy := '0';
854 v.state := IDLE;
855 else
856 v.do_intr := v.instr_done and v.fpscr(FPSCR_FEX) and r.fe_mode;
857 if v.state /= IDLE or v.do_intr = '1' then
858 v.busy := '1';
859 end if;
860 end if;
861
862 rin <= v;
863 e_out.illegal <= illegal;
864 end process;
865
866 end architecture behaviour;