Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 #include <asm/div64.h>
0024 
0025 #define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */
0026 
0027 #define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */
0028 
0029 #define SHIFTED_2 (2 << SHIFT_AMOUNT)
0030 #define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */
0031 
0032 /* -------------------------------------------------------------------------------
0033  * NEW TYPE - fINT
0034  * -------------------------------------------------------------------------------
0035  * A variable of type fInt can be accessed in 3 ways using the dot (.) operator
0036  * fInt A;
0037  * A.full => The full number as it is. Generally not easy to read
0038  * A.partial.real => Only the integer portion
0039  * A.partial.decimal => Only the fractional portion
0040  */
0041 typedef union _fInt {
0042     int full;
0043     struct _partial {
0044         unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/
0045         int real: 32 - SHIFT_AMOUNT;
0046     } partial;
0047 } fInt;
0048 
0049 /* -------------------------------------------------------------------------------
0050  * Function Declarations
0051  *  -------------------------------------------------------------------------------
0052  */
0053 static fInt ConvertToFraction(int);                       /* Use this to convert an INT to a FINT */
0054 static fInt Convert_ULONG_ToFraction(uint32_t);           /* Use this to convert an uint32_t to a FINT */
0055 static fInt GetScaledFraction(int, int);                  /* Use this to convert an INT to a FINT after scaling it by a factor */
0056 static int ConvertBackToInteger(fInt);                    /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */
0057 
0058 static fInt fNegate(fInt);                                /* Returns -1 * input fInt value */
0059 static fInt fAdd (fInt, fInt);                            /* Returns the sum of two fInt numbers */
0060 static fInt fSubtract (fInt A, fInt B);                   /* Returns A-B - Sometimes easier than Adding negative numbers */
0061 static fInt fMultiply (fInt, fInt);                       /* Returns the product of two fInt numbers */
0062 static fInt fDivide (fInt A, fInt B);                     /* Returns A/B */
0063 static fInt fGetSquare(fInt);                             /* Returns the square of a fInt number */
0064 static fInt fSqrt(fInt);                                  /* Returns the Square Root of a fInt number */
0065 
0066 static int uAbs(int);                                     /* Returns the Absolute value of the Int */
0067 static int uPow(int base, int exponent);                  /* Returns base^exponent an INT */
0068 
0069 static void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */
0070 static bool Equal(fInt, fInt);                            /* Returns true if two fInts are equal to each other */
0071 static bool GreaterThan(fInt A, fInt B);                  /* Returns true if A > B */
0072 
0073 static fInt fExponential(fInt exponent);                  /* Can be used to calculate e^exponent */
0074 static fInt fNaturalLog(fInt value);                      /* Can be used to calculate ln(value) */
0075 
0076 /* Fuse decoding functions
0077  * -------------------------------------------------------------------------------------
0078  */
0079 static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength);
0080 static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength);
0081 static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength);
0082 
0083 /* Internal Support Functions - Use these ONLY for testing or adding to internal functions
0084  * -------------------------------------------------------------------------------------
0085  * Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons.
0086  */
0087 static fInt Divide (int, int);                            /* Divide two INTs and return result as FINT */
0088 static fInt fNegate(fInt);
0089 
0090 static int uGetScaledDecimal (fInt);                      /* Internal function */
0091 static int GetReal (fInt A);                              /* Internal function */
0092 
0093 /* -------------------------------------------------------------------------------------
0094  * TROUBLESHOOTING INFORMATION
0095  * -------------------------------------------------------------------------------------
0096  * 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767)
0097  * 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767)
0098  * 3) fMultiply - OutputOutOfRangeException:
0099  * 4) fGetSquare - OutputOutOfRangeException:
0100  * 5) fDivide - DivideByZeroException
0101  * 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number
0102  */
0103 
0104 /* -------------------------------------------------------------------------------------
0105  * START OF CODE
0106  * -------------------------------------------------------------------------------------
0107  */
0108 static fInt fExponential(fInt exponent)        /*Can be used to calculate e^exponent*/
0109 {
0110     uint32_t i;
0111     bool bNegated = false;
0112 
0113     fInt fPositiveOne = ConvertToFraction(1);
0114     fInt fZERO = ConvertToFraction(0);
0115 
0116     fInt lower_bound = Divide(78, 10000);
0117     fInt solution = fPositiveOne; /*Starting off with baseline of 1 */
0118     fInt error_term;
0119 
0120     static const uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
0121     static const uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
0122 
0123     if (GreaterThan(fZERO, exponent)) {
0124         exponent = fNegate(exponent);
0125         bNegated = true;
0126     }
0127 
0128     while (GreaterThan(exponent, lower_bound)) {
0129         for (i = 0; i < 11; i++) {
0130             if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) {
0131                 exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000));
0132                 solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000));
0133             }
0134         }
0135     }
0136 
0137     error_term = fAdd(fPositiveOne, exponent);
0138 
0139     solution = fMultiply(solution, error_term);
0140 
0141     if (bNegated)
0142         solution = fDivide(fPositiveOne, solution);
0143 
0144     return solution;
0145 }
0146 
0147 static fInt fNaturalLog(fInt value)
0148 {
0149     uint32_t i;
0150     fInt upper_bound = Divide(8, 1000);
0151     fInt fNegativeOne = ConvertToFraction(-1);
0152     fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */
0153     fInt error_term;
0154 
0155     static const uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
0156     static const uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
0157 
0158     while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) {
0159         for (i = 0; i < 10; i++) {
0160             if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) {
0161                 value = fDivide(value, GetScaledFraction(k_array[i], 10000));
0162                 solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000));
0163             }
0164         }
0165     }
0166 
0167     error_term = fAdd(fNegativeOne, value);
0168 
0169     return (fAdd(solution, error_term));
0170 }
0171 
0172 static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength)
0173 {
0174     fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
0175     fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
0176 
0177     fInt f_decoded_value;
0178 
0179     f_decoded_value = fDivide(f_fuse_value, f_bit_max_value);
0180     f_decoded_value = fMultiply(f_decoded_value, f_range);
0181     f_decoded_value = fAdd(f_decoded_value, f_min);
0182 
0183     return f_decoded_value;
0184 }
0185 
0186 
0187 static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength)
0188 {
0189     fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
0190     fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
0191 
0192     fInt f_CONSTANT_NEG13 = ConvertToFraction(-13);
0193     fInt f_CONSTANT1 = ConvertToFraction(1);
0194 
0195     fInt f_decoded_value;
0196 
0197     f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1);
0198     f_decoded_value = fNaturalLog(f_decoded_value);
0199     f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13));
0200     f_decoded_value = fAdd(f_decoded_value, f_average);
0201 
0202     return f_decoded_value;
0203 }
0204 
0205 static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength)
0206 {
0207     fInt fLeakage;
0208     fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
0209 
0210     fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse));
0211     fLeakage = fDivide(fLeakage, f_bit_max_value);
0212     fLeakage = fExponential(fLeakage);
0213     fLeakage = fMultiply(fLeakage, f_min);
0214 
0215     return fLeakage;
0216 }
0217 
0218 static fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */
0219 {
0220     fInt temp;
0221 
0222     if (X <= MAX)
0223         temp.full = (X << SHIFT_AMOUNT);
0224     else
0225         temp.full = 0;
0226 
0227     return temp;
0228 }
0229 
0230 static fInt fNegate(fInt X)
0231 {
0232     fInt CONSTANT_NEGONE = ConvertToFraction(-1);
0233     return (fMultiply(X, CONSTANT_NEGONE));
0234 }
0235 
0236 static fInt Convert_ULONG_ToFraction(uint32_t X)
0237 {
0238     fInt temp;
0239 
0240     if (X <= MAX)
0241         temp.full = (X << SHIFT_AMOUNT);
0242     else
0243         temp.full = 0;
0244 
0245     return temp;
0246 }
0247 
0248 static fInt GetScaledFraction(int X, int factor)
0249 {
0250     int times_shifted, factor_shifted;
0251     bool bNEGATED;
0252     fInt fValue;
0253 
0254     times_shifted = 0;
0255     factor_shifted = 0;
0256     bNEGATED = false;
0257 
0258     if (X < 0) {
0259         X = -1*X;
0260         bNEGATED = true;
0261     }
0262 
0263     if (factor < 0) {
0264         factor = -1*factor;
0265         bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */
0266     }
0267 
0268     if ((X > MAX) || factor > MAX) {
0269         if ((X/factor) <= MAX) {
0270             while (X > MAX) {
0271                 X = X >> 1;
0272                 times_shifted++;
0273             }
0274 
0275             while (factor > MAX) {
0276                 factor = factor >> 1;
0277                 factor_shifted++;
0278             }
0279         } else {
0280             fValue.full = 0;
0281             return fValue;
0282         }
0283     }
0284 
0285     if (factor == 1)
0286         return ConvertToFraction(X);
0287 
0288     fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor));
0289 
0290     fValue.full = fValue.full << times_shifted;
0291     fValue.full = fValue.full >> factor_shifted;
0292 
0293     return fValue;
0294 }
0295 
0296 /* Addition using two fInts */
0297 static fInt fAdd (fInt X, fInt Y)
0298 {
0299     fInt Sum;
0300 
0301     Sum.full = X.full + Y.full;
0302 
0303     return Sum;
0304 }
0305 
0306 /* Addition using two fInts */
0307 static fInt fSubtract (fInt X, fInt Y)
0308 {
0309     fInt Difference;
0310 
0311     Difference.full = X.full - Y.full;
0312 
0313     return Difference;
0314 }
0315 
0316 static bool Equal(fInt A, fInt B)
0317 {
0318     if (A.full == B.full)
0319         return true;
0320     else
0321         return false;
0322 }
0323 
0324 static bool GreaterThan(fInt A, fInt B)
0325 {
0326     if (A.full > B.full)
0327         return true;
0328     else
0329         return false;
0330 }
0331 
0332 static fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */
0333 {
0334     fInt Product;
0335     int64_t tempProduct;
0336 
0337     /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/
0338     /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION
0339     bool X_LessThanOne, Y_LessThanOne;
0340 
0341     X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0);
0342     Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0);
0343 
0344     if (X_LessThanOne && Y_LessThanOne) {
0345         Product.full = X.full * Y.full;
0346         return Product
0347     }*/
0348 
0349     tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */
0350     tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */
0351     Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */
0352 
0353     return Product;
0354 }
0355 
0356 static fInt fDivide (fInt X, fInt Y)
0357 {
0358     fInt fZERO, fQuotient;
0359     int64_t longlongX, longlongY;
0360 
0361     fZERO = ConvertToFraction(0);
0362 
0363     if (Equal(Y, fZERO))
0364         return fZERO;
0365 
0366     longlongX = (int64_t)X.full;
0367     longlongY = (int64_t)Y.full;
0368 
0369     longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */
0370 
0371     div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */
0372 
0373     fQuotient.full = (int)longlongX;
0374     return fQuotient;
0375 }
0376 
0377 static int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/
0378 {
0379     fInt fullNumber, scaledDecimal, scaledReal;
0380 
0381     scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */
0382 
0383     scaledDecimal.full = uGetScaledDecimal(A);
0384 
0385     fullNumber = fAdd(scaledDecimal,scaledReal);
0386 
0387     return fullNumber.full;
0388 }
0389 
0390 static fInt fGetSquare(fInt A)
0391 {
0392     return fMultiply(A,A);
0393 }
0394 
0395 /* x_new = x_old - (x_old^2 - C) / (2 * x_old) */
0396 static fInt fSqrt(fInt num)
0397 {
0398     fInt F_divide_Fprime, Fprime;
0399     fInt test;
0400     fInt twoShifted;
0401     int seed, counter, error;
0402     fInt x_new, x_old, C, y;
0403 
0404     fInt fZERO = ConvertToFraction(0);
0405 
0406     /* (0 > num) is the same as (num < 0), i.e., num is negative */
0407 
0408     if (GreaterThan(fZERO, num) || Equal(fZERO, num))
0409         return fZERO;
0410 
0411     C = num;
0412 
0413     if (num.partial.real > 3000)
0414         seed = 60;
0415     else if (num.partial.real > 1000)
0416         seed = 30;
0417     else if (num.partial.real > 100)
0418         seed = 10;
0419     else
0420         seed = 2;
0421 
0422     counter = 0;
0423 
0424     if (Equal(num, fZERO)) /*Square Root of Zero is zero */
0425         return fZERO;
0426 
0427     twoShifted = ConvertToFraction(2);
0428     x_new = ConvertToFraction(seed);
0429 
0430     do {
0431         counter++;
0432 
0433         x_old.full = x_new.full;
0434 
0435         test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */
0436         y = fSubtract(test, C); /*y = f(x) = x^2 - C; */
0437 
0438         Fprime = fMultiply(twoShifted, x_old);
0439         F_divide_Fprime = fDivide(y, Fprime);
0440 
0441         x_new = fSubtract(x_old, F_divide_Fprime);
0442 
0443         error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old);
0444 
0445         if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/
0446             return x_new;
0447 
0448     } while (uAbs(error) > 0);
0449 
0450     return (x_new);
0451 }
0452 
0453 static void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[])
0454 {
0455     fInt *pRoots = &Roots[0];
0456     fInt temp, root_first, root_second;
0457     fInt f_CONSTANT10, f_CONSTANT100;
0458 
0459     f_CONSTANT100 = ConvertToFraction(100);
0460     f_CONSTANT10 = ConvertToFraction(10);
0461 
0462     while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) {
0463         A = fDivide(A, f_CONSTANT10);
0464         B = fDivide(B, f_CONSTANT10);
0465         C = fDivide(C, f_CONSTANT10);
0466     }
0467 
0468     temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */
0469     temp = fMultiply(temp, C); /* root = 4*A*C */
0470     temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */
0471     temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */
0472 
0473     root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */
0474     root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */
0475 
0476     root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
0477     root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
0478 
0479     root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
0480     root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
0481 
0482     *(pRoots + 0) = root_first;
0483     *(pRoots + 1) = root_second;
0484 }
0485 
0486 /* -----------------------------------------------------------------------------
0487  * SUPPORT FUNCTIONS
0488  * -----------------------------------------------------------------------------
0489  */
0490 
0491 /* Conversion Functions */
0492 static int GetReal (fInt A)
0493 {
0494     return (A.full >> SHIFT_AMOUNT);
0495 }
0496 
0497 static fInt Divide (int X, int Y)
0498 {
0499     fInt A, B, Quotient;
0500 
0501     A.full = X << SHIFT_AMOUNT;
0502     B.full = Y << SHIFT_AMOUNT;
0503 
0504     Quotient = fDivide(A, B);
0505 
0506     return Quotient;
0507 }
0508 
0509 static int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */
0510 {
0511     int dec[PRECISION];
0512     int i, scaledDecimal = 0, tmp = A.partial.decimal;
0513 
0514     for (i = 0; i < PRECISION; i++) {
0515         dec[i] = tmp / (1 << SHIFT_AMOUNT);
0516         tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]);
0517         tmp *= 10;
0518         scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
0519     }
0520 
0521     return scaledDecimal;
0522 }
0523 
0524 static int uPow(int base, int power)
0525 {
0526     if (power == 0)
0527         return 1;
0528     else
0529         return (base)*uPow(base, power - 1);
0530 }
0531 
0532 static int uAbs(int X)
0533 {
0534     if (X < 0)
0535         return (X * -1);
0536     else
0537         return X;
0538 }
0539 
0540 static fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term)
0541 {
0542     fInt solution;
0543 
0544     solution = fDivide(A, fStepSize);
0545     solution.partial.decimal = 0; /*All fractional digits changes to 0 */
0546 
0547     if (error_term)
0548         solution.partial.real += 1; /*Error term of 1 added */
0549 
0550     solution = fMultiply(solution, fStepSize);
0551     solution = fAdd(solution, fStepSize);
0552 
0553     return solution;
0554 }
0555