From 6072f0c42f414f425b81a5adb45ea35ab058931f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 4 Jul 2014 17:49:08 +0200 Subject: [PATCH] Basic SoC and runtime design --- soc/runtime/Makefile | 56 ++++++++++++++++++ soc/runtime/elf_loader.c | 125 +++++++++++++++++++++++++++++++++++++++ soc/runtime/elf_loader.h | 6 ++ soc/runtime/esr.c | 30 ++++++++++ soc/runtime/main.c | 87 +++++++++++++++++++++++++++ soc/targets/artiq.py | 95 +++++++++++++++++++++++++++++ 6 files changed, 399 insertions(+) create mode 100644 soc/runtime/Makefile create mode 100644 soc/runtime/elf_loader.c create mode 100644 soc/runtime/elf_loader.h create mode 100644 soc/runtime/esr.c create mode 100644 soc/runtime/main.c create mode 100644 soc/targets/artiq.py diff --git a/soc/runtime/Makefile b/soc/runtime/Makefile new file mode 100644 index 000000000..d7653cdce --- /dev/null +++ b/soc/runtime/Makefile @@ -0,0 +1,56 @@ +include $(MSCDIR)/software/common.mak + +BOARD=papilio_pro +SERIAL=/dev/ttyUSB1 + +OBJECTS=esr.o elf_loader.o main.o + +all: runtime.bin + +# pull in dependency info for *existing* .o files +-include $(OBJECTS:.o=.d) + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ + chmod -x $@ + +%.fbi: %.bin + $(MSCDIR)/mkmscimg.py -f -o $@ $< + +runtime.elf: $(OBJECTS) libs + +%.elf: + $(LD) $(LDFLAGS) \ + -T $(MSCDIR)/software/libbase/linker-sdram.ld \ + -N -o $@ \ + $(MSCDIR)/software/libbase/crt0-$(CPU).o \ + $(OBJECTS) \ + -L$(MSCDIR)/software/libbase \ + -L$(MSCDIR)/software/libcompiler-rt \ + -lbase -lcompiler-rt + chmod -x $@ + +main.o: main.c + $(compile-dep) + +%.o: %.c + $(compile-dep) + +%.o: %.S + $(assemble) + +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 .*~ *~ + +.PHONY: all main.o clean libs load diff --git a/soc/runtime/elf_loader.c b/soc/runtime/elf_loader.c new file mode 100644 index 000000000..f2ade1987 --- /dev/null +++ b/soc/runtime/elf_loader.c @@ -0,0 +1,125 @@ +#include +#include + +#include "elf_loader.h" + +#define EI_NIDENT 16 + +struct elf32_ehdr { + unsigned char ident[EI_NIDENT]; /* ident bytes */ + unsigned short type; /* file type */ + unsigned short machine; /* target machine */ + unsigned int version; /* file version */ + unsigned int entry; /* start address */ + unsigned int phoff; /* phdr file offset */ + unsigned int shoff; /* shdr file offset */ + unsigned int flags; /* file flags */ + unsigned short ehsize; /* sizeof ehdr */ + unsigned short phentsize; /* sizeof phdr */ + unsigned short phnum; /* number phdrs */ + unsigned short shentsize; /* sizeof shdr */ + unsigned short shnum; /* number shdrs */ + unsigned short shstrndx; /* shdr string index */ +} __attribute__((packed)); + +static const unsigned char elf_magic_header[] = { + 0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */ + 0x01, /* Only 32-bit objects. */ + 0x02, /* Only big-endian. */ + 0x01, /* Only ELF version 1. */ +}; + +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ + +#define EM_OR1K 0x005c + +struct elf32_shdr { + unsigned int name; /* section name */ + unsigned int type; /* SHT_... */ + unsigned int flags; /* SHF_... */ + unsigned int addr; /* virtual address */ + unsigned int offset; /* file offset */ + unsigned int size; /* section size */ + unsigned int link; /* misc info */ + unsigned int info; /* misc info */ + unsigned int addralign; /* memory alignment */ + unsigned int entsize; /* entry size if table */ +} __attribute__((packed)); + +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +struct elf32_name { + char name[12]; +} __attribute__((packed)); + +#define SANITIZE_OFFSET_SIZE(offset, size) \ + if(offset > 0x10000000) \ + return 0; \ + if((offset + size) > elf_length) \ + return 0 + +#define GET_POINTER_SAFE(target, target_type, offset) \ + SANITIZE_OFFSET_SIZE(offset, sizeof(target_type)); \ + target = (target_type *)((char *)elf_data + offset) + +int load_elf(void *elf_data, int elf_length, void *dest, int dest_length) +{ + struct elf32_ehdr *ehdr; + struct elf32_shdr *strtable; + struct elf32_shdr *shdr; + struct elf32_name *name; + unsigned int shdrptr; + int i; + + unsigned int textoff; + unsigned int textsize; + + + GET_POINTER_SAFE(ehdr, struct elf32_ehdr, 0); + if(memcmp(ehdr->ident, elf_magic_header, sizeof(elf_magic_header)) != 0) + return 0; + if(ehdr->type != ET_REL) return 0; + if(ehdr->machine != EM_OR1K) return 0; + + GET_POINTER_SAFE(strtable, struct elf32_shdr, ehdr->shoff + ehdr->shentsize*ehdr->shstrndx); + + textoff = textsize = 0; + shdrptr = ehdr->shoff; + for(i=0;ishnum;i++) { + GET_POINTER_SAFE(shdr, struct elf32_shdr, shdrptr); + GET_POINTER_SAFE(name, struct elf32_name, strtable->offset + shdr->name); + + if(strncmp(name->name, ".text", 5) == 0) { + textoff = shdr->offset; + textsize = shdr->size; + } + + shdrptr += ehdr->shentsize; + } + + SANITIZE_OFFSET_SIZE(textoff, textsize); + if(textsize > dest_length) + return 0; + memcpy(dest, (char *)elf_data + textoff, textsize); + + return 1; +} diff --git a/soc/runtime/elf_loader.h b/soc/runtime/elf_loader.h new file mode 100644 index 000000000..1672f8199 --- /dev/null +++ b/soc/runtime/elf_loader.h @@ -0,0 +1,6 @@ +#ifndef __ELF_LOADER_H +#define __ELF_LOADER_H + +int load_elf(void *elf_data, int elf_length, void *dest, int dest_length); + +#endif /* __ELF_LOADER_H */ diff --git a/soc/runtime/esr.c b/soc/runtime/esr.c new file mode 100644 index 000000000..f9bf1756c --- /dev/null +++ b/soc/runtime/esr.c @@ -0,0 +1,30 @@ +#include +#include +#include + +static void isr(void) +{ + unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + + if(irqs & (1 << UART_INTERRUPT)) + uart_isr(); +} + +#define EXTERNAL_IRQ 0x800 +#define SYSTEM_CALL 0xc00 + +void exception_handler(unsigned long vect, unsigned long *sp); +void exception_handler(unsigned long vect, unsigned long *sp) +{ + vect &= 0xf00; + if(vect == SYSTEM_CALL) { + puts("scall"); + } else if(vect == EXTERNAL_IRQ) { + isr(); + } else { + /* Unhandled exception */ + for(;;); + } +} diff --git a/soc/runtime/main.c b/soc/runtime/main.c new file mode 100644 index 000000000..8d7554b12 --- /dev/null +++ b/soc/runtime/main.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "elf_loader.h" + +static void receive_sync(void) +{ + char c; + int recognized; + + recognized = 0; + while(1) { + c = readchar(); + if(c == 0x5a) { + recognized++; + if(recognized == 4) + return; + } else + recognized = 0; + } +} + +static int receive_length(void) +{ + int r, i; + + r = 0; + for(i=0;i<4;i++) { + r <<= 8; + r |= readchar(); + } + return r; +} + +static int download_kernel(void *buffer, int maxlength) +{ + int length; + int i; + unsigned char *_buffer = buffer; + + receive_sync(); + length = receive_length(); + if(length > maxlength) + return -1; + for(i=0;i 0) { + load_elf(kbuf, length, kcode, sizeof(kcode)); + flush_cpu_icache(); + for(i=0;i<20;i++) { + printf("=== %2d ===\n", i); + readchar(); + k(i); + } + } + } + + return 0; +} diff --git a/soc/targets/artiq.py b/soc/targets/artiq.py new file mode 100644 index 000000000..6e5364d05 --- /dev/null +++ b/soc/targets/artiq.py @@ -0,0 +1,95 @@ +from fractions import Fraction + +from migen.fhdl.std import * + +from misoclib import lasmicon, spiflash +from misoclib.sdramphy import gensdrphy +from misoclib.gensoc import SDRAMSoC + +class _CRG(Module): + def __init__(self, platform, clk_freq): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys_ps = ClockDomain() + + f0 = 32*1000*1000 + clk32 = platform.request("clk32") + clk32a = Signal() + self.specials += Instance("IBUFG", i_I=clk32, o_O=clk32a) + clk32b = Signal() + self.specials += Instance("BUFIO2", p_DIVIDE=1, + p_DIVIDE_BYPASS="TRUE", p_I_INVERT="FALSE", + i_I=clk32a, o_DIVCLK=clk32b) + f = Fraction(int(clk_freq), int(f0)) + n, m, p = f.denominator, f.numerator, 8 + assert f0/n*m == clk_freq + pll_lckd = Signal() + pll_fb = Signal() + pll = Signal(6) + self.specials.pll = Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6", + p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL", + p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT", + i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0, + p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0., + i_CLKIN1=clk32b, i_CLKIN2=0, i_CLKINSEL=1, + p_CLKIN1_PERIOD=1/f0, p_CLKIN2_PERIOD=0., + i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd, + o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5, + o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5, + o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5, + o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5, + o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5, + o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5, + p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//1, + p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=p//1, + p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=p//1, + p_CLKOUT3_PHASE=0., p_CLKOUT3_DIVIDE=p//1, + p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p//1, # sys + p_CLKOUT5_PHASE=270., p_CLKOUT5_DIVIDE=p//1, # sys_ps + ) + self.specials += Instance("BUFG", i_I=pll[4], o_O=self.cd_sys.clk) + self.specials += Instance("BUFG", i_I=pll[5], o_O=self.cd_sys_ps.clk) + self.specials += Instance("FD", p_INIT=1, i_D=~pll_lckd, + i_C=self.cd_sys.clk, o_Q=self.cd_sys.rst) + + self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE", + p_INIT=0, p_SRTYPE="SYNC", + i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1, + i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk, + o_Q=platform.request("sdram_clock")) + +class ARTIQSoC(SDRAMSoC): + default_platform = "papilio_pro" + + def __init__(self, platform, cpu_type="or1k", **kwargs): + clk_freq = 80*1000*1000 + SDRAMSoC.__init__(self, platform, clk_freq, + cpu_reset_address=0x160000, cpu_type=cpu_type, **kwargs) + + self.submodules.crg = _CRG(platform, clk_freq) + + sdram_geom = lasmicon.GeomSettings( + bank_a=2, + row_a=12, + col_a=8 + ) + sdram_timing = lasmicon.TimingSettings( + tRP=self.ns(15), + tRCD=self.ns(15), + tWR=self.ns(14), + tWTR=2, + tREFI=self.ns(64*1000*1000/4096, False), + tRFC=self.ns(66), + req_queue_size=8, + read_time=32, + write_time=16 + ) + self.submodules.sdrphy = gensdrphy.GENSDRPHY(platform.request("sdram")) + self.register_sdram_phy(self.sdrphy.dfi, self.sdrphy.phy_settings, sdram_geom, sdram_timing) + + # BIOS is in SPI flash + self.submodules.spiflash = spiflash.SpiFlash(platform.request("spiflash2x"), + cmd=0xefef, cmd_width=16, addr_width=24, dummy=4, div=4) + self.flash_boot_address = 0x70000 + self.register_rom(self.spiflash.bus) + +default_subtarget = ARTIQSoC