IORunner.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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 <cstdlib>
  35. #include <cstdio>
  36. #include "IORunner.h"
  37. #include "Error.h"
  38. #include "Timing.h"
  39. #include "arm_math_types.h"
  40. #include "Calibrate.h"
  41. #ifdef CORTEXA
  42. #define CALIBNB 1
  43. #else
  44. #define CALIBNB 20
  45. #endif
  46. using namespace std;
  47. namespace Client
  48. {
  49. IORunner::IORunner(IO *io,PatternMgr *mgr, Testing::RunningMode runningMode):m_io(io), m_mgr(mgr)
  50. {
  51. volatile Testing::cycles_t current;
  52. this->m_runningMode = runningMode;
  53. // Set running mode on PatternMgr.
  54. if (runningMode == Testing::kDumpOnly)
  55. {
  56. mgr->setDumpMode();
  57. }
  58. if (runningMode == Testing::kTestAndDump)
  59. {
  60. mgr->setTestAndDumpMode();
  61. }
  62. initCycleMeasurement();
  63. /*
  64. For calibration :
  65. Calibration means, in this context, removing the overhad of calling
  66. a C++ function pointer from the cycle measurements.
  67. */
  68. Calibrate c((Testing::testID_t)0);
  69. Client::Suite *s=(Client::Suite *)&c;
  70. Client::test t = (Client::test)&Calibrate::empty;
  71. calibration = 0;
  72. /*
  73. For calibration, we measure the time it takes to call 20 times an empty benchmark and compute
  74. the average.
  75. (20 is an arbitrary value.)
  76. This overhead is removed from benchmarks in the Runner..
  77. Calibration is removed from the python script when external trace is used for the cycles.
  78. Indeed, in that case the calibration value can only be measured by parsing the trace.
  79. Otherwise, the calibration is measured below.
  80. */
  81. /*
  82. We want to ensure that the calibration of the overhead of the
  83. measurement is the same here and when we do the measurement later.
  84. So to ensure the conditions are always the same, the instruction cache
  85. and branch predictor are flushed.
  86. */
  87. #ifdef CORTEXA
  88. __set_BPIALL(0);
  89. __DSB();
  90. __ISB();
  91. __set_ICIALLU(0);
  92. __DSB();
  93. __ISB();
  94. #endif
  95. /*
  96. We always call the empty function once to ensure it is in the cache
  97. because it is how the measurement is done.
  98. */
  99. if (!m_mgr->HasMemError())
  100. {
  101. (s->*t)();
  102. }
  103. /*
  104. We measure the cycles required for a measurement,
  105. The cycleMeasurement starts, getCycles and cycleMeasurementStop
  106. should not be in the cache.
  107. So, for the overhead we always have the value corresponding to
  108. the code not in cache.
  109. While for the code itself we have the value for the code in cache.
  110. */
  111. /*
  112. EXTBENCH is set when benchmarking is done through external traces
  113. instead of using internal counters.
  114. Currently the post-processing scripts are only supporting traces generated from
  115. fast models.
  116. */
  117. #if defined(EXTBENCH) || defined(CACHEANALYSIS)
  118. startSection();
  119. #endif
  120. for(int i=0;i < CALIBNB;i++)
  121. {
  122. cycleMeasurementStart();
  123. if (!m_mgr->HasMemError())
  124. {
  125. (s->*t)();
  126. }
  127. #ifndef EXTBENCH
  128. current = getCycles();
  129. #endif
  130. calibration += current;
  131. cycleMeasurementStop();
  132. }
  133. #if defined(EXTBENCH) || defined(CACHEANALYSIS)
  134. stopSection();
  135. #endif
  136. #ifndef EXTBENCH
  137. calibration=calibration / CALIBNB;
  138. #endif
  139. }
  140. // Testing.
  141. // When false we are in dump mode and the failed assertion are ignored
  142. // (But exception is taken so assert should be at end of the test and not in the
  143. // middle )
  144. IORunner::IORunner(IO *io,PatternMgr *mgr):m_io(io), m_mgr(mgr)
  145. {
  146. this->m_runningMode = Testing::kTestOnly;
  147. }
  148. IORunner::~IORunner()
  149. {
  150. }
  151. /** Read driver data to control execution of a suite
  152. */
  153. Testing::TestStatus IORunner::run(Suite *s)
  154. {
  155. Testing::TestStatus finalResult = Testing::kTestPassed;
  156. int nbTests = s->getNbTests();
  157. int failedTests=0;
  158. Testing::errorID_t error=0;
  159. unsigned long line = 0;
  160. char details[200];
  161. volatile Testing::cycles_t cycles=0;
  162. Testing::nbParameters_t nbParams;
  163. // Read node identification (suite)
  164. m_io->ReadIdentification();
  165. // Read suite nb of parameters
  166. nbParams = m_io->ReadNbParameters();
  167. // Read list of patterns
  168. m_io->ReadPatternList();
  169. // Read list of output
  170. m_io->ReadOutputList();
  171. // Read list of parameters
  172. m_io->ReadParameterList(nbParams);
  173. // Iterate on tests
  174. for(int i=1; i <= nbTests; i++)
  175. {
  176. test t = s->getTest(i);
  177. Testing::TestStatus result = Testing::kTestPassed;
  178. error = UNKNOWN_ERROR;
  179. line = 0;
  180. cycles = 0;
  181. details[0]='\0';
  182. Testing::param_t *paramData=NULL;
  183. Testing::nbParameterEntries_t entries=0;
  184. std::vector<Testing::param_t> params(nbParams);
  185. bool canExecute=true;
  186. unsigned long dataIndex=0;
  187. Testing::ParameterKind paramKind;
  188. // Read test identification (test ID)
  189. m_io->ReadTestIdentification();
  190. if (m_io->hasParam())
  191. {
  192. Testing::PatternID_t paramID=m_io->getParamID();
  193. paramData = m_io->ImportParams(paramID,entries,paramKind);
  194. dataIndex = 0;
  195. }
  196. while(canExecute)
  197. {
  198. canExecute = false;
  199. if (m_io->hasParam() && paramData)
  200. {
  201. // Load new params
  202. for(unsigned long j=0; j < nbParams ; j++)
  203. {
  204. params[j] = paramData[nbParams*dataIndex+j];
  205. }
  206. // Update condition for new execution
  207. dataIndex += 1;
  208. canExecute = dataIndex < entries;
  209. }
  210. // Execute test
  211. try {
  212. // Prepare memory for test
  213. // setUp will generally load patterns
  214. // and do specific initialization for the tests
  215. s->setUp(m_io->CurrentTestID(),params,m_mgr);
  216. // Run the test once to force the code to be in cache.
  217. // By default it is disabled in the suite.
  218. #ifdef CORTEXA
  219. __set_BPIALL(0);
  220. __DSB();
  221. __ISB();
  222. __set_ICIALLU(0);
  223. __DSB();
  224. __ISB();
  225. #endif
  226. /* If cache analysis mode, we don't force the code to be in cache. */
  227. #if !defined(CACHEANALYSIS)
  228. if (s->isForcedInCache())
  229. {
  230. if (!m_mgr->HasMemError())
  231. {
  232. (s->*t)();
  233. }
  234. }
  235. #endif
  236. // Run the test
  237. cycleMeasurementStart();
  238. #if defined(EXTBENCH) || defined(CACHEANALYSIS)
  239. startSection();
  240. #endif
  241. if (!m_mgr->HasMemError())
  242. {
  243. (s->*t)();
  244. }
  245. #if defined(EXTBENCH) || defined(CACHEANALYSIS)
  246. stopSection();
  247. #endif
  248. #ifndef EXTBENCH
  249. cycles=getCycles();
  250. cycles=cycles-calibration;
  251. #endif
  252. cycleMeasurementStop();
  253. }
  254. catch(Error &ex)
  255. {
  256. cycleMeasurementStop();
  257. // In dump only mode we ignore the tests
  258. // since the reference patterns are not loaded
  259. // so tests will fail.
  260. if (this->m_runningMode != Testing::kDumpOnly)
  261. {
  262. error = ex.errorID;
  263. line = ex.lineNumber;
  264. strcpy(details,ex.details);
  265. result=Testing::kTestFailed;
  266. }
  267. }
  268. catch (...) {
  269. cycleMeasurementStop();
  270. // In dump only mode we ignore the tests
  271. // since the reference patterns are not loaded
  272. // so tests will fail.
  273. if (this->m_runningMode != Testing::kDumpOnly)
  274. {
  275. result = Testing::kTestFailed;
  276. error = UNKNOWN_ERROR;
  277. line = 0;
  278. }
  279. }
  280. try {
  281. // Clean memory after this test
  282. // May dump output and do specific cleaning for a test
  283. s->tearDown(m_io->CurrentTestID(),m_mgr);
  284. }
  285. catch(...)
  286. {
  287. }
  288. if (m_mgr->HasMemError())
  289. {
  290. /* We keep the current error if set.
  291. */
  292. if (result == Testing::kTestPassed)
  293. {
  294. result = Testing::kTestFailed;
  295. error = MEMORY_ALLOCATION_ERROR;
  296. line = 0;
  297. }
  298. }
  299. // Free all memory of memory manager so that next test
  300. // is starting in a clean and controlled tests
  301. m_mgr->freeAll();
  302. // Dump test status to output
  303. m_io->DispStatus(result,error,line,cycles);
  304. m_io->DispErrorDetails(details);
  305. m_io->DumpParams(params);
  306. }
  307. if (paramData)
  308. {
  309. if (paramKind == Testing::kDynamicBuffer)
  310. {
  311. free(paramData);
  312. }
  313. paramData = NULL;
  314. }
  315. if (result == Testing::kTestFailed)
  316. {
  317. failedTests ++;
  318. finalResult = Testing::kTestFailed;
  319. }
  320. }
  321. // Signal end of group processing to output
  322. m_io->EndGroup();
  323. return(finalResult);
  324. }
  325. /** Read driver data to control execution of a group
  326. */
  327. Testing::TestStatus IORunner::run(Group *g)
  328. {
  329. int nbTests = g->getNbContainer();
  330. int failedTests=0;
  331. // Read Node identification
  332. m_io->ReadIdentification();
  333. Testing::TestStatus finalResult = Testing::kTestPassed;
  334. // Iterate on group elements
  335. for(int i=1; i <= nbTests; i++)
  336. {
  337. TestContainer *c = g->getContainer(i);
  338. if (c != NULL)
  339. {
  340. // Execute runner for this group
  341. Testing::TestStatus result = c->accept(this);
  342. if (result == Testing::kTestFailed)
  343. {
  344. failedTests ++;
  345. finalResult = Testing::kTestFailed;
  346. }
  347. }
  348. }
  349. // Signal to output that processing of this group has finished.
  350. m_io->EndGroup();
  351. return(finalResult);
  352. }
  353. }