Thanks, again! (I hope that we have
readers!)
Good tip to add the decimal point in the log. Now done. I didn't because I had a reasonably good mental understanding of it.
I think your discussion of the decimal point format stuff is kind of a summary of this. Agree.
Would have been fun to see whether
xy64_t is "necessary", or whether the optimalization flattens that the same way as
ah and
al usage.
Plus. I love your conclusion that we don't need to compare the LSB. I had that stomach feeling, and had commented it in the previous code examples as well, but you broke through! I do agree with your conclusion, which spells out in this code:
Code: Select all
typedef struct {
uint32_t lsb;
uint32_t msb;
} parts64_t;
typedef struct {
union {
int64_t int64_val;
uint64_t uint64_val;
parts64_t parts64;
} u;
} xy64_t;
static inline int32_t sat31_int64_C (const xy64_t ahl, const int mant, unsigned &sat_cnt) {
asm volatile("#sat31_int64_C:");
xy64_t ahl_64 = ahl;
const int pos=mant;
asm("lsats %0,%1,%2":
"=r"(ahl_64.u.parts64.msb),"=r"(ahl_64.u.parts64.lsb):
"r"(pos),"0"(ahl_64.u.parts64.msb),"1"(ahl_64.u.parts64.lsb));
// ===
if (ahl_64.u.parts64.msb != ahl.u.parts64.msb) { // lsb testing not needed ref. fabriceo Fri May 31, 2024 8:59 am
sat_cnt++;
} else {}
// ===
asm("lextract %0,%1,%2,%3,32":
"=r"(ahl_64.u.parts64.lsb):
"r"(ahl_64.u.parts64.msb),"r"(ahl_64.u.parts64.lsb),"r"(pos));
return ahl_64.u.parts64.lsb;
}
The logs. Here I have decorated with
test_num as well as the decimal point values.
But again, it's the
lsats that leaves the saturation value, right? Also again: Observe that in 2.0-2.3
res = 0x7FFFFFFF is
not a sat value.
Code: Select all
7654321076543210
1.0: mant 28, shift_left_num 58, offset 0, ahl = 0x0400000000000000
1.1: res = 0x40000000 = 4.000000000000
1.2: res = 0x40000000 = 4.000000000000, sat_cnt = 0
1.3: res = 0x40000000 = 4.000000000000, sat_cnt = 0
-----1--........--------........s-------........--------........
2.0: mant 28, shift_left_num 59, offset -1, ahl = 0x07FFFFFFFFFFFFFF // pos 0000011111111111111111111111111111111111111111111111111111111111
2.1: res = 0x7FFFFFFF = 7.999999996275 // >>28 0000000000000000000000000000000001111111111111111111111111111111
2.2: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 0
2.3: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 0
----1---........--------........s-------........--------........
3.0: mant 28, shift_left_num 59, offset 1, ahl = 0x0800000000000001 // pos 0000100000000000000000000000000000000000000000000000000000000001
3.1: res = 0x7FFFFFFF = 7.999999996275 // >>28 0000000000000000000000000000000010000000000000000000000000000000
3.2: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 1
3.3: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 2
4.0: mant 28, shift_left_num 59, offset 0, ahl = 0x0800000000000000
4.1: res = 0x7FFFFFFF = 7.999999996275
4.2: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 1
4.3: res = 0x7FFFFFFF = 7.999999996275, sat_cnt = 2
And here are my tests, which print out the above:
Code: Select all
static inline void mymath_test_B (const unsigned test_num, const int mant, const unsigned shift_left_num, const int offset) {
const long long ahl = (1ULL << shift_left_num) + offset;
xy64_t ahl_64;
unsigned sat_cnt = 0;
int res;
printf ("\n%u.0: mant %u, shift_left_num %u, offset %d, ahl = 0x%016llX\n", test_num, mant, shift_left_num, offset, ahl);
res = sat31_int64 (ahl, mant);
printf ("%u.1: res = 0x%X = %1.12f\n", test_num, res, fm(res,mant));
res = sat31_int64_B (ahl, mant, sat_cnt);
printf ("%u.2: res = 0x%X = %1.12f, sat_cnt = %u\n", test_num, res, fm(res,mant),sat_cnt);
ahl_64.u.int64_val = ahl;
res = sat31_int64_C (ahl_64, mant, sat_cnt);
printf ("%u.3: res = 0x%X = %1.12f, sat_cnt = %u\n", test_num, res, fm(res,mant), sat_cnt);
}
I have kept the (mantissa*2+x) because I wanted to show on exacly which bit value the saturation started (for a positve number, mentally easier..):
Code: Select all
#define VER_STR \
"v106"
// v106 31May2024 See fabriceo Fri May 31, 2024 8:59 am
// v105 30May2024 Teig as of Thu May 30, 2024 8:53 pm on XCore Exchange
// v104 30May2024 Teig ahl_sat_64
// v103 29May2024 Teig added sat_cnt, ok by Fabriceo Wed May 29, 2024 6:34 pm
// v102 18May2024 Fabrice new versions of both the .h and this file. See "Sat May 18, 2024 2:49 pm" there
// v101 13May2024 Fabriceo orig with -O3 and name _ends (cannnot see any difference in log)
// v100 13May2024 Fabriceo orig with -O2
int main(){
printf("Hello, test with XC compiler (%s):\n", VER_STR);
mymath_test (mantissa);
mymath_test_B (1, mantissa, mantissa+mantissa+2, 0); // 58
mymath_test_B (2, mantissa, mantissa+mantissa+3, -1); // 59
mymath_test_B (3, mantissa, mantissa+mantissa+3, 1); // 59 Saturates
mymath_test_B (4, mantissa, mantissa+mantissa+3, 0); // 59 Saturates
printf("Bye\n");
return 0;
}
...