benchmark.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #ifndef NO_FLOAT
  2. #include <math.h>
  3. #endif
  4. #include <fix16.h>
  5. #include "interface.h"
  6. #include <stdio.h>
  7. /* Autogenerated testcases */
  8. #include "testcases.c"
  9. /* Tools for profiling */
  10. typedef struct {
  11. uint32_t min;
  12. uint32_t max;
  13. uint32_t sum;
  14. uint32_t count;
  15. } cyclecount_t;
  16. // Initializer for cyclecount_t structure.
  17. // Max is initialized to 0 and min is 2^32-1 so that first call to cyclecount_update will set them.
  18. #define CYCLECOUNT_INIT {0xFFFFFFFF, 0, 0, 0}
  19. // Update cyclecount_t structure after a single measurement has been made.
  20. static void cyclecount_update(cyclecount_t *data, uint32_t cycles)
  21. {
  22. if (cycles < data->min)
  23. data->min = cycles;
  24. if (cycles > data->max)
  25. data->max = cycles;
  26. data->sum += cycles;
  27. data->count++;
  28. }
  29. #define MEASURE(variable, statement) { \
  30. start_timing(); \
  31. statement; \
  32. cyclecount_update(&variable, end_timing()); \
  33. }
  34. #define PRINT(variable, label) { \
  35. print_value(label " min", variable.min); \
  36. print_value(label " max", variable.max); \
  37. print_value(label " avg", variable.sum / variable.count); \
  38. }
  39. static cyclecount_t exp_cycles = CYCLECOUNT_INIT;
  40. static cyclecount_t sqrt_cycles = CYCLECOUNT_INIT;
  41. static cyclecount_t add_cycles = CYCLECOUNT_INIT;
  42. static cyclecount_t sub_cycles = CYCLECOUNT_INIT;
  43. static cyclecount_t div_cycles = CYCLECOUNT_INIT;
  44. static cyclecount_t mul_cycles = CYCLECOUNT_INIT;
  45. #ifndef NO_FLOAT
  46. static cyclecount_t float_sqrtf_cycles = CYCLECOUNT_INIT;
  47. static cyclecount_t float_add_cycles = CYCLECOUNT_INIT;
  48. static cyclecount_t float_sub_cycles = CYCLECOUNT_INIT;
  49. static cyclecount_t float_div_cycles = CYCLECOUNT_INIT;
  50. static cyclecount_t float_mul_cycles = CYCLECOUNT_INIT;
  51. #endif
  52. static fix16_t delta(fix16_t result, fix16_t expected)
  53. {
  54. #ifdef FIXMATH_NO_OVERFLOW
  55. // Ignore overflow errors when the detection is turned off
  56. if (expected == fix16_minimum)
  57. return 0;
  58. #endif
  59. if (result >= expected)
  60. {
  61. return result - expected;
  62. }
  63. else
  64. {
  65. return expected - result;
  66. }
  67. }
  68. #ifdef FIXMATH_NO_ROUNDING
  69. const fix16_t max_delta = 1;
  70. #else
  71. const fix16_t max_delta = 0;
  72. #endif
  73. int main()
  74. {
  75. int i;
  76. interface_init();
  77. start_timing();
  78. print_value("Timestamp bias", end_timing());
  79. for (i = 0; i < TESTCASES1_COUNT; i++)
  80. {
  81. fix16_t input = testcases1[i].a;
  82. fix16_t result;
  83. fix16_t expected = testcases1[i].sqrt;
  84. MEASURE(sqrt_cycles, result = fix16_sqrt(input));
  85. if (input > 0 && delta(result, expected) > max_delta)
  86. {
  87. print_value("Failed SQRT, i", i);
  88. print_value("Failed SQRT, input", input);
  89. print_value("Failed SQRT, output", result);
  90. print_value("Failed SQRT, expected", expected);
  91. }
  92. expected = testcases1[i].exp;
  93. MEASURE(exp_cycles, result = fix16_exp(input));
  94. if (delta(result, expected) > 400)
  95. {
  96. print_value("Failed EXP, i", i);
  97. print_value("Failed EXP, input", input);
  98. print_value("Failed EXP, output", result);
  99. print_value("Failed EXP, expected", expected);
  100. }
  101. }
  102. PRINT(sqrt_cycles, "fix16_sqrt");
  103. PRINT(exp_cycles, "fix16_exp");
  104. for (i = 0; i < TESTCASES2_COUNT; i++)
  105. {
  106. fix16_t a = testcases2[i].a;
  107. fix16_t b = testcases2[i].b;
  108. volatile fix16_t result;
  109. fix16_t expected = testcases2[i].add;
  110. MEASURE(add_cycles, result = fix16_add(a, b));
  111. if (delta(result, expected) > max_delta)
  112. {
  113. print_value("Failed ADD, i", i);
  114. print_value("Failed ADD, a", a);
  115. print_value("Failed ADD, b", b);
  116. print_value("Failed ADD, output", result);
  117. print_value("Failed ADD, expected", expected);
  118. }
  119. expected = testcases2[i].sub;
  120. MEASURE(sub_cycles, result = fix16_sub(a, b));
  121. if (delta(result, expected) > max_delta)
  122. {
  123. print_value("Failed SUB, i", i);
  124. print_value("Failed SUB, a", a);
  125. print_value("Failed SUB, b", b);
  126. print_value("Failed SUB, output", result);
  127. print_value("Failed SUB, expected", expected);
  128. }
  129. expected = testcases2[i].mul;
  130. MEASURE(mul_cycles, result = fix16_mul(a, b));
  131. if (delta(result, expected) > max_delta)
  132. {
  133. print_value("Failed MUL, i", i);
  134. print_value("Failed MUL, a", a);
  135. print_value("Failed MUL, b", b);
  136. print_value("Failed MUL, output", result);
  137. print_value("Failed MUL, expected", expected);
  138. }
  139. if (b != 0)
  140. {
  141. expected = testcases2[i].div;
  142. MEASURE(div_cycles, result = fix16_div(a, b));
  143. if (delta(result, expected) > max_delta)
  144. {
  145. print_value("Failed DIV, i", i);
  146. print_value("Failed DIV, a", a);
  147. print_value("Failed DIV, b", b);
  148. print_value("Failed DIV, output", result);
  149. print_value("Failed DIV, expected", expected);
  150. }
  151. }
  152. }
  153. PRINT(add_cycles, "fix16_add");
  154. PRINT(sub_cycles, "fix16_sub");
  155. PRINT(mul_cycles, "fix16_mul");
  156. PRINT(div_cycles, "fix16_div");
  157. /* Compare with floating point performance */
  158. #ifndef NO_FLOAT
  159. for (i = 0; i < TESTCASES1_COUNT; i++)
  160. {
  161. float input = fix16_to_float(testcases1[i].a);
  162. volatile float result;
  163. MEASURE(float_sqrtf_cycles, result = sqrtf(input));
  164. }
  165. PRINT(float_sqrtf_cycles, "float sqrtf");
  166. for (i = 0; i < TESTCASES2_COUNT; i++)
  167. {
  168. float a = fix16_to_float(testcases2[i].a);
  169. float b = fix16_to_float(testcases2[i].b);
  170. volatile float result;
  171. MEASURE(float_add_cycles, result = a + b);
  172. MEASURE(float_sub_cycles, result = a - b);
  173. MEASURE(float_mul_cycles, result = a * b);
  174. if (b != 0)
  175. {
  176. MEASURE(float_div_cycles, result = a / b);
  177. }
  178. }
  179. PRINT(float_add_cycles, "float add");
  180. PRINT(float_sub_cycles, "float sub");
  181. PRINT(float_mul_cycles, "float mul");
  182. PRINT(float_div_cycles, "float div");
  183. #endif
  184. return 0;
  185. }