NMSIS-Core  Version 1.4.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_plic.h
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  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_PLIC__
19 #define __CORE_FEATURE_PLIC__
24 /*
25  * PLIC Feature Configuration Macro:
26  * 1. __PLIC_PRESENT: Define whether Platform Level Interrupt Controller (PLIC) Unit is present or not
27  * * 0: Not present
28  * * 1: Present
29  * 2. __PLIC_BASEADDR: Base address of the PLIC unit.
30  * 3. __PLIC_INTNUM : Define the external interrupt number of PLIC Unit
31  *
32  */
33 #ifdef __cplusplus
34  extern "C" {
35 #endif
36 
37 #include "core_feature_base.h"
38 
39 #if defined(__PLIC_PRESENT) && (__PLIC_PRESENT == 1)
48 /* 32 bits per source */
49 #define PLIC_PRIORITY_OFFSET _AC(0x0000,UL)
50 #define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
51 /* 1 bit per source (1 address) */
52 #define PLIC_PENDING_OFFSET _AC(0x1000,UL)
53 #define PLIC_PENDING_SHIFT_PER_SOURCE 0
55 /* 0x80 per context */
56 #define PLIC_ENABLE_OFFSET _AC(0x2000,UL)
57 #define PLIC_ENABLE_SHIFT_PER_CONTEXT 7
59 #define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL)
60 #define PLIC_CLAIM_OFFSET _AC(0x200004,UL)
61 #define PLIC_THRESHOLD_SHIFT_PER_CONTEXT 12
62 #define PLIC_CLAIM_SHIFT_PER_CONTEXT 12
64 #ifndef __PLIC_BASEADDR
65 /* Base address of PLIC(__PLIC_BASEADDR) should be defined in <Device.h> */
66 #error "__PLIC_BASEADDR is not defined, please check!"
67 #endif
68 
69 /* PLIC Memory mapping of Device */
70 #define PLIC_BASE __PLIC_BASEADDR
79 #ifndef __PLIC_HARTID
80 #define PLIC_GetHartID() (__get_hart_index())
81 #define PLIC_GetHartID_S() (__get_hart_index_s())
82 #else
83 #define PLIC_GetHartID() (__PLIC_HARTID)
84 #define PLIC_GetHartID_S() (__PLIC_HARTID)
85 #endif
86 
87 #define PLIC_GetHartMContextID() (PLIC_GetHartID() << 1)
88 // TODO SMODE HARTID need to handle, maybe use a predefined variable of hartid
89 #define PLIC_GetHartSContextID() ((PLIC_GetHartID_S() << 1) + 1)
90 
91 #define PLIC_PRIORITY_REGADDR(source) ((PLIC_BASE) + (PLIC_PRIORITY_OFFSET) + ((source) << PLIC_PRIORITY_SHIFT_PER_SOURCE))
92 #define PLIC_PENDING_REGADDR(source) ((PLIC_BASE) + (PLIC_PENDING_OFFSET) + (((source) >> 5) * 4))
93 #define PLIC_ENABLE_REGADDR(ctxid, source) ((PLIC_BASE) + (PLIC_ENABLE_OFFSET) + ((ctxid) << PLIC_ENABLE_SHIFT_PER_CONTEXT) + ((source) >> 5) * 4)
94 #define PLIC_THRESHOLD_REGADDR(ctxid) ((PLIC_BASE) + (PLIC_THRESHOLD_OFFSET) + ((ctxid) << PLIC_THRESHOLD_SHIFT_PER_CONTEXT))
95 #define PLIC_CLAIM_REGADDR(ctxid) ((PLIC_BASE) + (PLIC_CLAIM_OFFSET) + ((ctxid) << PLIC_CLAIM_SHIFT_PER_CONTEXT))
96 #define PLIC_COMPLETE_REGADDR(ctxid) (PLIC_CLAIM_REGADDR(ctxid))
97 
98  /* end of group NMSIS_Core_PLIC_Registers */
100 
101 /* ########################## PLIC functions #################################### */
119 __STATIC_FORCEINLINE void PLIC_SetContextThreshold(uint32_t ctxid, uint32_t thresh)
120 {
121  volatile uint32_t *thresh_reg = (uint32_t *)PLIC_THRESHOLD_REGADDR(ctxid);
122 
123  *thresh_reg = thresh;
124 }
125 
137 {
138  volatile uint32_t *thresh_reg = (uint32_t *)PLIC_THRESHOLD_REGADDR(ctxid);
139 
140  return (*thresh_reg);
141 }
142 
153 __STATIC_FORCEINLINE void PLIC_EnableContextInterrupt(uint32_t ctxid, uint32_t source)
154 {
155  volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
156 
157  uint32_t current = *enable_reg;
158  current = current | (1UL << (source & 0x1F));
159  *enable_reg = current;
160 }
161 
172 __STATIC_FORCEINLINE void PLIC_DisableContextInterrupt(uint32_t ctxid, uint32_t source)
173 {
174  volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
175 
176  uint32_t current = *enable_reg;
177  current = current & (~(1UL << (source & 0x1F)));
178  *enable_reg = current;
179 }
180 
193 __STATIC_FORCEINLINE uint32_t PLIC_GetContextInterruptEnable(uint32_t ctxid, uint32_t source)
194 {
195  volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
196 
197  uint32_t current = *enable_reg;
198  current = (current >> (source & 0x1F)) & 0x1;
199  return current;
200 }
201 
213 {
214  volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
215 
216  uint32_t current = *pending_reg;
217  current = current | (1UL << (source & 0x1F));
218  *pending_reg = current;
219 }
220 
232 {
233  volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
234 
235  uint32_t current = *pending_reg;
236  current = current & (~(1UL << (source & 0x1F)));
237  *pending_reg = current;
238 }
239 
252 {
253  volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
254 
255  uint32_t current = *pending_reg;
256  current = (current >> (source & 0x1F)) & 0x1;
257  return current;
258 }
259 
270 __STATIC_FORCEINLINE void PLIC_SetPriority(uint32_t source, uint32_t priority)
271 {
272  volatile uint32_t *priority_reg = (uint32_t *)PLIC_PRIORITY_REGADDR(source);
273 
274  *priority_reg = priority;
275 }
276 
287 __STATIC_FORCEINLINE uint32_t PLIC_GetPriority(uint32_t source)
288 {
289  volatile uint32_t *priority_reg = (uint32_t *)PLIC_PRIORITY_REGADDR(source);
290 
291  return (*priority_reg);
292 }
293 
309 {
310  volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM_REGADDR(ctxid);
311 
312  return (*claim_reg);
313 }
314 
332 __STATIC_FORCEINLINE void PLIC_CompleteContextInterrupt(uint32_t ctxid, uint32_t source)
333 {
334  volatile uint32_t *complete_reg = (uint32_t *)PLIC_COMPLETE_REGADDR(ctxid);
335 
336  *complete_reg = source;
337 }
338 
351 __STATIC_FORCEINLINE void PLIC_Context_Init(uint32_t ctxid, uint32_t num_sources, uint32_t enable, uint32_t thresh)
352 {
353  uint32_t i;
354 
355  for (i = 0; i < num_sources; i ++) {
356  if (enable) {
357  PLIC_EnableContextInterrupt(ctxid, i);
358  } else {
360  }
361  }
362  PLIC_SetContextThreshold(ctxid, thresh);
363 }
364 
365 #define PLIC_Init(num_sources, enable, thresh) PLIC_Context_Init(PLIC_GetHartMContextID(), (num_sources), (enable), (thresh))
366 #define PLIC_Init_S(num_sources, enable, thresh) PLIC_Context_Init(PLIC_GetHartSContextID(), (num_sources), (enable), (thresh))
367 
368 #define PLIC_ClaimInterrupt() PLIC_ClaimContextInterrupt(PLIC_GetHartMContextID())
369 #define PLIC_ClaimInterrupt_S() PLIC_ClaimContextInterrupt(PLIC_GetHartSContextID())
370 
371 #define PLIC_CompleteInterrupt(source) PLIC_CompleteContextInterrupt(PLIC_GetHartMContextID(), (source))
372 #define PLIC_CompleteInterrupt_S(source) PLIC_CompleteContextInterrupt(PLIC_GetHartSContextID(), (source))
373 
374 #define PLIC_GetInterruptEnable(source) PLIC_GetContextInterruptEnable(PLIC_GetHartMContextID(), (source))
375 #define PLIC_GetInterruptEnable_S(source) PLIC_GetContextInterruptEnable(PLIC_GetHartSContextID(), (source))
376 
377 #define PLIC_EnableInterrupt(source) PLIC_EnableContextInterrupt(PLIC_GetHartMContextID(), (source))
378 #define PLIC_EnableInterrupt_S(source) PLIC_EnableContextInterrupt(PLIC_GetHartSContextID(), (source))
379 
380 #define PLIC_DisableInterrupt(source) PLIC_DisableContextInterrupt(PLIC_GetHartMContextID(), (source))
381 #define PLIC_DisableInterrupt_S(source) PLIC_DisableContextInterrupt(PLIC_GetHartSContextID(), (source))
382 
383 #define PLIC_SetThreshold(source, thresh) PLIC_SetContextThreshold(PLIC_GetHartMContextID(), (source), (thresh))
384 #define PLIC_SetThreshold_S(source, thresh) PLIC_SetContextThreshold(PLIC_GetHartSContextID(), (source), (thresh))
385 
386 #define PLIC_GetThreshold() PLIC_GetContextThreshold(PLIC_GetHartMContextID())
387 #define PLIC_GetThreshold_S() PLIC_GetContextThreshold(PLIC_GetHartSContextID())
388 
400 {
401  addr &= (rv_csr_t)(~0x7);
402  __RV_CSR_WRITE(CSR_MTVEC, addr);
403 }
404 
416 {
417  unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
418  return (addr);
419 }
420  /* End of Doxygen Group NMSIS_Core_IntExc */
422 
423 #endif /* defined(__PLIC_PRESENT) && (__PLIC_PRESENT == 1) */
424 
425 #ifdef __cplusplus
426 }
427 #endif
428 #endif
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
#define CSR_MTVEC
#define __STATIC_FORCEINLINE
Define a static function that should be always inlined by the compiler.
Definition: nmsis_gcc.h:70
__STATIC_FORCEINLINE uint32_t PLIC_ClaimContextInterrupt(uint32_t ctxid)
Claim interrupt for plic for selected context.
__STATIC_FORCEINLINE void PLIC_SetInterruptPending(uint32_t source)
Set interrupt pending of selected source plic.
__STATIC_FORCEINLINE uint32_t PLIC_GetInterruptPending(uint32_t source)
Get interrupt pending status of selected source plic.
__STATIC_FORCEINLINE void PLIC_SetContextThreshold(uint32_t ctxid, uint32_t thresh)
Set priority threshold value of plic for selected context.
__STATIC_FORCEINLINE void PLIC_CompleteContextInterrupt(uint32_t ctxid, uint32_t source)
Complete interrupt for plic for selected context.
__STATIC_FORCEINLINE void __set_trap_entry(rv_csr_t addr)
Set Trap entry address.
__STATIC_FORCEINLINE uint32_t PLIC_GetContextInterruptEnable(uint32_t ctxid, uint32_t source)
Get interrupt enable status of selected source plic for selected context.
__STATIC_FORCEINLINE void PLIC_EnableContextInterrupt(uint32_t ctxid, uint32_t source)
Enable interrupt of selected source plic for selected context.
__STATIC_FORCEINLINE rv_csr_t __get_trap_entry(void)
Get trap entry address.
__STATIC_FORCEINLINE void PLIC_Context_Init(uint32_t ctxid, uint32_t num_sources, uint32_t enable, uint32_t thresh)
Perform init for plic for selected context.
__STATIC_FORCEINLINE uint32_t PLIC_GetPriority(uint32_t source)
Get interrupt priority for selected source plic.
__STATIC_FORCEINLINE void PLIC_SetPriority(uint32_t source, uint32_t priority)
Set interrupt priority for selected source plic.
__STATIC_FORCEINLINE void PLIC_ClearInterruptPending(uint32_t source)
Clear interrupt pending of selected source plic.
__STATIC_FORCEINLINE void PLIC_DisableContextInterrupt(uint32_t ctxid, uint32_t source)
Disable interrupt of selected source plic for selected context.
__STATIC_FORCEINLINE uint32_t PLIC_GetContextThreshold(uint32_t ctxid)
Get priority threshold value of plic for selected context.
#define PLIC_PENDING_REGADDR(source)
#define PLIC_PRIORITY_REGADDR(source)
#define PLIC_ENABLE_REGADDR(ctxid, source)
#define PLIC_THRESHOLD_REGADDR(ctxid)
#define PLIC_CLAIM_REGADDR(ctxid)
#define PLIC_COMPLETE_REGADDR(ctxid)
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.