@@ -484,4 +484,309 @@ function softfloat_normRoundPackToF32 {
484484 return softfloat_roundPackToF32(sign, exp, sig << shiftDist, mode);
485485 }
486486 }
487- }
487+ }
488+
489+ function signF32UI {
490+ returns Bits<1>
491+ arguments
492+ Bits<32> a,
493+ description {
494+ Extract sign-bit of a 32-bit floating point number
495+ }
496+ body {
497+ return a[31];
498+ }
499+ }
500+
501+ function expF32UI {
502+ returns Bits<8>
503+ arguments
504+ Bits<32> a,
505+ description {
506+ Extract exponent of a 32-bit floating point number
507+ }
508+ body {
509+ return a[30:23];
510+ }
511+ }
512+
513+ function fracF32UI {
514+ returns Bits<23>
515+ arguments
516+ Bits<32> a,
517+ description {
518+ Extract significand of a 32-bit floating point number
519+ }
520+ body {
521+ return a[22:0];
522+ }
523+ }
524+
525+ function returnNonSignalingNaN {
526+ returns U32
527+ arguments
528+ U32 a
529+ description {
530+ Returns a non-signalling NaN version of the floating-point number
531+ Does not modify the input
532+ }
533+ body {
534+ U32 a_copy = a;
535+ a_copy[22] = 1'b1;
536+ return a_copy;
537+ }
538+ }
539+
540+ function returnMag {
541+ returns U32
542+ arguments
543+ U32 a
544+ description {
545+ Returns magnitude of the given number
546+ Does not modify the input
547+ }
548+ body {
549+ U32 a_copy = a;
550+ # make sign bit zero
551+ a_copy[31] = 1'b0;
552+ return a_copy;
553+ }
554+ }
555+
556+ function returnLargerMag {
557+ returns U32
558+ arguments
559+ U32 a,
560+ U32 b
561+ description {
562+ Returns the larger number between a and b by magnitude
563+ If either number is signaling NaN then that is made quiet
564+ }
565+ body {
566+ U32 mag_a = returnMag(a);
567+ U32 mag_b = returnMag(b);
568+ U32 nonsig_a = returnNonSignalingNaN(a);
569+ U32 nonsig_b = returnNonSignalingNaN(b);
570+ if (mag_a < mag_b) {
571+ return nonsig_b;
572+ }
573+ if (mag_b < mag_a) {
574+ return nonsig_a;
575+ }
576+ return (nonsig_a < nonsig_b) ? nonsig_a : nonsig_b;
577+ }
578+ }
579+
580+ function softfloat_propagateNaNF32UI {
581+ returns U32
582+ arguments
583+ U32 a,
584+ U32 b
585+ description {
586+ Interpreting 'a' and 'b' as the bit patterns of two 32-bit floating-
587+ | point values, at least one of which is a NaN, returns the bit pattern of
588+ | the combined NaN result. If either 'a' or 'b' has the pattern of a
589+ | signaling NaN, the invalid exception is raised.
590+ }
591+ body {
592+ # check if a and b are signalling
593+ Boolean isSigNaN_a = is_sp_signaling_nan(a);
594+ Boolean isSigNaN_b = is_sp_signaling_nan(b);
595+
596+ # get non Signalling versions of a and b
597+ U32 nonsig_a = returnNonSignalingNaN(a);
598+ U32 nonsig_b = returnNonSignalingNaN(b);
599+
600+ if (isSigNaN_a | isSigNaN_b) {
601+ # raise invalid flag if either number is NaN
602+ set_fp_flag(FpFlag::NV);
603+ if ( isSigNaN_a ) {
604+ if ( isSigNaN_b ) {
605+ # if both numbers are NaN return larger magnitude and remove NaN signaling
606+ return returnLargerMag(a, b);
607+ }
608+ # if b is NaN return non signaling value of b
609+ return is_sp_nan(b) ? nonsig_b : nonsig_a;
610+ } else {
611+ return is_sp_nan(a) ? nonsig_a : nonsig_b;
612+ }
613+ }
614+
615+ }
616+ }
617+
618+ function softfloat_addMagsF32 {
619+ returns U32
620+ arguments
621+ U32 a,
622+ U32 b,
623+ RoundingMode mode
624+ description {
625+ Returns sum of the magnitudes of 2 floating point numbers
626+ }
627+ body {
628+
629+ # extract exponents and significands of a and b
630+ Bits<8> expA = expF32UI(a);
631+ Bits<23> sigA = fracF32UI(a);
632+ Bits<8> expB = expF32UI(b);
633+ Bits<23> sigB = fracF32UI(b);
634+
635+ # declare a variable to store significand of sum
636+ U32 sigZ;
637+ # declare a variable to store sum of the magnitudes of the 2 numbers
638+ U32 z;
639+ # declare a variable to store sign of sum
640+ Bits<1> signZ;
641+
642+ # declare a variable to store the exponent part of sum
643+ Bits<8> expZ;
644+
645+ # calculate difference of exponents
646+ Bits<8> expDiff = expA - expB
647+
648+ if (expDiff == 8'd0) {
649+ if (expA == 8'd0) {
650+ z = a + b;
651+ return z; # if exponents of both numbers are zero, then return sum of both numbers
652+ }
653+
654+ # check if A is infinity or NaN
655+ if (expA == 8'hFF) {
656+ # A is NaN if significand is non-zero and exponent is 8'hFF
657+ if ((sigA != 8'd0) | (sigB != 8'd0)) {
658+ softfloat_propagateNaNF32UI(a, b);
659+ }
660+ # return infinity if A is infinity
661+ return a;
662+ }
663+
664+ signZ = signF32UI(a);
665+ expZ = expA;
666+ sigZ = 32'h01000000 + sigA + sigB;
667+
668+ # check if significand is even and exponent is less than 8'FE
669+ if (((sigZ & 0x1) == 0) && (expZ < 8'hFE)) {
670+ # if significand is even, remove trailing zero
671+ sigZ = sigZ >> 1;
672+ # pack the sign, exponent and significand
673+ return (32'h0 + (signZ << 31) + (expZ << 23) + sigZ);
674+ }
675+
676+ sigZ = sigZ << 6;
677+ } else {
678+
679+ signZ = signF32UI(a);
680+
681+ U32 sigA_32 = 32'h0 + (sigA << 6);
682+ U32 sigB_32 = 32'h0 + (sigA << 6);
683+
684+ # check if B has a bigger exponent value than A
685+ if (expDiff < 0) {
686+ # check if B is infinity or NaN
687+ if (expB == 8'hFF) {
688+ # B is NaN if exponent is 8'hFF and significand is non-zero
689+ if (sigB != 0) {
690+ softfloat_propagateNaNF32UI(a, b);
691+ }
692+ # return infinity with same sign as A
693+ return packToF32UI(signZ, 8'hFF, 23'h0);
694+ }
695+ expZ = expB;
696+
697+ sigA_32 = (expA == 0) ? 2*sigA_32 : (sigA_32 + 0x20000000);
698+ sigA_32 = softfloat_shiftRightJam32(sigA_32, (32'h0 - expDiff));
699+ } else {
700+ # check if A is infinity or NaN
701+ if (expA == 8'hFF) {
702+ # A is NaN if exponent is 8'hFF and significand is non-zero
703+ if (sigA != 0) {
704+ softfloat_propagateNaNF32UI(a, b);
705+ }
706+ # return infinity with same sign as A
707+ return a;
708+ }
709+
710+ expZ = expA;
711+ sigB_32 = (expB == 0) ? 2*sigB_32 : (sigB_32 + 0x20000000);
712+ sigB_32 = softfloat_shiftRightJam32(sigB_32, (32'h0 + expDiff));
713+ }
714+
715+ U32 sigZ = 0x20000000 + sigA + sigB;
716+ if ( sigZ < 0x40000000 ) {
717+ expZ = expZ - 1;
718+ sigZ = sigZ << 1;
719+ }
720+ }
721+ return softfloat_roundPackToF32(signZ, expZ, sigZ[22:0], mode);
722+ }
723+ }
724+
725+ function softfloat_subMagsF32 {
726+ returns U32
727+ arguments
728+ U32 a,
729+ U32 b,
730+ RoundingMode mode
731+ description {
732+ Returns difference of the magnitudes of 2 floating point numbers
733+ }
734+ body {
735+
736+ # extract exponents and significands of a and b
737+ Bits<8> expA = expF32UI(a);
738+ Bits<23> sigA = fracF32UI(a);
739+ Bits<8> expB = expF32UI(b);
740+ Bits<23> sigB = fracF32UI(b);
741+
742+ # declare a variable to store significand of difference
743+ U32 sigZ;
744+ # declare a variable to store difference of the magnitudes of the 2 numbers
745+ U32 z;
746+ # declare a variable to store sign of difference
747+ Bits<1> signZ;
748+
749+ # declare a variable to store the exponent part of difference
750+ Bits<8> expZ;
751+
752+ # declare a variable to store the difference in significand
753+ U32 sigDiff;
754+
755+ # declare a variable to store shift distance
756+ Bits<8> shiftDist;
757+
758+ # calculate difference of exponents
759+ Bits<8> expDiff = expA - expB
760+
761+ if (expDiff == 8'd0) {
762+
763+ # check if A is infinity or NaN
764+ if (expA == 8'hFF) {
765+ # A is NaN if significand is non-zero and exponent is 8'hFF
766+ if ((sigA != 8'd0) | (sigB != 8'd0)) {
767+ softfloat_propagateNaNF32UI(a, b);
768+ }
769+ # return infinity if A is infinity
770+ return a;
771+ }
772+
773+ sigDiff = sigA - sigB;
774+
775+ # check if no difference in significand
776+ if (sigDiff == 0) {
777+ # return -0 if rounding mode is round down, else return +0
778+ return packToF32UI((mode == RoundingMode::RDN),0,0);
779+ }
780+
781+ if (expA != 0) {
782+ expA = expA - 1;
783+ }
784+
785+ signZ = signF32UI(a);
786+ if (sigDiff < 0) {
787+ signZ != signZ;
788+ sigDiff = -32'hs1 * sigDiff;
789+ }
790+
791+
792+
0 commit comments