diff --git a/Include/dsp/utils.h b/Include/dsp/utils.h index 7f5acb37..7b1da5ba 100755 --- a/Include/dsp/utils.h +++ b/Include/dsp/utils.h @@ -27,6 +27,7 @@ #define _ARM_MATH_UTILS_H_ #include "arm_math_types.h" +#include #ifdef __cplusplus extern "C" @@ -47,6 +48,7 @@ extern "C" /** * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + It should not be used with negative values. */ __STATIC_FORCEINLINE uint32_t arm_recip_q31( q31_t in, @@ -60,11 +62,11 @@ extern "C" if (in > 0) { - signBits = ((uint32_t) (__CLZ( in) - 1)); + signBits = ((uint32_t) (__CLZ( (uint32_t)in) - 1)); } else { - signBits = ((uint32_t) (__CLZ(-in) - 1)); + signBits = ((uint32_t) (__CLZ((uint32_t)(-in)) - 1)); } /* Convert input sample to 1.31 format */ @@ -98,6 +100,7 @@ extern "C" /** * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + It should not be used with negative values. */ __STATIC_FORCEINLINE uint32_t arm_recip_q15( q15_t in, @@ -105,21 +108,21 @@ extern "C" const q15_t * pRecipTable) { q15_t out = 0; - uint32_t tempVal = 0; + int32_t tempVal = 0; uint32_t index = 0, i = 0; uint32_t signBits = 0; if (in > 0) { - signBits = ((uint32_t)(__CLZ( in) - 17)); + signBits = ((uint32_t)(__CLZ( (uint32_t)in) - 17)); } else { - signBits = ((uint32_t)(__CLZ(-in) - 17)); + signBits = ((uint32_t)(__CLZ((uint32_t)(-in)) - 17)); } /* Convert input sample to 1.15 format */ - in = (in << signBits); + in = (q15_t)(in << signBits); /* calculation of index for initial approximated Val */ index = (uint32_t)(in >> 8); @@ -132,8 +135,8 @@ extern "C" /* running approximation for two iterations */ for (i = 0U; i < 2U; i++) { - tempVal = (uint32_t) (((q31_t) in * out) >> 15); - tempVal = 0x7FFFu - tempVal; + tempVal = (((q31_t) in * out) >> 15); + tempVal = 0x7FFF - tempVal; /* 1.15 with exp 1 */ out = (q15_t) (((q31_t) out * tempVal) >> 14); /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ @@ -159,13 +162,13 @@ __STATIC_INLINE void arm_norm_64_to_32u(uint64_t in, int32_t * normalized, int3 int32_t hi = (int32_t) (in >> 32); int32_t lo = (int32_t) ((in << 32) >> 32); - n1 = __CLZ(hi) - 32; + n1 = __CLZ((uint32_t)hi) - 32; if (!n1) { /* * input fits in 32-bit */ - n1 = __CLZ(lo); + n1 = __CLZ((uint32_t)lo); if (!n1) { /* @@ -201,13 +204,13 @@ __STATIC_INLINE void arm_norm_64_to_32u(uint64_t in, int32_t * normalized, int3 /* * 64 bit normalization */ - *normalized = (((uint32_t) lo) >> n1) | (hi << (32 - n1)); + *normalized = (int32_t)(((uint32_t)lo) >> n1) | (hi << (32 - n1)); } } -__STATIC_INLINE q31_t arm_div_q63_to_q31(q63_t num, q31_t den) +__STATIC_INLINE int32_t arm_div_int64_to_int32(int64_t num, int32_t den) { - q31_t result; + int32_t result; uint64_t absNum; int32_t normalized; int32_t norm; @@ -216,18 +219,25 @@ __STATIC_INLINE q31_t arm_div_q63_to_q31(q63_t num, q31_t den) * if sum fits in 32bits * avoid costly 64-bit division */ - absNum = num > 0 ? num : -num; + if (num == (int64_t)LONG_MIN) + { + absNum = LONG_MAX; + } + else + { + absNum = (uint64_t) (num > 0 ? num : -num); + } arm_norm_64_to_32u(absNum, &normalized, &norm); if (norm > 0) /* * 32-bit division */ - result = (q31_t) num / den; + result = (int32_t) num / den; else /* * 64-bit division */ - result = (q31_t) (num / den); + result = (int32_t) (num / den); return result; } diff --git a/PythonWrapper/testrecip.py b/PythonWrapper/testrecip.py new file mode 100755 index 00000000..29bc09af --- /dev/null +++ b/PythonWrapper/testrecip.py @@ -0,0 +1,28 @@ +import cmsisdsp as dsp +import numpy as np + +recipQ15=np.array([0x7F03, 0x7D13, 0x7B31, 0x795E, 0x7798, 0x75E0, + 0x7434, 0x7294, 0x70FF, 0x6F76, 0x6DF6, 0x6C82, + 0x6B16, 0x69B5, 0x685C, 0x670C, 0x65C4, 0x6484, + 0x634C, 0x621C, 0x60F3, 0x5FD0, 0x5EB5, 0x5DA0, + 0x5C91, 0x5B88, 0x5A85, 0x5988, 0x5890, 0x579E, + 0x56B0, 0x55C8, 0x54E4, 0x5405, 0x532B, 0x5255, + 0x5183, 0x50B6, 0x4FEC, 0x4F26, 0x4E64, 0x4DA6, + 0x4CEC, 0x4C34, 0x4B81, 0x4AD0, 0x4A23, 0x4978, + 0x48D1, 0x482D, 0x478C, 0x46ED, 0x4651, 0x45B8, + 0x4521, 0x448D, 0x43FC, 0x436C, 0x42DF, 0x4255, + 0x41CC, 0x4146, 0x40C2, 0x4040]) + +s,v=dsp.arm_recip_q15(int(0x2000),recipQ15) +print("1 / 0.25") +print(s) +print("%04X -> %f" % (v,((v< %f" % (v,((v<> 15; diff --git a/Testing/CMakeLists.txt b/Testing/CMakeLists.txt index 578e768d..9bb8546b 100644 --- a/Testing/CMakeLists.txt +++ b/Testing/CMakeLists.txt @@ -277,6 +277,7 @@ endif() if (FASTMATH) set(FASTMATHSRC Source/Tests/FastMathF64.cpp Source/Tests/FastMathF32.cpp + Source/Tests/FastMathQ63.cpp Source/Tests/FastMathQ31.cpp Source/Tests/FastMathQ15.cpp) endif() diff --git a/Testing/FrameworkInclude/Error.h b/Testing/FrameworkInclude/Error.h index be502d00..08a436b5 100644 --- a/Testing/FrameworkInclude/Error.h +++ b/Testing/FrameworkInclude/Error.h @@ -202,7 +202,7 @@ void assert_equal(unsigned long nb,AnyPattern &pa, AnyPattern &pb) } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -258,7 +258,7 @@ void assert_near_equal(unsigned long nb,AnyPattern &pa, AnyPattern &pb, T } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } diff --git a/Testing/FrameworkInclude/FPGA.h b/Testing/FrameworkInclude/FPGA.h index 1ba68c93..04628ba8 100644 --- a/Testing/FrameworkInclude/FPGA.h +++ b/Testing/FrameworkInclude/FPGA.h @@ -69,6 +69,7 @@ FPGA driver. Used to read a C array describing how to drive the test. virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb); virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb); virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb); + virtual void ImportPattern_u64(Testing::PatternID_t,char*,Testing::nbSamples_t nb); virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb); virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb); virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb); @@ -87,6 +88,7 @@ FPGA driver. Used to read a C array describing how to drive the test. virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t* data); virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t* data); virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t* data); + virtual void DumpPattern_u64(Testing::outputID_t,Testing::nbSamples_t nb, uint64_t* data); virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t* data); virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t* data); virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t* data); diff --git a/Testing/FrameworkInclude/Pattern.h b/Testing/FrameworkInclude/Pattern.h index d083e3d8..767e5215 100644 --- a/Testing/FrameworkInclude/Pattern.h +++ b/Testing/FrameworkInclude/Pattern.h @@ -68,6 +68,9 @@ q15_t *loadPattern(Testing::PatternID_t id, PatternMgr *mgr,Testing::nbSamples_t template <> q7_t *loadPattern(Testing::PatternID_t id, PatternMgr *mgr,Testing::nbSamples_t &nb, Testing::nbSamples_t maxSamples); +template <> +uint64_t *loadPattern(Testing::PatternID_t id, PatternMgr *mgr,Testing::nbSamples_t &nb, Testing::nbSamples_t maxSamples); + template <> uint32_t *loadPattern(Testing::PatternID_t id, PatternMgr *mgr,Testing::nbSamples_t &nb, Testing::nbSamples_t maxSamples); @@ -108,6 +111,9 @@ q15_t *localPattern(Testing::nbSamples_t nb, PatternMgr *mgr); template <> q7_t *localPattern(Testing::nbSamples_t nb, PatternMgr *mgr); +template <> +uint64_t *localPattern(Testing::nbSamples_t nb, PatternMgr *mgr); + template <> uint32_t *localPattern(Testing::nbSamples_t nb, PatternMgr *mgr); @@ -126,6 +132,7 @@ extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,q63_t*,Patte extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,q31_t*,PatternMgr *); extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,q15_t*,PatternMgr *); extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,q7_t*,PatternMgr *); +extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,uint64_t*,PatternMgr *); extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,uint32_t*,PatternMgr *); extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,uint16_t*,PatternMgr *); extern void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t,uint8_t*,PatternMgr *); diff --git a/Testing/FrameworkInclude/Semihosting.h b/Testing/FrameworkInclude/Semihosting.h index 91759df5..463c733c 100644 --- a/Testing/FrameworkInclude/Semihosting.h +++ b/Testing/FrameworkInclude/Semihosting.h @@ -74,6 +74,7 @@ Semihosting driver. Used to read a text file describing how to drive the test. virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); + virtual void ImportPattern_u64(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb=0); @@ -93,6 +94,7 @@ Semihosting driver. Used to read a text file describing how to drive the test. virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t*); virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t*); virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t*); + virtual void DumpPattern_u64(Testing::outputID_t,Testing::nbSamples_t nb, uint64_t*); virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t*); virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t*); virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t*); diff --git a/Testing/FrameworkInclude/Test.h b/Testing/FrameworkInclude/Test.h index 55317a08..e66e8c3c 100644 --- a/Testing/FrameworkInclude/Test.h +++ b/Testing/FrameworkInclude/Test.h @@ -306,6 +306,7 @@ API of Memory managers used in the test framework virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; + virtual void ImportPattern_u64(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0; @@ -338,6 +339,7 @@ API of Memory managers used in the test framework virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t*)=0; virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t*)=0; virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t*)=0; + virtual void DumpPattern_u64(Testing::outputID_t,Testing::nbSamples_t nb, uint64_t*)=0; virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t*)=0; virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t*)=0; virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t*)=0; @@ -421,6 +423,7 @@ public: q15_t *load_q15(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); q7_t *load_q7(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); + uint64_t *load_u64(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); uint32_t *load_u32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); uint16_t *load_u16(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); uint8_t *load_u8(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES); @@ -441,6 +444,7 @@ public: q15_t *local_q15(Testing::nbSamples_t); q7_t *local_q7(Testing::nbSamples_t); + uint64_t *local_u64(Testing::nbSamples_t); uint32_t *local_u32(Testing::nbSamples_t); uint16_t *local_u16(Testing::nbSamples_t); uint8_t *local_u8(Testing::nbSamples_t); @@ -459,6 +463,7 @@ public: void dumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t,q15_t*); void dumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t,q7_t*); + void dumpPattern_u64(Testing::outputID_t,Testing::nbSamples_t,uint64_t*); void dumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t,uint32_t*); void dumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t,uint16_t*); void dumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t,uint8_t*); diff --git a/Testing/FrameworkSource/Error.cpp b/Testing/FrameworkSource/Error.cpp index 5a9ddd95..99f4b5d0 100644 --- a/Testing/FrameworkSource/Error.cpp +++ b/Testing/FrameworkSource/Error.cpp @@ -265,7 +265,7 @@ void assert_relative_error(unsigned long nb,AnyPattern &pa, AnyPatter } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -296,7 +296,7 @@ void assert_relative_error(unsigned long nb,AnyPattern &pa, AnyPatter } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -328,7 +328,7 @@ void assert_relative_error(unsigned long nb,AnyPattern &pa, AnyPatter } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -371,7 +371,7 @@ void assert_close_error(unsigned long nb,AnyPattern &pref, AnyPattern } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -414,7 +414,7 @@ void assert_close_error(unsigned long nb,AnyPattern &pref, AnyPattern } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } @@ -458,7 +458,7 @@ void assert_close_error(unsigned long nb,AnyPattern &pref, AnyPattern } catch(Error &err) { - sprintf(id," (nb=%lu)",i+1); + sprintf(id," (nb=%lu)",i); strcat(err.details,id); throw(err); } diff --git a/Testing/FrameworkSource/FPGA.cpp b/Testing/FrameworkSource/FPGA.cpp index 22b29f61..7fc8c922 100644 --- a/Testing/FrameworkSource/FPGA.cpp +++ b/Testing/FrameworkSource/FPGA.cpp @@ -100,10 +100,7 @@ namespace Client delete(this->outputNames); } - /** Read word 64 from C array - - */ - + /** Read word 32 from C array */ @@ -642,6 +639,26 @@ namespace Client } } + void FPGA::ImportPattern_u64(Testing::PatternID_t id,char* p,Testing::nbSamples_t nb) + { + unsigned long offset,i; + + offset=this->getPatternOffset(id); + + const char *patternStart = this->m_patterns + offset; + const uint64_t *src = (const uint64_t*)patternStart; + uint64_t *dst = (uint64_t*)p; + + if (dst) + { + for(i=0; i < nb; i++) + { + *dst++ = *src++; + } + } + } + + void FPGA::ImportPattern_u32(Testing::PatternID_t id,char* p,Testing::nbSamples_t nb) { unsigned long offset,i; @@ -842,6 +859,26 @@ namespace Client } } + void FPGA::DumpPattern_u64(Testing::outputID_t id,Testing::nbSamples_t nb, uint64_t* data) + { + std::string fileName = this->getOutputPath(id); + if (data) + { + printf("D: %s\n",fileName.c_str()); + Testing::nbSamples_t i=0; + uint64_t t; + uint64_t v; + for(i=0; i < nb; i++) + { + v = data[i]; + t = (uint64_t)v; + printf("D: 0x%016llx\n",t); + } + printf("D: END\n"); + } + } + + void FPGA::DumpPattern_u32(Testing::outputID_t id,Testing::nbSamples_t nb, uint32_t* data) { std::string fileName = this->getOutputPath(id); diff --git a/Testing/FrameworkSource/Pattern.cpp b/Testing/FrameworkSource/Pattern.cpp index a15052f3..b9f1e7b0 100644 --- a/Testing/FrameworkSource/Pattern.cpp +++ b/Testing/FrameworkSource/Pattern.cpp @@ -79,6 +79,13 @@ q7_t *loadPattern(Testing::PatternID_t id, Client::PatternMgr *mgr,Testing::nbSa return(mgr->load_q7(id,nb,maxSamples)); } +template <> +uint64_t *loadPattern(Testing::PatternID_t id, Client::PatternMgr *mgr,Testing::nbSamples_t &nb, Testing::nbSamples_t maxSamples) +{ + return(mgr->load_u64(id,nb,maxSamples)); +} + + template <> uint32_t *loadPattern(Testing::PatternID_t id, Client::PatternMgr *mgr,Testing::nbSamples_t &nb, Testing::nbSamples_t maxSamples) { @@ -142,6 +149,12 @@ q7_t *localPattern(Testing::PatternID_t id, Client::PatternMgr *mgr) return(mgr->local_q7(id)); } +template <> +uint64_t *localPattern(Testing::PatternID_t id, Client::PatternMgr *mgr) +{ + return(mgr->local_u64(id)); +} + template <> uint32_t *localPattern(Testing::PatternID_t id, Client::PatternMgr *mgr) { @@ -197,6 +210,11 @@ void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t nbSamples,q7_t* dat mgr->dumpPattern_q7(id,nbSamples,data); } +void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t nbSamples,uint64_t* data,PatternMgr *mgr) +{ + mgr->dumpPattern_u64(id,nbSamples,data); +} + void dumpPattern(Testing::outputID_t id,Testing::nbSamples_t nbSamples,uint32_t* data,PatternMgr *mgr) { mgr->dumpPattern_u32(id,nbSamples,data); diff --git a/Testing/FrameworkSource/PatternMgr.cpp b/Testing/FrameworkSource/PatternMgr.cpp index 8157408a..10b985f9 100644 --- a/Testing/FrameworkSource/PatternMgr.cpp +++ b/Testing/FrameworkSource/PatternMgr.cpp @@ -55,6 +55,7 @@ LOCAL(q63_t,q63) LOCAL(q31_t,q31) LOCAL(q15_t,q15) LOCAL(q7_t,q7) +LOCAL(uint64_t,u64) LOCAL(uint32_t,u32) LOCAL(uint16_t,u16) LOCAL(uint8_t,u8) @@ -185,6 +186,23 @@ q7_t *PatternMgr::load_q7(Testing::PatternID_t id,Testing::nbSamples_t& nbSample return((q7_t*)b); } +uint64_t *PatternMgr::load_u64(Testing::PatternID_t id,Testing::nbSamples_t& nbSamples,Testing::nbSamples_t maxSamples) +{ + nbSamples=m_io->GetPatternSize(id); + + if ((maxSamples != MAX_NB_SAMPLES) && (maxSamples < nbSamples)) + { + nbSamples = maxSamples; + } + + char *b = m_mem->NewBuffer(sizeof(uint64_t)*nbSamples); + if (b != NULL) + { + m_io->ImportPattern_u64(id,b,nbSamples); + } + return((uint64_t*)b); +} + uint32_t *PatternMgr::load_u32(Testing::PatternID_t id,Testing::nbSamples_t& nbSamples,Testing::nbSamples_t maxSamples) { nbSamples=m_io->GetPatternSize(id); @@ -274,6 +292,11 @@ void PatternMgr::dumpPattern_q7(Testing::outputID_t id,Testing::nbSamples_t nbSa m_io->DumpPattern_q7(id,nbSamples,data); } +void PatternMgr::dumpPattern_u64(Testing::outputID_t id,Testing::nbSamples_t nbSamples,uint64_t* data) +{ + m_io->DumpPattern_u64(id,nbSamples,data); +} + void PatternMgr::dumpPattern_u32(Testing::outputID_t id,Testing::nbSamples_t nbSamples,uint32_t* data) { m_io->DumpPattern_u32(id,nbSamples,data); diff --git a/Testing/FrameworkSource/Semihosting.cpp b/Testing/FrameworkSource/Semihosting.cpp index e46f940c..e831a5bb 100644 --- a/Testing/FrameworkSource/Semihosting.cpp +++ b/Testing/FrameworkSource/Semihosting.cpp @@ -865,6 +865,44 @@ namespace Client } + void Semihosting::ImportPattern_u64(Testing::PatternID_t id,char* p,Testing::nbSamples_t nb) + { + char tmp[256]; + Testing::nbSamples_t len; + Testing::nbSamples_t i=0; + + uint64_t val; + uint64_t *ptr=(uint64_t*)p; + + std::string fileName = this->getPatternPath(id); + FILE *pattern=fopen(fileName.c_str(), "r"); + // Ignore word size format + fgets(tmp,256,pattern); + // Get nb of samples + fgets(tmp,256,pattern); + len=atoi(tmp); + + if ((nb != MAX_NB_SAMPLES) && (nb < len)) + { + len = nb; + } + + if (ptr) + { + for(i=0;igetOutputPath(id); + if (data) + { + FILE *f = fopen(fileName.c_str(),"w"); + Testing::nbSamples_t i=0; + uint64_t t; + for(i=0; i < nb; i++) + { + t = (uint64_t)data[i]; + fprintf(f,"0x%016llx\n",t); + } + fclose(f); + } + } + void Semihosting::DumpPattern_u32(Testing::outputID_t id,Testing::nbSamples_t nb, uint32_t* data) { std::string fileName = this->getOutputPath(id); diff --git a/Testing/Include/Tests/FastMathQ15.h b/Testing/Include/Tests/FastMathQ15.h index 730c260d..7a4ec7e3 100755 --- a/Testing/Include/Tests/FastMathQ15.h +++ b/Testing/Include/Tests/FastMathQ15.h @@ -21,7 +21,6 @@ class FastMathQ15:public Client::Suite Client::LocalPattern output; Client::LocalPattern shift; - // Reference patterns are not loaded when we are in dump mode Client::RefPattern ref; Client::RefPattern refShift; diff --git a/Testing/Include/Tests/FastMathQ63.h b/Testing/Include/Tests/FastMathQ63.h new file mode 100755 index 00000000..380fe25f --- /dev/null +++ b/Testing/Include/Tests/FastMathQ63.h @@ -0,0 +1,31 @@ +#include "Test.h" +#include "Pattern.h" + +#include "dsp/fast_math_functions.h" + +class FastMathQ63:public Client::Suite + { + public: + FastMathQ63(Testing::testID_t id); + virtual void setUp(Testing::testID_t,std::vector& paramsArgs,Client::PatternMgr *mgr); + virtual void tearDown(Testing::testID_t,Client::PatternMgr *mgr); + private: + #include "FastMathQ63_decl.h" + + Client::Pattern input; + Client::Pattern inputU64; + Client::Pattern inputS64; + Client::Pattern inputS32; + + + Client::LocalPattern outputVals; + Client::LocalPattern outputNorms; + + + // Reference patterns are not loaded when we are in dump mode + Client::RefPattern refVal; + Client::RefPattern refNorm; + + + + }; diff --git a/Testing/PatternGeneration/FastMath.py b/Testing/PatternGeneration/FastMath.py index 73775026..f114538c 100755 --- a/Testing/PatternGeneration/FastMath.py +++ b/Testing/PatternGeneration/FastMath.py @@ -94,6 +94,12 @@ def initLogValues(format): ref = ref / 16.0 return(vals,ref) +def normalizeToOne(x): + s = 0 + while (abs(x)>1): + x = x /2.0 + s = s + 1 + return(int(s),x) def writeTests(config,format): @@ -143,7 +149,7 @@ def writeTests(config,format): resultValue=[x[0] for x in result] resultShift=[x[1] for x in result] - config.setOverwrite(True) + config.setOverwrite(False) config.writeInput(1, numerator,"Numerator") config.writeInput(1, denominator,"Denominator") config.writeReference(1, resultValue,"DivisionValue") @@ -185,8 +191,87 @@ def writeTests(config,format): config.setOverwrite(False) + if format == Tools.Q31 or format == Tools.Q15: + + if format == Tools.Q31: + theInput=np.array([1.0-1e-6,0.6,0.5,0.3,0.25,0.1,1.0/(1<<31)]) + + if format == Tools.Q15: + theInput=np.array([1.0-1e-6,0.6,0.5,0.3,0.25,0.1,1.0/(1<<15)]) + + ref=1.0 / theInput + shiftAndScaled=np.array([normalizeToOne(x) for x in ref]).transpose() + shiftValues=shiftAndScaled[0].astype(np.int16) + scaledValues=shiftAndScaled[1] + #print(shiftAndScaled) + config.writeInput(1, np.array(theInput),"RecipInput") + config.writeReference(1, scaledValues,"RecipRef") + config.writeReferenceS16(1, shiftValues,"RecipShift") + + + +def tocint32(x): + if x < 0: + return((0x10000000000000000 + x) & 0xFFFFFFFF) + else: + return(x & 0xFFFFFFFF) + +# C and Python are not rounding the integer division +# in the same way +def cdiv(a,b): + sign = 1 + if ((a<0) and (b>0)) or ((a>0) and (b<0)): + sign = -1 + + a= abs(a) + b = abs(b) + + d = sign*(a // b) + + return(d) + +def testInt64(config): + theInput=[0x1000000080000000, + 0x0000000080000000, + 0x0000000020000000, + 0x0000000000000000] + + ref=[0x40000002, + 0x40000000, + 0x40000000, + 0 + ] + norms=[-30,-1,1,0] + config.writeInputU64(1,np.array(theInput),"Norm64To32_Input") + config.writeReferenceS16(1,norms,"RefNorm64To32_Norms") + config.writeReferenceS32(1,ref,"RefNorm64To32_Vals") + + config.setOverwrite(False) + + allCombinations=[(0x7FFFFFFFFFFFFFFF,2), + (-0x7FFFFFFFFFFFFFFF-1,2), + ( 0x4000000000000000,0x7FFFFFFF), + ( -0x4000000000000000,0x7FFFFFFF), + ( 0x2000000000000000,0x7FFFFFFF), + ( -0x2000000000000000,0x7FFFFFFF), + ( 0x1000000000000000,0x7FFFFFFF), + ( -0x1000000000000000,0x7FFFFFFF), + ( 0x0000000080000000,2), + ( -0x0000000080000000,2), + ( 0x0000000040000000,2), + ( -0x0000000080000000,2) + ] + + res = [tocint32(cdiv(x,y)) for (x,y) in allCombinations] + + allCombinations=np.array(allCombinations,dtype=np.int64).flatten() + config.writeInputS64(1,allCombinations[0::2],"DivDenInput") + config.writeInputS32(1,allCombinations[1::2],"DivNumInput") + + config.writeReferenceU32(1, res,"DivRef") + config.setOverwrite(False) def writeTestsFloat(config,format): @@ -225,6 +310,9 @@ def generatePatterns(): configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16") configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31") configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15") + + configq64=Tools.Config(PATTERNDIR,PARAMDIR,"q63") + configf64.setOverwrite(False) @@ -232,6 +320,7 @@ def generatePatterns(): configf16.setOverwrite(False) configq31.setOverwrite(False) configq15.setOverwrite(False) + configq64.setOverwrite(False) writeTestsFloat(configf64,Tools.F64) writeTestsFloat(configf32,0) @@ -239,6 +328,8 @@ def generatePatterns(): writeTests(configq31,31) writeTests(configq15,15) + testInt64(configq64) + if __name__ == '__main__': generatePatterns() diff --git a/Testing/PatternGeneration/Tools.py b/Testing/PatternGeneration/Tools.py index 964783e5..27313c1d 100755 --- a/Testing/PatternGeneration/Tools.py +++ b/Testing/PatternGeneration/Tools.py @@ -13,6 +13,7 @@ BODYANDTAIL = 3 F64 = 64 F32 = 0 F16 = 16 +Q63 = 63 Q31 = 31 Q15 = 15 Q7 = 7 @@ -20,7 +21,7 @@ Q7 = 7 def loopnb(format,loopkind): nb = 0 if loopkind == TAILONLY: - if format == 64: + if format == 64 or format == Tools.Q63: nb = 2 if format == 0 or format == 31: nb = 3 @@ -29,7 +30,7 @@ def loopnb(format,loopkind): if format == 7: nb = 15 if loopkind == BODYONLY: - if format == 64: + if format == 64 or format == Tools.Q63: nb = 4 if format == 0 or format == 31: nb = 8 @@ -38,7 +39,7 @@ def loopnb(format,loopkind): if format == 7: nb = 32 if loopkind == BODYANDTAIL: - if format == 64: + if format == 64 or format == Tools.Q63: nb = 5 if format == 0 or format == 31: nb = 11 # 9 @@ -146,15 +147,30 @@ def to_q7(v): def s8(r): return ("0x%s" % format(struct.unpack('& paramsArgs,Client::PatternMgr *mgr) { @@ -222,6 +242,19 @@ a double precision computation. } break; + case FastMathQ15::TEST_RECIP_Q15_10: + { + input.reload(FastMathQ15::RECIPINPUT1_Q15_ID,mgr); + + ref.reload(FastMathQ15::RECIP_VAL_Q15_ID,mgr); + refShift.reload(FastMathQ15::RECIP_SHIFT_S16_ID,mgr); + + output.create(ref.nbSamples(),FastMathQ15::OUT_Q15_ID,mgr); + shift.create(ref.nbSamples(),FastMathQ15::SHIFT_S16_ID,mgr); + + } + break; + } } diff --git a/Testing/Source/Tests/FastMathQ31.cpp b/Testing/Source/Tests/FastMathQ31.cpp index 9ea921ec..79fc49e7 100755 --- a/Testing/Source/Tests/FastMathQ31.cpp +++ b/Testing/Source/Tests/FastMathQ31.cpp @@ -3,6 +3,8 @@ #include "Error.h" #include "Test.h" +#include "arm_common_tables.h" +#include "dsp/utils.h" #define SNR_THRESHOLD 100 /* @@ -18,6 +20,7 @@ a double precision computation. #define LOG_ABS_ERROR ((q31_t)2) #define ABS_ATAN_ERROR ((q31_t)3) +#define RECIP_ERROR ((q31_t)10) void FastMathQ31::test_atan2_scalar_q31() { @@ -127,6 +130,24 @@ a double precision computation. } + void FastMathQ31::test_recip_q31() + { + const q31_t *inp = input.ptr(); + q31_t *outp = output.ptr(); + int16_t *shiftp = shift.ptr(); + + + for(unsigned long i=0; i < ref.nbSamples(); i++) + { + shiftp[i] = arm_recip_q31(inp[i],&outp[i],armRecipTableQ31); + } + + + ASSERT_SNR(ref,output,(float32_t)SNR_THRESHOLD); + ASSERT_NEAR_EQ(ref,output,RECIP_ERROR); + ASSERT_EQ(refShift,shift); + + } void FastMathQ31::setUp(Testing::testID_t id,std::vector& paramsArgs,Client::PatternMgr *mgr) { @@ -210,7 +231,7 @@ a double precision computation. } break; - case FastMathQ31::TEST_ATAN2_SCALAR_Q31_9: + case FastMathQ31::TEST_ATAN2_SCALAR_Q31_9: { input.reload(FastMathQ31::ATAN2INPUT1_Q31_ID,mgr); ref.reload(FastMathQ31::ATAN2_Q31_ID,mgr); @@ -218,6 +239,19 @@ a double precision computation. } break; + case FastMathQ31::TEST_RECIP_Q31_10: + { + input.reload(FastMathQ31::RECIPINPUT1_Q31_ID,mgr); + + ref.reload(FastMathQ31::RECIP_VAL_Q31_ID,mgr); + refShift.reload(FastMathQ31::RECIP_SHIFT_S16_ID,mgr); + + output.create(ref.nbSamples(),FastMathQ31::OUT_Q31_ID,mgr); + shift.create(ref.nbSamples(),FastMathQ31::SHIFT_S16_ID,mgr); + + } + break; + } } diff --git a/Testing/Source/Tests/FastMathQ63.cpp b/Testing/Source/Tests/FastMathQ63.cpp new file mode 100755 index 00000000..e0fa5d44 --- /dev/null +++ b/Testing/Source/Tests/FastMathQ63.cpp @@ -0,0 +1,102 @@ +#include "FastMathQ63.h" +#include +#include "Error.h" +#include "Test.h" + +#include "arm_common_tables.h" +#include "dsp/utils.h" + +#define SNR_THRESHOLD 100 +/* + +Reference patterns are generated with +a double precision computation. + +*/ +#define ABS_ERROR ((q63_t)0) + + void FastMathQ63::test_norm_64_to_32u() + { + + const uint64_t *inp = inputU64.ptr(); + int32_t *outValp = outputVals.ptr(); + int16_t *outNormp = outputNorms.ptr(); + unsigned long i; + + for(i=0; i < refVal.nbSamples(); i++) + { + int32_t val; + int32_t norm; + + arm_norm_64_to_32u(inp[i],&val,&norm); + outValp[i]=val; + outNormp[i]=norm; + } + + ASSERT_EQ(refVal,outputVals); + ASSERT_EQ(refNorm,outputNorms); + + } + + void FastMathQ63::test_div_int64_to_int32() + { + const int64_t *denp = inputS64.ptr(); + const int32_t *nump = inputS32.ptr(); + + int32_t *outValp = outputVals.ptr(); + unsigned long i; + + for(i=0; i < refVal.nbSamples(); i++) + { + int32_t val; + + val = arm_div_int64_to_int32(denp[i],nump[i]); + outValp[i]=val; + + } + + ASSERT_EQ(refVal,outputVals); + } + + + void FastMathQ63::setUp(Testing::testID_t id,std::vector& paramsArgs,Client::PatternMgr *mgr) + { + (void)paramsArgs; + switch(id) + { + case FastMathQ63::TEST_NORM_64_TO_32U_1: + { + inputU64.reload(FastMathQ63::NORMINPUT1_U64_ID,mgr); + + refVal.reload(FastMathQ63::NORM_REF_VALS_S32_ID,mgr); + refNorm.reload(FastMathQ63::NORM_REF_S16_ID,mgr); + + outputVals.create(refVal.nbSamples(),FastMathQ63::OUT_S32_ID,mgr); + outputNorms.create(refNorm.nbSamples(),FastMathQ63::NORMS_S16_ID,mgr); + + } + break; + + case FastMathQ63::TEST_DIV_INT64_TO_INT32_2: + { + inputS64.reload(FastMathQ63::DIV_DEN_INPUT1_S64_ID,mgr); + inputS32.reload(FastMathQ63::DIV_NUM_INPUT1_S32_ID,mgr); + + refVal.reload(FastMathQ63::DIV_REF_S32_ID,mgr); + + outputVals.create(refVal.nbSamples(),FastMathQ63::OUT_S32_ID,mgr); + + } + break; + + } + + } + + void FastMathQ63::tearDown(Testing::testID_t id,Client::PatternMgr *mgr) + { + (void)id; + (void)mgr; + //output.dump(mgr); + + } diff --git a/Testing/desc.txt b/Testing/desc.txt index 8a551931..ff67eccb 100644 --- a/Testing/desc.txt +++ b/Testing/desc.txt @@ -1830,6 +1830,10 @@ group Root { Pattern ATAN2INPUT1_Q31_ID : Atan2Input1_q31.txt Pattern ATAN2_Q31_ID : Atan2Ref1_q31.txt + + Pattern RECIPINPUT1_Q31_ID : RecipInput1_q31.txt + Pattern RECIP_VAL_Q31_ID : RecipRef1_q31.txt + Pattern RECIP_SHIFT_S16_ID : RecipShift1_s16.txt Pattern COS1_Q31_ID : Cos1_q31.txt Pattern SIN1_Q31_ID : Sin1_q31.txt @@ -1856,6 +1860,7 @@ group Root { test_vlog_q31 nb=4n:test_vlog_q31 test_vlog_q31 nb=4n+1:test_vlog_q31 test_atan2_scalar_q31:test_atan2_scalar_q31 + test_recip_q31:test_recip_q31 } } @@ -1880,6 +1885,10 @@ group Root { Pattern ATAN2INPUT1_Q15_ID : Atan2Input1_q15.txt Pattern ATAN2_Q15_ID : Atan2Ref1_q15.txt + Pattern RECIPINPUT1_Q15_ID : RecipInput1_q15.txt + Pattern RECIP_VAL_Q15_ID : RecipRef1_q15.txt + Pattern RECIP_SHIFT_S16_ID : RecipShift1_s16.txt + Output OUT_Q15_ID : Output Output SHIFT_S16_ID : Output @@ -1893,6 +1902,28 @@ group Root { test_vlog_q15 nb=4n:test_vlog_q15 test_vlog_q15 nb=4n+1:test_vlog_q15 test_atan2_scalar_q15:test_atan2_scalar_q15 + test_recip_q15:test_recip_q15 + } + } + + suite Fast Maths Q63 { + class = FastMathQ63 + folder = FastMathQ63 + + Pattern NORMINPUT1_U64_ID : Norm64To32_Input1_u64.txt + Pattern NORM_REF_S16_ID : RefNorm64To32_Norms1_s16.txt + Pattern NORM_REF_VALS_S32_ID : RefNorm64To32_Vals1_s32.txt + + Pattern DIV_DEN_INPUT1_S64_ID : DivDenInput1_s64.txt + Pattern DIV_NUM_INPUT1_S32_ID : DivNumInput1_s32.txt + Pattern DIV_REF_S32_ID : DivRef1_u32.txt + + Output OUT_S32_ID : Output + Output NORMS_S16_ID : Output + + Functions { + test_norm_64_to_32u:test_norm_64_to_32u + test_div_int64_to_int32:test_div_int64_to_int32 } } }