diff --git a/soc/runtime/Makefile b/soc/runtime/Makefile index a4513cb4a..3ef30f3b4 100644 --- a/soc/runtime/Makefile +++ b/soc/runtime/Makefile @@ -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 \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 diff --git a/soc/runtime/comm_serial.c b/soc/runtime/comm_serial.c index 35532a88f..a6d532817 100644 --- a/soc/runtime/comm_serial.c +++ b/soc/runtime/comm_serial.c @@ -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; } diff --git a/soc/runtime/exceptions.c b/soc/runtime/exceptions.c index fc72d0ae9..e43901e04 100644 --- a/soc/runtime/exceptions.c +++ b/soc/runtime/exceptions.c @@ -1,5 +1,9 @@ +#include + #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); } } diff --git a/soc/runtime/gen_service_table.py b/soc/runtime/gen_service_table.py new file mode 100755 index 000000000..3bcbe085b --- /dev/null +++ b/soc/runtime/gen_service_table.py @@ -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() diff --git a/soc/runtime/gpio.c b/soc/runtime/gpio.c deleted file mode 100644 index de0b64bbb..000000000 --- a/soc/runtime/gpio.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#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); -} diff --git a/soc/runtime/gpio.h b/soc/runtime/gpio.h deleted file mode 100644 index 63301cca5..000000000 --- a/soc/runtime/gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __GPIO_H -#define __GPIO_H - -void gpio_set(int channel, int value); - -#endif /* __GPIO_H */ diff --git a/soc/runtime/kernelcpu.c b/soc/runtime/kernelcpu.c index 671e3eae2..07a8c36c3 100644 --- a/soc/runtime/kernelcpu.c +++ b/soc/runtime/kernelcpu.c @@ -1,20 +1,19 @@ -#include - -#ifdef CSR_KERNEL_CPU_BASE - #include #include #include +#include + #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 */ diff --git a/soc/runtime/kernelcpu.h b/soc/runtime/kernelcpu.h index 5b64ff0d7..f997e8e1e 100644 --- a/soc/runtime/kernelcpu.h +++ b/soc/runtime/kernelcpu.h @@ -4,11 +4,11 @@ #include #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 */ diff --git a/soc/runtime/ksupport.c b/soc/runtime/ksupport.c index 08d74fe10..f0aa15f55 100644 --- a/soc/runtime/ksupport.c +++ b/soc/runtime/ksupport.c @@ -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; } diff --git a/soc/runtime/ksupport.ld b/soc/runtime/ksupport.ld index 723b1bd0c..da55618dd 100644 --- a/soc/runtime/ksupport.ld +++ b/soc/runtime/ksupport.ld @@ -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. */ diff --git a/soc/runtime/linker.ld b/soc/runtime/linker.ld index 89bb133dc..75513c922 100644 --- a/soc/runtime/linker.ld +++ b/soc/runtime/linker.ld @@ -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); diff --git a/soc/runtime/main.c b/soc/runtime/main.c index 47f21e4ac..946a5ad64 100644 --- a/soc/runtime/main.c +++ b/soc/runtime/main.c @@ -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; diff --git a/soc/runtime/service_table.h b/soc/runtime/service_table.h new file mode 100644 index 000000000..437285d47 --- /dev/null +++ b/soc/runtime/service_table.h @@ -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} +}; diff --git a/soc/runtime/services.c b/soc/runtime/services.c index 064bcc102..8c602379f 100644 --- a/soc/runtime/services.c +++ b/soc/runtime/services.c @@ -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" diff --git a/soc/runtime/test_mode.c b/soc/runtime/test_mode.c index f132e1092..655752693 100644 --- a/soc/runtime/test_mode.c +++ b/soc/runtime/test_mode.c @@ -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 */