Add minimal multicore launch code

This commit is contained in:
Luke Wren 2021-12-17 01:24:11 +00:00
parent 01d9617f9c
commit 5ab60422ad
8 changed files with 74 additions and 26 deletions

View File

@ -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

View File

@ -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) {

View File

@ -0,0 +1,5 @@
SRCS := ../common/init.S main.c
APP := hello_multicore
CCFLAGS = -march=rv32imc -Os
include ../common/src_only_app.mk

View File

@ -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"
);
}

View File

@ -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));
}

View File

@ -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>();

View File

@ -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)
);

View File

@ -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)
);