Test.h 20 KB

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