core_state.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. /* local functions */
  16. enum CORE_STATE core_state_transition(ee_u8 **instr, ee_u32 *transition_count);
  17. /*
  18. Topic: Description
  19. Simple state machines like this one are used in many embedded products.
  20. For more complex state machines, sometimes a state transition table
  21. implementation is used instead, trading speed of direct coding for ease of
  22. maintenance.
  23. Since the main goal of using a state machine in CoreMark is to excercise
  24. the switch/if behaviour, we are using a small moore machine.
  25. In particular, this machine tests type of string input,
  26. trying to determine whether the input is a number or something else.
  27. (see core_state.png).
  28. */
  29. /* Function: core_bench_state
  30. Benchmark function
  31. Go over the input twice, once direct, and once after introducing some
  32. corruption.
  33. */
  34. ee_u16
  35. core_bench_state(ee_u32 blksize,
  36. ee_u8 *memblock,
  37. ee_s16 seed1,
  38. ee_s16 seed2,
  39. ee_s16 step,
  40. ee_u16 crc)
  41. {
  42. ee_u32 final_counts[NUM_CORE_STATES];
  43. ee_u32 track_counts[NUM_CORE_STATES];
  44. ee_u8 *p = memblock;
  45. ee_u32 i;
  46. #if CORE_DEBUG
  47. ee_printf("State Bench: %d,%d,%d,%04x\n", seed1, seed2, step, crc);
  48. #endif
  49. for (i = 0; i < NUM_CORE_STATES; i++)
  50. {
  51. final_counts[i] = track_counts[i] = 0;
  52. }
  53. /* run the state machine over the input */
  54. while (*p != 0)
  55. {
  56. enum CORE_STATE fstate = core_state_transition(&p, track_counts);
  57. final_counts[fstate]++;
  58. #if CORE_DEBUG
  59. ee_printf("%d,", fstate);
  60. }
  61. ee_printf("\n");
  62. #else
  63. }
  64. #endif
  65. p = memblock;
  66. while (p < (memblock + blksize))
  67. { /* insert some corruption */
  68. if (*p != ',')
  69. *p ^= (ee_u8)seed1;
  70. p += step;
  71. }
  72. p = memblock;
  73. /* run the state machine over the input again */
  74. while (*p != 0)
  75. {
  76. enum CORE_STATE fstate = core_state_transition(&p, track_counts);
  77. final_counts[fstate]++;
  78. #if CORE_DEBUG
  79. ee_printf("%d,", fstate);
  80. }
  81. ee_printf("\n");
  82. #else
  83. }
  84. #endif
  85. p = memblock;
  86. while (p < (memblock + blksize))
  87. { /* undo corruption is seed1 and seed2 are equal */
  88. if (*p != ',')
  89. *p ^= (ee_u8)seed2;
  90. p += step;
  91. }
  92. /* end timing */
  93. for (i = 0; i < NUM_CORE_STATES; i++)
  94. {
  95. crc = crcu32(final_counts[i], crc);
  96. crc = crcu32(track_counts[i], crc);
  97. }
  98. return crc;
  99. }
  100. /* Default initialization patterns */
  101. static ee_u8 *intpat[4]
  102. = { (ee_u8 *)"5012", (ee_u8 *)"1234", (ee_u8 *)"-874", (ee_u8 *)"+122" };
  103. static ee_u8 *floatpat[4] = { (ee_u8 *)"35.54400",
  104. (ee_u8 *)".1234500",
  105. (ee_u8 *)"-110.700",
  106. (ee_u8 *)"+0.64400" };
  107. static ee_u8 *scipat[4] = { (ee_u8 *)"5.500e+3",
  108. (ee_u8 *)"-.123e-2",
  109. (ee_u8 *)"-87e+832",
  110. (ee_u8 *)"+0.6e-12" };
  111. static ee_u8 *errpat[4] = { (ee_u8 *)"T0.3e-1F",
  112. (ee_u8 *)"-T.T++Tq",
  113. (ee_u8 *)"1T3.4e4z",
  114. (ee_u8 *)"34.0e-T^" };
  115. /* Function: core_init_state
  116. Initialize the input data for the state machine.
  117. Populate the input with several predetermined strings, interspersed.
  118. Actual patterns chosen depend on the seed parameter.
  119. Note:
  120. The seed parameter MUST be supplied from a source that cannot be
  121. determined at compile time
  122. */
  123. void
  124. core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p)
  125. {
  126. ee_u32 total = 0, next = 0, i;
  127. ee_u8 *buf = 0;
  128. #if CORE_DEBUG
  129. ee_u8 *start = p;
  130. ee_printf("State: %d,%d\n", size, seed);
  131. #endif
  132. size--;
  133. next = 0;
  134. while ((total + next + 1) < size)
  135. {
  136. if (next > 0)
  137. {
  138. for (i = 0; i < next; i++)
  139. *(p + total + i) = buf[i];
  140. *(p + total + i) = ',';
  141. total += next + 1;
  142. }
  143. seed++;
  144. switch (seed & 0x7)
  145. {
  146. case 0: /* int */
  147. case 1: /* int */
  148. case 2: /* int */
  149. buf = intpat[(seed >> 3) & 0x3];
  150. next = 4;
  151. break;
  152. case 3: /* float */
  153. case 4: /* float */
  154. buf = floatpat[(seed >> 3) & 0x3];
  155. next = 8;
  156. break;
  157. case 5: /* scientific */
  158. case 6: /* scientific */
  159. buf = scipat[(seed >> 3) & 0x3];
  160. next = 8;
  161. break;
  162. case 7: /* invalid */
  163. buf = errpat[(seed >> 3) & 0x3];
  164. next = 8;
  165. break;
  166. default: /* Never happen, just to make some compilers happy */
  167. break;
  168. }
  169. }
  170. size++;
  171. while (total < size)
  172. { /* fill the rest with 0 */
  173. *(p + total) = 0;
  174. total++;
  175. }
  176. #if CORE_DEBUG
  177. ee_printf("State Input: %s\n", start);
  178. #endif
  179. }
  180. static ee_u8
  181. ee_isdigit(ee_u8 c)
  182. {
  183. ee_u8 retval;
  184. retval = ((c >= '0') & (c <= '9')) ? 1 : 0;
  185. return retval;
  186. }
  187. /* Function: core_state_transition
  188. Actual state machine.
  189. The state machine will continue scanning until either:
  190. 1 - an invalid input is detected.
  191. 2 - a valid number has been detected.
  192. The input pointer is updated to point to the end of the token, and the
  193. end state is returned (either specific format determined or invalid).
  194. */
  195. enum CORE_STATE
  196. core_state_transition(ee_u8 **instr, ee_u32 *transition_count)
  197. {
  198. ee_u8 * str = *instr;
  199. ee_u8 NEXT_SYMBOL;
  200. enum CORE_STATE state = CORE_START;
  201. for (; *str && state != CORE_INVALID; str++)
  202. {
  203. NEXT_SYMBOL = *str;
  204. if (NEXT_SYMBOL == ',') /* end of this input */
  205. {
  206. str++;
  207. break;
  208. }
  209. switch (state)
  210. {
  211. case CORE_START:
  212. if (ee_isdigit(NEXT_SYMBOL))
  213. {
  214. state = CORE_INT;
  215. }
  216. else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-')
  217. {
  218. state = CORE_S1;
  219. }
  220. else if (NEXT_SYMBOL == '.')
  221. {
  222. state = CORE_FLOAT;
  223. }
  224. else
  225. {
  226. state = CORE_INVALID;
  227. transition_count[CORE_INVALID]++;
  228. }
  229. transition_count[CORE_START]++;
  230. break;
  231. case CORE_S1:
  232. if (ee_isdigit(NEXT_SYMBOL))
  233. {
  234. state = CORE_INT;
  235. transition_count[CORE_S1]++;
  236. }
  237. else if (NEXT_SYMBOL == '.')
  238. {
  239. state = CORE_FLOAT;
  240. transition_count[CORE_S1]++;
  241. }
  242. else
  243. {
  244. state = CORE_INVALID;
  245. transition_count[CORE_S1]++;
  246. }
  247. break;
  248. case CORE_INT:
  249. if (NEXT_SYMBOL == '.')
  250. {
  251. state = CORE_FLOAT;
  252. transition_count[CORE_INT]++;
  253. }
  254. else if (!ee_isdigit(NEXT_SYMBOL))
  255. {
  256. state = CORE_INVALID;
  257. transition_count[CORE_INT]++;
  258. }
  259. break;
  260. case CORE_FLOAT:
  261. if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e')
  262. {
  263. state = CORE_S2;
  264. transition_count[CORE_FLOAT]++;
  265. }
  266. else if (!ee_isdigit(NEXT_SYMBOL))
  267. {
  268. state = CORE_INVALID;
  269. transition_count[CORE_FLOAT]++;
  270. }
  271. break;
  272. case CORE_S2:
  273. if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-')
  274. {
  275. state = CORE_EXPONENT;
  276. transition_count[CORE_S2]++;
  277. }
  278. else
  279. {
  280. state = CORE_INVALID;
  281. transition_count[CORE_S2]++;
  282. }
  283. break;
  284. case CORE_EXPONENT:
  285. if (ee_isdigit(NEXT_SYMBOL))
  286. {
  287. state = CORE_SCIENTIFIC;
  288. transition_count[CORE_EXPONENT]++;
  289. }
  290. else
  291. {
  292. state = CORE_INVALID;
  293. transition_count[CORE_EXPONENT]++;
  294. }
  295. break;
  296. case CORE_SCIENTIFIC:
  297. if (!ee_isdigit(NEXT_SYMBOL))
  298. {
  299. state = CORE_INVALID;
  300. transition_count[CORE_INVALID]++;
  301. }
  302. break;
  303. default:
  304. break;
  305. }
  306. }
  307. *instr = str;
  308. return state;
  309. }