core_matrix.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. Author : Shay Gal-On, EEMBC
  3. This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009
  4. All rights reserved.
  5. EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the
  6. CoreMark License that is distributed with the official EEMBC COREMARK Software release.
  7. If you received this EEMBC CoreMark Software without the accompanying CoreMark License,
  8. you must discontinue use and download the official release from www.coremark.org.
  9. Also, if you are publicly displaying scores generated from the EEMBC CoreMark software,
  10. make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file.
  11. EEMBC
  12. 4354 Town Center Blvd. Suite 114-200
  13. El Dorado Hills, CA, 95762
  14. */
  15. #include "coremark.h"
  16. /*
  17. Topic: Description
  18. Matrix manipulation benchmark
  19. This very simple algorithm forms the basis of many more complex algorithms.
  20. The tight inner loop is the focus of many optimizations (compiler as well as hardware based)
  21. and is thus relevant for embedded processing.
  22. The total available data space will be divided to 3 parts:
  23. NxN Matrix A - initialized with small values (upper 3/4 of the bits all zero).
  24. NxN Matrix B - initialized with medium values (upper half of the bits all zero).
  25. NxN Matrix C - used for the result.
  26. The actual values for A and B must be derived based on input that is not available at compile time.
  27. */
  28. ee_s16 matrix_test(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B, MATDAT val);
  29. ee_s16 matrix_sum(ee_u32 N, MATRES* C, MATDAT clipval);
  30. void matrix_mul_const(ee_u32 N, MATRES* C, MATDAT* A, MATDAT val);
  31. void matrix_mul_vect(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B);
  32. void matrix_mul_matrix(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B);
  33. void matrix_mul_matrix_bitextract(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B);
  34. void matrix_add_const(ee_u32 N, MATDAT* A, MATDAT val);
  35. #define matrix_test_next(x) (x+1)
  36. #define matrix_clip(x,y) ((y) ? (x) & 0x0ff : (x) & 0x0ffff)
  37. #define matrix_big(x) (0xf000 | (x))
  38. // TODO: clang not yet provide any xxlcz instruction support
  39. #if (defined(__riscv_xxlczbitop) || (defined(__riscv_xxlcz))) && !defined(__clang__) && !defined(NO_EXTRACTU)
  40. #include "riscv_nuclei_xlcz.h"
  41. #define BIT_EXTRACT(x, from, to) (__xl_extractu(x, from, to))
  42. #else
  43. #define BIT_EXTRACT(x, from, to) (((x)>>(from)) & (~(0xffffffff << (to))))
  44. #endif
  45. #if CORE_DEBUG
  46. void printmat(MATDAT* A, ee_u32 N, char* name)
  47. {
  48. ee_u32 i, j;
  49. ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
  50. for (i = 0; i < N; i++) {
  51. for (j = 0; j < N; j++) {
  52. if (j != 0) {
  53. ee_printf(",");
  54. }
  55. ee_printf("%d", A[i * N + j]);
  56. }
  57. ee_printf("\n");
  58. }
  59. }
  60. void printmatC(MATRES* C, ee_u32 N, char* name)
  61. {
  62. ee_u32 i, j;
  63. ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
  64. for (i = 0; i < N; i++) {
  65. for (j = 0; j < N; j++) {
  66. if (j != 0) {
  67. ee_printf(",");
  68. }
  69. ee_printf("%d", C[i * N + j]);
  70. }
  71. ee_printf("\n");
  72. }
  73. }
  74. #endif
  75. /* Function: core_bench_matrix
  76. Benchmark function
  77. Iterate <matrix_test> N times,
  78. changing the matrix values slightly by a constant amount each time.
  79. */
  80. ee_u16 core_bench_matrix(mat_params* p, ee_s16 seed, ee_u16 crc)
  81. {
  82. ee_u32 N = p->N;
  83. MATRES* C = p->C;
  84. MATDAT* A = p->A;
  85. MATDAT* B = p->B;
  86. MATDAT val = (MATDAT)seed;
  87. crc = crc16(matrix_test(N, C, A, B, val), crc);
  88. return crc;
  89. }
  90. /* Function: matrix_test
  91. Perform matrix manipulation.
  92. Parameters:
  93. N - Dimensions of the matrix.
  94. C - memory for result matrix.
  95. A - input matrix
  96. B - operator matrix (not changed during operations)
  97. Returns:
  98. A CRC value that captures all results calculated in the function.
  99. In particular, crc of the value calculated on the result matrix
  100. after each step by <matrix_sum>.
  101. Operation:
  102. 1 - Add a constant value to all elements of a matrix.
  103. 2 - Multiply a matrix by a constant.
  104. 3 - Multiply a matrix by a vector.
  105. 4 - Multiply a matrix by a matrix.
  106. 5 - Add a constant value to all elements of a matrix.
  107. After the last step, matrix A is back to original contents.
  108. */
  109. ee_s16 matrix_test(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B, MATDAT val)
  110. {
  111. ee_u16 crc = 0;
  112. MATDAT clipval = matrix_big(val);
  113. matrix_add_const(N, A, val); /* make sure data changes */
  114. #if CORE_DEBUG
  115. printmat(A, N, "matrix_add_const");
  116. #endif
  117. matrix_mul_const(N, C, A, val);
  118. crc = crc16(matrix_sum(N, C, clipval), crc);
  119. #if CORE_DEBUG
  120. printmatC(C, N, "matrix_mul_const");
  121. #endif
  122. matrix_mul_vect(N, C, A, B);
  123. crc = crc16(matrix_sum(N, C, clipval), crc);
  124. #if CORE_DEBUG
  125. printmatC(C, N, "matrix_mul_vect");
  126. #endif
  127. matrix_mul_matrix(N, C, A, B);
  128. crc = crc16(matrix_sum(N, C, clipval), crc);
  129. #if CORE_DEBUG
  130. printmatC(C, N, "matrix_mul_matrix");
  131. #endif
  132. matrix_mul_matrix_bitextract(N, C, A, B);
  133. crc = crc16(matrix_sum(N, C, clipval), crc);
  134. #if CORE_DEBUG
  135. printmatC(C, N, "matrix_mul_matrix_bitextract");
  136. #endif
  137. matrix_add_const(N, A, -val); /* return matrix to initial value */
  138. return crc;
  139. }
  140. /* Function : matrix_init
  141. Initialize the memory block for matrix benchmarking.
  142. Parameters:
  143. blksize - Size of memory to be initialized.
  144. memblk - Pointer to memory block.
  145. seed - Actual values chosen depend on the seed parameter.
  146. p - pointers to <mat_params> containing initialized matrixes.
  147. Returns:
  148. Matrix dimensions.
  149. Note:
  150. The seed parameter MUST be supplied from a source that cannot be determined at compile time
  151. */
  152. ee_u32 core_init_matrix(ee_u32 blksize, void* memblk, ee_s32 seed, mat_params* p)
  153. {
  154. ee_u32 N = 0;
  155. MATDAT* A;
  156. MATDAT* B;
  157. ee_s32 order = 1;
  158. MATDAT val;
  159. ee_u32 i = 0, j = 0;
  160. if (seed == 0) {
  161. seed = 1;
  162. }
  163. while (j < blksize) {
  164. i++;
  165. j = i * i * 2 * 4;
  166. }
  167. N = i - 1;
  168. A = (MATDAT*)align_mem(memblk);
  169. B = A + N * N;
  170. for (i = 0; i < N; i++) {
  171. for (j = 0; j < N; j++) {
  172. seed = ((order * seed) % 65536);
  173. val = (seed + order);
  174. val = matrix_clip(val, 0);
  175. B[i * N + j] = val;
  176. val = (val + order);
  177. val = matrix_clip(val, 1);
  178. A[i * N + j] = val;
  179. order++;
  180. }
  181. }
  182. p->A = A;
  183. p->B = B;
  184. p->C = (MATRES*)align_mem(B + N * N);
  185. p->N = N;
  186. #if CORE_DEBUG
  187. printmat(A, N, "A");
  188. printmat(B, N, "B");
  189. #endif
  190. return N;
  191. }
  192. /* Function: matrix_sum
  193. Calculate a function that depends on the values of elements in the matrix.
  194. For each element, accumulate into a temporary variable.
  195. As long as this value is under the parameter clipval,
  196. add 1 to the result if the element is bigger then the previous.
  197. Otherwise, reset the accumulator and add 10 to the result.
  198. */
  199. ee_s16 matrix_sum(ee_u32 N, MATRES* C, MATDAT clipval)
  200. {
  201. MATRES tmp = 0, prev = 0, cur = 0;
  202. ee_s16 ret = 0;
  203. ee_u32 i, j;
  204. for (i = 0; i < N; i++) {
  205. for (j = 0; j < N; j++) {
  206. cur = C[i * N + j];
  207. tmp += cur;
  208. if (tmp > clipval) {
  209. ret += 10;
  210. tmp = 0;
  211. } else {
  212. ret += (cur > prev) ? 1 : 0;
  213. }
  214. prev = cur;
  215. }
  216. }
  217. return ret;
  218. }
  219. /* Function: matrix_mul_const
  220. Multiply a matrix by a constant.
  221. This could be used as a scaler for instance.
  222. */
  223. void matrix_mul_const(ee_u32 N, MATRES* C, MATDAT* A, MATDAT val)
  224. {
  225. ee_u32 i, j;
  226. for (i = 0; i < N; i++) {
  227. for (j = 0; j < N; j++) {
  228. C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val;
  229. }
  230. }
  231. }
  232. /* Function: matrix_add_const
  233. Add a constant value to all elements of a matrix.
  234. */
  235. void matrix_add_const(ee_u32 N, MATDAT* A, MATDAT val)
  236. {
  237. ee_u32 i, j;
  238. for (i = 0; i < N; i++) {
  239. for (j = 0; j < N; j++) {
  240. A[i * N + j] += val;
  241. }
  242. }
  243. }
  244. /* Function: matrix_mul_vect
  245. Multiply a matrix by a vector.
  246. This is common in many simple filters (e.g. fir where a vector of coefficients is applied to the matrix.)
  247. */
  248. void matrix_mul_vect(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B)
  249. {
  250. ee_u32 i, j;
  251. for (i = 0; i < N; i++) {
  252. C[i] = 0;
  253. for (j = 0; j < N; j++) {
  254. C[i] += (MATRES)A[i * N + j] * (MATRES)B[j];
  255. }
  256. }
  257. }
  258. /* Function: matrix_mul_matrix
  259. Multiply a matrix by a matrix.
  260. Basic code is used in many algorithms, mostly with minor changes such as scaling.
  261. */
  262. void matrix_mul_matrix(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B)
  263. {
  264. ee_u32 i, j, k;
  265. for (i = 0; i < N; i++) {
  266. for (j = 0; j < N; j++) {
  267. C[i * N + j] = 0;
  268. for (k = 0; k < N; k++) {
  269. C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
  270. }
  271. }
  272. }
  273. }
  274. /* Function: matrix_mul_matrix_bitextract
  275. Multiply a matrix by a matrix, and extract some bits from the result.
  276. Basic code is used in many algorithms, mostly with minor changes such as scaling.
  277. */
  278. void matrix_mul_matrix_bitextract(ee_u32 N, MATRES* C, MATDAT* A, MATDAT* B)
  279. {
  280. ee_u32 i, j, k;
  281. for (i = 0; i < N; i++) {
  282. for (j = 0; j < N; j++) {
  283. C[i * N + j] = 0;
  284. for (k = 0; k < N; k++) {
  285. MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
  286. C[i * N + j] += BIT_EXTRACT(tmp, 2, 4) * BIT_EXTRACT(tmp, 5, 7);
  287. }
  288. }
  289. }
  290. }