core_matrix.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. Original Author: Shay Gal-on
  13. */
  14. #include "coremark.h"
  15. /*
  16. Topic: Description
  17. Matrix manipulation benchmark
  18. This very simple algorithm forms the basis of many more complex
  19. algorithms.
  20. The tight inner loop is the focus of many optimizations (compiler as
  21. well as hardware based) 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
  24. zero). NxN Matrix B - initialized with medium values (upper half of the bits all
  25. zero). NxN Matrix C - used for the result.
  26. The actual values for A and B must be derived based on input that is not
  27. available at compile time.
  28. */
  29. ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val);
  30. ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval);
  31. void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val);
  32. void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
  33. void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
  34. void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
  35. void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val);
  36. #define matrix_test_next(x) (x + 1)
  37. #define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff)
  38. #define matrix_big(x) (0xf000 | (x))
  39. #define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to))))
  40. #if CORE_DEBUG
  41. void
  42. printmat(MATDAT *A, ee_u32 N, char *name)
  43. {
  44. ee_u32 i, j;
  45. ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
  46. for (i = 0; i < N; i++)
  47. {
  48. for (j = 0; j < N; j++)
  49. {
  50. if (j != 0)
  51. ee_printf(",");
  52. ee_printf("%d", A[i * N + j]);
  53. }
  54. ee_printf("\n");
  55. }
  56. }
  57. void
  58. printmatC(MATRES *C, ee_u32 N, char *name)
  59. {
  60. ee_u32 i, j;
  61. ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
  62. for (i = 0; i < N; i++)
  63. {
  64. for (j = 0; j < N; j++)
  65. {
  66. if (j != 0)
  67. ee_printf(",");
  68. ee_printf("%d", C[i * N + j]);
  69. }
  70. ee_printf("\n");
  71. }
  72. }
  73. #endif
  74. /* Function: core_bench_matrix
  75. Benchmark function
  76. Iterate <matrix_test> N times,
  77. changing the matrix values slightly by a constant amount each time.
  78. */
  79. ee_u16
  80. 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
  110. matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val)
  111. {
  112. ee_u16 crc = 0;
  113. MATDAT clipval = matrix_big(val);
  114. matrix_add_const(N, A, val); /* make sure data changes */
  115. #if CORE_DEBUG
  116. printmat(A, N, "matrix_add_const");
  117. #endif
  118. matrix_mul_const(N, C, A, val);
  119. crc = crc16(matrix_sum(N, C, clipval), crc);
  120. #if CORE_DEBUG
  121. printmatC(C, N, "matrix_mul_const");
  122. #endif
  123. matrix_mul_vect(N, C, A, B);
  124. crc = crc16(matrix_sum(N, C, clipval), crc);
  125. #if CORE_DEBUG
  126. printmatC(C, N, "matrix_mul_vect");
  127. #endif
  128. matrix_mul_matrix(N, C, A, B);
  129. crc = crc16(matrix_sum(N, C, clipval), crc);
  130. #if CORE_DEBUG
  131. printmatC(C, N, "matrix_mul_matrix");
  132. #endif
  133. matrix_mul_matrix_bitextract(N, C, A, B);
  134. crc = crc16(matrix_sum(N, C, clipval), crc);
  135. #if CORE_DEBUG
  136. printmatC(C, N, "matrix_mul_matrix_bitextract");
  137. #endif
  138. matrix_add_const(N, A, -val); /* return matrix to initial value */
  139. return crc;
  140. }
  141. /* Function : matrix_init
  142. Initialize the memory block for matrix benchmarking.
  143. Parameters:
  144. blksize - Size of memory to be initialized.
  145. memblk - Pointer to memory block.
  146. seed - Actual values chosen depend on the seed parameter.
  147. p - pointers to <mat_params> containing initialized matrixes.
  148. Returns:
  149. Matrix dimensions.
  150. Note:
  151. The seed parameter MUST be supplied from a source that cannot be
  152. determined at compile time
  153. */
  154. ee_u32
  155. core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p)
  156. {
  157. ee_u32 N = 0;
  158. MATDAT *A;
  159. MATDAT *B;
  160. ee_s32 order = 1;
  161. MATDAT val;
  162. ee_u32 i = 0, j = 0;
  163. if (seed == 0)
  164. seed = 1;
  165. while (j < blksize)
  166. {
  167. i++;
  168. j = i * i * 2 * 4;
  169. }
  170. N = i - 1;
  171. A = (MATDAT *)align_mem(memblk);
  172. B = A + N * N;
  173. for (i = 0; i < N; i++)
  174. {
  175. for (j = 0; j < N; j++)
  176. {
  177. seed = ((order * seed) % 65536);
  178. val = (seed + order);
  179. val = matrix_clip(val, 0);
  180. B[i * N + j] = val;
  181. val = (val + order);
  182. val = matrix_clip(val, 1);
  183. A[i * N + j] = val;
  184. order++;
  185. }
  186. }
  187. p->A = A;
  188. p->B = B;
  189. p->C = (MATRES *)align_mem(B + N * N);
  190. p->N = N;
  191. #if CORE_DEBUG
  192. printmat(A, N, "A");
  193. printmat(B, N, "B");
  194. #endif
  195. return N;
  196. }
  197. /* Function: matrix_sum
  198. Calculate a function that depends on the values of elements in the
  199. matrix.
  200. For each element, accumulate into a temporary variable.
  201. As long as this value is under the parameter clipval,
  202. add 1 to the result if the element is bigger then the previous.
  203. Otherwise, reset the accumulator and add 10 to the result.
  204. */
  205. ee_s16
  206. matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval)
  207. {
  208. MATRES tmp = 0, prev = 0, cur = 0;
  209. ee_s16 ret = 0;
  210. ee_u32 i, j;
  211. for (i = 0; i < N; i++)
  212. {
  213. for (j = 0; j < N; j++)
  214. {
  215. cur = C[i * N + j];
  216. tmp += cur;
  217. if (tmp > clipval)
  218. {
  219. ret += 10;
  220. tmp = 0;
  221. }
  222. else
  223. {
  224. ret += (cur > prev) ? 1 : 0;
  225. }
  226. prev = cur;
  227. }
  228. }
  229. return ret;
  230. }
  231. /* Function: matrix_mul_const
  232. Multiply a matrix by a constant.
  233. This could be used as a scaler for instance.
  234. */
  235. void
  236. matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val)
  237. {
  238. ee_u32 i, j;
  239. for (i = 0; i < N; i++)
  240. {
  241. for (j = 0; j < N; j++)
  242. {
  243. C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val;
  244. }
  245. }
  246. }
  247. /* Function: matrix_add_const
  248. Add a constant value to all elements of a matrix.
  249. */
  250. void
  251. matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val)
  252. {
  253. ee_u32 i, j;
  254. for (i = 0; i < N; i++)
  255. {
  256. for (j = 0; j < N; j++)
  257. {
  258. A[i * N + j] += val;
  259. }
  260. }
  261. }
  262. /* Function: matrix_mul_vect
  263. Multiply a matrix by a vector.
  264. This is common in many simple filters (e.g. fir where a vector of
  265. coefficients is applied to the matrix.)
  266. */
  267. void
  268. matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
  269. {
  270. ee_u32 i, j;
  271. for (i = 0; i < N; i++)
  272. {
  273. C[i] = 0;
  274. for (j = 0; j < N; j++)
  275. {
  276. C[i] += (MATRES)A[i * N + j] * (MATRES)B[j];
  277. }
  278. }
  279. }
  280. /* Function: matrix_mul_matrix
  281. Multiply a matrix by a matrix.
  282. Basic code is used in many algorithms, mostly with minor changes such as
  283. scaling.
  284. */
  285. void
  286. matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
  287. {
  288. ee_u32 i, j, k;
  289. for (i = 0; i < N; i++)
  290. {
  291. for (j = 0; j < N; j++)
  292. {
  293. C[i * N + j] = 0;
  294. for (k = 0; k < N; k++)
  295. {
  296. C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
  297. }
  298. }
  299. }
  300. }
  301. /* Function: matrix_mul_matrix_bitextract
  302. Multiply a matrix by a matrix, and extract some bits from the result.
  303. Basic code is used in many algorithms, mostly with minor changes such as
  304. scaling.
  305. */
  306. void
  307. matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
  308. {
  309. ee_u32 i, j, k;
  310. for (i = 0; i < N; i++)
  311. {
  312. for (j = 0; j < N; j++)
  313. {
  314. C[i * N + j] = 0;
  315. for (k = 0; k < N; k++)
  316. {
  317. MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
  318. C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7);
  319. }
  320. }
  321. }
  322. }