IORunner.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: IORunner.cpp
  4. * Description: IORunner
  5. *
  6. * Runner implementation for runner running on device
  7. * under test
  8. *
  9. * $Date: 20. June 2019
  10. * $Revision: V1.0.0
  11. *
  12. * Target Processor: Cortex-M cores
  13. * -------------------------------------------------------------------- */
  14. /*
  15. * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
  16. *
  17. * SPDX-License-Identifier: Apache-2.0
  18. *
  19. * Licensed under the Apache License, Version 2.0 (the License); you may
  20. * not use this file except in compliance with the License.
  21. * You may obtain a copy of the License at
  22. *
  23. * www.apache.org/licenses/LICENSE-2.0
  24. *
  25. * Unless required by applicable law or agreed to in writing, software
  26. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  27. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  28. * See the License for the specific language governing permissions and
  29. * limitations under the License.
  30. */
  31. #include "Test.h"
  32. #include <string>
  33. #include <cstddef>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include "IORunner.h"
  37. #include "Error.h"
  38. #include "Timing.h"
  39. #include "arm_math.h"
  40. #include "Calibrate.h"
  41. namespace Client
  42. {
  43. IORunner::IORunner(IO *io,PatternMgr *mgr, Testing::RunningMode runningMode):m_io(io), m_mgr(mgr)
  44. {
  45. this->m_runningMode = runningMode;
  46. // Set running mode on PatternMgr.
  47. if (runningMode == Testing::kDumpOnly)
  48. {
  49. mgr->setDumpMode();
  50. }
  51. if (runningMode == Testing::kTestAndDump)
  52. {
  53. mgr->setTestAndDumpMode();
  54. }
  55. initCycleMeasurement();
  56. /*
  57. For calibration :
  58. Calibration means, in this context, removing the overhad of calling
  59. a C++ function pointer from the cycle measurements.
  60. */
  61. Calibrate c((Testing::testID_t)0);
  62. Client::Suite *s=(Client::Suite *)&c;
  63. Client::test t = (Client::test)&Calibrate::empty;
  64. cycleMeasurementStart();
  65. /*
  66. EXTBENCH is set when benchmarking is done through external traces
  67. instead of using internal counters.
  68. Currently the post-processing scripts are only supporting traces generated from
  69. fast models.
  70. */
  71. #ifdef EXTBENCH
  72. startSection();
  73. #endif
  74. /*
  75. For calibration, we measure the time it takes to call 20 times an empty benchmark and compute
  76. the average.
  77. (20 is an arbitrary value.)
  78. This overhead is removed from benchmarks in the Runner..
  79. Calibration is removed from the python script when external trace is used for the cycles.
  80. Indeed, in that case the calibration value can only be measured by parsing the trace.
  81. Otherwise, the calibration is measured below.
  82. */
  83. for(int i=0;i < 20;i++)
  84. {
  85. if (!m_mgr->HasMemError())
  86. {
  87. (s->*t)();
  88. }
  89. }
  90. #ifdef EXTBENCH
  91. stopSection();
  92. #endif
  93. #ifndef EXTBENCH
  94. calibration=getCycles() / 20;
  95. #endif
  96. cycleMeasurementStop();
  97. }
  98. // Testing.
  99. // When false we are in dump mode and the failed assertion are ignored
  100. // (But exception is taken so assert should be at end of the test and not in the
  101. // middle )
  102. IORunner::IORunner(IO *io,PatternMgr *mgr):m_io(io), m_mgr(mgr)
  103. {
  104. this->m_runningMode = Testing::kTestOnly;
  105. }
  106. IORunner::~IORunner()
  107. {
  108. }
  109. /** Read driver data to control execution of a suite
  110. */
  111. Testing::TestStatus IORunner::run(Suite *s)
  112. {
  113. Testing::TestStatus finalResult = Testing::kTestPassed;
  114. int nbTests = s->getNbTests();
  115. int failedTests=0;
  116. Testing::errorID_t error=0;
  117. unsigned long line = 0;
  118. char details[200];
  119. Testing::cycles_t cycles=0;
  120. Testing::nbParameters_t nbParams;
  121. // Read node identification (suite)
  122. m_io->ReadIdentification();
  123. // Read suite nb of parameters
  124. nbParams = m_io->ReadNbParameters();
  125. // Read list of patterns
  126. m_io->ReadPatternList();
  127. // Read list of output
  128. m_io->ReadOutputList();
  129. // Read list of parameters
  130. m_io->ReadParameterList(nbParams);
  131. // Iterate on tests
  132. for(int i=1; i <= nbTests; i++)
  133. {
  134. test t = s->getTest(i);
  135. Testing::TestStatus result = Testing::kTestPassed;
  136. error = UNKNOWN_ERROR;
  137. line = 0;
  138. cycles = 0;
  139. details[0]='\0';
  140. Testing::param_t *paramData=NULL;
  141. Testing::nbParameterEntries_t entries=0;
  142. std::vector<Testing::param_t> params(nbParams);
  143. bool canExecute=true;
  144. int dataIndex=0;
  145. Testing::ParameterKind paramKind;
  146. // Read test identification (test ID)
  147. m_io->ReadTestIdentification();
  148. if (m_io->hasParam())
  149. {
  150. Testing::PatternID_t paramID=m_io->getParamID();
  151. paramData = m_io->ImportParams(paramID,entries,paramKind);
  152. dataIndex = 0;
  153. }
  154. while(canExecute)
  155. {
  156. canExecute = false;
  157. if (m_io->hasParam() && paramData)
  158. {
  159. // Load new params
  160. for(int j=0; j < nbParams ; j++)
  161. {
  162. params[j] = paramData[nbParams*dataIndex+j];
  163. }
  164. // Update condition for new execution
  165. dataIndex += 1;
  166. canExecute = dataIndex < entries;
  167. }
  168. // Execute test
  169. try {
  170. // Prepare memory for test
  171. // setUp will generally load patterns
  172. // and do specific initialization for the tests
  173. s->setUp(m_io->CurrentTestID(),params,m_mgr);
  174. // Run the test
  175. cycleMeasurementStart();
  176. #ifdef EXTBENCH
  177. startSection();
  178. #endif
  179. if (!m_mgr->HasMemError())
  180. {
  181. (s->*t)();
  182. }
  183. #ifdef EXTBENCH
  184. stopSection();
  185. #endif
  186. #ifndef EXTBENCH
  187. cycles=getCycles()-calibration;
  188. #endif
  189. cycleMeasurementStop();
  190. }
  191. catch(Error &ex)
  192. {
  193. cycleMeasurementStop();
  194. // In dump only mode we ignore the tests
  195. // since the reference patterns are not loaded
  196. // so tests will fail.
  197. if (this->m_runningMode != Testing::kDumpOnly)
  198. {
  199. error = ex.errorID;
  200. line = ex.lineNumber;
  201. strcpy(details,ex.details);
  202. result=Testing::kTestFailed;
  203. }
  204. }
  205. catch (...) {
  206. cycleMeasurementStop();
  207. // In dump only mode we ignore the tests
  208. // since the reference patterns are not loaded
  209. // so tests will fail.
  210. if (this->m_runningMode != Testing::kDumpOnly)
  211. {
  212. result = Testing::kTestFailed;
  213. error = UNKNOWN_ERROR;
  214. line = 0;
  215. }
  216. }
  217. try {
  218. // Clean memory after this test
  219. // May dump output and do specific cleaning for a test
  220. s->tearDown(m_io->CurrentTestID(),m_mgr);
  221. }
  222. catch(...)
  223. {
  224. }
  225. if (m_mgr->HasMemError())
  226. {
  227. /* We keep the current error if set.
  228. */
  229. if (result == Testing::kTestPassed)
  230. {
  231. result = Testing::kTestFailed;
  232. error = MEMORY_ALLOCATION_ERROR;
  233. line = 0;
  234. }
  235. }
  236. // Free all memory of memory manager so that next test
  237. // is starting in a clean and controlled tests
  238. m_mgr->freeAll();
  239. // Dump test status to output
  240. m_io->DispStatus(result,error,line,cycles);
  241. m_io->DispErrorDetails(details);
  242. m_io->DumpParams(params);
  243. }
  244. if (paramData)
  245. {
  246. if (paramKind == Testing::kDynamicBuffer)
  247. {
  248. free(paramData);
  249. }
  250. paramData = NULL;
  251. }
  252. if (result == Testing::kTestFailed)
  253. {
  254. failedTests ++;
  255. finalResult = Testing::kTestFailed;
  256. }
  257. }
  258. // Signal end of group processing to output
  259. m_io->EndGroup();
  260. return(finalResult);
  261. }
  262. /** Read driver data to control execution of a group
  263. */
  264. Testing::TestStatus IORunner::run(Group *g)
  265. {
  266. int nbTests = g->getNbContainer();
  267. int failedTests=0;
  268. // Read Node identification
  269. m_io->ReadIdentification();
  270. Testing::TestStatus finalResult = Testing::kTestPassed;
  271. // Iterate on group elements
  272. for(int i=1; i <= nbTests; i++)
  273. {
  274. TestContainer *c = g->getContainer(i);
  275. if (c != NULL)
  276. {
  277. // Execute runner for this group
  278. Testing::TestStatus result = c->accept(this);
  279. if (result == Testing::kTestFailed)
  280. {
  281. failedTests ++;
  282. finalResult = Testing::kTestFailed;
  283. }
  284. }
  285. }
  286. // Signal to output that processing of this group has finished.
  287. m_io->EndGroup();
  288. return(finalResult);
  289. }
  290. }