Add minimal multicore launch code
This commit is contained in:
parent
01d9617f9c
commit
5ab60422ad
|
@ -62,8 +62,12 @@ j \name
|
|||
.p2align 2
|
||||
1:
|
||||
// Set up trap vector table. mtvec LSB enables vectoring
|
||||
la t0, .vector_table + 1
|
||||
csrw mtvec, t0
|
||||
la a0, .vector_table + 1
|
||||
csrw mtvec, a0
|
||||
|
||||
// Put spare cores to sleep before setting up core 0 stack
|
||||
csrr a0, mhartid
|
||||
bnez a0, .core1_wait
|
||||
|
||||
// Set up stack pointer before doing anything else
|
||||
la sp, __stack_top
|
||||
|
@ -78,6 +82,22 @@ j \name
|
|||
jal _start
|
||||
j .halt
|
||||
|
||||
.core1_wait:
|
||||
// IRQs disabled, but soft IRQ unmasked -> soft IRQ will exit WFI.
|
||||
csrci mstatus, 0x8
|
||||
csrw mie, 0x8
|
||||
.core1_wait_loop:
|
||||
wfi
|
||||
la a0, core1_entry_vector
|
||||
lw a0, (a0)
|
||||
beqz a0, .core1_wait_loop
|
||||
la sp, __stack_top - 0x10000
|
||||
jalr a0
|
||||
.p2align 2
|
||||
.global core1_entry_vector
|
||||
core1_entry_vector:
|
||||
.word 0
|
||||
|
||||
.global _exit
|
||||
_exit:
|
||||
li a1, IO_EXIT
|
||||
|
|
|
@ -71,16 +71,16 @@ static inline void tb_printf(const char *fmt, ...) {
|
|||
|
||||
#define tb_assert(cond, ...) if (!(cond)) {tb_printf(__VA_ARGS__); tb_exit(-1);}
|
||||
|
||||
static inline void tb_set_softirq() {
|
||||
mm_io->set_softirq = 1;
|
||||
static inline void tb_set_softirq(int idx) {
|
||||
mm_io->set_softirq = 1u << idx;
|
||||
}
|
||||
|
||||
static inline void tb_clr_softirq() {
|
||||
mm_io->clr_softirq = 1;
|
||||
static inline void tb_clr_softirq(int idx) {
|
||||
mm_io->clr_softirq = 1u << idx;
|
||||
}
|
||||
|
||||
static inline bool tb_get_softirq() {
|
||||
return (bool)mm_io->set_softirq;
|
||||
static inline bool tb_get_softirq(int idx) {
|
||||
return (bool)(mm_io->set_softirq & (1u << idx));
|
||||
}
|
||||
|
||||
static inline void tb_set_irq_masked(uint32_t mask) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
SRCS := ../common/init.S main.c
|
||||
APP := hello_multicore
|
||||
CCFLAGS = -march=rv32imc -Os
|
||||
|
||||
include ../common/src_only_app.mk
|
|
@ -0,0 +1,23 @@
|
|||
#include "tb_cxxrtl_io.h"
|
||||
|
||||
extern volatile uintptr_t core1_entry_vector;
|
||||
|
||||
void launch_core1(void (*entry)(void)) {
|
||||
core1_entry_vector = (uintptr_t)entry;
|
||||
tb_set_softirq(1);
|
||||
}
|
||||
|
||||
void core1_main() {
|
||||
tb_clr_softirq(1);
|
||||
tb_puts("Hello world from core 1\n");
|
||||
tb_exit(0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
tb_puts("Hello world from core 0!\n");
|
||||
launch_core1(core1_main);
|
||||
asm volatile (
|
||||
"1: wfi\n"
|
||||
" j 1b\n"
|
||||
);
|
||||
}
|
|
@ -23,12 +23,12 @@ int main() {
|
|||
tb_assert(!(read_csr(mip) & mip_msip), "mip.msip should be clear at start of test\n");
|
||||
|
||||
tb_puts("Dry run\n");
|
||||
tb_set_softirq();
|
||||
tb_assert(tb_get_softirq(), "Failed to set soft_irq through tb\n");
|
||||
tb_set_softirq(0);
|
||||
tb_assert(tb_get_softirq(0), "Failed to set soft_irq through tb\n");
|
||||
tb_assert(read_csr(mip) & mip_msip, "soft_irq not reflected in mip\n");
|
||||
|
||||
tb_clr_softirq();
|
||||
tb_assert(!tb_get_softirq(), "Failed to clear soft_irq through tb\n");
|
||||
tb_clr_softirq(0);
|
||||
tb_assert(!tb_get_softirq(0), "Failed to clear soft_irq through tb\n");
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq clear not reflected in mip\n");
|
||||
|
||||
tb_puts("Set mie only\n");
|
||||
|
@ -37,18 +37,18 @@ int main() {
|
|||
// IRQ should not fire yet.
|
||||
|
||||
tb_puts("Then set IRQ\n");
|
||||
tb_set_softirq();
|
||||
tb_set_softirq(0);
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq should have been cleared by IRQ\n");
|
||||
tb_puts("Returned from IRQ\n");
|
||||
|
||||
tb_puts("Clear mie, do another dry run\n");
|
||||
write_csr(mie, 0);
|
||||
tb_set_softirq();
|
||||
tb_assert(tb_get_softirq(), "Failed to set soft_irq through tb\n");
|
||||
tb_set_softirq(0);
|
||||
tb_assert(tb_get_softirq(0), "Failed to set soft_irq through tb\n");
|
||||
tb_assert(read_csr(mip) & mip_msip, "soft_irq not reflected in mip\n");
|
||||
|
||||
tb_clr_softirq();
|
||||
tb_assert(!tb_get_softirq(), "Failed to clear soft_irq through tb\n");
|
||||
tb_clr_softirq(0);
|
||||
tb_assert(!tb_get_softirq(0), "Failed to clear soft_irq through tb\n");
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq clear not reflected in mip\n");
|
||||
|
||||
return 0;
|
||||
|
@ -58,7 +58,7 @@ void __attribute__((interrupt)) isr_machine_softirq() {
|
|||
tb_puts("-> handle_soft_irq\n");
|
||||
tb_printf("mip = %08x\n", read_csr(mip));
|
||||
tb_printf("mie = %08x\n", read_csr(mie));
|
||||
tb_clr_softirq();
|
||||
tb_clr_softirq(0);
|
||||
tb_printf("mcause = %08x\n", read_csr(mcause));
|
||||
tb_printf("mstatus = %08x\n", read_csr(mstatus));
|
||||
}
|
||||
|
|
|
@ -106,10 +106,10 @@ bus_response mem_access(cxxrtl_design::p_tb &tb, mem_io_state &memio, bus_reques
|
|||
}
|
||||
}
|
||||
else if (req.addr == IO_BASE + IO_SET_SOFTIRQ) {
|
||||
tb.p_soft__irq.set<bool>(true);
|
||||
tb.p_soft__irq.set<uint8_t>(tb.p_soft__irq.get<uint8_t>() | req.wdata);
|
||||
}
|
||||
else if (req.addr == IO_BASE + IO_CLR_SOFTIRQ) {
|
||||
tb.p_soft__irq.set<bool>(false);
|
||||
tb.p_soft__irq.set<uint8_t>(tb.p_soft__irq.get<uint8_t>() & ~req.wdata);
|
||||
}
|
||||
else if (req.addr == IO_BASE + IO_SET_IRQ) {
|
||||
tb.p_irq.set<uint32_t>(tb.p_irq.get<uint32_t>() | req.wdata);
|
||||
|
@ -143,7 +143,7 @@ bus_response mem_access(cxxrtl_design::p_tb &tb, mem_io_state &memio, bus_reques
|
|||
memio.mem[req.addr + 3] << 24;
|
||||
}
|
||||
else if (req.addr == IO_BASE + IO_SET_SOFTIRQ || req.addr == IO_BASE + IO_CLR_SOFTIRQ) {
|
||||
resp.rdata = tb.p_soft__irq.get<bool>();
|
||||
resp.rdata = tb.p_soft__irq.get<uint8_t>();
|
||||
}
|
||||
else if (req.addr == IO_BASE + IO_SET_IRQ || req.addr == IO_BASE + IO_CLR_IRQ) {
|
||||
resp.rdata = tb.p_irq.get<uint32_t>();
|
||||
|
|
|
@ -49,7 +49,7 @@ module tb #(
|
|||
|
||||
// Level-sensitive interrupt sources
|
||||
input wire [NUM_IRQ-1:0] irq, // -> mip.meip
|
||||
input wire soft_irq, // -> mip.msip
|
||||
input wire [1:0] soft_irq, // -> mip.msip
|
||||
input wire timer_irq // -> mip.mtip
|
||||
);
|
||||
|
||||
|
@ -231,7 +231,7 @@ hazard3_cpu_2port #(
|
|||
.dbg_instr_caught_ebreak (hart_instr_caught_ebreak),
|
||||
|
||||
.irq (irq),
|
||||
.soft_irq (soft_irq),
|
||||
.soft_irq (soft_irq[0]),
|
||||
.timer_irq (timer_irq)
|
||||
);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ module tb #(
|
|||
|
||||
// Level-sensitive interrupt sources
|
||||
input wire [NUM_IRQ-1:0] irq, // -> mip.meip
|
||||
input wire soft_irq, // -> mip.msip
|
||||
input wire [1:0] soft_irq, // -> mip.msip
|
||||
input wire timer_irq // -> mip.mtip
|
||||
);
|
||||
|
||||
|
@ -249,7 +249,7 @@ hazard3_cpu_1port #(
|
|||
.dbg_instr_caught_ebreak (hart_instr_caught_ebreak [0]),
|
||||
|
||||
.irq (irq),
|
||||
.soft_irq (soft_irq),
|
||||
.soft_irq (soft_irq[0]),
|
||||
.timer_irq (timer_irq)
|
||||
);
|
||||
|
||||
|
@ -313,7 +313,7 @@ hazard3_cpu_1port #(
|
|||
.dbg_instr_caught_ebreak (hart_instr_caught_ebreak [1]),
|
||||
|
||||
.irq (irq),
|
||||
.soft_irq (soft_irq),
|
||||
.soft_irq (soft_irq[1]),
|
||||
.timer_irq (timer_irq)
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue