Rename 'hart' to 'core'
parent
b223a0a662
commit
ccd55ebad0
|
@ -26,11 +26,11 @@ extern "C" {
|
|||
0 \
|
||||
}
|
||||
|
||||
#define HARTLOCK_INIT \
|
||||
#define CORELOCK_INIT \
|
||||
{ \
|
||||
.lock = SPINLOCK_INIT, \
|
||||
.count = 0, \
|
||||
.hart = -1 \
|
||||
.core = -1 \
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,12 +65,12 @@ typedef struct _semaphore_t
|
|||
} semaphore_t;
|
||||
|
||||
|
||||
typedef struct _hartlock_t
|
||||
typedef struct _corelock_t
|
||||
{
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int hart;
|
||||
} hartlock_t;
|
||||
int core;
|
||||
} corelock_t;
|
||||
|
||||
|
||||
static inline int spinlock_trylock(spinlock_t *lock)
|
||||
|
@ -136,23 +136,23 @@ static inline int semaphore_waiting(semaphore_t *semaphore)
|
|||
return atomic_read(&(semaphore->waiting));
|
||||
}
|
||||
|
||||
static inline int hartlock_trylock(hartlock_t *lock)
|
||||
static inline int corelock_trylock(corelock_t *lock)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned long hart;
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(hart));
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->hart = hart;
|
||||
lock->core = core;
|
||||
res = 0;
|
||||
}
|
||||
else if (lock->hart == hart)
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
|
@ -168,21 +168,21 @@ static inline int hartlock_trylock(hartlock_t *lock)
|
|||
return res;
|
||||
}
|
||||
|
||||
static inline void hartlock_lock(hartlock_t *lock)
|
||||
static inline void corelock_lock(corelock_t *lock)
|
||||
{
|
||||
unsigned long hart;
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(hart));
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->hart = hart;
|
||||
lock->core = core;
|
||||
}
|
||||
else if (lock->hart == hart)
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
|
@ -196,26 +196,26 @@ static inline void hartlock_lock(hartlock_t *lock)
|
|||
{
|
||||
while (atomic_read(&lock->count))
|
||||
;
|
||||
} while (hartlock_trylock(lock));
|
||||
} while (corelock_trylock(lock));
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
}
|
||||
|
||||
static inline void hartlock_unlock(hartlock_t *lock)
|
||||
static inline void corelock_unlock(corelock_t *lock)
|
||||
{
|
||||
unsigned long hart;
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(hart));
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->hart == hart)
|
||||
if (lock->core == core)
|
||||
{
|
||||
/* Same core release lock */
|
||||
lock->count--;
|
||||
if (lock->count <= 0)
|
||||
{
|
||||
lock->hart = -1;
|
||||
lock->core = -1;
|
||||
lock->count = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
|
||||
#define read_time() read_csr(mtime)
|
||||
#define read_cycle() read_csr(mcycle)
|
||||
#define read_hartid() read_csr(mhartid)
|
||||
#define current_coreid() read_csr(mhartid)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* File: printf.c
|
||||
*
|
||||
|
@ -120,7 +120,7 @@ struct param
|
|||
size_t bf_len; /* Buffer length */
|
||||
};
|
||||
|
||||
static hartlock_t lock = HARTLOCK_INIT;
|
||||
static corelock_t lock = CORELOCK_INIT;
|
||||
|
||||
|
||||
|
||||
|
@ -657,10 +657,10 @@ int printk(const char *format, ...)
|
|||
|
||||
va_start(ap, format);
|
||||
/* Begin protected code */
|
||||
hartlock_lock(&lock);
|
||||
corelock_lock(&lock);
|
||||
tfp_format(stdout_putp, uart_putf, format, ap);
|
||||
/* End protected code */
|
||||
hartlock_unlock(&lock);
|
||||
corelock_unlock(&lock);
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -102,10 +102,10 @@ char *_heap_cur = &_heap_start[0];
|
|||
|
||||
void __attribute__((noreturn)) sys_exit(int code)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* First print some diagnostic information. */
|
||||
LOGW(TAG, "sys_exit called by core %ld with 0x%lx\n", hart_id, (uint64_t)code);
|
||||
LOGW(TAG, "sys_exit called by core %ld with 0x%lx\n", core_id, (uint64_t)code);
|
||||
/* Write exit register to pause netlist simulation */
|
||||
volatile uint32_t *reg = (volatile uint32_t *)0x50440080UL;
|
||||
/* Write stop bit and write back */
|
||||
|
|
|
@ -19,25 +19,25 @@
|
|||
#include "sysctl.h"
|
||||
|
||||
volatile clint_t* const clint = (volatile clint_t*)CLINT_BASE_ADDR;
|
||||
static clint_timer_instance_t clint_timer_instance[CLINT_NUM_HARTS];
|
||||
static clint_ipi_instance_t clint_ipi_instance[CLINT_NUM_HARTS];
|
||||
static clint_timer_instance_t clint_timer_instance[CLINT_NUM_CORES];
|
||||
static clint_ipi_instance_t clint_ipi_instance[CLINT_NUM_CORES];
|
||||
|
||||
uint64_t clint_get_time(void)
|
||||
{
|
||||
/* No difference on harts */
|
||||
/* No difference on cores */
|
||||
return clint->mtime;
|
||||
}
|
||||
|
||||
int clint_timer_init(void)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
/* Fill hart's instance with original data */
|
||||
/* Fill core's instance with original data */
|
||||
|
||||
/* clang-format off */
|
||||
clint_timer_instance[hart_id] = (const clint_timer_instance_t)
|
||||
clint_timer_instance[core_id] = (const clint_timer_instance_t)
|
||||
{
|
||||
.interval = 0,
|
||||
.cycles = 0,
|
||||
|
@ -65,8 +65,8 @@ uint64_t clint_timer_get_freq(void)
|
|||
|
||||
int clint_timer_start(uint64_t interval, int single_shot)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set timer interval */
|
||||
if (clint_timer_set_interval(interval) != 0)
|
||||
return -1;
|
||||
|
@ -74,16 +74,16 @@ int clint_timer_start(uint64_t interval, int single_shot)
|
|||
if (clint_timer_set_single_shot(single_shot) != 0)
|
||||
return -1;
|
||||
/* Check settings to prevent interval is 0 */
|
||||
if (clint_timer_instance[hart_id].interval == 0)
|
||||
if (clint_timer_instance[core_id].interval == 0)
|
||||
return -1;
|
||||
/* Check settings to prevent cycles is 0 */
|
||||
if (clint_timer_instance[hart_id].cycles == 0)
|
||||
if (clint_timer_instance[core_id].cycles == 0)
|
||||
return -1;
|
||||
/* Add cycle interval to mtimecmp */
|
||||
uint64_t now = clint->mtime;
|
||||
uint64_t then = now + clint_timer_instance[hart_id].cycles;
|
||||
/* Set mtimecmp by hart id */
|
||||
clint->mtimecmp[hart_id] = then;
|
||||
uint64_t then = now + clint_timer_instance[core_id].cycles;
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] = then;
|
||||
/* Enable interrupts in general */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Enable the Machine-Timer bit in MIE */
|
||||
|
@ -93,51 +93,51 @@ int clint_timer_start(uint64_t interval, int single_shot)
|
|||
|
||||
uint64_t clint_timer_get_interval(void)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
return clint_timer_instance[hart_id].interval;
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
return clint_timer_instance[core_id].interval;
|
||||
}
|
||||
|
||||
int clint_timer_set_interval(uint64_t interval)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Check parameter */
|
||||
if (interval == 0)
|
||||
return -1;
|
||||
|
||||
/* Assign user interval with Millisecond(ms) */
|
||||
clint_timer_instance[hart_id].interval = interval;
|
||||
clint_timer_instance[core_id].interval = interval;
|
||||
/* Convert interval to cycles */
|
||||
clint_timer_instance[hart_id].cycles = interval * clint_timer_get_freq() / 1000ULL;
|
||||
clint_timer_instance[core_id].cycles = interval * clint_timer_get_freq() / 1000ULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_get_single_shot(void)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Get single shot mode by hart id */
|
||||
return clint_timer_instance[hart_id].single_shot;
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get single shot mode by core id */
|
||||
return clint_timer_instance[core_id].single_shot;
|
||||
}
|
||||
|
||||
int clint_timer_set_single_shot(int single_shot)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Set single shot mode by hart id */
|
||||
clint_timer_instance[hart_id].single_shot = single_shot;
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set single shot mode by core id */
|
||||
clint_timer_instance[core_id].single_shot = single_shot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_register(clint_timer_callback_t callback, void* ctx)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_timer_instance[hart_id].callback = callback;
|
||||
clint_timer_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_timer_instance[hart_id].ctx = ctx;
|
||||
clint_timer_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -149,13 +149,13 @@ int clint_timer_deregister(void)
|
|||
|
||||
int clint_ipi_init(void)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
/* Fill hart's instance with original data */
|
||||
/* Fill core's instance with original data */
|
||||
/* clang-format off */
|
||||
clint_ipi_instance[hart_id] = (const clint_ipi_instance_t){
|
||||
clint_ipi_instance[core_id] = (const clint_ipi_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
|
@ -180,21 +180,21 @@ int clint_ipi_disable(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_send(size_t hart_id)
|
||||
int clint_ipi_send(size_t core_id)
|
||||
{
|
||||
if (hart_id >= CLINT_NUM_HARTS)
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
clint->msip[hart_id].msip = 1;
|
||||
clint->msip[core_id].msip = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_clear(size_t hart_id)
|
||||
int clint_ipi_clear(size_t core_id)
|
||||
{
|
||||
if (hart_id >= CLINT_NUM_HARTS)
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
if (clint->msip[hart_id].msip)
|
||||
if (clint->msip[core_id].msip)
|
||||
{
|
||||
clint->msip[hart_id].msip = 0;
|
||||
clint->msip[core_id].msip = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -202,12 +202,12 @@ int clint_ipi_clear(size_t hart_id)
|
|||
|
||||
int clint_ipi_register(clint_ipi_callback_t callback, void* ctx)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_ipi_instance[hart_id].callback = callback;
|
||||
clint_ipi_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_ipi_instance[hart_id].ctx = ctx;
|
||||
clint_ipi_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -219,23 +219,23 @@ int clint_ipi_deregister(void)
|
|||
|
||||
uintptr_t handle_irq_m_timer(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/* Read hart id */
|
||||
uint64_t hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
if (clint_timer_instance[hart_id].callback != NULL)
|
||||
clint_timer_instance[hart_id].callback(
|
||||
clint_timer_instance[hart_id].ctx);
|
||||
if (clint_timer_instance[core_id].callback != NULL)
|
||||
clint_timer_instance[core_id].callback(
|
||||
clint_timer_instance[core_id].ctx);
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
write_csr(mie, ie_flag);
|
||||
/* If not single shot and cycle interval is not 0, repeat this timer */
|
||||
if (!clint_timer_instance[hart_id].single_shot && clint_timer_instance[hart_id].cycles != 0)
|
||||
if (!clint_timer_instance[core_id].single_shot && clint_timer_instance[core_id].cycles != 0)
|
||||
{
|
||||
/* Set mtimecmp by hart id */
|
||||
clint->mtimecmp[hart_id] += clint_timer_instance[hart_id].cycles;
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] += clint_timer_instance[core_id].cycles;
|
||||
}
|
||||
else
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
|
@ -244,15 +244,15 @@ uintptr_t handle_irq_m_timer(uintptr_t cause, uintptr_t epc)
|
|||
|
||||
uintptr_t handle_irq_m_soft(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/* Read hart id */
|
||||
uint64_t hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Clear the Machine-Software bit in MIE to prevent call again */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Clear ipi flag */
|
||||
clint_ipi_clear(hart_id);
|
||||
if (clint_ipi_instance[hart_id].callback != NULL)
|
||||
clint_ipi_instance[hart_id].callback(clint_ipi_instance[hart_id].ctx);
|
||||
clint_ipi_clear(core_id);
|
||||
if (clint_ipi_instance[core_id].callback != NULL)
|
||||
clint_ipi_instance[core_id].callback(clint_ipi_instance[core_id].ctx);
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
set_csr(mie, MIP_MSIP);
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
*
|
||||
* | Address -| Description |
|
||||
* |------------|---------------------------------|
|
||||
* | 0x02000000 | msip for hart 0 |
|
||||
* | 0x02000004 | msip for hart 1 |
|
||||
* | 0x02000000 | msip for core 0 |
|
||||
* | 0x02000004 | msip for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x02003FF8 | msip for hart 4094 |
|
||||
* | 0x02003FF8 | msip for core 4094 |
|
||||
* | | |
|
||||
* | 0x02004000 | mtimecmp for hart 0 |
|
||||
* | 0x02004008 | mtimecmp for hart 1 |
|
||||
* | 0x02004000 | mtimecmp for core 0 |
|
||||
* | 0x02004008 | mtimecmp for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x0200BFF0 | mtimecmp For hart 4094 |
|
||||
* | 0x0200BFF0 | mtimecmp For core 4094 |
|
||||
* | 0x0200BFF8 | mtime |
|
||||
* | | |
|
||||
* | 0x0200C000 | Reserved |
|
||||
|
@ -57,9 +57,9 @@ extern "C" {
|
|||
#define CLINT_MTIME (0xBFF8)
|
||||
#define CLINT_MTIME_SIZE (0x8)
|
||||
/* Max number of cores */
|
||||
#define CLINT_MAX_HARTS (4095)
|
||||
#define CLINT_MAX_CORES (4095)
|
||||
/* Real number of cores */
|
||||
#define CLINT_NUM_HARTS (2)
|
||||
#define CLINT_NUM_CORES (2)
|
||||
/* Clock frequency division factor */
|
||||
#define CLINT_CLOCK_DIV (50)
|
||||
/* clang-format on */
|
||||
|
@ -68,11 +68,11 @@ extern "C" {
|
|||
* @brief MSIP Registers
|
||||
*
|
||||
* Machine-mode software interrupts are generated by writing to a
|
||||
* per-hart memory-mapped control register. The msip registers are
|
||||
* per-core memory-mapped control register. The msip registers are
|
||||
* 32-bit wide WARL registers, where the LSB is reflected in the
|
||||
* msip bit of the associated hart’s mip register. Other bits in
|
||||
* msip bit of the associated core’s mip register. Other bits in
|
||||
* the msip registers are hardwired to zero. The mapping supports
|
||||
* up to 4095 machine-mode harts.
|
||||
* up to 4095 machine-mode cores.
|
||||
*/
|
||||
typedef struct _clint_msip_t
|
||||
{
|
||||
|
@ -82,13 +82,13 @@ typedef struct _clint_msip_t
|
|||
|
||||
/**
|
||||
* @brief Timer compare Registers Machine-mode timer interrupts are
|
||||
* generated by a real-time counter and a per-hart comparator. The
|
||||
* generated by a real-time counter and a per-core comparator. The
|
||||
* mtime register is a 64-bit read-only register that contains the
|
||||
* current value of the real-time counter. Each mtimecmp register
|
||||
* holds its hart’s time comparator. A timer interrupt is pending
|
||||
* holds its core’s time comparator. A timer interrupt is pending
|
||||
* whenever mtime is greater than or equal to the value in a
|
||||
* hart’s mtimecmp register. The timer interrupt is reflected in
|
||||
* the mtip bit of the associated hart’s mip register.
|
||||
* core’s mtimecmp register. The timer interrupt is reflected in
|
||||
* the mtip bit of the associated core’s mip register.
|
||||
*/
|
||||
typedef uint64_t clint_mtimecmp_t;
|
||||
|
||||
|
@ -117,11 +117,11 @@ typedef uint64_t clint_mtime_t;
|
|||
typedef struct _clint_t
|
||||
{
|
||||
/* 0x0000 to 0x3FF8, MSIP Registers */
|
||||
clint_msip_t msip[CLINT_MAX_HARTS];
|
||||
clint_msip_t msip[CLINT_MAX_CORES];
|
||||
/* Resverd space, do not use */
|
||||
uint32_t resv0;
|
||||
/* 0x4000 to 0xBFF0, Timer Compare Registers */
|
||||
clint_mtimecmp_t mtimecmp[CLINT_MAX_HARTS];
|
||||
clint_mtimecmp_t mtimecmp[CLINT_MAX_CORES];
|
||||
/* 0xBFF8, Time Register */
|
||||
clint_mtime_t mtime;
|
||||
} __attribute__((packed, aligned(4))) clint_t;
|
||||
|
@ -287,27 +287,27 @@ int clint_ipi_enable(void);
|
|||
int clint_ipi_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Send local interprocessor interrupt to core by hart id
|
||||
* @brief Send local interprocessor interrupt to core by core id
|
||||
*
|
||||
* @param[in] hart_id The hart identifier
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_send(size_t hart_id);
|
||||
int clint_ipi_send(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Clear local interprocessor interrupt
|
||||
*
|
||||
* @param[in] hart_id The hart identifier
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 1 An IPI was pending
|
||||
* - 0 Non IPI was pending
|
||||
* - -1 Fail
|
||||
*/
|
||||
int clint_ipi_clear(size_t hart_id);
|
||||
int clint_ipi_clear(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Set user callback function when interprocessor interrupt
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @file
|
||||
* @brief The PLIC complies with the RISC-V Privileged Architecture
|
||||
* specification, and can support a maximum of 1023 external
|
||||
* interrupt sources targeting up to 15,872 hart contexts.
|
||||
* interrupt sources targeting up to 15,872 core contexts.
|
||||
*
|
||||
* @note PLIC RAM Layout
|
||||
*
|
||||
|
@ -72,7 +72,7 @@ extern "C" {
|
|||
#define PLIC_NUM_PRIORITIES (7)
|
||||
|
||||
/* Real number of cores */
|
||||
#define PLIC_NUM_HARTS (2)
|
||||
#define PLIC_NUM_CORES (2)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
|
@ -336,7 +336,7 @@ typedef struct _plic_target_t
|
|||
* PLIC is Platform-Level Interrupt Controller. The PLIC complies
|
||||
* with the RISC-V Privileged Architecture specification, and can
|
||||
* support a maximum of 1023 external interrupt sources targeting
|
||||
* up to 15,872 hart contexts.
|
||||
* up to 15,872 core contexts.
|
||||
*/
|
||||
typedef struct _plic_t
|
||||
{
|
||||
|
|
|
@ -27,31 +27,31 @@ typedef struct _plic_instance_t
|
|||
void* ctx;
|
||||
} plic_instance_t;
|
||||
|
||||
static plic_instance_t plic_instance[PLIC_NUM_HARTS][IRQN_MAX];
|
||||
static plic_instance_t plic_instance[PLIC_NUM_CORES][IRQN_MAX];
|
||||
|
||||
int plic_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* Get current hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Get current core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
|
||||
/* Disable all interrupts for the current hart. */
|
||||
/* Disable all interrupts for the current core. */
|
||||
for (i = 0; i < ((PLIC_NUM_SOURCES + 32u) / 32u); i++)
|
||||
plic->target_enables.target[hart_id].enable[i] = 0;
|
||||
plic->target_enables.target[core_id].enable[i] = 0;
|
||||
|
||||
/* Set priorities to zero. */
|
||||
for (i = 0; i < PLIC_NUM_SOURCES; i++)
|
||||
plic->source_priorities.priority[i] = 0;
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
plic->targets.target[hart_id].priority_threshold = 0;
|
||||
plic->targets.target[core_id].priority_threshold = 0;
|
||||
|
||||
/* Clear PLIC instance for every cores */
|
||||
for (i = 0; i < IRQN_MAX; i++)
|
||||
{
|
||||
/* clang-format off */
|
||||
plic_instance[hart_id][i] = (const plic_instance_t){
|
||||
plic_instance[core_id][i] = (const plic_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
|
@ -64,7 +64,7 @@ int plic_init(void)
|
|||
* at any time, even if the EIP is not set.
|
||||
*/
|
||||
i = 0;
|
||||
while (plic->targets.target[hart_id].claim_complete > 0 && i < 100)
|
||||
while (plic->targets.target[core_id].claim_complete > 0 && i < 100)
|
||||
{
|
||||
/* This loop will clear pending bit on the interrupt source */
|
||||
i++;
|
||||
|
@ -80,13 +80,13 @@ int plic_irq_enable(plic_irq_t irq_number)
|
|||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long hart_id = read_hartid();
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[hart_id].enable[irq_number / 32];
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Set enable bit in enable bit array */
|
||||
current |= (uint32_t)1 << (irq_number % 32);
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[hart_id].enable[irq_number / 32] = current;
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,13 +95,13 @@ int plic_irq_disable(plic_irq_t irq_number)
|
|||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long hart_id = read_hartid();
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[hart_id].enable[irq_number / 32];
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Clear enable bit in enable bit array */
|
||||
current &= ~((uint32_t)1 << (irq_number % 32));
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[hart_id].enable[irq_number / 32] = current;
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -126,27 +126,27 @@ uint32_t plic_get_priority(plic_irq_t irq_number)
|
|||
|
||||
uint32_t plic_irq_claim(void)
|
||||
{
|
||||
unsigned long hart_id = read_hartid();
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ claim */
|
||||
return plic->targets.target[hart_id].claim_complete;
|
||||
return plic->targets.target[core_id].claim_complete;
|
||||
}
|
||||
|
||||
int plic_irq_complete(uint32_t source)
|
||||
{
|
||||
unsigned long hart_id = read_hartid();
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[hart_id].claim_complete = source;
|
||||
plic->targets.target[core_id].claim_complete = source;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void* ctx)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
plic_instance[hart_id][irq].callback = callback;
|
||||
plic_instance[core_id][irq].callback = callback;
|
||||
/* Assign user context */
|
||||
plic_instance[hart_id][irq].ctx = ctx;
|
||||
plic_instance[core_id][irq].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -171,25 +171,25 @@ uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
|
|||
*/
|
||||
if (read_csr(mip) & MIP_MEIP)
|
||||
{
|
||||
/* Get current hart id */
|
||||
uint64_t hart_id = read_hartid();
|
||||
/* Get current core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Get primitive interrupt enable flag */
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
/* Get current IRQ num */
|
||||
uint32_t int_num = plic->targets.target[hart_id].claim_complete;
|
||||
uint32_t int_num = plic->targets.target[core_id].claim_complete;
|
||||
/* Get primitive IRQ threshold */
|
||||
uint32_t int_threshold = plic->targets.target[hart_id].priority_threshold;
|
||||
uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
|
||||
/* Set new IRQ threshold = current IRQ threshold */
|
||||
plic->targets.target[hart_id].priority_threshold = plic->source_priorities.priority[int_num];
|
||||
plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
|
||||
/* Disable software interrupt and timer interrupt */
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
/* Enable global interrupt */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
if (plic_instance[hart_id][int_num].callback)
|
||||
plic_instance[hart_id][int_num].callback(
|
||||
plic_instance[hart_id][int_num].ctx);
|
||||
if (plic_instance[core_id][int_num].callback)
|
||||
plic_instance[core_id][int_num].callback(
|
||||
plic_instance[core_id][int_num].ctx);
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[hart_id].claim_complete = int_num;
|
||||
plic->targets.target[core_id].claim_complete = int_num;
|
||||
/* Disable global interrupt */
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
/* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
|
||||
|
@ -197,7 +197,7 @@ uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
|
|||
/* Restore primitive interrupt enable flag */
|
||||
write_csr(mie, ie_flag);
|
||||
/* Restore primitive IRQ threshold */
|
||||
plic->targets.target[hart_id].priority_threshold = int_threshold;
|
||||
plic->targets.target[core_id].priority_threshold = int_threshold;
|
||||
}
|
||||
|
||||
return epc;
|
||||
|
|
|
@ -23,12 +23,12 @@ volatile uarths_t *const uarths = (volatile uarths_t *)UARTHS_BASE_ADDR;
|
|||
|
||||
static inline int uart_putc(char c)
|
||||
{
|
||||
/* Read hart id */
|
||||
unsigned long hart_id = read_hartid();
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set print data reg */
|
||||
volatile uint32_t *reg = (volatile uint32_t *)0x50440080UL;
|
||||
/* Push data out */
|
||||
if (hart_id == 0)
|
||||
if (core_id == 0)
|
||||
{
|
||||
/* Select core 0 data reg */
|
||||
*reg = (0UL << 30) | c;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "encoding.h"
|
||||
int main()
|
||||
{
|
||||
uint64_t core_id = read_hartid();
|
||||
uint64_t core_id = current_coreid();
|
||||
if (core_id == 0)
|
||||
{
|
||||
printf("Core 0 Hello, world!\n");
|
||||
|
|
Loading…
Reference in New Issue