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