feat: add lab-rv32i-c-interrupts card
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#ifndef C10_COMMON_H
|
||||
#define C10_COMMON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hazard3_csr.h"
|
||||
#include "tb_cxxrtl_io.h"
|
||||
|
||||
#define MSTATUS_MIE UINT32_C(0x00000008)
|
||||
#define MIE_MSIE UINT32_C(0x00000008)
|
||||
#define MIP_MSIP UINT32_C(0x00000008)
|
||||
#define MACHINE_ECALL_CAUSE UINT32_C(0x0000000b)
|
||||
#define MACHINE_SOFTWARE_IRQ_CAUSE UINT32_C(0x80000003)
|
||||
|
||||
static inline void c10_global_irq_enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
else
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
}
|
||||
|
||||
static inline void c10_software_irq_enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
set_csr(mie, MIE_MSIE);
|
||||
else
|
||||
clear_csr(mie, MIE_MSIE);
|
||||
}
|
||||
|
||||
static inline void c10_disable_interrupts(void)
|
||||
{
|
||||
c10_global_irq_enable(false);
|
||||
c10_software_irq_enable(false);
|
||||
tb_clr_softirq(0);
|
||||
}
|
||||
|
||||
static inline void c10_settle(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < 32u; ++i)
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
|
||||
static inline bool c10_wait_for(volatile uint32_t *value, uint32_t expected)
|
||||
{
|
||||
for (uint32_t i = 0; i < 100000u; ++i) {
|
||||
if (*value == expected)
|
||||
return true;
|
||||
__asm__ volatile("wfi");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void c10_report(const char *label, uint32_t value)
|
||||
{
|
||||
tb_puts(label);
|
||||
tb_put_u32(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "c10_common.h"
|
||||
|
||||
volatile uint32_t g_task01_count;
|
||||
volatile uint32_t g_task01_mcause;
|
||||
volatile uint32_t g_task01_mepc;
|
||||
volatile uint32_t g_task01_resume_pc;
|
||||
volatile uint32_t g_task01_resumed;
|
||||
volatile uint32_t g_task01_pass;
|
||||
|
||||
void __attribute__((interrupt("machine"))) handle_exception(void)
|
||||
{
|
||||
const uint32_t cause = read_csr(mcause);
|
||||
const uint32_t pc = read_csr(mepc);
|
||||
|
||||
g_task01_count++;
|
||||
g_task01_mcause = cause;
|
||||
g_task01_mepc = pc;
|
||||
g_task01_resume_pc = pc + 4u;
|
||||
write_csr(mepc, g_task01_resume_pc);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
c10_disable_interrupts();
|
||||
__asm__ volatile("ecall");
|
||||
g_task01_resumed = 1u;
|
||||
|
||||
g_task01_pass = g_task01_count == 1u &&
|
||||
g_task01_mcause == MACHINE_ECALL_CAUSE &&
|
||||
g_task01_resume_pc - g_task01_mepc == 4u &&
|
||||
g_task01_resumed == 1u;
|
||||
|
||||
c10_report("T01 count=", g_task01_count);
|
||||
c10_report("T01 mcause=", g_task01_mcause);
|
||||
c10_report("T01 mepc=", g_task01_mepc);
|
||||
c10_report("T01 resume_pc=", g_task01_resume_pc);
|
||||
c10_report("T01 delta=", g_task01_resume_pc - g_task01_mepc);
|
||||
c10_report("T01 resumed=", g_task01_resumed);
|
||||
c10_report("T01 pass=", g_task01_pass);
|
||||
return g_task01_pass ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "c10_common.h"
|
||||
|
||||
volatile uint32_t g_task02_count;
|
||||
volatile uint32_t g_task02_mcause;
|
||||
volatile uint32_t g_task02_pending_in_handler;
|
||||
volatile uint32_t g_task02_pending_before_enable;
|
||||
volatile uint32_t g_task02_pending_after;
|
||||
volatile uint32_t g_task02_resumed;
|
||||
volatile uint32_t g_task02_pass;
|
||||
|
||||
void __attribute__((interrupt("machine"))) isr_machine_softirq(void)
|
||||
{
|
||||
g_task02_mcause = read_csr(mcause);
|
||||
g_task02_pending_in_handler =
|
||||
(read_csr(mip) & MIP_MSIP) != 0u ? 1u : 0u;
|
||||
tb_clr_softirq(0);
|
||||
g_task02_count++;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
c10_disable_interrupts();
|
||||
c10_software_irq_enable(true);
|
||||
tb_set_softirq(0);
|
||||
c10_settle();
|
||||
g_task02_pending_before_enable =
|
||||
(read_csr(mip) & MIP_MSIP) != 0u ? 1u : 0u;
|
||||
|
||||
c10_global_irq_enable(true);
|
||||
const bool handled = c10_wait_for(&g_task02_count, 1u);
|
||||
g_task02_resumed = 1u;
|
||||
|
||||
c10_global_irq_enable(false);
|
||||
c10_settle();
|
||||
g_task02_pending_after =
|
||||
(read_csr(mip) & MIP_MSIP) != 0u ? 1u : 0u;
|
||||
c10_software_irq_enable(false);
|
||||
|
||||
g_task02_pass = handled &&
|
||||
g_task02_count == 1u &&
|
||||
g_task02_mcause == MACHINE_SOFTWARE_IRQ_CAUSE &&
|
||||
g_task02_pending_in_handler == 1u &&
|
||||
g_task02_pending_before_enable == 1u &&
|
||||
g_task02_pending_after == 0u &&
|
||||
g_task02_resumed == 1u;
|
||||
|
||||
c10_report("T02 count=", g_task02_count);
|
||||
c10_report("T02 mcause=", g_task02_mcause);
|
||||
c10_report("T02 pending_before=", g_task02_pending_before_enable);
|
||||
c10_report("T02 pending_in_handler=", g_task02_pending_in_handler);
|
||||
c10_report("T02 pending_after=", g_task02_pending_after);
|
||||
c10_report("T02 resumed=", g_task02_resumed);
|
||||
c10_report("T02 pass=", g_task02_pass);
|
||||
return g_task02_pass ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "c10_common.h"
|
||||
|
||||
volatile uint32_t g_task03_count;
|
||||
volatile uint32_t g_task03_mcause;
|
||||
volatile uint32_t g_task03_pending_asserted;
|
||||
volatile uint32_t g_task03_blocked_without_msie;
|
||||
volatile uint32_t g_task03_blocked_without_mie;
|
||||
volatile uint32_t g_task03_delivered_with_both;
|
||||
volatile uint32_t g_task03_pending_after;
|
||||
volatile uint32_t g_task03_pass;
|
||||
|
||||
void __attribute__((interrupt("machine"))) isr_machine_softirq(void)
|
||||
{
|
||||
g_task03_mcause = read_csr(mcause);
|
||||
tb_clr_softirq(0);
|
||||
g_task03_count++;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
c10_disable_interrupts();
|
||||
tb_set_softirq(0);
|
||||
c10_settle();
|
||||
g_task03_pending_asserted =
|
||||
(read_csr(mip) & MIP_MSIP) != 0u ? 1u : 0u;
|
||||
|
||||
c10_global_irq_enable(true);
|
||||
c10_settle();
|
||||
g_task03_blocked_without_msie = g_task03_count == 0u ? 1u : 0u;
|
||||
|
||||
c10_global_irq_enable(false);
|
||||
c10_software_irq_enable(true);
|
||||
c10_settle();
|
||||
g_task03_blocked_without_mie = g_task03_count == 0u ? 1u : 0u;
|
||||
|
||||
c10_global_irq_enable(true);
|
||||
g_task03_delivered_with_both = c10_wait_for(&g_task03_count, 1u) ? 1u : 0u;
|
||||
|
||||
c10_global_irq_enable(false);
|
||||
c10_settle();
|
||||
g_task03_pending_after =
|
||||
(read_csr(mip) & MIP_MSIP) != 0u ? 1u : 0u;
|
||||
c10_software_irq_enable(false);
|
||||
|
||||
g_task03_pass = g_task03_pending_asserted == 1u &&
|
||||
g_task03_blocked_without_msie == 1u &&
|
||||
g_task03_blocked_without_mie == 1u &&
|
||||
g_task03_delivered_with_both == 1u &&
|
||||
g_task03_count == 1u &&
|
||||
g_task03_mcause == MACHINE_SOFTWARE_IRQ_CAUSE &&
|
||||
g_task03_pending_after == 0u;
|
||||
|
||||
c10_report("T03 pending=", g_task03_pending_asserted);
|
||||
c10_report("T03 blocked_no_msie=", g_task03_blocked_without_msie);
|
||||
c10_report("T03 blocked_no_mie=", g_task03_blocked_without_mie);
|
||||
c10_report("T03 delivered_both=", g_task03_delivered_with_both);
|
||||
c10_report("T03 count=", g_task03_count);
|
||||
c10_report("T03 mcause=", g_task03_mcause);
|
||||
c10_report("T03 pending_after=", g_task03_pending_after);
|
||||
c10_report("T03 pass=", g_task03_pass);
|
||||
return g_task03_pass ? 0 : 1;
|
||||
}
|
||||
Reference in New Issue
Block a user