core_feature_ecc.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. /*
  2. * Copyright (c) 2019 Nuclei Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. */
  16. #ifndef __CORE_FEATURE_ECC_H__
  17. #define __CORE_FEATURE_ECC_H__
  18. /*!
  19. * @file core_feature_ecc.h
  20. * @brief ECC feature API header file for Nuclei N/NX Core
  21. */
  22. /*
  23. * ECC Feature Configuration Macro:
  24. *
  25. * 1. __ECC_PRESENT: Define whether Error Correction Code (ECC) feature is present or not
  26. * * 0: Not present
  27. * * 1: Present
  28. * 2. __ICACHE_PRESENT: Define whether I-Cache Unit is present or not.
  29. * * 0: Not present
  30. * * 1: Present
  31. * 3. __DCACHE_PRESENT: Define whether D-Cache Unit is present or not.
  32. * * 0: Not present
  33. * * 1: Present
  34. * 4. __CCM_PRESENT: Define whether Nuclei Cache Control and Maintainence(CCM) Unit is present or not.
  35. * * 0: Not present
  36. * * 1: Present
  37. *
  38. */
  39. #ifdef __cplusplus
  40. extern "C" {
  41. #endif
  42. #include "core_feature_base.h"
  43. #if defined(__ECC_PRESENT) && (__ECC_PRESENT == 1)
  44. /**
  45. * \defgroup NMSIS_Core_ECC_Functions ECC Functions
  46. * \ingroup NMSIS_Core
  47. * \brief Functions that related to the ECC feature
  48. * \details
  49. * These functions provide access to the Error Correction Code (ECC) feature
  50. * available in Nuclei N/NX processor cores. ECC is a memory protection mechanism
  51. * that can detect and correct single-bit errors and detect double-bit errors in
  52. * memory systems such as caches and local memories.
  53. *
  54. * The ECC feature includes:
  55. * - Detection of ECC support in various memory components (I-Cache, D-Cache, ILM, DLM, TLB)
  56. * - Control functions to enable/disable ECC for different memory components
  57. * - Error injection capabilities for testing purposes
  58. * - Error detection and clearing functions for both single-bit and double-bit errors
  59. * - Configuration of ECC exception handling
  60. *
  61. * @{
  62. */
  63. /**
  64. * \brief Check if the core globally supports ECC
  65. * \details
  66. * This function reads the machine configuration info CSR
  67. * and checks if ECC is supported globally in the core.
  68. * \return 1 if ECC is globally supported, 0 otherwise
  69. */
  70. __STATIC_FORCEINLINE int32_t ECC_IsGlobalSupportECC(void)
  71. {
  72. CSR_MCFGINFO_Type mcfginfo;
  73. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  74. return mcfginfo.b.ecc;
  75. }
  76. /**
  77. * \brief Check if I-Cache supports ECC
  78. * \details
  79. * This function checks if both I-Cache and ECC are supported in the core.
  80. * \return 1 if I-Cache supports ECC, 0 otherwise
  81. */
  82. __STATIC_FORCEINLINE int32_t ECC_IsICacheSupportECC(void)
  83. {
  84. CSR_MCFGINFO_Type mcfginfo;
  85. CSR_MICFGINFO_Type micfginfo;
  86. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  87. micfginfo.d = __RV_CSR_READ(CSR_MICFG_INFO);
  88. return mcfginfo.b.icache && micfginfo.b.ecc;
  89. }
  90. /**
  91. * \brief Check if D-Cache supports ECC
  92. * \details
  93. * This function checks if both D-Cache and ECC are supported in the core.
  94. * \return 1 if D-Cache supports ECC, 0 otherwise
  95. */
  96. __STATIC_FORCEINLINE int32_t ECC_IsDCacheSupportECC(void)
  97. {
  98. CSR_MCFGINFO_Type mcfginfo;
  99. CSR_MDCFGINFO_Type mdcfginfo;
  100. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  101. mdcfginfo.d = __RV_CSR_READ(CSR_MDCFG_INFO);
  102. return mcfginfo.b.dcache && mdcfginfo.b.ecc;
  103. }
  104. /**
  105. * \brief Check if TLB supports ECC
  106. * \details
  107. * This function checks if both PLIC and TLB ECC are supported in the core.
  108. * Note: TLB is only present with MMU, and when PLIC is present, MMU will be present.
  109. * \return 1 if TLB supports ECC, 0 otherwise
  110. */
  111. __STATIC_FORCEINLINE int32_t ECC_IsTLBSupportECC(void)
  112. {
  113. CSR_MCFGINFO_Type mcfginfo;
  114. CSR_MTLBCFGINFO_Type mtlbcfginfo;
  115. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  116. mtlbcfginfo.d = __RV_CSR_READ(CSR_MTLBCFG_INFO);
  117. /* TLB only present with MMU, when PLIC present MMU will present */
  118. return mcfginfo.b.plic && mtlbcfginfo.b.ecc;
  119. }
  120. /**
  121. * \brief Check if ILM supports ECC
  122. * \details
  123. * This function checks if both ILM and ECC are supported in the core.
  124. * \return 1 if ILM supports ECC, 0 otherwise
  125. */
  126. __STATIC_FORCEINLINE int32_t ECC_IsILMSupportECC(void)
  127. {
  128. CSR_MCFGINFO_Type mcfginfo;
  129. CSR_MICFGINFO_Type micfginfo;
  130. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  131. micfginfo.d = __RV_CSR_READ(CSR_MICFG_INFO);
  132. return mcfginfo.b.ilm && micfginfo.b.lm_ecc;
  133. }
  134. /**
  135. * \brief Check if DLM supports ECC
  136. * \details
  137. * This function checks if both DLM and ECC are supported in the core.
  138. * \return 1 if DLM supports ECC, 0 otherwise
  139. */
  140. __STATIC_FORCEINLINE int32_t ECC_IsDLMSupportECC(void)
  141. {
  142. CSR_MCFGINFO_Type mcfginfo;
  143. CSR_MDCFGINFO_Type mdcfginfo;
  144. mcfginfo.d = __RV_CSR_READ(CSR_MCFG_INFO);
  145. mdcfginfo.d = __RV_CSR_READ(CSR_MDCFG_INFO);
  146. return mcfginfo.b.dlm && mdcfginfo.b.lm_ecc;
  147. }
  148. /**
  149. * \brief Check if XOR error injection mode is supported
  150. * \details
  151. * This function reads the machine ECC code CSR and checks if error injection mode is suppported.
  152. * \return 1 if XOR error injection mode is enabled, 0 otherwise
  153. */
  154. __STATIC_FORCEINLINE int32_t ECC_IsXorErrorInjectMode(void)
  155. {
  156. CSR_MECC_CODE_Type mecc_code;
  157. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  158. return mecc_code.b.ecc_inj_mode;
  159. }
  160. /**
  161. * \brief Enable ECC for I-Cache
  162. * \details
  163. * This function enables ECC for the instruction cache by setting the appropriate bit
  164. * in the machine cache control CSR.
  165. */
  166. __STATIC_FORCEINLINE void ECC_EnableICacheECC(void)
  167. {
  168. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_EN);
  169. }
  170. /**
  171. * \brief Disable ECC for I-Cache
  172. * \details
  173. * This function disables ECC for the instruction cache by clearing the appropriate bit
  174. * in the machine cache control CSR.
  175. */
  176. __STATIC_FORCEINLINE void ECC_DisableICacheECC(void)
  177. {
  178. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_EN);
  179. }
  180. /**
  181. * \brief Enable ECC exception for I-Cache
  182. * \details
  183. * This function enables ECC exception for the instruction cache by setting the appropriate bit
  184. * in the machine cache control CSR.
  185. */
  186. __STATIC_FORCEINLINE void ECC_EnableICacheECCExcp(void)
  187. {
  188. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_EXCP_EN);
  189. }
  190. /**
  191. * \brief Disable ECC exception for I-Cache
  192. * \details
  193. * This function disables ECC exception for the instruction cache by clearing the appropriate bit
  194. * in the machine cache control CSR.
  195. */
  196. __STATIC_FORCEINLINE void ECC_DisableICacheECCExcp(void)
  197. {
  198. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_EXCP_EN);
  199. }
  200. /**
  201. * \brief Enable ECC checking for I-Cache
  202. * \details
  203. * This function enables ECC checking for the instruction cache by setting the appropriate bit
  204. * in the machine cache control CSR.
  205. */
  206. __STATIC_FORCEINLINE void ECC_EnableICacheECCCheck(void)
  207. {
  208. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_CHK_EN);
  209. }
  210. /**
  211. * \brief Disable ECC checking for I-Cache
  212. * \details
  213. * This function disables ECC checking for the instruction cache by clearing the appropriate bit
  214. * in the machine cache control CSR.
  215. */
  216. __STATIC_FORCEINLINE void ECC_DisableICacheECCCheck(void)
  217. {
  218. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_IC_ECC_CHK_EN);
  219. }
  220. /**
  221. * \brief Enable ECC for D-Cache
  222. * \details
  223. * This function enables ECC for the data cache by setting the appropriate bit
  224. * in the machine cache control CSR.
  225. */
  226. __STATIC_FORCEINLINE void ECC_EnableDCacheECC(void)
  227. {
  228. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_EN);
  229. }
  230. /**
  231. * \brief Disable ECC for D-Cache
  232. * \details
  233. * This function disables ECC for the data cache by clearing the appropriate bit
  234. * in the machine cache control CSR.
  235. */
  236. __STATIC_FORCEINLINE void ECC_DisableDCacheECC(void)
  237. {
  238. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_EN);
  239. }
  240. /**
  241. * \brief Enable ECC exception for D-Cache
  242. * \details
  243. * This function enables ECC exception for the data cache by setting the appropriate bit
  244. * in the machine cache control CSR.
  245. */
  246. __STATIC_FORCEINLINE void ECC_EnableDCacheECCExcp(void)
  247. {
  248. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_EXCP_EN);
  249. }
  250. /**
  251. * \brief Disable ECC exception for D-Cache
  252. * \details
  253. * This function disables ECC exception for the data cache by clearing the appropriate bit
  254. * in the machine cache control CSR.
  255. */
  256. __STATIC_FORCEINLINE void ECC_DisableDCacheECCExcp(void)
  257. {
  258. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_EXCP_EN);
  259. }
  260. /**
  261. * \brief Enable ECC checking for D-Cache
  262. * \details
  263. * This function enables ECC checking for the data cache by setting the appropriate bit
  264. * in the machine cache control CSR.
  265. */
  266. __STATIC_FORCEINLINE void ECC_EnableDCacheECCCheck(void)
  267. {
  268. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_CHK_EN);
  269. }
  270. /**
  271. * \brief Disable ECC checking for D-Cache
  272. * \details
  273. * This function disables ECC checking for the data cache by clearing the appropriate bit
  274. * in the machine cache control CSR.
  275. */
  276. __STATIC_FORCEINLINE void ECC_DisableDCacheECCCheck(void)
  277. {
  278. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_DC_ECC_CHK_EN);
  279. }
  280. #if defined(__CCM_PRESENT) && (__CCM_PRESENT == 1)
  281. #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1)
  282. /**
  283. * \brief Inject error into I-Cache Tag RAM
  284. * \details
  285. * This function injects an error into the I-Cache Tag RAM at the specified address
  286. * with the given ECC code.
  287. * \param[in] ecc_code ECC code to inject
  288. * \param[in] addr Address where error should be injected
  289. */
  290. __STATIC_FORCEINLINE void ECC_ICacheTRamErrInject(uint32_t ecc_code, void *addr)
  291. {
  292. /* Write ecc_code into mecc_code csr also clear all error status */
  293. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  294. MInvalICacheLine((unsigned long)addr);
  295. __RWMB();
  296. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_IC_TRAM_ECC_INJ_EN);
  297. MLockICacheLine((unsigned long)addr);
  298. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_IC_TRAM_ECC_INJ_EN);
  299. __RWMB();
  300. }
  301. /**
  302. * \brief Inject error into I-Cache Data RAM
  303. * \details
  304. * This function injects an error into the I-Cache Data RAM at the specified address
  305. * with the given ECC code.
  306. * \param[in] ecc_code ECC code to inject
  307. * \param[in] addr Address where error should be injected
  308. */
  309. __STATIC_FORCEINLINE void ECC_ICacheDRamErrInject(uint32_t ecc_code, void *addr)
  310. {
  311. /* Write ecc_code into mecc_code csr also clear all error status */
  312. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  313. MInvalICacheLine((unsigned long)addr);
  314. __RWMB();
  315. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_IC_DRAM_ECC_INJ_EN);
  316. MLockICacheLine((unsigned long)addr);
  317. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_IC_DRAM_ECC_INJ_EN);
  318. __RWMB();
  319. }
  320. /**
  321. * \brief Restore I-Cache error at specified address
  322. * \details
  323. * This function restores the correct ECC code for the I-Cache line at the specified address.
  324. * \param[in] addr Address to restore
  325. */
  326. __STATIC_FORCEINLINE void ECC_ICacheErrRestore(void *addr)
  327. {
  328. /* Re-lock cache to restore the correct ecc code */
  329. MInvalICacheLine((unsigned long)addr);
  330. MLockICacheLine((unsigned long)addr);
  331. }
  332. #endif /* #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1) */
  333. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1)
  334. /**
  335. * \brief Inject error into D-Cache Tag RAM
  336. * \details
  337. * This function injects an error into the D-Cache Tag RAM at the specified address
  338. * with the given ECC code.
  339. * \param[in] ecc_code ECC code to inject
  340. * \param[in] addr Address where error should be injected
  341. */
  342. __STATIC_FORCEINLINE void ECC_DCacheTRamErrInject(uint32_t ecc_code, void *addr)
  343. {
  344. /* Write ecc_code into mecc_code csr also clear all error status */
  345. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  346. ECC_DisableDCacheECCCheck();
  347. MFlushInvalDCacheLine((unsigned long)addr);
  348. __RWMB();
  349. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_DC_TRAM_ECC_INJ_EN);
  350. MLockDCacheLine((unsigned long)addr);
  351. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_DC_TRAM_ECC_INJ_EN);
  352. __RWMB();
  353. ECC_EnableDCacheECCCheck();
  354. }
  355. /**
  356. * \brief Inject error into D-Cache Data RAM
  357. * \details
  358. * This function injects an error into the D-Cache Data RAM at the specified address
  359. * with the given ECC code.
  360. * \param[in] ecc_code ECC code to inject
  361. * \param[in] addr Address where error should be injected
  362. */
  363. __STATIC_FORCEINLINE void ECC_DCacheDRamErrInject(uint32_t ecc_code, void *addr)
  364. {
  365. /* Write ecc_code into mecc_code csr also clear all error status */
  366. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  367. ECC_DisableDCacheECCCheck();
  368. MFlushInvalDCacheLine((unsigned long)addr);
  369. __RWMB();
  370. __RV_CSR_SET(CSR_MCACHE_CTL, MCACHE_CTL_DC_DRAM_ECC_INJ_EN);
  371. MLockDCacheLine((unsigned long)addr);
  372. __RV_CSR_CLEAR(CSR_MCACHE_CTL, MCACHE_CTL_DC_DRAM_ECC_INJ_EN);
  373. __RWMB();
  374. ECC_EnableDCacheECCCheck();
  375. }
  376. /**
  377. * \brief Restore D-Cache error at specified address
  378. * \details
  379. * This function restores the correct ECC code for the D-Cache line at the specified address.
  380. * \param[in] addr Address to restore
  381. */
  382. __STATIC_FORCEINLINE void ECC_DCacheErrRestore(void *addr)
  383. {
  384. ECC_DisableDCacheECCCheck();
  385. MFlushInvalDCacheLine((unsigned long)addr);
  386. MLockDCacheLine((unsigned long)addr);
  387. ECC_EnableDCacheECCCheck();
  388. }
  389. #endif /* #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1) */
  390. #endif /* #if defined(__CCM_PRESENT) && (__CCM_PRESENT == 1) */
  391. /**
  392. * \brief Enable ILM
  393. * \details
  394. * This function enables ILM by setting the appropriate bit in the machine ILM control CSR.
  395. */
  396. __STATIC_FORCEINLINE void ECC_EnableILM(void)
  397. {
  398. __RV_CSR_SET(CSR_MILM_CTL, MILM_CTL_ILM_EN);
  399. }
  400. /**
  401. * \brief Disable ILM
  402. * \details
  403. * This function disables ILM by clearing the appropriate bit in the machine ILM control CSR.
  404. */
  405. __STATIC_FORCEINLINE void ECC_DisableILM(void)
  406. {
  407. __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_EN);
  408. }
  409. /**
  410. * \brief Enable ECC for ILM
  411. * \details
  412. * This function enables ECC for ILM by setting the appropriate bit in the machine ILM control CSR.
  413. */
  414. __STATIC_FORCEINLINE void ECC_EnableILMECC(void)
  415. {
  416. __RV_CSR_SET(CSR_MILM_CTL, MILM_CTL_ILM_ECC_EN);
  417. }
  418. /**
  419. * \brief Disable ECC for ILM
  420. * \details
  421. * This function disables ECC for ILM by clearing the appropriate bit in the machine ILM control CSR.
  422. */
  423. __STATIC_FORCEINLINE void ECC_DisableILMECC(void)
  424. {
  425. __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_ECC_EN);
  426. }
  427. /**
  428. * \brief Enable ECC exception for ILM
  429. * \details
  430. * This function enables ECC exception for ILM by setting the appropriate bit in the machine ILM control CSR.
  431. */
  432. __STATIC_FORCEINLINE void ECC_EnableILMECCExcp(void)
  433. {
  434. __RV_CSR_SET(CSR_MILM_CTL, MILM_CTL_ILM_ECC_EXCP_EN);
  435. }
  436. /**
  437. * \brief Disable ECC exception for ILM
  438. * \details
  439. * This function disables ECC exception for ILM by clearing the appropriate bit in the machine ILM control CSR.
  440. */
  441. __STATIC_FORCEINLINE void ECC_DisableILMECCExcp(void)
  442. {
  443. __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_ECC_EXCP_EN);
  444. }
  445. /**
  446. * \brief Enable ECC checking for ILM
  447. * \details
  448. * This function enables ECC checking for ILM by setting the appropriate bit in the machine ILM control CSR.
  449. */
  450. __STATIC_FORCEINLINE void ECC_EnableILMECCCheck(void)
  451. {
  452. __RV_CSR_SET(CSR_MILM_CTL, MILM_CTL_ILM_ECC_CHK_EN);
  453. }
  454. /**
  455. * \brief Disable ECC checking for ILM
  456. * \details
  457. * This function disables ECC checking for ILM by clearing the appropriate bit in the machine ILM control CSR.
  458. */
  459. __STATIC_FORCEINLINE void ECC_DisableILMECCCheck(void)
  460. {
  461. __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_ECC_CHK_EN);
  462. }
  463. /**
  464. * \brief Inject error into ILM
  465. * \details
  466. * This function injects an error into the ILM at the specified address with the given ECC code.
  467. * \param[in] ecc_code ECC code to inject
  468. * \param[in] addr Address where error should be injected
  469. */
  470. __STATIC_FORCEINLINE void ECC_ILMErrInject(uint32_t ecc_code, void *addr)
  471. {
  472. /* Write ecc_code into mecc_code csr also clear all error status */
  473. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  474. ECC_DisableILMECCCheck();
  475. uint32_t val = __LW(addr);
  476. __RWMB(); // make sure setting the ECC_INJ_EN bit before any other memory access
  477. __RV_CSR_SET(CSR_MILM_CTL, MILM_CTL_ILM_ECC_INJ_EN);
  478. __SW(addr, val);
  479. __RWMB(); // make sure the error injection is finished
  480. __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_ECC_INJ_EN);
  481. __RWMB(); // make sure clearing the ECC_INJ_EN bit before any other memory access
  482. ECC_EnableILMECCCheck();
  483. }
  484. /**
  485. * \brief Restore ILM error at specified address
  486. * \details
  487. * This function restores the correct ECC code for the ILM at the specified address.
  488. * \param[in] addr Address to restore
  489. */
  490. __STATIC_FORCEINLINE void ECC_ILMErrRestore(void *addr)
  491. {
  492. ECC_DisableILMECCCheck();
  493. __RWMB();
  494. __SW(addr, __LW(addr));
  495. __RWMB();
  496. ECC_EnableILMECCCheck();
  497. }
  498. /**
  499. * \brief Enable DLM
  500. * \details
  501. * This function enables DLM by setting the appropriate bit in the machine DLM control CSR.
  502. */
  503. __STATIC_FORCEINLINE void ECC_EnableDLM(void)
  504. {
  505. __RV_CSR_SET(CSR_MDLM_CTL, MDLM_CTL_DLM_EN);
  506. }
  507. /**
  508. * \brief Disable DLM
  509. * \details
  510. * This function disables DLM by clearing the appropriate bit in the machine DLM control CSR.
  511. */
  512. __STATIC_FORCEINLINE void ECC_DisableDLM(void)
  513. {
  514. __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_EN);
  515. }
  516. /**
  517. * \brief Enable ECC for DLM
  518. * \details
  519. * This function enables ECC for DLM by setting the appropriate bit in the machine DLM control CSR.
  520. */
  521. __STATIC_FORCEINLINE void ECC_EnableDLMECC(void)
  522. {
  523. __RV_CSR_SET(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_EN);
  524. }
  525. /**
  526. * \brief Disable ECC for DLM
  527. * \details
  528. * This function disables ECC for DLM by clearing the appropriate bit in the machine DLM control CSR.
  529. */
  530. __STATIC_FORCEINLINE void ECC_DisableDLMECC(void)
  531. {
  532. __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_EN);
  533. }
  534. /**
  535. * \brief Enable ECC exception for DLM
  536. * \details
  537. * This function enables ECC exception for DLM by setting the appropriate bit in the machine DLM control CSR.
  538. */
  539. __STATIC_FORCEINLINE void ECC_EnableDLMECCExcp(void)
  540. {
  541. __RV_CSR_SET(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_EXCP_EN);
  542. }
  543. /**
  544. * \brief Disable ECC exception for DLM
  545. * \details
  546. * This function disables ECC exception for DLM by clearing the appropriate bit in the machine DLM control CSR.
  547. */
  548. __STATIC_FORCEINLINE void ECC_DisableDLMECCExcp(void)
  549. {
  550. __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_EXCP_EN);
  551. }
  552. /**
  553. * \brief Enable ECC checking for DLM
  554. * \details
  555. * This function enables ECC checking for DLM by setting the appropriate bit in the machine DLM control CSR.
  556. */
  557. __STATIC_FORCEINLINE void ECC_EnableDLMECCCheck(void)
  558. {
  559. __RV_CSR_SET(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_CHK_EN);
  560. }
  561. /**
  562. * \brief Disable ECC checking for DLM
  563. * \details
  564. * This function disables ECC checking for DLM by clearing the appropriate bit in the machine DLM control CSR.
  565. */
  566. __STATIC_FORCEINLINE void ECC_DisableDLMECCCheck(void)
  567. {
  568. __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_CHK_EN);
  569. }
  570. /**
  571. * \brief Inject error into DLM
  572. * \details
  573. * This function injects an error into the DLM at the specified address with the given ECC code.
  574. * \param[in] ecc_code ECC code to inject
  575. * \param[in] addr Address where error should be injected
  576. */
  577. __STATIC_FORCEINLINE void ECC_DLMErrInject(uint32_t ecc_code, void *addr)
  578. {
  579. /* Write ecc_code into mecc_code csr also clear all error status */
  580. __RV_CSR_WRITE(CSR_MECC_CODE, ecc_code);
  581. ECC_DisableDLMECCCheck();
  582. uint32_t val = __LW(addr);
  583. __RWMB(); // make sure setting the ECC_INJ_EN bit before any other memory access
  584. __RV_CSR_SET(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_INJ_EN);
  585. __SW(addr, val);
  586. __RWMB(); // make sure the error injection is finished
  587. __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_ECC_INJ_EN);
  588. __RWMB(); // make sure clearing the ECC_INJ_EN bit before any other memory access
  589. ECC_EnableDLMECCCheck();
  590. }
  591. /**
  592. * \brief Restore DLM error at specified address
  593. * \details
  594. * This function restores the correct ECC code for the DLM at the specified address.
  595. * \param[in] addr Address to restore
  596. */
  597. __STATIC_FORCEINLINE void ECC_DLMErrRestore(void *addr)
  598. {
  599. ECC_DisableDLMECCCheck();
  600. __RWMB();
  601. __SW(addr, __LW(addr));
  602. __RWMB();
  603. ECC_EnableDLMECCCheck();
  604. }
  605. #define ECC_ERROR_RAMID_MASK_ICACHE 1U
  606. #define ECC_ERROR_RAMID_MASK_DCACHE 2U
  607. #define ECC_ERROR_RAMID_MASK_TLB 4U
  608. #define ECC_ERROR_RAMID_MASK_ILM 8U
  609. #define ECC_ERROR_RAMID_MASK_DLM 16U
  610. /**
  611. * \brief Check if any single-bit error has occurred
  612. * \details
  613. * This function checks if any single-bit error has occurred by reading the machine ECC code CSR.
  614. * \return 1 if any single-bit error has occurred, 0 otherwise
  615. */
  616. __STATIC_FORCEINLINE int32_t ECC_IsAnySingleBitErrorOccured(void)
  617. {
  618. CSR_MECC_CODE_Type mecc_code;
  619. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  620. return mecc_code.b.sramid;
  621. }
  622. /**
  623. * \brief Check if I-Cache single-bit error has occurred
  624. * \details
  625. * This function checks if a single-bit error has occurred in the I-Cache.
  626. * \return 1 if I-Cache single-bit error has occurred, 0 otherwise
  627. */
  628. __STATIC_FORCEINLINE int32_t ECC_IsICacheSingleBitErrorOccured(void)
  629. {
  630. CSR_MECC_CODE_Type mecc_code;
  631. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  632. return mecc_code.b.sramid & ECC_ERROR_RAMID_MASK_ICACHE;
  633. }
  634. /**
  635. * \brief Check if D-Cache single-bit error has occurred
  636. * \details
  637. * This function checks if a single-bit error has occurred in the D-Cache.
  638. * \return 1 if D-Cache single-bit error has occurred, 0 otherwise
  639. */
  640. __STATIC_FORCEINLINE int32_t ECC_IsDCacheSingleBitErrorOccured(void)
  641. {
  642. CSR_MECC_CODE_Type mecc_code;
  643. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  644. return mecc_code.b.sramid & ECC_ERROR_RAMID_MASK_DCACHE;
  645. }
  646. /**
  647. * \brief Check if TLB single-bit error has occurred
  648. * \details
  649. * This function checks if a single-bit error has occurred in the TLB.
  650. * \return 1 if TLB single-bit error has occurred, 0 otherwise
  651. */
  652. __STATIC_FORCEINLINE int32_t ECC_IsTLBSingleBitErrorOccured(void)
  653. {
  654. CSR_MECC_CODE_Type mecc_code;
  655. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  656. return mecc_code.b.sramid & ECC_ERROR_RAMID_MASK_DLM;
  657. }
  658. /**
  659. * \brief Check if ILM single-bit error has occurred
  660. * \details
  661. * This function checks if a single-bit error has occurred in the ILM.
  662. * \return 1 if ILM single-bit error has occurred, 0 otherwise
  663. */
  664. __STATIC_FORCEINLINE int32_t ECC_IsILMSingleBitErrorOccured(void)
  665. {
  666. CSR_MECC_CODE_Type mecc_code;
  667. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  668. return mecc_code.b.sramid & ECC_ERROR_RAMID_MASK_ILM;
  669. }
  670. /**
  671. * \brief Check if DLM single-bit error has occurred
  672. * \details
  673. * This function checks if a single-bit error has occurred in the DLM.
  674. * \return 1 if DLM single-bit error has occurred, 0 otherwise
  675. */
  676. __STATIC_FORCEINLINE int32_t ECC_IsDLMSingleBitErrorOccured(void)
  677. {
  678. CSR_MECC_CODE_Type mecc_code;
  679. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  680. return mecc_code.b.sramid & ECC_ERROR_RAMID_MASK_DLM;
  681. }
  682. /**
  683. * \brief Clear all single-bit errors
  684. * \details
  685. * This function clears all single-bit errors by clearing the appropriate bits
  686. * in the machine ECC code CSR.
  687. */
  688. __STATIC_FORCEINLINE void ECC_ClearAllSingleBitError(void)
  689. {
  690. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID);
  691. }
  692. /**
  693. * \brief Clear I-Cache single-bit error
  694. * \details
  695. * This function clears the single-bit error in the I-Cache by clearing the appropriate bits
  696. * in the machine ECC code CSR.
  697. */
  698. __STATIC_FORCEINLINE void ECC_ClearICacheSingleBitError(void)
  699. {
  700. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID_IC);
  701. }
  702. /**
  703. * \brief Clear D-Cache single-bit error
  704. * \details
  705. * This function clears the single-bit error in the D-Cache by clearing the appropriate bits
  706. * in the machine ECC code CSR.
  707. */
  708. __STATIC_FORCEINLINE void ECC_ClearDCacheSingleBitError(void)
  709. {
  710. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID_DC);
  711. }
  712. /**
  713. * \brief Clear TLB single-bit error
  714. * \details
  715. * This function clears the single-bit error in the TLB by clearing the appropriate bits
  716. * in the machine ECC code CSR.
  717. */
  718. __STATIC_FORCEINLINE void ECC_ClearTLBSingleBitError(void)
  719. {
  720. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID_TLB);
  721. }
  722. /**
  723. * \brief Clear ILM single-bit error
  724. * \details
  725. * This function clears the single-bit error in the ILM by clearing the appropriate bits
  726. * in the machine ECC code CSR.
  727. */
  728. __STATIC_FORCEINLINE void ECC_ClearILMSingleBitError(void)
  729. {
  730. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID_ILM);
  731. }
  732. /**
  733. * \brief Clear DLM single-bit error
  734. * \details
  735. * This function clears the single-bit error in the DLM by clearing the appropriate bits
  736. * in the machine ECC code CSR.
  737. */
  738. __STATIC_FORCEINLINE void ECC_ClearDLMSingleBitError(void)
  739. {
  740. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_SRAMID_DLM);
  741. }
  742. /**
  743. * \brief Check if any double-bit error has occurred
  744. * \details
  745. * This function checks if any double-bit error has occurred by reading the machine ECC code CSR.
  746. * \return 1 if any double-bit error has occurred, 0 otherwise
  747. */
  748. __STATIC_FORCEINLINE int32_t ECC_IsAnyDoubleBitErrorOccured(void)
  749. {
  750. CSR_MECC_CODE_Type mecc_code;
  751. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  752. return mecc_code.b.ramid;
  753. }
  754. /**
  755. * \brief Check if I-Cache double-bit error has occurred
  756. * \details
  757. * This function checks if a double-bit error has occurred in the I-Cache.
  758. * \return 1 if I-Cache double-bit error has occurred, 0 otherwise
  759. */
  760. __STATIC_FORCEINLINE int32_t ECC_IsICacheDoubleBitErrorOccured(void)
  761. {
  762. CSR_MECC_CODE_Type mecc_code;
  763. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  764. return mecc_code.b.ramid & ECC_ERROR_RAMID_MASK_ICACHE;
  765. }
  766. /**
  767. * \brief Check if D-Cache double-bit error has occurred
  768. * \details
  769. * This function checks if a double-bit error has occurred in the D-Cache.
  770. * \return 1 if D-Cache double-bit error has occurred, 0 otherwise
  771. */
  772. __STATIC_FORCEINLINE int32_t ECC_IsDCacheDoubleBitErrorOccured(void)
  773. {
  774. CSR_MECC_CODE_Type mecc_code;
  775. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  776. return mecc_code.b.ramid & ECC_ERROR_RAMID_MASK_DCACHE;
  777. }
  778. /**
  779. * \brief Check if TLB double-bit error has occurred
  780. * \details
  781. * This function checks if a double-bit error has occurred in the TLB.
  782. * \return 1 if TLB double-bit error has occurred, 0 otherwise
  783. */
  784. __STATIC_FORCEINLINE int32_t ECC_IsTLBDoubleBitErrorOccured(void)
  785. {
  786. CSR_MECC_CODE_Type mecc_code;
  787. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  788. return mecc_code.b.ramid & ECC_ERROR_RAMID_MASK_DLM;
  789. }
  790. /**
  791. * \brief Check if ILM double-bit error has occurred
  792. * \details
  793. * This function checks if a double-bit error has occurred in the ILM.
  794. * \return 1 if ILM double-bit error has occurred, 0 otherwise
  795. */
  796. __STATIC_FORCEINLINE int32_t ECC_IsILMDoubleBitErrorOccured(void)
  797. {
  798. CSR_MECC_CODE_Type mecc_code;
  799. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  800. return mecc_code.b.ramid & ECC_ERROR_RAMID_MASK_ILM;
  801. }
  802. /**
  803. * \brief Check if DLM double-bit error has occurred
  804. * \details
  805. * This function checks if a double-bit error has occurred in the DLM.
  806. * \return 1 if DLM double-bit error has occurred, 0 otherwise
  807. */
  808. __STATIC_FORCEINLINE int32_t ECC_IsDLMDoubleBitErrorOccured(void)
  809. {
  810. CSR_MECC_CODE_Type mecc_code;
  811. mecc_code.d = __RV_CSR_READ(CSR_MECC_CODE);
  812. return mecc_code.b.ramid & ECC_ERROR_RAMID_MASK_DLM;
  813. }
  814. /**
  815. * \brief Clear all double-bit errors
  816. * \details
  817. * This function clears all double-bit errors by clearing the appropriate bits
  818. * in the machine ECC code CSR.
  819. */
  820. __STATIC_FORCEINLINE void ECC_ClearAllDoubleBitError(void)
  821. {
  822. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID);
  823. }
  824. /**
  825. * \brief Clear I-Cache double-bit error
  826. * \details
  827. * This function clears the double-bit error in the I-Cache by clearing the appropriate bits
  828. * in the machine ECC code CSR.
  829. */
  830. __STATIC_FORCEINLINE void ECC_ClearICacheDoubleBitError(void)
  831. {
  832. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID_IC);
  833. }
  834. /**
  835. * \brief Clear D-Cache double-bit error
  836. * \details
  837. * This function clears the double-bit error in the D-Cache by clearing the appropriate bits
  838. * in the machine ECC code CSR.
  839. */
  840. __STATIC_FORCEINLINE void ECC_ClearDCacheDoubleBitError(void)
  841. {
  842. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID_DC);
  843. }
  844. /**
  845. * \brief Clear TLB double-bit error
  846. * \details
  847. * This function clears the double-bit error in the TLB by clearing the appropriate bits
  848. * in the machine ECC code CSR.
  849. */
  850. __STATIC_FORCEINLINE void ECC_ClearTLBDoubleBitError(void)
  851. {
  852. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID_TLB);
  853. }
  854. /**
  855. * \brief Clear ILM double-bit error
  856. * \details
  857. * This function clears the double-bit error in the ILM by clearing the appropriate bits
  858. * in the machine ECC code CSR.
  859. */
  860. __STATIC_FORCEINLINE void ECC_ClearILMDoubleBitError(void)
  861. {
  862. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID_ILM);
  863. }
  864. /**
  865. * \brief Clear DLM double-bit error
  866. * \details
  867. * This function clears the double-bit error in the DLM by clearing the appropriate bits
  868. * in the machine ECC code CSR.
  869. */
  870. __STATIC_FORCEINLINE void ECC_ClearDLMDoubleBitError(void)
  871. {
  872. __RV_CSR_CLEAR(CSR_MECC_CODE, MECC_CODE_RAMID_DLM);
  873. }
  874. /**
  875. * \brief Generate ECC code for a 32-bit value
  876. * \details
  877. * This function calculates the ECC code for a 32-bit input value
  878. * using Hamming code algorithm. It generates a 7-bit ECC code that can be used to
  879. * detect and correct single-bit errors and detect double-bit errors.
  880. * \param[in] a 32-bit value for which ECC code is to be generated
  881. * \return 8-bit ECC code (7 bits used, 1 bit unused)
  882. */
  883. static uint8_t ECC_GenerateECCCodeU32(uint32_t a)
  884. {
  885. uint8_t ecc_bits = 0;
  886. uint8_t ecc_bit_0 = ((a >> 0) & 1) ^ ((a >> 1) & 1) ^ ((a >> 3) & 1) ^ ((a >> 4) & 1) ^
  887. ((a >> 6) & 1) ^ ((a >> 8) & 1) ^ ((a >> 10) & 1) ^ ((a >> 12) & 1) ^
  888. ((a >> 14) & 1) ^ ((a >> 17) & 1) ^ ((a >> 19) & 1) ^ ((a >> 20) & 1) ^
  889. ((a >> 24) & 1) ^ ((a >> 28) & 1);
  890. uint8_t ecc_bit_1 = ((a >> 0) & 1) ^ ((a >> 2) & 1) ^ ((a >> 3) & 1) ^ ((a >> 5) & 1) ^
  891. ((a >> 6) & 1) ^ ((a >> 9) & 1) ^ ((a >> 11) & 1) ^ ((a >> 12) & 1) ^
  892. ((a >> 15) & 1) ^ ((a >> 20) & 1) ^ ((a >> 22) & 1) ^ ((a >> 25) & 1) ^
  893. ((a >> 29) & 1);
  894. uint8_t ecc_bit_2 = ((a >> 1) & 1) ^ ((a >> 2) & 1) ^ ((a >> 3) & 1) ^ ((a >> 7) & 1) ^
  895. ((a >> 8) & 1) ^ ((a >> 9) & 1) ^ ((a >> 13) & 1) ^ ((a >> 14) & 1) ^
  896. ((a >> 15) & 1) ^ ((a >> 18) & 1) ^ ((a >> 21) & 1) ^ ((a >> 22) & 1) ^
  897. ((a >> 26) & 1) ^ ((a >> 30) & 1);
  898. uint8_t ecc_bit_3 = ((a >> 4) & 1) ^ ((a >> 5) & 1) ^ ((a >> 6) & 1) ^ ((a >> 7) & 1) ^
  899. ((a >> 8) & 1) ^ ((a >> 9) & 1) ^ ((a >> 16) & 1) ^ ((a >> 17) & 1) ^
  900. ((a >> 18) & 1) ^ ((a >> 23) & 1) ^ ((a >> 24) & 1) ^ ((a >> 25) & 1) ^
  901. ((a >> 26) & 1) ^ ((a >> 31) & 1);
  902. uint8_t ecc_bit_4 = ((a >> 10) & 1) ^ ((a >> 11) & 1) ^ ((a >> 12) & 1) ^ ((a >> 13) & 1) ^
  903. ((a >> 14) & 1) ^ ((a >> 15) & 1) ^ ((a >> 16) & 1) ^ ((a >> 17) & 1) ^
  904. ((a >> 18) & 1) ^ ((a >> 27) & 1) ^ ((a >> 28) & 1) ^ ((a >> 29) & 1) ^
  905. ((a >> 30) & 1) ^ ((a >> 31) & 1);
  906. uint8_t ecc_bit_5 = ((a >> 19) & 1) ^ ((a >> 20) & 1) ^ ((a >> 21) & 1) ^ ((a >> 22) & 1) ^
  907. ((a >> 23) & 1) ^ ((a >> 24) & 1) ^ ((a >> 25) & 1) ^ ((a >> 26) & 1) ^
  908. ((a >> 27) & 1) ^ ((a >> 28) & 1) ^ ((a >> 29) & 1) ^ ((a >> 30) & 1) ^
  909. ((a >> 31) & 1);
  910. uint8_t ecc_bit_6 = ((a >> 0) & 1) ^ ((a >> 1) & 1) ^ ((a >> 2) & 1) ^ ((a >> 4) & 1) ^
  911. ((a >> 5) & 1) ^ ((a >> 7) & 1) ^ ((a >> 10) & 1) ^ ((a >> 11) & 1) ^
  912. ((a >> 13) & 1) ^ ((a >> 16) & 1) ^ ((a >> 19) & 1) ^ ((a >> 21) & 1) ^
  913. ((a >> 23) & 1) ^ ((a >> 27) & 1);
  914. ecc_bits = (ecc_bit_6 << 6) | (ecc_bit_5 << 5) | (ecc_bit_4 << 4) | (ecc_bit_3 << 3) |
  915. (ecc_bit_2 << 2) | (ecc_bit_1 << 1) | ecc_bit_0;
  916. return ecc_bits;
  917. }
  918. /**
  919. * \brief Generate ECC code for a 64-bit value
  920. * \details
  921. * This function calculates the ECC for a 64-bit input value
  922. * using Hamming code algorithm. It generates an 8-bit ECC code that can be used to
  923. * detect and correct single-bit errors and detect double-bit errors.
  924. * \param[in] a 64-bit value for which ECC code is to be generated
  925. * \return 8-bit ECC code
  926. */
  927. static uint8_t ECC_GenerateECCCodeU64(uint64_t a)
  928. {
  929. uint8_t ecc_bits = 0;
  930. uint8_t ecc_bit_0 =
  931. (((a >> 0) & 1) ^ ((a >> 1) & 1) ^ ((a >> 3) & 1) ^ ((a >> 4) & 1) ^ ((a >> 6) & 1) ^
  932. ((a >> 8) & 1) ^ ((a >> 10) & 1) ^ ((a >> 12) & 1) ^ ((a >> 14) & 1) ^ ((a >> 17) & 1) ^
  933. ((a >> 20) & 1) ^ ((a >> 22) & 1) ^ ((a >> 24) & 1) ^ ((a >> 27) & 1) ^ ((a >> 30) & 1) ^
  934. ((a >> 32) & 1) ^ ((a >> 36) & 1) ^ ((a >> 37) & 1) ^ ((a >> 38) & 1) ^ ((a >> 40) & 1) ^
  935. ((a >> 42) & 1) ^ ((a >> 45) & 1) ^ ((a >> 47) & 1) ^ ((a >> 51) & 1) ^ ((a >> 54) & 1) ^
  936. ((a >> 57) & 1));
  937. uint8_t ecc_bit_1 =
  938. (((a >> 0) & 1) ^ ((a >> 2) & 1) ^ ((a >> 3) & 1) ^ ((a >> 5) & 1) ^ ((a >> 6) & 1) ^
  939. ((a >> 9) & 1) ^ ((a >> 11) & 1) ^ ((a >> 12) & 1) ^ ((a >> 15) & 1) ^ ((a >> 18) & 1) ^
  940. ((a >> 21) & 1) ^ ((a >> 22) & 1) ^ ((a >> 25) & 1) ^ ((a >> 28) & 1) ^ ((a >> 30) & 1) ^
  941. ((a >> 33) & 1) ^ ((a >> 37) & 1) ^ ((a >> 39) & 1) ^ ((a >> 40) & 1) ^ ((a >> 43) & 1) ^
  942. ((a >> 46) & 1) ^ ((a >> 47) & 1) ^ ((a >> 49) & 1) ^ ((a >> 52) & 1) ^ ((a >> 58) & 1) ^
  943. ((a >> 63) & 1));
  944. uint8_t ecc_bit_2 =
  945. (((a >> 1) & 1) ^ ((a >> 2) & 1) ^ ((a >> 3) & 1) ^ ((a >> 7) & 1) ^ ((a >> 8) & 1) ^
  946. ((a >> 9) & 1) ^ ((a >> 13) & 1) ^ ((a >> 14) & 1) ^ ((a >> 15) & 1) ^ ((a >> 19) & 1) ^
  947. ((a >> 23) & 1) ^ ((a >> 24) & 1) ^ ((a >> 25) & 1) ^ ((a >> 29) & 1) ^ ((a >> 30) & 1) ^
  948. ((a >> 34) & 1) ^ ((a >> 41) & 1) ^ ((a >> 42) & 1) ^ ((a >> 43) & 1) ^ ((a >> 48) & 1) ^
  949. ((a >> 49) & 1) ^ ((a >> 53) & 1) ^ ((a >> 54) & 1) ^ ((a >> 59) & 1) ^ ((a >> 62) & 1) ^
  950. ((a >> 63) & 1));
  951. uint8_t ecc_bit_3 =
  952. (((a >> 4) & 1) ^ ((a >> 5) & 1) ^ ((a >> 6) & 1) ^ ((a >> 7) & 1) ^ ((a >> 8) & 1) ^
  953. ((a >> 9) & 1) ^ ((a >> 16) & 1) ^ ((a >> 17) & 1) ^ ((a >> 18) & 1) ^ ((a >> 19) & 1) ^
  954. ((a >> 26) & 1) ^ ((a >> 27) & 1) ^ ((a >> 28) & 1) ^ ((a >> 29) & 1) ^ ((a >> 30) & 1) ^
  955. ((a >> 35) & 1) ^ ((a >> 36) & 1) ^ ((a >> 37) & 1) ^ ((a >> 44) & 1) ^ ((a >> 45) & 1) ^
  956. ((a >> 46) & 1) ^ ((a >> 47) & 1) ^ ((a >> 48) & 1) ^ ((a >> 49) & 1) ^ ((a >> 55) & 1) ^
  957. ((a >> 60) & 1));
  958. uint8_t ecc_bit_4 =
  959. (((a >> 10) & 1) ^ ((a >> 11) & 1) ^ ((a >> 12) & 1) ^ ((a >> 13) & 1) ^ ((a >> 14) & 1) ^
  960. ((a >> 15) & 1) ^ ((a >> 16) & 1) ^ ((a >> 17) & 1) ^ ((a >> 18) & 1) ^ ((a >> 19) & 1) ^
  961. ((a >> 31) & 1) ^ ((a >> 32) & 1) ^ ((a >> 33) & 1) ^ ((a >> 34) & 1) ^ ((a >> 35) & 1) ^
  962. ((a >> 36) & 1) ^ ((a >> 37) & 1) ^ ((a >> 50) & 1) ^ ((a >> 51) & 1) ^ ((a >> 52) & 1) ^
  963. ((a >> 53) & 1) ^ ((a >> 54) & 1) ^ ((a >> 55) & 1) ^ ((a >> 61) & 1) ^ ((a >> 62) & 1) ^
  964. ((a >> 63) & 1));
  965. uint8_t ecc_bit_5 =
  966. (((a >> 20) & 1) ^ ((a >> 21) & 1) ^ ((a >> 22) & 1) ^ ((a >> 23) & 1) ^ ((a >> 24) & 1) ^
  967. ((a >> 25) & 1) ^ ((a >> 26) & 1) ^ ((a >> 27) & 1) ^ ((a >> 28) & 1) ^ ((a >> 29) & 1) ^
  968. ((a >> 30) & 1) ^ ((a >> 31) & 1) ^ ((a >> 32) & 1) ^ ((a >> 33) & 1) ^ ((a >> 34) & 1) ^
  969. ((a >> 35) & 1) ^ ((a >> 36) & 1) ^ ((a >> 37) & 1) ^ ((a >> 56) & 1) ^ ((a >> 57) & 1) ^
  970. ((a >> 58) & 1) ^ ((a >> 59) & 1) ^ ((a >> 60) & 1) ^ ((a >> 61) & 1) ^ ((a >> 62) & 1) ^
  971. ((a >> 63) & 1));
  972. uint8_t ecc_bit_6 =
  973. (((a >> 38) & 1) ^ ((a >> 39) & 1) ^ ((a >> 40) & 1) ^ ((a >> 41) & 1) ^ ((a >> 42) & 1) ^
  974. ((a >> 43) & 1) ^ ((a >> 44) & 1) ^ ((a >> 45) & 1) ^ ((a >> 46) & 1) ^ ((a >> 47) & 1) ^
  975. ((a >> 48) & 1) ^ ((a >> 49) & 1) ^ ((a >> 50) & 1) ^ ((a >> 51) & 1) ^ ((a >> 52) & 1) ^
  976. ((a >> 53) & 1) ^ ((a >> 54) & 1) ^ ((a >> 55) & 1) ^ ((a >> 56) & 1) ^ ((a >> 57) & 1) ^
  977. ((a >> 58) & 1) ^ ((a >> 59) & 1) ^ ((a >> 60) & 1) ^ ((a >> 61) & 1) ^ ((a >> 62) & 1) ^
  978. ((a >> 63) & 1));
  979. uint8_t ecc_bit_7 =
  980. (((a >> 0) & 1) ^ ((a >> 1) & 1) ^ ((a >> 2) & 1) ^ ((a >> 4) & 1) ^ ((a >> 5) & 1) ^
  981. ((a >> 7) & 1) ^ ((a >> 10) & 1) ^ ((a >> 11) & 1) ^ ((a >> 13) & 1) ^ ((a >> 16) & 1) ^
  982. ((a >> 20) & 1) ^ ((a >> 21) & 1) ^ ((a >> 23) & 1) ^ ((a >> 26) & 1) ^ ((a >> 31) & 1) ^
  983. ((a >> 36) & 1) ^ ((a >> 38) & 1) ^ ((a >> 39) & 1) ^ ((a >> 41) & 1) ^ ((a >> 44) & 1) ^
  984. ((a >> 47) & 1) ^ ((a >> 49) & 1) ^ ((a >> 50) & 1) ^ ((a >> 54) & 1) ^ ((a >> 56) & 1) ^
  985. ((a >> 62) & 1));
  986. ecc_bits = (ecc_bit_7 << 7) | (ecc_bit_6 << 6) | (ecc_bit_5 << 5) | (ecc_bit_4 << 4) |
  987. (ecc_bit_3 << 3) | (ecc_bit_2 << 2) | (ecc_bit_1 << 1) | ecc_bit_0;
  988. return ecc_bits;
  989. }
  990. #endif /* defined(__ECC_PRESENT) && (__ECC_PRESENT == 1) */
  991. /** @} */ /* End of Doxygen Group NMSIS_Core_ECC_Functions */
  992. #ifdef __cplusplus
  993. }
  994. #endif
  995. #endif /* __CORE_FEATURE_ECC_H__ */