Test.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: Test.h
  4. * Description: Test Framework Header
  5. *
  6. * $Date: 20. June 2019
  7. * $Revision: V1.0.0
  8. *
  9. * Target Processor: Cortex-M cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #ifndef _TEST_H_
  29. #define _TEST_H_
  30. #include <cstdlib>
  31. #include <vector>
  32. #include <queue>
  33. #include <cstdio>
  34. #include "arm_math.h"
  35. #include "arm_math_f16.h"
  36. // This special value means no limit on the number of samples.
  37. // It is used when importing patterns and we want to read
  38. // all the samples contained in the pattern.
  39. #define MAX_NB_SAMPLES 0
  40. // Pattern files are containing hexadecimal values.
  41. // So we need to be able to convert some int into float without convertion
  42. #define TOINT16(v) *((uint16_t*)&v)
  43. #define TOINT32(v) *((uint32_t*)&v)
  44. #define TOINT64(v) *((uint64_t*)&v)
  45. // Or convert some float into a uint32 or uint64 without convertion
  46. #define TOTYP(TYP,v) *((TYP*)&v)
  47. // So it is a cast and not a data conversion.
  48. // (uint32_t)1.0 would give 1. We want the hexadecimal representation of the float.
  49. // TOINT32(1.0) can be used
  50. namespace Testing
  51. {
  52. enum TestStatus
  53. {
  54. kTestFailed=0,
  55. kTestPassed=1
  56. };
  57. /* In Dump only, reference patterns are never read.
  58. So tests are failing
  59. and we dump output.
  60. In this mode we are only interested in the output data and
  61. not the test status.
  62. In test only mode, no output is dumped.
  63. */
  64. enum RunningMode
  65. {
  66. kTestOnly=0,
  67. kDumpOnly=1,
  68. kTestAndDump=2
  69. };
  70. // test ID are ID of nodes in the tree of tests.
  71. // So a group ID, suite ID or test ID all have the same type
  72. // testID_t
  73. typedef unsigned long testID_t;
  74. typedef unsigned long outputID_t;
  75. typedef unsigned long PatternID_t;
  76. typedef unsigned long testIndex_t;
  77. typedef unsigned long nbSamples_t;
  78. typedef unsigned long errorID_t;
  79. typedef uint32_t cycles_t;
  80. typedef unsigned long nbMeasurements_t;
  81. // parameter value
  82. // (always int since we need to be able to iterate on
  83. // different parameter values which are often dimensions of
  84. // input data)
  85. typedef int param_t;
  86. // Number of parameters for a given configuration
  87. typedef unsigned long nbParameters_t;
  88. // Number of parameter configurations
  89. typedef unsigned long nbParameterEntries_t;
  90. // To know if parameter array is malloc buffer or static buffer in C array
  91. enum ParameterKind
  92. {
  93. kStaticBuffer=0,
  94. kDynamicBuffer=1,
  95. };
  96. }
  97. namespace Client
  98. {
  99. /*
  100. Client code
  101. */
  102. class Suite;
  103. class Group;
  104. // Type of a test function
  105. // It is not a function pointer (because the function is
  106. // a method of a CPP class)
  107. typedef void (Suite::*test)();
  108. /*
  109. API of Memory managers used in the test framework
  110. */
  111. class Memory
  112. {
  113. public:
  114. // Allocate a new buffer of size length
  115. // and generate a pointer to this buffer.
  116. // It does not imply that any malloc is done.
  117. // It depends on how the Memory manager is implemented.
  118. virtual char *NewBuffer(size_t length)=0;
  119. // Free all the memory allocated by the memory manager
  120. // and increment the memory generation number.
  121. virtual void FreeMemory()=0;
  122. // Memory allocation errors must be tracked during a test.
  123. // The runner should force the test status to FAILED
  124. // when a memory error occured.
  125. virtual bool HasMemError()=0;
  126. // When memory manager is supporting tail
  127. // then we can check that the tail of the buffer has not been
  128. // corrupted.
  129. // The tail being the additional words after the end of the buffer allocated
  130. // by the memory manager so that there is some seperation between
  131. // successive buffers.
  132. // When memory manager is not supporting tail, this function should
  133. // always succeed.
  134. virtual bool IsTailEmpty(char *, size_t)=0;
  135. // Get the memory generation number
  136. unsigned long generation()
  137. {
  138. return(m_generation);
  139. }
  140. protected:
  141. unsigned long m_generation=0;
  142. };
  143. // A runner is a class driving the tests
  144. // It can use information from driving files
  145. // or in the future could communicate with a process
  146. // on a host computer which would be the real driver of the
  147. // testing.
  148. // It is following the visitor pattern. IT is the reason for an accept
  149. // function in Group class.
  150. // Run is the visitor
  151. class Runner
  152. {
  153. public:
  154. virtual Testing::TestStatus run(Suite*) = 0;
  155. virtual Testing::TestStatus run(Group*) = 0;
  156. };
  157. // Abstract the IO needs of the test framework.
  158. // IO could be done from semihosting, socket, C array in memory etc ...
  159. class IO
  160. {
  161. public:
  162. /** Read the identification of a node from driver data.
  163. Update the node kind and node id and local folder.
  164. To be used for group and suite. Generally update
  165. the path to the folder by using this new local folder
  166. which is appended to the path.
  167. */
  168. virtual void ReadIdentification()=0;
  169. /** Read the identification of a node driver data.
  170. Update the node kind and node id and local folder.
  171. */
  172. virtual void ReadTestIdentification()=0;
  173. /** Read the number of parameters for all the tests in a suite
  174. Used for benchmarking. Same functions executed with
  175. different initializations controlled by the parameters.
  176. */
  177. virtual Testing::nbParameters_t ReadNbParameters()=0;
  178. /** Dump the test status
  179. For format of output, refer to Python script.
  180. The format must be coherent with the Python script
  181. parsing the output.
  182. */
  183. virtual void DispStatus(Testing::TestStatus,Testing::errorID_t,unsigned long,Testing::cycles_t cycles)=0;
  184. /** Dump additional details for the error
  185. For instance, for SNR error, it may contain the SNR value.
  186. */
  187. virtual void DispErrorDetails(const char* )=0;
  188. /** Dump parameters for a test
  189. When a test is run several time with different
  190. parameters for benchmarking,
  191. the parameters are displayed after test status.
  192. Line should begin with b
  193. */
  194. virtual void DumpParams(std::vector<Testing::param_t>&)=0;
  195. /** Dump an end of group/suite to output
  196. Used by Python script parsing the output.
  197. */
  198. virtual void EndGroup()=0;
  199. /** Get the zize of a pattern in this suite.
  200. Pattern is identified with an ID.
  201. Using the local path and ID, the IO implementatiom should
  202. be able to access the pattern.
  203. The path do not have to be a file path. Just a way
  204. to identify patterns in a suite and know
  205. how to access them.
  206. */
  207. virtual Testing::nbSamples_t GetPatternSize(Testing::PatternID_t)=0;
  208. /** Get the size of a parameter pattern in this suite.
  209. Parameter is identified with an ID.
  210. Using the local path and ID, the IO implementatiom should
  211. be able to access the data.
  212. The path do not have to be a file path. Just a way
  213. to identify data in a suite and know
  214. how to access them.
  215. */
  216. //virtual Testing::nbSamples_t GetParameterSize(Testing::PatternID_t id)=0;
  217. /** Check if some parameters are controlling this test
  218. */
  219. virtual bool hasParam()=0;
  220. /** Get ID of parameter generator
  221. */
  222. virtual Testing::PatternID_t getParamID()=0;
  223. /** Import pattern.
  224. The nb field can be used to limit the number of samples read
  225. to a smaller value than the number of samples available in the
  226. pattern.
  227. */
  228. virtual void ImportPattern_f64(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  229. virtual void ImportPattern_f32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  230. #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
  231. virtual void ImportPattern_f16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  232. #endif
  233. virtual void ImportPattern_q63(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  234. virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  235. virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  236. virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  237. virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  238. virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  239. virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  240. /** Import params.
  241. This is allocating memory.
  242. The runner should free it after use.
  243. It is not using the Memory manager since tests don't have access
  244. to the array of parameters.
  245. They receive parameters as a vector argument for the setUp fucntion.
  246. */
  247. virtual Testing::param_t* ImportParams(Testing::PatternID_t,Testing::nbParameterEntries_t &,Testing::ParameterKind &)=0;
  248. /** Dump pattern.
  249. The output ID (and test ID) must be used to uniquely identify
  250. the dump.
  251. */
  252. virtual void DumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t nb, float64_t*)=0;
  253. virtual void DumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t nb, float32_t*)=0;
  254. #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
  255. virtual void DumpPattern_f16(Testing::outputID_t,Testing::nbSamples_t nb, float16_t*)=0;
  256. #endif
  257. virtual void DumpPattern_q63(Testing::outputID_t,Testing::nbSamples_t nb, q63_t*)=0;
  258. virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t*)=0;
  259. virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t*)=0;
  260. virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t*)=0;
  261. virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t*)=0;
  262. virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t*)=0;
  263. virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t*)=0;
  264. /** Import list of patterns from the driver
  265. for current suite.
  266. This list is used to identify a pattern from its pattern ID.
  267. The information of this list (local to the suite) is
  268. combined with the path to identify patterns in other part of the class.
  269. */
  270. virtual void ReadPatternList()=0;
  271. /** Import list of output from the driver
  272. for current suite.
  273. This list is used to identify an output from its pattern ID (and current test ID)
  274. The information of this list (local to the suite) is
  275. combined with the path and current test ID
  276. to identify output in other part of the class.
  277. */
  278. virtual void ReadOutputList()=0;
  279. /** Import list of parameters from the driver
  280. for current suite.
  281. This list is used to control a functions with different parameters
  282. for benchmarking purpose.
  283. A parameter can be a file of parameters or a generator
  284. of parameters (cartesian product of lists only).
  285. */
  286. virtual void ReadParameterList(Testing::nbParameters_t)=0;
  287. /** Get current node ID
  288. group, suite or test. A group of test is considered as a test hence
  289. the name of the function.
  290. */
  291. virtual Testing::testID_t CurrentTestID()=0;
  292. };
  293. // A pattern manager is making the link between
  294. // IO and the Memory manager.
  295. // It knows how to import patterns into memory or dump
  296. // memory into outputs (output which may be different from a file)
  297. // The running mode is controlling if dumping is disabled or not.
  298. // But cna also be used by the runner to know if test results must be ignored or not.
  299. // Pattern manager is used by the tests
  300. // In current version load and dump functions are visible to any body.
  301. // In theory they should only be visible to Patterns
  302. class PatternMgr
  303. {
  304. public:
  305. PatternMgr(IO*,Memory*);
  306. /** In those loading APIs, nb samples is coming from the pattern read.
  307. maxSamples is coming from the test.
  308. A test does not know what is the length of a pattern since the test
  309. has no visiblity on how the pattern is imported (file, serial port, include files
  310. etc ...).
  311. So the test is specifying the max sampls it needs.
  312. The pattern is specifying its lengths.
  313. Those functions are importing at most what is needed and what is available.
  314. */
  315. float64_t *load_f64(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  316. float32_t *load_f32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  317. #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
  318. float16_t *load_f16(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  319. #endif
  320. q63_t *load_q63(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  321. q31_t *load_q31(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  322. q15_t *load_q15(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  323. q7_t *load_q7(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  324. uint32_t *load_u32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  325. uint16_t *load_u16(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  326. uint8_t *load_u8(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  327. /** Create a local pattern.
  328. Generally it is used as output of a test and has no
  329. correspondance to a pattern in the suite.
  330. */
  331. float64_t *local_f64(Testing::nbSamples_t);
  332. float32_t *local_f32(Testing::nbSamples_t);
  333. #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
  334. float16_t *local_f16(Testing::nbSamples_t);
  335. #endif
  336. q63_t *local_q63(Testing::nbSamples_t);
  337. q31_t *local_q31(Testing::nbSamples_t);
  338. q15_t *local_q15(Testing::nbSamples_t);
  339. q7_t *local_q7(Testing::nbSamples_t);
  340. uint32_t *local_u32(Testing::nbSamples_t);
  341. uint16_t *local_u16(Testing::nbSamples_t);
  342. uint8_t *local_u8(Testing::nbSamples_t);
  343. /** Dump a pattern
  344. */
  345. void dumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t,float64_t*);
  346. void dumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t,float32_t*);
  347. #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
  348. void dumpPattern_f16(Testing::outputID_t,Testing::nbSamples_t,float16_t*);
  349. #endif
  350. void dumpPattern_q63(Testing::outputID_t,Testing::nbSamples_t,q63_t*);
  351. void dumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t,q31_t*);
  352. void dumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t,q15_t*);
  353. void dumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t,q7_t*);
  354. void dumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t,uint32_t*);
  355. void dumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t,uint16_t*);
  356. void dumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t,uint8_t*);
  357. /** Free all allocated patterns.
  358. Just wrapper around the memory manager free function.
  359. */
  360. void freeAll();
  361. /** MeMory manager generation
  362. */
  363. unsigned long generation()
  364. {
  365. return(m_mem->generation());
  366. }
  367. // Memory allocation errors must be tracked during a test.
  368. // The runner should force the test status to FAILED
  369. // when a memory error occured.
  370. bool HasMemError()
  371. {
  372. return(m_mem->HasMemError());
  373. }
  374. // Set by the runner when in dump mode
  375. void setDumpMode()
  376. {
  377. this->m_runningMode = Testing::kDumpOnly;
  378. }
  379. void setTestAndDumpMode()
  380. {
  381. this->m_runningMode = Testing::kTestAndDump;
  382. }
  383. Testing::RunningMode runningMode()
  384. {
  385. return(this->m_runningMode);
  386. }
  387. bool IsTailEmpty(char *ptr, size_t length)
  388. {
  389. return(m_mem->IsTailEmpty(ptr,length));
  390. }
  391. private:
  392. IO *m_io;
  393. Memory *m_mem;
  394. Testing::RunningMode m_runningMode=Testing::kTestOnly;
  395. };
  396. // TestContainer which is a node of the tree of tests
  397. class TestContainer
  398. {
  399. public:
  400. TestContainer(Testing::testID_t);
  401. // Used for implementing the visitor pattern.
  402. // The visitor pattern is allowing to implement
  403. // different Runner for a tree of tests.
  404. virtual Testing::TestStatus accept(Runner* v) = 0;
  405. protected:
  406. // Node ID (test ID)
  407. Testing::testID_t m_containerID;
  408. };
  409. // A suite object
  410. // It contains a list of tests
  411. // Methods to get a test from the test ID
  412. // Initialization and cleanup (setUp and tearDown) to be called
  413. // between each test.
  414. // Those functions are used by the Runner to execute the tests
  415. class Suite:public TestContainer
  416. {
  417. public:
  418. Suite(Testing::testID_t);
  419. // Prepare memory for a test
  420. // (Load input and reference patterns)
  421. virtual void setUp(Testing::testID_t,std::vector<Testing::param_t>&,PatternMgr *mgr)=0;
  422. // Clean memory after a test
  423. // Free all memory
  424. // DUmp outputs
  425. virtual void tearDown(Testing::testID_t,PatternMgr *mgr)=0;
  426. // Add a test to be run.
  427. void addTest(Testing::testID_t,test aTest);
  428. // Get a test from its index. Used by runner when iterating
  429. // on all the tests. Index is not the test ID.
  430. // It is the index in internal list of tests
  431. test getTest(Testing::testIndex_t);
  432. // Get number of test in this suite.
  433. // The suite is only containing the active tests
  434. // (deprecated tests are never generated by python scripts)
  435. int getNbTests();
  436. // Used for implementing the visitor pattern.
  437. // The visitor pattern is allowing to implement
  438. // different Runner for a tree of tests.
  439. virtual Testing::TestStatus accept(Runner* v) override
  440. {
  441. return(v->run(this));
  442. }
  443. // Check if, for benchmark, we want to run the code once
  444. // before benchmarking it, to force it to be in the I-cache.
  445. bool isForcedInCache();
  446. // Change the status of the forceInCache mode.
  447. void setForceInCache(bool);
  448. private:
  449. bool m_forcedInCache=false;
  450. // List of tests
  451. std::vector<test> m_tests;
  452. // List of tests IDs (since they are not contiguous
  453. // due to deprecation feature in python scripts)
  454. std::vector<Testing::testID_t> m_testIds;
  455. };
  456. // A group
  457. // It is possible to add subgroups to a group
  458. // and get a subgroup from its ID.
  459. class Group:public TestContainer
  460. {
  461. public:
  462. Group(Testing::testID_t);
  463. // Add a group or suite to this group.
  464. void addContainer(TestContainer*);
  465. // Get a container from its index. (index is not the node ID)
  466. TestContainer *getContainer(Testing::testIndex_t);
  467. // Get number of containers
  468. int getNbContainer();
  469. virtual Testing::TestStatus accept(Runner* v) override
  470. {
  471. return(v->run(this));
  472. }
  473. public:
  474. std::vector<TestContainer*> m_groups;
  475. };
  476. }
  477. #endif