udb 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.data/cfgs/rv32-riscv-tests.yaml +5 -1
  3. data/.data/cfgs/rv64-riscv-tests.yaml +4 -1
  4. data/.data/spec/std/isa/inst/F/fadd.s.yaml +16 -1
  5. data/.data/spec/std/isa/inst/F/fclass.s.yaml +7 -0
  6. data/.data/spec/std/isa/inst/F/fcvt.l.s.yaml +3 -0
  7. data/.data/spec/std/isa/inst/F/fcvt.lu.s.yaml +3 -0
  8. data/.data/spec/std/isa/inst/F/fcvt.s.l.yaml +4 -0
  9. data/.data/spec/std/isa/inst/F/fcvt.s.lu.yaml +4 -0
  10. data/.data/spec/std/isa/inst/F/fcvt.w.s.yaml +1 -1
  11. data/.data/spec/std/isa/inst/F/fcvt.wu.s.yaml +1 -1
  12. data/.data/spec/std/isa/inst/F/fdiv.s.yaml +4 -0
  13. data/.data/spec/std/isa/inst/F/feq.s.yaml +1 -1
  14. data/.data/spec/std/isa/inst/F/fle.s.yaml +14 -7
  15. data/.data/spec/std/isa/inst/F/fleq.s.yaml +30 -0
  16. data/.data/spec/std/isa/inst/F/flt.s.yaml +13 -8
  17. data/.data/spec/std/isa/inst/F/fltq.s.yaml +21 -0
  18. data/.data/spec/std/isa/inst/F/fmadd.s.yaml +4 -0
  19. data/.data/spec/std/isa/inst/F/fmax.s.yaml +30 -0
  20. data/.data/spec/std/isa/inst/F/fmin.s.yaml +30 -0
  21. data/.data/spec/std/isa/inst/F/fmsub.s.yaml +4 -0
  22. data/.data/spec/std/isa/inst/F/fmul.s.yaml +4 -0
  23. data/.data/spec/std/isa/inst/F/fnmadd.s.yaml +7 -0
  24. data/.data/spec/std/isa/inst/F/fnmsub.s.yaml +4 -0
  25. data/.data/spec/std/isa/inst/F/fsqrt.s.yaml +4 -0
  26. data/.data/spec/std/isa/isa/fp.idl +911 -101
  27. data/.data/spec/std/isa/isa/globals.isa +2 -0
  28. data/.data/spec/std/isa/isa/util.idl +22 -0
  29. data/lib/udb/cfg_arch.rb +42 -6
  30. data/lib/udb/condition.rb +66 -2
  31. data/lib/udb/logic.rb +27 -1
  32. data/lib/udb/version.rb +1 -1
  33. metadata +2 -2
@@ -21,6 +21,7 @@ Bits<32> SP_NEG_INF = 32'b1_11111111_00000000000000000000000;
21
21
  Bits<32> SP_POS_ZERO = 32'b0_00000000_00000000000000000000000;
22
22
  Bits<32> SP_NEG_ZERO = 32'b1_00000000_00000000000000000000000;
23
23
  Bits<32> SP_CANONICAL_NAN = 32'b0_11111111_10000000000000000000000;
24
+
24
25
  Bits<16> HP_CANONICAL_NAN = 16'b0_11111_1000000000;
25
26
 
26
27
  Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed 32-bit integer
@@ -32,6 +33,13 @@ Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer
32
33
  Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer
33
34
  Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer
34
35
 
36
+ Bits<64> I64_NEG_OVERFLOW = 64'h8000_0000_0000_0000; # minimum signed 64-bit integer
37
+ Bits<64> I64_POS_OVERFLOW = 64'h7FFF_FFFF_FFFF_FFFF; # maximum signed 64-bit integer
38
+ Bits<64> UI64_NEG_OVERFLOW = 64'h0000_0000_0000_0000; # minimum unsigned 64-bit integer
39
+ Bits<64> UI64_POS_OVERFLOW = 64'hFFFF_FFFF_FFFF_FFFF; # maximum unsigned 64-bit integer
40
+ Bits<64> UI64_NAN = 64'hFFFF_FFFF_FFFF_FFFF; # NaN to unsigned 64-bit integer
41
+ Bits<64> I64_NAN = 64'h7FFF_FFFF_FFFF_FFFF; # NaN to signed 64-bit integer
42
+
35
43
  enum RoundingMode {
36
44
  RNE 0b000 # Round to Nearest, ties to Even
37
45
  RTZ 0b001 # Round toward Zero
@@ -49,6 +57,13 @@ enum FpFlag {
49
57
  NV 0b10000 # Invalid Operation
50
58
  }
51
59
 
60
+ # Operation modifier for fused multiply-add
61
+ enum F32MulAddOp {
62
+ Softfloat_mulAdd_addC 0 # (a * b) + c
63
+ Softfloat_mulAdd_subC 1 # (a * b) - c (negate c)
64
+ Softfloat_mulAdd_subProd 2 # -(a * b) + c (negate product)
65
+ }
66
+
52
67
  function set_fp_flag {
53
68
  arguments
54
69
  FpFlag flag
@@ -179,10 +194,7 @@ function is_sp_neg_norm? {
179
194
  return
180
195
  (sp_value[31] == 1) # negative
181
196
  && (sp_value[30:23] != 0b11111111) # not inf/NaN
182
- && !( # not subnornmal
183
- (sp_value[30:23] == 0b00000000)
184
- && sp_value[22:0] != 0
185
- );
197
+ && (sp_value[30:23] != 0b00000000); # not zero or subnormal
186
198
  }
187
199
  }
188
200
 
@@ -194,12 +206,9 @@ function is_sp_pos_norm? {
194
206
  }
195
207
  body {
196
208
  return
197
- (sp_value[31] == 0) # positive
209
+ (sp_value[31] == 0) # positive
198
210
  && (sp_value[30:23] != 0b11111111) # not inf/NaN
199
- && !( # not subnornmal
200
- (sp_value[30:23] == 0b00000000)
201
- && sp_value[22:0] != 0
202
- );
211
+ && (sp_value[30:23] != 0b00000000); # not zero
203
212
  }
204
213
  }
205
214
 
@@ -308,7 +317,7 @@ function softfloat_shiftRightJam32 {
308
317
  is zero or nonzero.
309
318
  }
310
319
  body {
311
- return (dist < 31) ? a>>dist | (((a<<(-dist & 31)) != 0) ? 1 : 0) : ((a != 0) ? 1 : 0);
320
+ return (dist < 31) ? a>>dist | ((a[dist-1:0] != 0) ? 1 : 0) : ((a != 0) ? 1 : 0);
312
321
  }
313
322
  }
314
323
 
@@ -328,7 +337,7 @@ function softfloat_shiftRightJam64 {
328
337
  is zero or nonzero.
329
338
  }
330
339
  body {
331
- return (dist < 63) ? a>>dist | (((a<<(-dist & 63)) != 0) ? 1 : 0) : ((a != 0) ? 1 : 0);
340
+ return (dist < 63) ? a>>dist | ((a[dist-1:0] != 0) ? 1 : 0) : ((a != 0) ? 1 : 0);
332
341
  }
333
342
  }
334
343
 
@@ -383,6 +392,679 @@ function softfloat_roundToI32 {
383
392
  }
384
393
  }
385
394
 
395
+ function f32_muladd {
396
+ returns U32
397
+ arguments
398
+ U32 a,
399
+ U32 b,
400
+ U32 c,
401
+ F32MulAddOp op,
402
+ RoundingMode mode
403
+ description {
404
+ Fused multiply-add for single-precision floats.
405
+ Computes (a * b) + c, with sign modifications based on op:
406
+ Softfloat_mulAdd_addC: (a * b) + c
407
+ Softfloat_mulAdd_subC: (a * b) - c (negate c)
408
+ Softfloat_mulAdd_subProd: -(a * b) + c (negate product)
409
+ Translated from Berkeley Softfloat softfloat_mulAddF32.
410
+ }
411
+ body {
412
+ Bits<1> signA = signF32UI(a);
413
+ Bits<16> expA = expF32UI(a);
414
+ Bits<32> sigA = fracF32UI(a);
415
+ Bits<1> signB = signF32UI(b);
416
+ Bits<16> expB = expF32UI(b);
417
+ Bits<32> sigB = fracF32UI(b);
418
+ Bits<1> signC = signF32UI(c) ^ ((op == F32MulAddOp::Softfloat_mulAdd_subC) ? 1 : 0);
419
+ Bits<16> expC = expF32UI(c);
420
+ Bits<32> sigC = fracF32UI(c);
421
+ Bits<1> signProd = (signA ^ signB) ^ ((op == F32MulAddOp::Softfloat_mulAdd_subProd) ? 1 : 0);
422
+
423
+ Bits<32> magBits;
424
+ Bits<64> sig64Z;
425
+
426
+ # Handle NaN/Inf in A
427
+ if (expA == 0xFF) {
428
+ if ((sigA != 0) || ((expB == 0xFF) && (sigB != 0))) {
429
+ return SP_CANONICAL_NAN;
430
+ }
431
+ magBits = expB | sigB;
432
+ if (magBits != 0) {
433
+ U32 zA = packToF32UI(signProd, 0xFF, 0);
434
+ if (expC != 0xFF) {
435
+ return zA;
436
+ }
437
+ if (sigC != 0) {
438
+ return SP_CANONICAL_NAN;
439
+ }
440
+ if (signProd == signC) {
441
+ return zA;
442
+ }
443
+ }
444
+ set_fp_flag(FpFlag::NV);
445
+ return SP_CANONICAL_NAN;
446
+ }
447
+
448
+ # Handle NaN/Inf in B
449
+ if (expB == 0xFF) {
450
+ if (sigB != 0) {
451
+ return SP_CANONICAL_NAN;
452
+ }
453
+ magBits = expA | sigA;
454
+ if (magBits != 0) {
455
+ U32 zB = packToF32UI(signProd, 0xFF, 0);
456
+ if (expC != 0xFF) {
457
+ return zB;
458
+ }
459
+ if (sigC != 0) {
460
+ return SP_CANONICAL_NAN;
461
+ }
462
+ if (signProd == signC) {
463
+ return zB;
464
+ }
465
+ }
466
+ set_fp_flag(FpFlag::NV);
467
+ return SP_CANONICAL_NAN;
468
+ }
469
+
470
+ # Handle NaN/Inf in C
471
+ if (expC == 0xFF) {
472
+ if (sigC != 0) {
473
+ return SP_CANONICAL_NAN;
474
+ }
475
+ return c;
476
+ }
477
+
478
+ # Handle zero/subnormal A
479
+ if (expA == 0) {
480
+ if (sigA == 0) {
481
+ if (((expC | sigC) == 0) && (signProd != signC)) {
482
+ return packToF32UI((mode == RoundingMode::RDN) ? 1 : 0, 0, 0);
483
+ }
484
+ return c;
485
+ }
486
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(sigA);
487
+ expA = norm.exp;
488
+ sigA = norm.sig;
489
+ }
490
+
491
+ # Handle zero/subnormal B
492
+ if (expB == 0) {
493
+ if (sigB == 0) {
494
+ if (((expC | sigC) == 0) && (signProd != signC)) {
495
+ return packToF32UI((mode == RoundingMode::RDN) ? 1 : 0, 0, 0);
496
+ }
497
+ return c;
498
+ }
499
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(sigB);
500
+ expB = norm.exp;
501
+ sigB = norm.sig;
502
+ }
503
+
504
+ # Compute product exponent and significand
505
+ Bits<16> expProd = expA + expB - 16'h007E;
506
+ sigA = (sigA | 32'h00800000) << 7;
507
+ sigB = (sigB | 32'h00800000) << 7;
508
+ U64 sigProd = sigA `* sigB;
509
+ if (sigProd < 64'h2000000000000000) {
510
+ expProd = expProd - 1;
511
+ sigProd = sigProd << 1;
512
+ }
513
+ Bits<1> signZ = signProd;
514
+ Bits<16> expZ;
515
+ Bits<32> sigZ;
516
+
517
+ # Handle zero/subnormal C
518
+ if (expC == 0) {
519
+ if (sigC == 0) {
520
+ expZ = expProd - 1;
521
+ sigZ = softfloat_shiftRightJam64(sigProd, 31);
522
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
523
+ }
524
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(sigC);
525
+ expC = norm.exp;
526
+ sigC = norm.sig;
527
+ }
528
+ sigC = (sigC | 0x00800000) << 6;
529
+
530
+ Bits<16> expDiff = expProd - expC;
531
+
532
+ if (signProd == signC) {
533
+ # Same sign: add magnitudes
534
+ if ($signed(expDiff) <= 0s) {
535
+ expZ = expC;
536
+ sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff);
537
+ } else {
538
+ expZ = expProd;
539
+ sig64Z = sigProd + softfloat_shiftRightJam64(sigC `<< 32, expDiff);
540
+ sigZ = softfloat_shiftRightJam64(sig64Z, 32);
541
+ }
542
+ if (sigZ < 0x40000000) {
543
+ expZ = expZ - 1;
544
+ sigZ = sigZ << 1;
545
+ }
546
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
547
+ } else {
548
+ # Different signs: subtract magnitudes
549
+ U64 sig64C = sigC `<< 32;
550
+ if ($signed(expDiff) < 0s) {
551
+ signZ = signC;
552
+ expZ = expC;
553
+ sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff);
554
+ } else if (expDiff == 0) {
555
+ expZ = expProd;
556
+ sig64Z = sigProd - sig64C;
557
+ if (sig64Z == 0) {
558
+ return packToF32UI((mode == RoundingMode::RDN) ? 1 : 0, 0, 0);
559
+ }
560
+ if ((sig64Z & 64'h8000000000000000) != 0) {
561
+ signZ = signZ ^ 1;
562
+ sig64Z = -sig64Z;
563
+ }
564
+ } else {
565
+ expZ = expProd;
566
+ sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff);
567
+ }
568
+ Bits<8> shiftDist = count_leading_zeros_64(64, sig64Z) - 1;
569
+ expZ = expZ - shiftDist;
570
+ shiftDist = shiftDist - 8'h20;
571
+ if ($signed(shiftDist) < 0s) {
572
+ sigZ = softfloat_shiftRightJam64(sig64Z, -shiftDist);
573
+ } else {
574
+ sigZ = sig64Z << shiftDist;
575
+ }
576
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
577
+ }
578
+ }
579
+ }
580
+
581
+ function f32_sqrt {
582
+ returns U32
583
+ arguments
584
+ U32 a,
585
+ RoundingMode mode
586
+ description {
587
+ Computes the square root of a 32-bit floating point number.
588
+ Translated from Berkeley Softfloat f32_sqrt.
589
+ }
590
+ body {
591
+ Bits<1> signA = signF32UI(a);
592
+ Bits<8> expA = expF32UI(a);
593
+ Bits<32> fracA = fracF32UI(a);
594
+
595
+ if (expA == 8'hFF) {
596
+ if (fracA != 0) { return SP_CANONICAL_NAN; }
597
+ if (signA == 0) { return a; }
598
+ set_fp_flag(FpFlag::NV);
599
+ return SP_CANONICAL_NAN;
600
+ }
601
+ if (signA == 1) {
602
+ if ((expA == 0) && (fracA == 0)) { return a; }
603
+ set_fp_flag(FpFlag::NV);
604
+ return SP_CANONICAL_NAN;
605
+ }
606
+ if (expA == 0) {
607
+ if (fracA == 0) { return a; }
608
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(fracA);
609
+ expA = norm.exp;
610
+ fracA = norm.sig;
611
+ }
612
+
613
+ Bits<16> expZ = ((expA - 16'h007F) >> 1) + 16'h007E;
614
+ Bits<1> oddExpA = expA[0];
615
+ Bits<32> sigA32 = (fracA | 32'h00800000) << 8;
616
+ Bits<32> sigZ = (sigA32 `* softfloat_approxRecipSqrt32_1(oddExpA, sigA32)) >> 32;
617
+ if (oddExpA == 1) {
618
+ sigZ = sigZ >> 1;
619
+ }
620
+ sigZ = sigZ + 2;
621
+
622
+ if ((sigZ & 0x3F) < 2) {
623
+ Bits<32> shiftedSigZ = sigZ >> 2;
624
+ Bits<32> negRem = shiftedSigZ * shiftedSigZ;
625
+ sigZ = sigZ & ~32'h3;
626
+ if ((negRem & 0x80000000) != 0) {
627
+ sigZ = sigZ | 1;
628
+ } else {
629
+ if (negRem != 0) { sigZ = sigZ - 1; }
630
+ }
631
+ }
632
+
633
+ return softfloat_roundPackToF32(0, expZ, sigZ, mode);
634
+ }
635
+ }
636
+
637
+ # Lookup tables for reciprocal and reciprocal-sqrt approximation (Berkeley Softfloat)
638
+ Bits<16> softfloat_approxRecip_1k0s[16] = [
639
+ 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201,
640
+ 0xAA97, 0xA3C1, 0x9D49, 0x9715, 0x9128, 0x8B7C, 0x8600, 0x80B6
641
+ ];
642
+ Bits<16> softfloat_approxRecip_1k1s[16] = [
643
+ 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDE, 0x8185, 0x7709,
644
+ 0x6E7D, 0x6794, 0x6188, 0x5C71, 0x5764, 0x52BE, 0x4E55, 0x4A67
645
+ ];
646
+ Bits<16> softfloat_approxRecipSqrt_1k0s[16] = [
647
+ 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29,
648
+ 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1
649
+ ];
650
+ Bits<16> softfloat_approxRecipSqrt_1k1s[16] = [
651
+ 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6,
652
+ 0x5CC7, 0x8335, 0x52A6, 0x74EA, 0x4A3E, 0x68C8, 0x42BC, 0x5EFF
653
+ ];
654
+
655
+ function softfloat_approxRecip32_1 {
656
+ returns U32
657
+ arguments
658
+ Bits<32> a
659
+ description {
660
+ Returns a 32-bit approximation of 1/a, where a is in [1, 2).
661
+ Translated from Berkeley Softfloat softfloat_approxRecip32_1.
662
+ }
663
+ body {
664
+ Bits<32> index = (a >> 27) & 0xF;
665
+ Bits<16> eps = a >> 11;
666
+ Bits<32> r0 = softfloat_approxRecip_1k0s[index]
667
+ - ((softfloat_approxRecip_1k1s[index] `* eps) >> 20);
668
+ Bits<32> sigma0 = ~((r0 `* a) >> 7);
669
+ Bits<32> r = (r0 << 16) + ((r0 `* sigma0) >> 24);
670
+ Bits<32> sqrSigma0 = (sigma0 `* sigma0) >> 32;
671
+ r = r + ((r `* sqrSigma0) >> 48);
672
+ return r;
673
+ }
674
+ }
675
+
676
+ function softfloat_approxRecipSqrt32_1 {
677
+ returns U32
678
+ arguments
679
+ Bits<1> oddExpA,
680
+ Bits<32> a
681
+ description {
682
+ Returns a 32-bit approximation of 1/sqrt(a).
683
+ Translated from Berkeley Softfloat softfloat_approxRecipSqrt32_1.
684
+ }
685
+ body {
686
+ Bits<8> index = ((a >> 27) & 0xE) + oddExpA;
687
+ Bits<16> eps = a >> 12;
688
+ Bits<16> r0 = softfloat_approxRecipSqrt_1k0s[index]
689
+ - ((softfloat_approxRecipSqrt_1k1s[index] `* eps) >> 20);
690
+ Bits<32> eSqrR0 = r0 `* r0;
691
+ if (oddExpA == 0) {
692
+ eSqrR0 = eSqrR0 << 1;
693
+ }
694
+ Bits<32> sigma0 = ~((eSqrR0 `* a) >> 23);
695
+ Bits<32> r = (r0 `<< 16) + ((r0 `* sigma0) >> 25);
696
+ Bits<32> sqrSigma0 = (sigma0 `* sigma0) >> 32;
697
+ Bits<32> adj = ((r >> 1) + (r >> 3) - (r0 `<< 14));
698
+ r = r + ((adj `* sqrSigma0) >> 48);
699
+ if ((r & 32'h80000000) == 0) {
700
+ r = 32'h80000000;
701
+ }
702
+ return r;
703
+ }
704
+ }
705
+
706
+ function f32_div {
707
+ returns U32
708
+ arguments
709
+ U32 a,
710
+ U32 b,
711
+ RoundingMode mode
712
+ description {
713
+ Divides two 32-bit floating point numbers.
714
+ Translated from Berkeley Softfloat f32_div.
715
+ }
716
+ body {
717
+ Bits<1> signA = signF32UI(a);
718
+ Bits<16> expA = expF32UI(a);
719
+ Bits<32> sigA = fracF32UI(a);
720
+ Bits<1> signB = signF32UI(b);
721
+ Bits<16> expB = expF32UI(b);
722
+ Bits<32> sigB = fracF32UI(b);
723
+ Bits<1> signZ = signA ^ signB;
724
+
725
+ Bits<16> expZ;
726
+
727
+ if (expA == 8'hFF) {
728
+ if (sigA != 0) { return SP_CANONICAL_NAN; }
729
+ if (expB == 8'hFF) {
730
+ if (sigB != 0) { return SP_CANONICAL_NAN; }
731
+ set_fp_flag(FpFlag::NV);
732
+ return SP_CANONICAL_NAN;
733
+ }
734
+ return packToF32UI(signZ, 8'hFF, 0);
735
+ }
736
+ if (expB == 8'hFF) {
737
+ if (sigB != 0) { return SP_CANONICAL_NAN; }
738
+ return packToF32UI(signZ, 0, 0);
739
+ }
740
+
741
+ if (expB == 0) {
742
+ if (sigB == 0) {
743
+ if ((expA == 0) && (sigA == 0)) {
744
+ set_fp_flag(FpFlag::NV);
745
+ return SP_CANONICAL_NAN;
746
+ }
747
+ set_fp_flag(FpFlag::DZ);
748
+ return packToF32UI(signZ, 8'hFF, 0);
749
+ }
750
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(sigB);
751
+ expB = norm.exp;
752
+ sigB = norm.sig;
753
+ }
754
+
755
+ if (expA == 0) {
756
+ if (sigA == 0) { return packToF32UI(signZ, 0, 0); }
757
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(sigA);
758
+ expA = norm.exp;
759
+ sigA = norm.sig;
760
+ }
761
+
762
+ expZ = expA - expB + 16'h007E;
763
+ sigA = sigA | 32'h00800000;
764
+ sigB = sigB | 32'h00800000;
765
+
766
+ if (sigA < sigB) {
767
+ expZ = expZ - 1;
768
+ sigA = sigA << 8;
769
+ } else {
770
+ sigA = sigA << 7;
771
+ }
772
+ sigB = sigB << 8;
773
+
774
+ Bits<32> recip32 = softfloat_approxRecip32_1(sigB);
775
+ Bits<32> sigZ = (sigA `* recip32) >> 32;
776
+ sigZ = sigZ + 2;
777
+
778
+ if ((sigZ & 0x3F) < 2) {
779
+ sigZ = sigZ & ~32'h3;
780
+ Bits<64> rem = (sigA `<< 31) - (sigZ `* sigB);
781
+ if ((rem & 64'h8000000000000000) != 0) {
782
+ sigZ = sigZ - 4;
783
+ } else {
784
+ if ( rem != 0 ) {
785
+ sigZ = sigZ | 1;
786
+ }
787
+ }
788
+ }
789
+
790
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
791
+ }
792
+ }
793
+
794
+ function f32_mul {
795
+ returns U32
796
+ arguments
797
+ U32 a,
798
+ U32 b,
799
+ RoundingMode mode
800
+ description {
801
+ Multiplies two 32-bit floating point numbers.
802
+ Translated from Berkeley Softfloat f32_mul.
803
+ }
804
+ body {
805
+ Bits<1> signA = signF32UI(a);
806
+ Bits<16> expA = expF32UI(a);
807
+ Bits<23> fracA = fracF32UI(a);
808
+ Bits<1> signB = signF32UI(b);
809
+ Bits<16> expB = expF32UI(b);
810
+ Bits<23> fracB = fracF32UI(b);
811
+ Bits<1> signZ = signA ^ signB;
812
+
813
+ Bits<32> sigA = fracA;
814
+ Bits<32> sigB = fracB;
815
+ Bits<16> expZ;
816
+ Bits<32> sigZ;
817
+
818
+ if (expA == 8'hFF) {
819
+ if ((fracA != 0) || ((expB == 8'hFF) && (fracB != 0))) {
820
+ return SP_CANONICAL_NAN;
821
+ }
822
+ if ((expB == 0) && (fracB == 0)) {
823
+ set_fp_flag(FpFlag::NV);
824
+ return SP_CANONICAL_NAN;
825
+ }
826
+ return packToF32UI(signZ, 8'hFF, 0);
827
+ }
828
+ if (expB == 8'hFF) {
829
+ if (fracB != 0) {
830
+ return SP_CANONICAL_NAN;
831
+ }
832
+ if ((expA == 0) && (fracA == 0)) {
833
+ set_fp_flag(FpFlag::NV);
834
+ return SP_CANONICAL_NAN;
835
+ }
836
+ return packToF32UI(signZ, 8'hFF, 0);
837
+ }
838
+
839
+ if (expA == 0) {
840
+ if (fracA == 0) { return packToF32UI(signZ, 0, 0); }
841
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(fracA);
842
+ expA = norm.exp;
843
+ sigA = norm.sig;
844
+ }
845
+
846
+ if (expB == 0) {
847
+ if (fracB == 0) { return packToF32UI(signZ, 0, 0); }
848
+ ExpAndSig norm = softfloat_normSubnormalF32Sig(fracB);
849
+ expB = norm.exp;
850
+ sigB = norm.sig;
851
+ }
852
+
853
+ expZ = expA + expB - 16'h007F;
854
+ sigA = (sigA | 32'h00800000)<<7;
855
+ sigB = (sigB | 32'h00800000)<<8;
856
+ sigZ = softfloat_shiftRightJam64(sigA `* sigB, 32);
857
+ if (sigZ < 0x40000000 ) {
858
+ expZ = expZ - 1;
859
+ sigZ = sigZ << 1;
860
+ }
861
+
862
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
863
+ }
864
+ }
865
+
866
+ function f32_to_i64 {
867
+ returns Bits<64>
868
+ arguments
869
+ U32 a,
870
+ RoundingMode mode
871
+ description {
872
+ Converts 32-bit floating point number to a signed 64-bit integer.
873
+ Translated from Berkeley Softfloat f32_to_i64.
874
+ }
875
+ body {
876
+ Bits<1> sign = signF32UI(a);
877
+ Bits<16> exp = expF32UI(a);
878
+ Bits<32> sig = fracF32UI(a);
879
+
880
+ Bits<16> shiftDist = 16'hBE - exp;
881
+ Bits<64> sig64;
882
+ Bits<64> extra;
883
+
884
+ if ($signed(shiftDist) < 0s) {
885
+ set_fp_flag(FpFlag::NV);
886
+ if ((exp == 16'hFF) && (sig != 0)) {
887
+ return I64_NAN;
888
+ } else {
889
+ return (sign == 1) ? I64_NEG_OVERFLOW : I64_POS_OVERFLOW;
890
+ }
891
+ }
892
+
893
+ if (exp != 0) {
894
+ sig = sig | 32'h00800000;
895
+ }
896
+
897
+ sig64 = sig `<< 40;
898
+ extra = 0;
899
+ if (shiftDist != 0) {
900
+ TwoU64s sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, $signed(shiftDist) );
901
+ sig64 = sig64Extra.u1;
902
+ extra = sig64Extra.u2;
903
+ }
904
+ return softfloat_roundToI64( sign, sig64, extra, mode );
905
+ }
906
+ }
907
+
908
+ struct TwoU64s {
909
+ Bits<64> u1;
910
+ Bits<64> u2;
911
+ }
912
+
913
+ function softfloat_shiftRightJam64Extra {
914
+ returns TwoU64s
915
+ arguments
916
+ Bits<64> a,
917
+ Bits<64> extra,
918
+ Bits<32> dist
919
+ description {
920
+ Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64
921
+ _plus_ the number of bits given in 'dist', which must not be zero. This
922
+ shifted value is at most 64 nonzero bits and is returned in the 'v' field
923
+ of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result
924
+ contains a value formed as follows from the bits that were shifted off: The
925
+ _last_ bit shifted off is the most-significant bit of the 'extra' field, and
926
+ the other 63 bits of the 'extra' field are all zero if and only if _all_but_
927
+ _the_last_ bits shifted off were all zero.
928
+ (This function makes more sense if 'a' and 'extra' are considered to form
929
+ an unsigned fixed-point number with binary point between 'a' and 'extra'.
930
+ This fixed-point value is shifted right by the number of bits given in
931
+ 'dist', and the integer part of this shifted value is returned in the 'v'
932
+ field of the result. The fractional part of the shifted value is modified
933
+ as described above and returned in the 'extra' field of the result.)
934
+ }
935
+ body {
936
+ TwoU64s z;
937
+
938
+ if (dist < 64) {
939
+ z.u1 = a >> dist;
940
+ z.u2 = a << (-dist & 63);
941
+ } else {
942
+ z.u1 = 0;
943
+ z.u2 = (dist == 64) ? a : ((a != 0) ? 1 : 0);
944
+ }
945
+ z.u2 = z.u2 | ((extra != 0) ? 1 : 0);
946
+
947
+ return z;
948
+ }
949
+ }
950
+
951
+ function f32_to_ui64 {
952
+ returns Bits<64>
953
+ arguments
954
+ U32 a,
955
+ RoundingMode mode
956
+ description {
957
+ Converts 32-bit floating point number to an unsigned 64-bit integer.
958
+ Translated from Berkeley Softfloat f32_to_ui64.
959
+ }
960
+ body {
961
+ Bits<1> sign = signF32UI(a);
962
+ Bits<16> exp = expF32UI(a);
963
+ Bits<32> sig = fracF32UI(a);
964
+
965
+ Bits<16> shiftDist;
966
+ Bits<64> sig64, extra;
967
+
968
+ # shiftDist = 0xBE - exp (0xBE = 190 = 127 + 63)
969
+ shiftDist = 16'hBE - exp;
970
+
971
+ if ($signed(shiftDist) < 0s) {
972
+ set_fp_flag(FpFlag::NV);
973
+ if ((exp == 0xFF) && (sig != 0)) {
974
+ return UI64_NAN;
975
+ } else if (sign != 0) {
976
+ return UI64_NEG_OVERFLOW;
977
+ } else {
978
+ return UI64_POS_OVERFLOW;
979
+ }
980
+ }
981
+
982
+ if (exp != 0) {
983
+ sig = sig | 32'h00800000;
984
+ }
985
+ sig64 = sig `<< 40;
986
+ extra = 0;
987
+ if (shiftDist != 0) {
988
+ TwoU64s sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, $signed(shiftDist));
989
+ sig64 = sig64Extra.u1;
990
+ extra = sig64Extra.u2;
991
+ }
992
+ return softfloat_roundToUI64( sign, sig64, extra, mode );
993
+ }
994
+ }
995
+
996
+ function i64_to_f32 {
997
+ returns U32
998
+ arguments
999
+ Bits<64> a,
1000
+ RoundingMode mode
1001
+ description {
1002
+ Converts 64-bit signed integer to 32-bit floating point number.
1003
+ Translated from Berkeley Softfloat i64_to_f32.
1004
+ }
1005
+ body {
1006
+ Bits<1> sign = a[63];
1007
+ Bits<64> absA;
1008
+
1009
+ if (sign == 1) {
1010
+ absA = -a;
1011
+ } else {
1012
+ absA = a;
1013
+ }
1014
+
1015
+ # count_leading_zeros<64> returns the number of leading zeros
1016
+ Bits<8> shiftDist = count_leading_zeros(64, absA) - 40;
1017
+ Bits<32> sig;
1018
+
1019
+ if ($signed(shiftDist) >= 0s) {
1020
+ if (a != 0) {
1021
+ return packToF32UI(sign, 16'h95 - shiftDist, absA << shiftDist);
1022
+ } else {
1023
+ return 0;
1024
+ }
1025
+ } else {
1026
+ shiftDist = shiftDist + 7;
1027
+ if ($signed(shiftDist) < 0s) {
1028
+ sig = softfloat_shortShiftRightJam64( absA, -shiftDist );
1029
+ } else {
1030
+ sig = absA << shiftDist;
1031
+ }
1032
+ return softfloat_roundPackToF32(sign, 8'h9C - shiftDist, sig, mode);
1033
+ }
1034
+ }
1035
+ }
1036
+
1037
+ function ui64_to_f32 {
1038
+ returns U32
1039
+ arguments
1040
+ Bits<64> a,
1041
+ RoundingMode mode
1042
+ description {
1043
+ Converts 64-bit unsigned integer to 32-bit floating point number.
1044
+ Translated from Berkeley Softfloat ui64_to_f32.
1045
+ }
1046
+ body {
1047
+ Bits<8> shiftDist = count_leading_zeros(64, a) - 40;
1048
+ Bits<32> sig;
1049
+
1050
+ if (0s <= $signed(shiftDist)) {
1051
+ if (a != 0) {
1052
+ return packToF32UI(0, 8'h95 - shiftDist, a << shiftDist);
1053
+ } else {
1054
+ return 0;
1055
+ }
1056
+ } else {
1057
+ shiftDist = shiftDist + 7;
1058
+ if ($signed(shiftDist) < 0s) {
1059
+ sig = softfloat_shortShiftRightJam64(a, -shiftDist);
1060
+ } else {
1061
+ sig = a << shiftDist;
1062
+ }
1063
+ return softfloat_roundPackToF32(0, 8'h9C - shiftDist, sig, mode);
1064
+ }
1065
+ }
1066
+ }
1067
+
386
1068
  function softfloat_roundToUI32 {
387
1069
  returns Bits<32>
388
1070
  arguments
@@ -438,12 +1120,12 @@ function packToF32UI {
438
1120
  arguments
439
1121
  Bits<1> sign,
440
1122
  Bits<8> exp,
441
- Bits<23> sig
1123
+ Bits<32> sig
442
1124
  description {
443
1125
  Pack components into a 32-bit value
444
1126
  }
445
1127
  body {
446
- return {sign, exp, sig};
1128
+ return (sign `<< 31) + (exp `<< 23) + sig;
447
1129
  }
448
1130
  }
449
1131
 
@@ -478,8 +1160,8 @@ function softfloat_roundPackToF32 {
478
1160
  returns Bits<32> # single precision value
479
1161
  arguments
480
1162
  Bits<1> sign,
481
- Bits<8> exp,
482
- Bits<23> sig,
1163
+ Bits<16> exp,
1164
+ Bits<32> sig,
483
1165
  RoundingMode mode
484
1166
  description {
485
1167
  Round FP value according to +mdode+ and then pack it in IEEE format.
@@ -515,7 +1197,10 @@ function softfloat_roundPackToF32 {
515
1197
  if (roundBits != 0) {
516
1198
  set_fp_flag(FpFlag::NX);
517
1199
  }
518
- sig = sig & ~((roundBits ^ 0x40) & ((mode == RoundingMode::RNE) ? 1 : 0));
1200
+ if ((roundBits == 0x40) && (mode == RoundingMode::RNE)) {
1201
+ sig = sig & ~32'b1; # Clear only the LSB
1202
+ }
1203
+ # sig = sig & ~((((roundBits ^ 0x40) == 0) ? 32'0 : 32'1) & ((mode == RoundingMode::RNE) ? 32'1 : 32'0));
519
1204
  if ( sig == 0 ) {
520
1205
  exp = 0;
521
1206
  }
@@ -527,8 +1212,8 @@ function softfloat_normRoundPackToF32 {
527
1212
  returns Bits<32>
528
1213
  arguments
529
1214
  Bits<1> sign,
530
- Bits<8> exp,
531
- Bits<23> sig,
1215
+ Bits<16> exp,
1216
+ Bits<32> sig,
532
1217
  RoundingMode mode
533
1218
  description {
534
1219
  Normalize, round, and pack into a 32-bit floating point value
@@ -635,30 +1320,6 @@ function returnLargerMag {
635
1320
  }
636
1321
  }
637
1322
 
638
- function softfloat_propagateNaNF32UI {
639
- returns U32
640
- arguments
641
- U32 a,
642
- U32 b
643
- description {
644
- Interpreting 'a' and 'b' as the bit patterns of two 32-bit floating-
645
- | point values, at least one of which is a NaN, returns the bit pattern of
646
- | the combined NaN result. If either 'a' or 'b' has the pattern of a
647
- | signaling NaN, the invalid exception is raised.
648
- }
649
- body {
650
- # check if a and b are signalling
651
- Boolean isSigNaN_a = is_sp_signaling_nan?(a);
652
- Boolean isSigNaN_b = is_sp_signaling_nan?(b);
653
-
654
- if (isSigNaN_a || isSigNaN_b) {
655
- # raise invalid flag if either number is NaN
656
- set_fp_flag(FpFlag::NV);
657
- }
658
- return SP_CANONICAL_NAN;
659
- }
660
- }
661
-
662
1323
  function softfloat_addMagsF32 {
663
1324
  returns U32
664
1325
  arguments
@@ -671,10 +1332,10 @@ function softfloat_addMagsF32 {
671
1332
  body {
672
1333
 
673
1334
  # extract exponents and significands of a and b
674
- Bits<8> expA = expF32UI(a);
675
- Bits<23> sigA = fracF32UI(a);
676
- Bits<8> expB = expF32UI(b);
677
- Bits<23> sigB = fracF32UI(b);
1335
+ Bits<16> expA = expF32UI(a);
1336
+ Bits<32> sigA = fracF32UI(a);
1337
+ Bits<16> expB = expF32UI(b);
1338
+ Bits<32> sigB = fracF32UI(b);
678
1339
 
679
1340
  # declare a variable to store significand of sum
680
1341
  U32 sigZ;
@@ -687,9 +1348,9 @@ function softfloat_addMagsF32 {
687
1348
  Bits<8> expZ;
688
1349
 
689
1350
  # calculate difference of exponents
690
- Bits<8> expDiff = expA - expB;
1351
+ Bits<16> expDiff = expA - expB;
691
1352
 
692
- if (expDiff == 8'd0) {
1353
+ if (expDiff == 16'd0) {
693
1354
  if (expA == 8'd0) {
694
1355
  z = a + b;
695
1356
  return z; # if exponents of both numbers are zero, then return sum of both numbers
@@ -699,7 +1360,7 @@ function softfloat_addMagsF32 {
699
1360
  if (expA == 8'hFF) {
700
1361
  # A is NaN if significand is non-zero and exponent is 8'hFF
701
1362
  if ((sigA != 8'd0) || (sigB != 8'd0)) {
702
- return softfloat_propagateNaNF32UI(a, b);
1363
+ return SP_CANONICAL_NAN;
703
1364
  }
704
1365
  # return infinity if A is infinity
705
1366
  return a;
@@ -722,47 +1383,47 @@ function softfloat_addMagsF32 {
722
1383
 
723
1384
  signZ = signF32UI(a);
724
1385
 
725
- U32 sigA_32 = 32'h0 + (sigA << 6);
726
- U32 sigB_32 = 32'h0 + (sigA << 6);
1386
+ sigA = sigA << 6;
1387
+ sigB = sigB << 6;
727
1388
 
728
1389
  # check if B has a bigger exponent value than A
729
- if (expDiff < 0) {
1390
+ if ($signed(expDiff) < 0s) {
730
1391
  # check if B is infinity or NaN
731
1392
  if (expB == 8'hFF) {
732
1393
  # B is NaN if exponent is 8'hFF and significand is non-zero
733
1394
  if (sigB != 0) {
734
- return softfloat_propagateNaNF32UI(a, b);
1395
+ return SP_CANONICAL_NAN;
735
1396
  }
736
1397
  # return infinity with same sign as A
737
1398
  return packToF32UI(signZ, 8'hFF, 23'h0);
738
1399
  }
739
1400
  expZ = expB;
740
1401
 
741
- sigA_32 = (expA == 0) ? 2*sigA_32 : (sigA_32 + 0x20000000);
742
- sigA_32 = softfloat_shiftRightJam32(sigA_32, (32'h0 - expDiff));
1402
+ sigA = (expA == 0) ? 2*sigA : (sigA + 0x20000000);
1403
+ sigA = softfloat_shiftRightJam32(sigA, -expDiff);
743
1404
  } else {
744
1405
  # check if A is infinity or NaN
745
1406
  if (expA == 8'hFF) {
746
1407
  # A is NaN if exponent is 8'hFF and significand is non-zero
747
1408
  if (sigA != 0) {
748
- return softfloat_propagateNaNF32UI(a, b);
1409
+ return SP_CANONICAL_NAN;
749
1410
  }
750
1411
  # return infinity with same sign as A
751
1412
  return a;
752
1413
  }
753
1414
 
754
1415
  expZ = expA;
755
- sigB_32 = (expB == 0) ? 2*sigB_32 : (sigB_32 + 0x20000000);
756
- sigB_32 = softfloat_shiftRightJam32(sigB_32, (32'h0 + expDiff));
1416
+ sigB = (expB == 0) ? 2*sigB : (sigB + 0x20000000);
1417
+ sigB = softfloat_shiftRightJam32(sigB, expDiff);
757
1418
  }
758
1419
 
759
- U32 sigZ = 0x20000000 + sigA + sigB;
1420
+ sigZ = 0x20000000 + sigA + sigB;
760
1421
  if ( sigZ < 0x40000000 ) {
761
1422
  expZ = expZ - 1;
762
1423
  sigZ = sigZ << 1;
763
1424
  }
764
1425
  }
765
- return softfloat_roundPackToF32(signZ, expZ, sigZ[22:0], mode);
1426
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, mode);
766
1427
  }
767
1428
  }
768
1429
 
@@ -778,10 +1439,10 @@ function softfloat_subMagsF32 {
778
1439
  body {
779
1440
 
780
1441
  # extract exponents and significands of a and b
781
- Bits<8> expA = expF32UI(a);
782
- Bits<23> sigA = fracF32UI(a);
783
- Bits<8> expB = expF32UI(b);
784
- Bits<23> sigB = fracF32UI(b);
1442
+ Bits<16> expA = expF32UI(a);
1443
+ Bits<32> sigA = fracF32UI(a);
1444
+ Bits<16> expB = expF32UI(b);
1445
+ Bits<32> sigB = fracF32UI(b);
785
1446
 
786
1447
  # declare a variable to store significand of difference
787
1448
  U32 sigZ;
@@ -800,26 +1461,18 @@ function softfloat_subMagsF32 {
800
1461
  U32 sigX;
801
1462
  U32 sigY;
802
1463
 
803
- # declare a U32 sigA and sigB
804
- U32 sigA_32;
805
- U32 sigB_32;
806
-
807
1464
  # declare a variable to store shift distance
808
1465
  Bits<8> shiftDist;
809
1466
 
810
1467
  # calculate difference of exponents
811
- Bits<8> expDiff = expA - expB;
1468
+ Bits<16> expDiff = expA - expB;
812
1469
 
813
- if (expDiff == 8'd0) {
1470
+ if (expDiff == 16'd0) {
814
1471
 
815
1472
  # check if A is infinity or NaN
816
1473
  if (expA == 8'hFF) {
817
- # A is NaN if significand is non-zero and exponent is 8'hFF
818
- if ((sigA != 8'd0) || (sigB != 8'd0)) {
819
- return softfloat_propagateNaNF32UI(a, b);
820
- }
821
- # return infinity if A is infinity
822
- return a;
1474
+ set_fp_flag(FpFlag::NV);
1475
+ return SP_CANONICAL_NAN;
823
1476
  }
824
1477
 
825
1478
  sigDiff = sigA - sigB;
@@ -855,30 +1508,30 @@ function softfloat_subMagsF32 {
855
1508
  } else {
856
1509
  # when difference in exponents are not zero
857
1510
  signZ = signF32UI(a);
858
- sigA_32 = 32'h0 + (sigA << 7);
859
- sigB_32 = 32'h0 + (sigB << 7);
860
- if (expDiff < 0) {
1511
+ sigA = sigA << 7;
1512
+ sigB = sigB << 7;
1513
+ if ($signed(expDiff) < 0s) {
861
1514
  signZ = ~signZ;
862
1515
  if (expB == 0xFF) {
863
- if (sigB_32 != 0) {
864
- return softfloat_propagateNaNF32UI(a, b);
1516
+ if (sigB != 0) {
1517
+ return SP_CANONICAL_NAN;
865
1518
  }
866
1519
  return packToF32UI(signZ, expB, 0);
867
1520
  }
868
1521
  expZ = expB - 1;
869
- sigX = sigB_32 | 0x40000000;
870
- sigY = sigA_32 + ((expA != 0) ? 0x40000000 : sigA_32);
1522
+ sigX = sigB | 0x40000000;
1523
+ sigY = sigA + ((expA != 0) ? 0x40000000 : sigA);
871
1524
  expDiff = - expDiff;
872
1525
  } else {
873
1526
  if (expA == 0xFF) {
874
- if (sigA_32 != 0) {
875
- return softfloat_propagateNaNF32UI(a, b);
1527
+ if (sigA != 0) {
1528
+ return SP_CANONICAL_NAN;
876
1529
  }
877
1530
  return a;
878
1531
  }
879
1532
  expZ = expA - 1;
880
- sigX = sigA_32 | 0x40000000;
881
- sigY = sigB_32 + ((expB != 0) ? 0x40000000 : sigB_32);
1533
+ sigX = sigA | 0x40000000;
1534
+ sigY = sigB + ((expB != 0) ? 0x40000000 : sigB);
882
1535
  }
883
1536
  return softfloat_normRoundPackToF32(signZ, expZ, sigX - softfloat_shiftRightJam32(sigY, expDiff), mode);
884
1537
  }
@@ -941,8 +1594,8 @@ function i32_to_f32 {
941
1594
  if ((a & 0x7FFFFFFF) == 0) {
942
1595
  return (sign == 1) ? packToF32UI(1, 0x9E, 0) : packToF32UI(0, 0, 0);
943
1596
  }
944
- U32 magnitude_of_A = returnMag(a);
945
- return softfloat_normRoundPackToF32(sign, 0x9C, magnitude_of_A, mode);
1597
+ U32 absA = (sign == 1) ? -a : a;
1598
+ return softfloat_normRoundPackToF32(sign, 0x9C, absA, mode);
946
1599
  }
947
1600
  }
948
1601
 
@@ -977,9 +1630,9 @@ function f32_to_i32 {
977
1630
  }
978
1631
  body {
979
1632
  Bits<1> sign = signF32UI(a);
980
- Bits<8> exp = expF32UI(a);
981
- Bits<23> sig = fracF32UI(a);
982
- Bits<8> shiftDist;
1633
+ Bits<16> exp = expF32UI(a);
1634
+ Bits<32> sig = fracF32UI(a);
1635
+ Bits<16> shiftDist;
983
1636
  U64 sig64;
984
1637
  # for NaN return the highest positive value and set floating-point flag to invalid.
985
1638
  if ((exp == 8'hFF) && (sig != 0)) {
@@ -996,7 +1649,7 @@ function f32_to_i32 {
996
1649
  sig64 = sig `<< 32;
997
1650
  shiftDist = 8'hAA - exp;
998
1651
 
999
- if (shiftDist > 0) {
1652
+ if ($signed(shiftDist) > 0s) {
1000
1653
  sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1001
1654
  }
1002
1655
 
@@ -1014,9 +1667,9 @@ function f32_to_ui32 {
1014
1667
  }
1015
1668
  body {
1016
1669
  Bits<1> sign = signF32UI(a);
1017
- Bits<8> exp = expF32UI(a);
1018
- Bits<23> sig = fracF32UI(a);
1019
- Bits<8> shiftDist;
1670
+ Bits<16> exp = expF32UI(a);
1671
+ Bits<32> sig = fracF32UI(a);
1672
+ Bits<16> shiftDist;
1020
1673
  U64 sig64;
1021
1674
  # for NaN return the highest positive value and set floating-point flag to invalid.
1022
1675
  if ((exp == 8'hFF) && (sig != 0)) {
@@ -1033,7 +1686,7 @@ function f32_to_ui32 {
1033
1686
  sig64 = sig `<< 32;
1034
1687
  shiftDist = 8'hAA - exp;
1035
1688
 
1036
- if (shiftDist > 0) {
1689
+ if ($signed(shiftDist) > 0s) {
1037
1690
  sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1038
1691
  }
1039
1692
 
@@ -1045,8 +1698,8 @@ function softfloat_roundPackToF32_no_flag {
1045
1698
  returns Bits<32> # single precision value
1046
1699
  arguments
1047
1700
  Bits<1> sign,
1048
- Bits<8> exp,
1049
- Bits<23> sig,
1701
+ Bits<16> exp,
1702
+ Bits<32> sig,
1050
1703
  RoundingMode mode
1051
1704
  description {
1052
1705
  Round FP value according to +mdode+ and then pack it in IEEE format.
@@ -1087,8 +1740,8 @@ function softfloat_normRoundPackToF32_no_flag {
1087
1740
  returns Bits<32>
1088
1741
  arguments
1089
1742
  Bits<1> sign,
1090
- Bits<8> exp,
1091
- Bits<23> sig,
1743
+ Bits<16> exp,
1744
+ Bits<32> sig,
1092
1745
  RoundingMode mode
1093
1746
  description {
1094
1747
  Normalize, round, and pack into a 32-bit floating point value
@@ -1235,3 +1888,160 @@ function round_f32_to_integral {
1235
1888
  return i32_to_f32_no_flag(intermediate, mode);
1236
1889
  }
1237
1890
  }
1891
+
1892
+ struct ExpAndSig {
1893
+ Bits<8> exp;
1894
+ Bits<32> sig;
1895
+ }
1896
+
1897
+ function softfloat_normSubnormalF32Sig {
1898
+ returns ExpAndSig
1899
+ arguments
1900
+ Bits<32> sig
1901
+ description {
1902
+ Normalize a subnormal F32 significand.
1903
+ Returns (exp, sig32) where exp is the adjusted exponent (two's complement
1904
+ in Bits<8>) and sig32 is the normalized significand with implicit leading 1
1905
+ at bit 23.
1906
+ }
1907
+ body {
1908
+ Bits<8> shiftDist = count_leading_zeros(32, sig) - 8;
1909
+ ExpAndSig ret;
1910
+ ret.exp = 1 - shiftDist;
1911
+ ret.sig = sig << shiftDist;
1912
+ return ret;
1913
+ }
1914
+ }
1915
+
1916
+ function softfloat_shortShiftRightJam64 {
1917
+ returns Bits<64>
1918
+ arguments
1919
+ Bits<64> a,
1920
+ Bits<8> dist
1921
+ description {
1922
+ Shifts +a+ right by +dist+ bits (dist must be in 1..31), jamming any
1923
+ shifted-off bits into the least-significant bit of the result.
1924
+ }
1925
+ body {
1926
+ return a >> dist | (((a & ((64'h1 << dist) - 1)) != 0) ? 1 : 0);
1927
+ }
1928
+ }
1929
+
1930
+ function softfloat_roundToI64 {
1931
+ returns Bits<64>
1932
+ arguments
1933
+ Bits<1> sign,
1934
+ Bits<64> sig,
1935
+ Bits<64> sigExtra,
1936
+ RoundingMode roundingMode
1937
+ description {
1938
+ Round to signed 64-bit integer, using +roundingMode+.
1939
+ Translated from Berkeley Softfloat softfloat_roundToI64.
1940
+ }
1941
+ body {
1942
+ Bits<64> z;
1943
+ Boolean needs_increment = false;
1944
+
1945
+ if ((roundingMode == RoundingMode::RMM) || (roundingMode == RoundingMode::RNE)) {
1946
+ if (64'h8000000000000000 <= sigExtra) {
1947
+ needs_increment = true;
1948
+ }
1949
+ } else {
1950
+ if ((sigExtra != 0) && ((sign != 0) ? (roundingMode == RoundingMode::RDN) : (roundingMode == RoundingMode::RUP))) {
1951
+ needs_increment = true;
1952
+ }
1953
+ }
1954
+
1955
+ if (needs_increment) {
1956
+ sig = sig + 1;
1957
+ if (sig == 0) {
1958
+ set_fp_flag(FpFlag::NV);
1959
+ return (sign == 1) ? I64_NEG_OVERFLOW : I64_POS_OVERFLOW;
1960
+ }
1961
+ if ((sigExtra == 64'h8000000000000000) && (roundingMode == RoundingMode::RNE)) {
1962
+ sig = sig & ~64'h1;
1963
+ }
1964
+ }
1965
+
1966
+ z = (sign == 1) ? -sig : sig;
1967
+ if ((z != 0) && (((($signed(z) < 0s) ? 1 : 0) ^ sign) == 1)) {
1968
+ set_fp_flag(FpFlag::NV);
1969
+ return (sign == 1) ? I64_NEG_OVERFLOW : I64_POS_OVERFLOW;
1970
+ }
1971
+
1972
+ if (sigExtra != 0) {
1973
+ set_fp_flag(FpFlag::NX);
1974
+ }
1975
+
1976
+ return z;
1977
+ }
1978
+ }
1979
+
1980
+ function softfloat_roundToUI64 {
1981
+ returns Bits<64>
1982
+ arguments
1983
+ Bits<1> sign,
1984
+ Bits<64> sig,
1985
+ Bits<64> sigExtra,
1986
+ RoundingMode roundingMode
1987
+ description {
1988
+ Round to unsigned 64-bit integer, using +roundingMode+.
1989
+ Translated from Berkeley Softfloat softfloat_roundToUI64.
1990
+ }
1991
+ body {
1992
+ Boolean needs_increment = false;
1993
+
1994
+ if ((roundingMode == RoundingMode::RMM) || (roundingMode == RoundingMode::RNE)) {
1995
+ if (64'h8000000000000000 <= sigExtra) {
1996
+ needs_increment = true;
1997
+ }
1998
+ } else {
1999
+ if (sign != 0) {
2000
+ if ((sig | sigExtra) == 0) {
2001
+ return 0;
2002
+ }
2003
+ if (roundingMode == RoundingMode::RDN) {
2004
+ set_fp_flag(FpFlag::NV);
2005
+ if (sign == 1) {
2006
+ return UI64_NEG_OVERFLOW;
2007
+ } else {
2008
+ return UI64_POS_OVERFLOW;
2009
+ }
2010
+ }
2011
+ } else {
2012
+ if ( (roundingMode == RoundingMode::RUP) && (sigExtra != 0)) {
2013
+ needs_increment = true;
2014
+ }
2015
+ }
2016
+ }
2017
+
2018
+ if (needs_increment) {
2019
+ sig = sig + 1;
2020
+ if (sig == 0) {
2021
+ set_fp_flag(FpFlag::NV);
2022
+ if (sign == 1) {
2023
+ return UI64_NEG_OVERFLOW;
2024
+ } else {
2025
+ return UI64_POS_OVERFLOW;
2026
+ }
2027
+ }
2028
+ if ( (sigExtra == 64'h8000000000000000) && (roundingMode == RoundingMode::RNE)) {
2029
+ sig = sig & ~64'h1;
2030
+ }
2031
+ }
2032
+
2033
+ if ( (sign != 0) && (sig != 0) ) {
2034
+ set_fp_flag(FpFlag::NV);
2035
+ if (sign == 1) {
2036
+ return UI64_NEG_OVERFLOW;
2037
+ } else {
2038
+ return UI64_POS_OVERFLOW;
2039
+ }
2040
+ }
2041
+
2042
+ if (sigExtra != 0) {
2043
+ set_fp_flag(FpFlag::NX);
2044
+ }
2045
+ return sig;
2046
+ }
2047
+ }