core_feature_ecc.h 36 KB

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