2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-25 03:08:27 +08:00

runtime: biprocessor support (incomplete, WIP)

This commit is contained in:
Sebastien Bourdeauducq 2015-04-04 22:08:32 +08:00
parent 277e038569
commit cbdc1ba46f
15 changed files with 201 additions and 82 deletions

View File

@ -1,9 +1,21 @@
include $(MSCDIR)/software/common.mak
BOARD=papilio_pro
SERIAL=/dev/ttyUSB1
OBJECTS_SERVICES=exception_jmp.o exceptions.o rtio.o dds.o
OBJECTS=isr.o elf_loader.o services.o comm_serial.o test_mode.o main.o
OBJECTS=isr.o elf_loader.o kernelcpu.o exception_jmp.o exceptions.o services.o comm_serial.o gpio.o rtio.o dds.o ksupport_data.o test_mode.o main.o
UNIPROCESSOR := $(shell echo -e "\#include <generated/csr.h>\nCSR_KERNEL_CPU_BASE" | $(CC_normal) $(CFLAGS) -E - | tail -n 1 | grep -c CSR_KERNEL_CPU_BASE)
ifeq ($(UNIPROCESSOR),0)
OBJECTS += kernelcpu.o ksupport_data.o
CFLAGS += -DARTIQ_BIPROCESSOR
SERVICE_TABLE_INPUT = ksupport.elf
else
ifeq ($(UNIPROCESSOR),1)
OBJECTS += $(OBJECTS_SERVICES)
else
$(error failed to determine uniprocessor/biprocessor build)
endif
endif
all: runtime.bin
@ -30,17 +42,22 @@ runtime.elf: $(OBJECTS) libs
-lbase -lcompiler-rt
@chmod -x $@
ksupport.elf: ksupport.o
ksupport.elf: $(OBJECTS_SERVICES) ksupport.o
$(LD) $(LDFLAGS) \
-T ksupport.ld \
-N -o $@ \
$(MSCDIR)/software/libbase/crt0-$(CPU).o \
ksupport.o
$^
@chmod -x $@
ksupport_data.o: ksupport.bin
$(LD) -r -b binary -o $@ $<
service_table.h: $(SERVICE_TABLE_INPUT)
@echo " GEN " $@ && ./gen_service_table.py $(SERVICE_TABLE_INPUT) > $@
services.c: service_table.h
main.o: main.c
$(compile-dep)
@ -54,15 +71,9 @@ libs:
$(MAKE) -C $(MSCDIR)/software/libcompiler-rt
$(MAKE) -C $(MSCDIR)/software/libbase
load: runtime.bin
$(MAKE) -C $(MSCDIR)/tools
$(MSCDIR)/tools/flterm --port $(SERIAL) --kernel runtime.bin
flash: runtime.fbi
$(MSCDIR)/flash_extra.py $(BOARD) runtime.fbi 0x70000
clean:
$(RM) $(OBJECTS) $(OBJECTS:.o=.d) runtime.elf runtime.bin runtime.fbi .*~ *~
$(RM) ksupport.d ksupport.o ksupport.elf ksupport.bin
$(RM) $(OBJECTS) $(OBJECTS:.o=.d) $(OBJECTS_SERVICES) $(OBJECTS_SERVICES:.o=.d)
$(RM) runtime.elf runtime.bin runtime.fbi .*~ *~
$(RM) service_table.h ksupport.d ksupport.o ksupport.elf ksupport.bin
.PHONY: all main.o clean libs load

View File

@ -151,7 +151,12 @@ static void receive_and_run_kernel(kernel_runner run_kernel)
send_char(MSGTYPE_KERNEL_EXCEPTION);
send_int(eid);
for(i=0;i<3;i++)
#ifdef ARTIQ_BIPROCESSOR
#warning TODO
send_llint(0LL);
#else
send_llint(exception_params[i]);
#endif
break;
case KERNEL_RUN_STARTUP_FAILED:
send_char(MSGTYPE_KERNEL_STARTUP_FAILED);
@ -172,9 +177,16 @@ void comm_serve(object_loader load_object, kernel_runner run_kernel)
if(msgtype == MSGTYPE_REQUEST_IDENT) {
send_char(MSGTYPE_IDENT);
send_int(0x41524f52); /* "AROR" - ARTIQ runtime on OpenRISC */
#ifdef ARTIQ_BIPROCESSOR
#warning TODO
send_int(125*1000*1000);
send_char(0);
send_char(1);
#else
send_int(rtio_frequency_i_read());
send_char(rtio_frequency_fn_read());
send_char(rtio_frequency_fd_read());
#endif
} else if(msgtype == MSGTYPE_LOAD_OBJECT)
receive_and_load_object(load_object);
else if(msgtype == MSGTYPE_RUN_KERNEL)
@ -253,8 +265,12 @@ int comm_rpc(int rpc_num, ...)
eid = receive_int();
retval = receive_int();
#ifdef ARTIQ_BIPROCESSOR
#warning TODO
#else
if(eid != EID_NONE)
exception_raise(eid);
#endif
return retval;
}

View File

@ -1,5 +1,9 @@
#include <generated/csr.h>
#include "exceptions.h"
#ifndef ARTIQ_BIPROCESSOR
#include "comm.h"
#endif
#define MAX_EXCEPTION_CONTEXTS 64
@ -45,7 +49,11 @@ void exception_raise_params(int id,
exception_params[2] = p2;
exception_longjmp(exception_contexts[--ec_top].jb);
} else {
#ifdef ARTIQ_BIPROCESSOR
#warning TODO
#else
comm_log("ERROR: uncaught exception, ID=%d\n", id);
#endif
while(1);
}
}

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
import sys
services = [
("syscalls", [
("rpc", "comm_rpc"),
("rtio_oe", "rtio_oe"),
("rtio_set", "rtio_set"),
("rtio_get_counter", "rtio_get_counter"),
("rtio_get", "rtio_get"),
("rtio_pileup_count", "rtio_pileup_count"),
("dds_phase_clear_en", "dds_phase_clear_en"),
("dds_program", "dds_program"),
]),
("eh", [
("setjmp", "exception_setjmp"),
("push", "exception_push"),
("pop", "exception_pop"),
("getid", "exception_getid"),
("raise", "exception_raise"),
])
]
def print_uniprocessor():
for name, contents in services:
print("static const struct symbol {}[] = {{".format(name))
for name, value in contents:
print(" {{\"{}\", {}}},".format(name, value))
print(" {NULL, NULL}")
print("};")
def print_biprocessor(ksupport_elf_filename):
from elftools.elf.elffile import ELFFile
with open(ksupport_elf_filename, "rb") as f:
elf = ELFFile(f)
symtab = elf.get_section_by_name(b".symtab")
symbols = {symbol.name: symbol.entry.st_value
for symbol in symtab.iter_symbols()}
for name, contents in services:
print("static const struct symbol {}[] = {{".format(name))
for name, value in contents:
print(" {{\"{}\", (void *)0x{:08x}}},"
.format(name, symbols[bytes(value, "ascii")]))
print(" {NULL, NULL}")
print("};")
def main():
if len(sys.argv) == 1:
print_uniprocessor()
elif len(sys.argv) == 2:
print_biprocessor(sys.argv[1])
else:
print("Incorrect number of command line arguments")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,14 +0,0 @@
#include <generated/csr.h>
#include "gpio.h"
void gpio_set(int channel, int value)
{
static int csr_value;
if(value)
csr_value |= 1 << channel;
else
csr_value &= ~(1 << channel);
leds_out_write(csr_value);
}

View File

@ -1,6 +0,0 @@
#ifndef __GPIO_H
#define __GPIO_H
void gpio_set(int channel, int value);
#endif /* __GPIO_H */

View File

@ -1,20 +1,19 @@
#include <generated/csr.h>
#ifdef CSR_KERNEL_CPU_BASE
#include <stdio.h>
#include <string.h>
#include <system.h>
#include <generated/csr.h>
#include "kernelcpu.h"
extern char _binary_ksupport_bin_start;
extern char _binary_ksupport_bin_end;
void kernelcpu_start(void)
void kernelcpu_start(void *addr)
{
memcpy((void *)KERNELCPU_EXEC_ADDRESS, &_binary_ksupport_bin_start,
&_binary_ksupport_bin_end - &_binary_ksupport_bin_start);
KERNELCPU_MAILBOX = (unsigned int)addr;
flush_l2_cache();
kernel_cpu_reset_write(0);
}
@ -23,5 +22,3 @@ void kernelcpu_stop(void)
{
kernel_cpu_reset_write(1);
}
#endif /* CSR_KERNEL_CPU_BASE */

View File

@ -4,11 +4,11 @@
#include <hw/common.h>
#define KERNELCPU_EXEC_ADDRESS 0x40020000
#define KERNELCPU_KMAIN_ADDRESS 0x40022000
#define KERNELCPU_PAYLOAD_ADDRESS 0x40024000
#define KERNELCPU_MAILBOX MMPTR(0xd0000000)
void kernelcpu_start(void);
void kernelcpu_start(void *addr);
void kernelcpu_stop(void);
#endif /* __KERNELCPU_H */

View File

@ -1,3 +1,9 @@
#include "kernelcpu.h"
#include "exceptions.h"
#include "comm.h"
#include "rtio.h"
#include "dds.h"
void exception_handler(unsigned long vect, unsigned long *sp);
void exception_handler(unsigned long vect, unsigned long *sp)
{
@ -5,12 +11,32 @@ void exception_handler(unsigned long vect, unsigned long *sp)
for(;;);
}
extern void kmain(void);
typedef void (*kernel_function)(void);
int main(void);
int main(void)
{
kmain();
/* TODO: report end of kernel to comm CPU */
kernel_function k;
void *jb;
k = (kernel_function)KERNELCPU_MAILBOX;
jb = exception_push();
if(exception_setjmp(jb))
KERNELCPU_MAILBOX = KERNEL_RUN_EXCEPTION;
else {
dds_init();
rtio_init();
k();
exception_pop(1);
KERNELCPU_MAILBOX = KERNEL_RUN_FINISHED;
}
while(1);
}
int comm_rpc(int rpc_num, ...);
int comm_rpc(int rpc_num, ...)
{
/* TODO */
return 0;
}

View File

@ -4,15 +4,12 @@ ENTRY(_start)
INCLUDE generated/regions.ld
/* First 128K of main memory are reserved for runtime code/data
* then comes kernel memory. First 8K of kernel memory are for support code.
* then comes kernel memory. First 16K of kernel memory are for support code.
*/
MEMORY {
ksupport : ORIGIN = 0x40020000, LENGTH = 0x2000
ksupport : ORIGIN = 0x40020000, LENGTH = 0x4000
}
/* Then comes the payload. */
PROVIDE(kmain = ORIGIN(ksupport) + LENGTH(ksupport));
/* On biprocessor systems, kernel stack is at the end of main RAM,
* before the runtime stack. Leave 1M for runtime stack.
*/

View File

@ -12,10 +12,7 @@ MEMORY {
/* Kernel memory space start right after the runtime,
* and ends before the runtime stack.
*/
PROVIDE(_kmem = 0x40020000);
/* Runtime stack is always at the end of main_ram.
* Runtime stack is always at the end of main_ram.
* This stack is shared with the kernel on uniprocessor systems.
*/
PROVIDE(_fstack = 0x40000000 + LENGTH(main_ram) - 4);

View File

@ -55,14 +55,12 @@ static int symtab_add(const char *name, void *target)
return 1;
}
extern int _kmem;
static int load_object(void *buffer, int length)
{
symtab_init();
return load_elf(
resolve_service_symbol, symtab_add,
buffer, length, &_kmem, 2*1024*1024);
buffer, length, (void *)KERNELCPU_PAYLOAD_ADDRESS, 4*1024*1024);
}
typedef void (*kernel_function)(void);
@ -70,7 +68,9 @@ typedef void (*kernel_function)(void);
static int run_kernel(const char *kernel_name, int *eid)
{
kernel_function k;
#ifndef ARTIQ_BIPROCESSOR
void *jb;
#endif
k = find_symbol(symtab, kernel_name);
if(k == NULL) {
@ -78,17 +78,32 @@ static int run_kernel(const char *kernel_name, int *eid)
return KERNEL_RUN_STARTUP_FAILED;
}
#ifdef ARTIQ_BIPROCESSOR
kernelcpu_start(k);
*eid = 0;
while(1) {
unsigned int r;
r = KERNELCPU_MAILBOX;
if(r < 0x40000000) {
kernelcpu_stop();
return r;
}
}
#else
jb = exception_push();
if(exception_setjmp(jb)) {
*eid = exception_getid();
return KERNEL_RUN_EXCEPTION;
} else {
dds_init();
rtio_init();
flush_cpu_icache();
k();
exception_pop(1);
return KERNEL_RUN_FINISHED;
}
#endif
}
static void blink_led(void)
@ -131,7 +146,7 @@ int main(void)
irq_setie(1);
uart_init();
#ifdef CSR_KERNEL_CPU_BASE
#ifdef ARTIQ_BIPROCESSOR
puts("ARTIQ runtime built "__DATE__" "__TIME__" for biprocessor systems\n");
#else
puts("ARTIQ runtime built "__DATE__" "__TIME__" for uniprocessor systems\n");
@ -143,7 +158,6 @@ int main(void)
test_main();
} else {
puts("Entering regular mode.");
dds_init();
comm_serve(load_object, run_kernel);
}
return 0;

View File

@ -0,0 +1,19 @@
static const struct symbol syscalls[] = {
{"rpc", (void *)0x40021ab0},
{"rtio_oe", (void *)0x40021478},
{"rtio_set", (void *)0x400214d4},
{"rtio_get_counter", (void *)0x400214a0},
{"rtio_get", (void *)0x400215ec},
{"rtio_pileup_count", (void *)0x400216f4},
{"dds_phase_clear_en", (void *)0x400218a4},
{"dds_program", (void *)0x40021960},
{NULL, NULL}
};
static const struct symbol eh[] = {
{"setjmp", (void *)0x40021248},
{"push", (void *)0x400213c8},
{"pop", (void *)0x400212c0},
{"getid", (void *)0x400212e8},
{"raise", (void *)0x4002139c},
{NULL, NULL}
};

View File

@ -2,33 +2,12 @@
#include "elf_loader.h"
#include "comm.h"
#include "gpio.h"
#include "rtio.h"
#include "dds.h"
#include "exceptions.h"
#include "services.h"
static const struct symbol syscalls[] = {
{"rpc", comm_rpc},
{"gpio_set", gpio_set},
{"rtio_oe", rtio_oe},
{"rtio_set", rtio_set},
{"rtio_get_counter", rtio_get_counter},
{"rtio_get", rtio_get},
{"rtio_pileup_count", rtio_pileup_count},
{"dds_phase_clear_en", dds_phase_clear_en},
{"dds_program", dds_program},
{NULL, NULL}
};
static const struct symbol eh[] = {
{"setjmp", exception_setjmp},
{"push", exception_push},
{"pop", exception_pop},
{"getid", exception_getid},
{"raise", exception_raise},
{NULL, NULL}
};
#include "service_table.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-int"

View File

@ -11,6 +11,17 @@
#include "rtio.h"
#include "dds.h"
#ifdef ARTIQ_BIPROCESSOR
#warning TODO
void test_main(void)
{
printf("Not implemented yet for biprocessor systems\n");
}
#else
static void leds(char *value)
{
char *c;
@ -341,3 +352,5 @@ void test_main(void)
do_command(buffer);
}
}
#endif /* ARTIQ_BIPROCESSOR */