From 7d5de86015fd090a5095b006d06150d9ab6b4681 Mon Sep 17 00:00:00 2001 From: Stas Date: Thu, 1 Oct 2020 17:18:29 +0200 Subject: [PATCH] start implementing FW to control SPN HW --- .gitignore | 3 - raven_spn/.project | 28 + raven_spn/Makefile | 29 + raven_spn/bsp/drivers/clic/clic_driver.c | 163 ++ raven_spn/bsp/drivers/clic/clic_driver.h | 44 + .../bsp/drivers/fe300prci/fe300prci_driver.c | 252 ++++ .../bsp/drivers/fe300prci/fe300prci_driver.h | 79 + raven_spn/bsp/drivers/plic/plic_driver.c | 122 ++ raven_spn/bsp/drivers/plic/plic_driver.h | 52 + raven_spn/bsp/env/common.mk | 66 + raven_spn/bsp/env/coreip-e2-arty/flash.lds | 161 ++ raven_spn/bsp/env/coreip-e2-arty/init.c | 98 ++ raven_spn/bsp/env/coreip-e2-arty/openocd.cfg | 31 + raven_spn/bsp/env/coreip-e2-arty/platform.h | 98 ++ raven_spn/bsp/env/coreip-e2-arty/settings.mk | 3 + .../bsp/env/coreip-e2-arty/tim-split.lds | 157 ++ raven_spn/bsp/env/coreip-e2-arty/tim.lds | 161 ++ raven_spn/bsp/env/coreplexip-arty.h | 102 ++ .../bsp/env/coreplexip-e31-arty/dhrystone.lds | 157 ++ .../bsp/env/coreplexip-e31-arty/flash.lds | 161 ++ raven_spn/bsp/env/coreplexip-e31-arty/init.c | 122 ++ .../bsp/env/coreplexip-e31-arty/openocd.cfg | 31 + .../bsp/env/coreplexip-e31-arty/platform.h | 100 ++ .../env/coreplexip-e31-arty/scratchpad.lds | 161 ++ .../bsp/env/coreplexip-e31-arty/settings.mk | 3 + .../bsp/env/coreplexip-e51-arty/dhrystone.lds | 157 ++ .../bsp/env/coreplexip-e51-arty/flash.lds | 161 ++ raven_spn/bsp/env/coreplexip-e51-arty/init.c | 122 ++ .../bsp/env/coreplexip-e51-arty/openocd.cfg | 31 + .../bsp/env/coreplexip-e51-arty/platform.h | 100 ++ .../env/coreplexip-e51-arty/scratchpad.lds | 161 ++ .../bsp/env/coreplexip-e51-arty/settings.mk | 3 + raven_spn/bsp/env/encoding.h | 1313 +++++++++++++++++ raven_spn/bsp/env/entry.S | 98 ++ raven_spn/bsp/env/freedom-e300-arty/flash.lds | 161 ++ raven_spn/bsp/env/freedom-e300-arty/init.c | 87 ++ .../bsp/env/freedom-e300-arty/openocd.cfg | 30 + .../bsp/env/freedom-e300-arty/platform.h | 124 ++ .../bsp/env/freedom-e300-arty/settings.mk | 3 + .../env/freedom-e300-hifive1/dhrystone.lds | 157 ++ .../bsp/env/freedom-e300-hifive1/flash.lds | 161 ++ raven_spn/bsp/env/freedom-e300-hifive1/init.c | 238 +++ .../bsp/env/freedom-e300-hifive1/openocd.cfg | 34 + .../bsp/env/freedom-e300-hifive1/platform.h | 133 ++ .../bsp/env/freedom-e300-hifive1/settings.mk | 3 + raven_spn/bsp/env/hifive1.h | 81 + raven_spn/bsp/env/start.S | 111 ++ raven_spn/bsp/env/ventry.S | 288 ++++ raven_spn/bsp/include/sifive/bits.h | 36 + raven_spn/bsp/include/sifive/const.h | 18 + raven_spn/bsp/include/sifive/devices/aon.h | 88 ++ raven_spn/bsp/include/sifive/devices/clic.h | 30 + raven_spn/bsp/include/sifive/devices/clint.h | 14 + raven_spn/bsp/include/sifive/devices/gpio.h | 24 + raven_spn/bsp/include/sifive/devices/otp.h | 23 + raven_spn/bsp/include/sifive/devices/plic.h | 31 + raven_spn/bsp/include/sifive/devices/prci.h | 56 + raven_spn/bsp/include/sifive/devices/pwm.h | 37 + raven_spn/bsp/include/sifive/devices/spi.h | 80 + raven_spn/bsp/include/sifive/devices/uart.h | 27 + raven_spn/bsp/include/sifive/sections.h | 17 + raven_spn/bsp/include/sifive/smp.h | 65 + raven_spn/bsp/libwrap/libwrap.mk | 56 + raven_spn/bsp/libwrap/misc/write_hex.c | 19 + raven_spn/bsp/libwrap/stdlib/malloc.c | 17 + raven_spn/bsp/libwrap/sys/_exit.c | 17 + raven_spn/bsp/libwrap/sys/close.c | 11 + raven_spn/bsp/libwrap/sys/execve.c | 11 + raven_spn/bsp/libwrap/sys/fork.c | 9 + raven_spn/bsp/libwrap/sys/fstat.c | 18 + raven_spn/bsp/libwrap/sys/getpid.c | 8 + raven_spn/bsp/libwrap/sys/isatty.c | 13 + raven_spn/bsp/libwrap/sys/kill.c | 11 + raven_spn/bsp/libwrap/sys/link.c | 11 + raven_spn/bsp/libwrap/sys/lseek.c | 16 + raven_spn/bsp/libwrap/sys/open.c | 11 + raven_spn/bsp/libwrap/sys/openat.c | 11 + raven_spn/bsp/libwrap/sys/puts.c | 28 + raven_spn/bsp/libwrap/sys/read.c | 32 + raven_spn/bsp/libwrap/sys/sbrk.c | 18 + raven_spn/bsp/libwrap/sys/stat.c | 12 + raven_spn/bsp/libwrap/sys/stub.h | 10 + raven_spn/bsp/libwrap/sys/times.c | 12 + raven_spn/bsp/libwrap/sys/unlink.c | 11 + raven_spn/bsp/libwrap/sys/wait.c | 9 + raven_spn/bsp/libwrap/sys/weak_under_alias.h | 7 + raven_spn/bsp/libwrap/sys/write.c | 31 + raven_spn/raven_spn | Bin 0 -> 118788 bytes raven_spn/src/bsp.h | 22 + raven_spn/src/delay.c | 123 ++ raven_spn/src/delay.h | 25 + raven_spn/src/io/gpio.h | 89 ++ raven_spn/src/io/pwm.h | 122 ++ raven_spn/src/io/spi.h | 200 +++ raven_spn/src/io/uart.h | 83 ++ raven_spn/src/raven_spn.cpp | 105 ++ raven_spn/src/raven_spn.h | 6 + raven_spn/src/spn_regs.h | 78 + raven_spn/src/util/bit_field.h | 179 +++ raven_spn/src/wrap_printf.c | 271 ++++ raven_spn/toolchain-rv32.cmake | 33 + riscv-bldc-forced-commutation/.project | 28 + 102 files changed, 8457 insertions(+), 3 deletions(-) create mode 100644 raven_spn/.project create mode 100644 raven_spn/Makefile create mode 100644 raven_spn/bsp/drivers/clic/clic_driver.c create mode 100644 raven_spn/bsp/drivers/clic/clic_driver.h create mode 100644 raven_spn/bsp/drivers/fe300prci/fe300prci_driver.c create mode 100644 raven_spn/bsp/drivers/fe300prci/fe300prci_driver.h create mode 100644 raven_spn/bsp/drivers/plic/plic_driver.c create mode 100644 raven_spn/bsp/drivers/plic/plic_driver.h create mode 100644 raven_spn/bsp/env/common.mk create mode 100644 raven_spn/bsp/env/coreip-e2-arty/flash.lds create mode 100644 raven_spn/bsp/env/coreip-e2-arty/init.c create mode 100644 raven_spn/bsp/env/coreip-e2-arty/openocd.cfg create mode 100644 raven_spn/bsp/env/coreip-e2-arty/platform.h create mode 100644 raven_spn/bsp/env/coreip-e2-arty/settings.mk create mode 100644 raven_spn/bsp/env/coreip-e2-arty/tim-split.lds create mode 100644 raven_spn/bsp/env/coreip-e2-arty/tim.lds create mode 100644 raven_spn/bsp/env/coreplexip-arty.h create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/dhrystone.lds create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/flash.lds create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/init.c create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/openocd.cfg create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/platform.h create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/scratchpad.lds create mode 100644 raven_spn/bsp/env/coreplexip-e31-arty/settings.mk create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/dhrystone.lds create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/flash.lds create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/init.c create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/openocd.cfg create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/platform.h create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/scratchpad.lds create mode 100644 raven_spn/bsp/env/coreplexip-e51-arty/settings.mk create mode 100644 raven_spn/bsp/env/encoding.h create mode 100644 raven_spn/bsp/env/entry.S create mode 100644 raven_spn/bsp/env/freedom-e300-arty/flash.lds create mode 100644 raven_spn/bsp/env/freedom-e300-arty/init.c create mode 100644 raven_spn/bsp/env/freedom-e300-arty/openocd.cfg create mode 100644 raven_spn/bsp/env/freedom-e300-arty/platform.h create mode 100644 raven_spn/bsp/env/freedom-e300-arty/settings.mk create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/dhrystone.lds create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/flash.lds create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/init.c create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/openocd.cfg create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/platform.h create mode 100644 raven_spn/bsp/env/freedom-e300-hifive1/settings.mk create mode 100644 raven_spn/bsp/env/hifive1.h create mode 100644 raven_spn/bsp/env/start.S create mode 100644 raven_spn/bsp/env/ventry.S create mode 100644 raven_spn/bsp/include/sifive/bits.h create mode 100644 raven_spn/bsp/include/sifive/const.h create mode 100644 raven_spn/bsp/include/sifive/devices/aon.h create mode 100644 raven_spn/bsp/include/sifive/devices/clic.h create mode 100644 raven_spn/bsp/include/sifive/devices/clint.h create mode 100644 raven_spn/bsp/include/sifive/devices/gpio.h create mode 100644 raven_spn/bsp/include/sifive/devices/otp.h create mode 100644 raven_spn/bsp/include/sifive/devices/plic.h create mode 100644 raven_spn/bsp/include/sifive/devices/prci.h create mode 100644 raven_spn/bsp/include/sifive/devices/pwm.h create mode 100644 raven_spn/bsp/include/sifive/devices/spi.h create mode 100644 raven_spn/bsp/include/sifive/devices/uart.h create mode 100644 raven_spn/bsp/include/sifive/sections.h create mode 100644 raven_spn/bsp/include/sifive/smp.h create mode 100644 raven_spn/bsp/libwrap/libwrap.mk create mode 100644 raven_spn/bsp/libwrap/misc/write_hex.c create mode 100644 raven_spn/bsp/libwrap/stdlib/malloc.c create mode 100644 raven_spn/bsp/libwrap/sys/_exit.c create mode 100644 raven_spn/bsp/libwrap/sys/close.c create mode 100644 raven_spn/bsp/libwrap/sys/execve.c create mode 100644 raven_spn/bsp/libwrap/sys/fork.c create mode 100644 raven_spn/bsp/libwrap/sys/fstat.c create mode 100644 raven_spn/bsp/libwrap/sys/getpid.c create mode 100644 raven_spn/bsp/libwrap/sys/isatty.c create mode 100644 raven_spn/bsp/libwrap/sys/kill.c create mode 100644 raven_spn/bsp/libwrap/sys/link.c create mode 100644 raven_spn/bsp/libwrap/sys/lseek.c create mode 100644 raven_spn/bsp/libwrap/sys/open.c create mode 100644 raven_spn/bsp/libwrap/sys/openat.c create mode 100644 raven_spn/bsp/libwrap/sys/puts.c create mode 100644 raven_spn/bsp/libwrap/sys/read.c create mode 100644 raven_spn/bsp/libwrap/sys/sbrk.c create mode 100644 raven_spn/bsp/libwrap/sys/stat.c create mode 100644 raven_spn/bsp/libwrap/sys/stub.h create mode 100644 raven_spn/bsp/libwrap/sys/times.c create mode 100644 raven_spn/bsp/libwrap/sys/unlink.c create mode 100644 raven_spn/bsp/libwrap/sys/wait.c create mode 100644 raven_spn/bsp/libwrap/sys/weak_under_alias.h create mode 100644 raven_spn/bsp/libwrap/sys/write.c create mode 100755 raven_spn/raven_spn create mode 100644 raven_spn/src/bsp.h create mode 100644 raven_spn/src/delay.c create mode 100644 raven_spn/src/delay.h create mode 100644 raven_spn/src/io/gpio.h create mode 100644 raven_spn/src/io/pwm.h create mode 100644 raven_spn/src/io/spi.h create mode 100644 raven_spn/src/io/uart.h create mode 100644 raven_spn/src/raven_spn.cpp create mode 100644 raven_spn/src/raven_spn.h create mode 100644 raven_spn/src/spn_regs.h create mode 100644 raven_spn/src/util/bit_field.h create mode 100644 raven_spn/src/wrap_printf.c create mode 100644 raven_spn/toolchain-rv32.cmake create mode 100644 riscv-bldc-forced-commutation/.project diff --git a/.gitignore b/.gitignore index 828b8ea..c6c7f67 100644 --- a/.gitignore +++ b/.gitignore @@ -99,9 +99,6 @@ local.properties .loadpath .recommenders -# Eclipse Core -.project - # External tool builders .externalToolBuilders/ diff --git a/raven_spn/.project b/raven_spn/.project new file mode 100644 index 0000000..9afd5e4 --- /dev/null +++ b/raven_spn/.project @@ -0,0 +1,28 @@ + + + raven_spn + + + bsp + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/raven_spn/Makefile b/raven_spn/Makefile new file mode 100644 index 0000000..62aacf0 --- /dev/null +++ b/raven_spn/Makefile @@ -0,0 +1,29 @@ + +TARGET = raven_spn +C_SRCS = $(wildcard src/*.c) $(BSP_BASE)/drivers/fe300prci/fe300prci_driver.c $(BSP_BASE)/drivers/plic/plic_driver.c +CXX_SRCS = $(wildcard src/*.cpp) +HEADERS = $(wildcard src/*.h) +CFLAGS = -g -fno-builtin-printf -DUSE_PLIC -I./src +CXXFLAGS = -fno-use-cxa-atexit +LDFLAGS = -Wl,--wrap=printf +LDFLAGS += -g -lstdc++ -fno-use-cxa-atexit -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=medany + + +BOARD=freedom-e300-hifive1 +LINK_TARGET=flash +RISCV_ARCH=rv32imac +RISCV_ABI=ilp32 + +TOOL_DIR=/home/stas/Downloads/riscv64-unknown-elf-gcc-8.3.0-2020.04.0-x86_64-linux-ubuntu14/bin +#TOOL_DIR?=/opt/riscv/FreedomStudio/20180122/SiFive/riscv64-unknown-elf-gcc-20171231-x86_64-linux-centos6/bin + +BSP_BASE = ./bsp +include $(BSP_BASE)/env/common.mk + +.PHONY: all +all: $(TARGET).dump + +$(TARGET).dump: $(TARGET) + $(TOOL_DIR)/$(TRIPLET)-objdump -d -S -C $< > $@ + + diff --git a/raven_spn/bsp/drivers/clic/clic_driver.c b/raven_spn/bsp/drivers/clic/clic_driver.c new file mode 100644 index 0000000..0612e58 --- /dev/null +++ b/raven_spn/bsp/drivers/clic/clic_driver.c @@ -0,0 +1,163 @@ +// See LICENSE for license details. + +#include "sifive/devices/clic.h" +#include "clic/clic_driver.h" +#include "platform.h" +#include "encoding.h" +#include + + +void volatile_memzero(uint8_t * base, unsigned int size) { + volatile uint8_t * ptr; + for (ptr = base; ptr < (base + size); ptr++){ + *ptr = 0; + } +} + +// Note that there are no assertions or bounds checking on these +// parameter values. +void clic_init ( + clic_instance_t * this_clic, + uintptr_t hart_addr, + interrupt_function_ptr_t* vect_table, + interrupt_function_ptr_t default_handler, + uint32_t num_irq, + uint32_t num_config_bits + ) +{ + this_clic->hart_addr= hart_addr; + this_clic->vect_table= vect_table; + this_clic->num_config_bits= num_config_bits; + + //initialize vector table + for(int i=0;i++;ivect_table[i] = default_handler; + } + + //set base vectors + write_csr(mtvt, vect_table); + + + //clear all interrupt enables and pending + volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIE), num_irq); + volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIP), num_irq); + + //clear nlbits and nvbits; all interrupts trap to level 15 + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG)=0; + +} + +void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler) { + this_clic->vect_table[source] = handler; +} + +void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source) { + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 1; +} + +void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source){ + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 0; +} + +void clic_set_pending(clic_instance_t * this_clic, uint32_t source){ + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 1; +} + +void clic_clear_pending(clic_instance_t * this_clic, uint32_t source){ + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 0; +} + +void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg){ + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source) = intcfg; +} + +uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source){ + return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source); +} + +void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg){ + *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG) = cfg; +} + +uint8_t clic_get_cliccfg (clic_instance_t * this_clic){ + return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG); +} + +//sets an interrupt level based encoding of nmbits, nlbits +uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level) { + //extract nlbits + uint8_t nlbits = clic_get_cliccfg(this_clic); + nlbits = (nlbits >>1) & 0x7; + + //shift level right to mask off unused bits + level = level>>((this_clic->num_config_bits)-nlbits); //plus this_clic->nmbits which is always 0 for now. + //shift level into correct bit position + level = level << (8-this_clic->num_config_bits) + (this_clic->num_config_bits - nlbits); + + //write to clicintcfg + uint8_t current_intcfg = clic_get_intcfg(this_clic, source); + clic_set_intcfg(this_clic, source, (current_intcfg | level)); + + return level; +} + +//gets an interrupt level based encoding of nmbits, nlbits +uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source) { + uint8_t level; + level = clic_get_intcfg(this_clic, source); + + //extract nlbits + uint8_t nlbits = clic_get_cliccfg(this_clic); + nlbits = (nlbits >>1) & 0x7; + + //shift level + level = level >> (8-(this_clic->num_config_bits)); + + //shift level right to mask off priority bits + level = level>>(this_clic->num_config_bits-nlbits); //this_clic->nmbits which is always 0 for now. + + return level; +} + +//sets an interrupt priority based encoding of nmbits, nlbits +uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority) { + //priority bits = num_config_bits - nlbits + //extract nlbits + uint8_t nlbits = clic_get_cliccfg(this_clic); + nlbits = (nlbits >>1) & 0x7; + + uint8_t priority_bits = this_clic->num_config_bits-nlbits; + if(priority_bits = 0) { + //no bits to set + return 0; + } + //mask off unused bits + priority = priority >> (8-priority_bits); + //shift into the correct bit position + priority = priority << (8-(this_clic->num_config_bits)); + + //write to clicintcfg + uint8_t current_intcfg = clic_get_intcfg(this_clic, source); + clic_set_intcfg(this_clic, source, (current_intcfg | priority)); + return current_intcfg; +} + +//gets an interrupt priority based encoding of nmbits, nlbits +uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source) { + uint8_t priority; + priority = clic_get_intcfg(this_clic, source); + + //extract nlbits + uint8_t nlbits = clic_get_cliccfg(this_clic); + nlbits = (nlbits >>1) & 0x7; + + //shift left to mask off level bits + priority = priority << nlbits; + + //shift priority + priority = priority >> (8-((this_clic->num_config_bits)+nlbits)); + + return priority; +} + + diff --git a/raven_spn/bsp/drivers/clic/clic_driver.h b/raven_spn/bsp/drivers/clic/clic_driver.h new file mode 100644 index 0000000..27c34c2 --- /dev/null +++ b/raven_spn/bsp/drivers/clic/clic_driver.h @@ -0,0 +1,44 @@ +// See LICENSE file for licence details + +#ifndef PLIC_DRIVER_H +#define PLIC_DRIVER_H + + +__BEGIN_DECLS + +#include "platform.h" + +typedef void (*interrupt_function_ptr_t) (void); + +typedef struct __clic_instance_t +{ + uintptr_t hart_addr; + interrupt_function_ptr_t* vect_table; + uint32_t num_config_bits; + uint32_t num_sources; +} clic_instance_t; + +// Note that there are no assertions or bounds checking on these +// parameter values. +void clic_init (clic_instance_t * this_clic, uintptr_t hart_addr, interrupt_function_ptr_t* vect_table, interrupt_function_ptr_t default_handler, uint32_t num_irq,uint32_t num_config_bits); +void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler); +void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source); +void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source); +void clic_set_pending(clic_instance_t * this_clic, uint32_t source); +void clic_clear_pending(clic_instance_t * this_clic, uint32_t source); +void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg); +uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source); +void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg); +uint8_t clic_get_cliccfg (clic_instance_t * this_clic); +//sets an interrupt level based encoding of nmbits, nlbits +uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level); +//get an interrupt level based encoding of nmbits, nlbits +uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source); +//sets an interrupt priority based encoding of nmbits, nlbits +uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority); +//sets an interrupt priority based encoding of nmbits, nlbits +uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source); + +__END_DECLS + +#endif diff --git a/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.c b/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.c new file mode 100644 index 0000000..8eeaafc --- /dev/null +++ b/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.c @@ -0,0 +1,252 @@ +// See LICENSE file for license details + +#include "platform.h" + +#ifdef PRCI_CTRL_ADDR +#include "fe300prci/fe300prci_driver.h" +#include + +#define rdmcycle(x) { \ + uint32_t lo, hi, hi2; \ + __asm__ __volatile__ ("1:\n\t" \ + "csrr %0, mcycleh\n\t" \ + "csrr %1, mcycle\n\t" \ + "csrr %2, mcycleh\n\t" \ + "bne %0, %2, 1b\n\t" \ + : "=r" (hi), "=r" (lo), "=r" (hi2)) ; \ + *(x) = lo | ((uint64_t) hi << 32); \ + } + +uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq) +{ + + uint32_t start_mtime = CLINT_REG(CLINT_MTIME); + uint32_t end_mtime = start_mtime + mtime_ticks + 1; + + // Make sure we won't get rollover. + while (end_mtime < start_mtime){ + start_mtime = CLINT_REG(CLINT_MTIME); + end_mtime = start_mtime + mtime_ticks + 1; + } + + // Don't start measuring until mtime edge. + uint32_t tmp = start_mtime; + do { + start_mtime = CLINT_REG(CLINT_MTIME); + } while (start_mtime == tmp); + + uint64_t start_mcycle; + rdmcycle(&start_mcycle); + + while (CLINT_REG(CLINT_MTIME) < end_mtime) ; + + uint64_t end_mcycle; + rdmcycle(&end_mcycle); + uint32_t difference = (uint32_t) (end_mcycle - start_mcycle); + + uint64_t freq = ((uint64_t) difference * mtime_freq) / mtime_ticks; + return (uint32_t) freq & 0xFFFFFFFF; + +} + + +void PRCI_use_hfrosc(int div, int trim) +{ + // Make sure the HFROSC is running at its default setting + // It is OK to change this even if we are running off of it. + + PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1)); + + while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0); + + PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1); +} + +void PRCI_use_pll(int refsel, int bypass, + int r, int f, int q, int finaldiv, + int hfroscdiv, int hfrosctrim) +{ + // Ensure that we aren't running off the PLL before we mess with it. + if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) { + // Make sure the HFROSC is running at its default setting + PRCI_use_hfrosc(4, 16); + } + + // Set PLL Source to be HFXOSC if desired. + uint32_t config_value = 0; + + config_value |= PLL_REFSEL(refsel); + + if (bypass) { + // Bypass + config_value |= PLL_BYPASS(1); + + PRCI_REG(PRCI_PLLCFG) = config_value; + + // If we don't have an HFXTAL, this doesn't really matter. + // Set our Final output divide to divide-by-1: + PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0)); + } else { + + // To overclock, use the hfrosc + if (hfrosctrim >= 0 && hfroscdiv >= 0) { + PRCI_use_hfrosc(hfroscdiv, hfrosctrim); + } + + // Set DIV Settings for PLL + + // (Legal values of f_REF are 6-48MHz) + + // Set DIVR to divide-by-2 to get 8MHz frequency + // (legal values of f_R are 6-12 MHz) + + config_value |= PLL_BYPASS(1); + config_value |= PLL_R(r); + + // Set DIVF to get 512Mhz frequncy + // There is an implied multiply-by-2, 16Mhz. + // So need to write 32-1 + // (legal values of f_F are 384-768 MHz) + config_value |= PLL_F(f); + + // Set DIVQ to divide-by-2 to get 256 MHz frequency + // (legal values of f_Q are 50-400Mhz) + config_value |= PLL_Q(q); + + // Set our Final output divide to divide-by-1: + if (finaldiv == 1){ + PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0)); + } else { + PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV(finaldiv-1)); + } + + PRCI_REG(PRCI_PLLCFG) = config_value; + + // Un-Bypass the PLL. + PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1); + + // Wait for PLL Lock + // Note that the Lock signal can be glitchy. + // Need to wait 100 us + // RTC is running at 32kHz. + // So wait 4 ticks of RTC. + uint32_t now = CLINT_REG(CLINT_MTIME); + while (CLINT_REG(CLINT_MTIME) - now < 4) ; + + // Now it is safe to check for PLL Lock + while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0); + + } + + // Switch over to PLL Clock source + PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1); + + // If we're running off HFXOSC, turn off the HFROSC to + // save power. + if (refsel) { + PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1); + } + +} + +void PRCI_use_default_clocks() +{ + // Turn off the LFROSC + AON_REG(AON_LFROSC) &= ~ROSC_EN(1); + + // Use HFROSC + PRCI_use_hfrosc(4, 16); +} + +void PRCI_use_hfxosc(uint32_t finaldiv) +{ + + PRCI_use_pll(1, // Use HFXTAL + 1, // Bypass = 1 + 0, // PLL settings don't matter + 0, // PLL settings don't matter + 0, // PLL settings don't matter + finaldiv, + -1, + -1); +} + +// This is a generic function, which +// doesn't span the entire range of HFROSC settings. +// It only adjusts the trim, which can span a hundred MHz or so. +// This function does not check the legality of the PLL settings +// at all, and it is quite possible to configure invalid PLL settings +// this way. +// It returns the actual measured CPU frequency. + +uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target ) +{ + + uint32_t hfrosctrim = 0; + uint32_t hfroscdiv = 4; + uint32_t prev_trim = 0; + + // In this function we use PLL settings which + // will give us a 32x multiplier from the output + // of the HFROSC source to the output of the + // PLL. We first measure our HFROSC to get the + // right trim, then finally use it as the PLL source. + // We should really check here that the f_cpu + // requested is something in the limit of the PLL. For + // now that is up to the user. + + // This will undershoot for frequencies not divisible by 16. + uint32_t desired_hfrosc_freq = (f_cpu/ 16); + + PRCI_use_hfrosc(hfroscdiv, hfrosctrim); + + // Ignore the first run (for icache reasons) + uint32_t cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ); + + cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ); + uint32_t prev_freq = cpu_freq; + + while ((cpu_freq < desired_hfrosc_freq) && (hfrosctrim < 0x1F)){ + prev_trim = hfrosctrim; + prev_freq = cpu_freq; + hfrosctrim ++; + PRCI_use_hfrosc(hfroscdiv, hfrosctrim); + cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ); + } + + // We couldn't go low enough + if (prev_freq > desired_hfrosc_freq){ + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim); + cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ); + return cpu_freq; + } + + // We couldn't go high enough + if (cpu_freq < desired_hfrosc_freq){ + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim); + cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ); + return cpu_freq; + } + + // Check for over/undershoot + switch(target) { + case(PRCI_FREQ_CLOSEST): + if ((desired_hfrosc_freq - prev_freq) < (cpu_freq - desired_hfrosc_freq)) { + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim); + } else { + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim); + } + break; + case(PRCI_FREQ_UNDERSHOOT): + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim); + break; + default: + PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim); + } + + cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ); + return cpu_freq; + +} + +#endif diff --git a/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.h b/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.h new file mode 100644 index 0000000..7100f46 --- /dev/null +++ b/raven_spn/bsp/drivers/fe300prci/fe300prci_driver.h @@ -0,0 +1,79 @@ +// See LICENSE file for license details + +#ifndef _FE300PRCI_DRIVER_H_ +#define _FE300PRCI_DRIVER_H_ + +__BEGIN_DECLS + +#include + +typedef enum prci_freq_target { + + PRCI_FREQ_OVERSHOOT, + PRCI_FREQ_CLOSEST, + PRCI_FREQ_UNDERSHOOT + +} PRCI_freq_target; + +/* Measure and return the approximate frequency of the + * CPU, as given by measuring the mcycle counter against + * the mtime ticks. + */ +uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq); + +/* Safely switch over to the HFROSC using the given div + * and trim settings. + */ +void PRCI_use_hfrosc(int div, int trim); + +/* Safely switch over to the 16MHz HFXOSC, + * applying the finaldiv clock divider (1 is the lowest + * legal value). + */ +void PRCI_use_hfxosc(uint32_t finaldiv); + +/* Safely switch over to the PLL using the given + * settings. + * + * Note that not all combinations of the inputs are actually + * legal, and this function does not check for their + * legality ("safely" means that this function won't turn off + * or glitch the clock the CPU is actually running off, but + * doesn't protect against you making it too fast or slow.) + */ + +void PRCI_use_pll(int refsel, int bypass, + int r, int f, int q, int finaldiv, + int hfroscdiv, int hfrosctrim); + +/* Use the default clocks configured at reset. + * This is ~16Mhz HFROSC and turns off the LFROSC + * (on the current FE310 Dev Platforms, an external LFROSC is + * used as it is more power efficient). + */ +void PRCI_use_default_clocks(); + +/* This routine will adjust the HFROSC trim + * while using HFROSC as the clock source, + * measure the resulting frequency, then + * use it as the PLL clock source, + * in an attempt to get over, under, or close to the + * requested frequency. It returns the actual measured + * frequency. + * + * Note that the requested frequency must be within the + * range supported by the PLL so not all values are + * achievable with this function, and not all + * are guaranteed to actually work. The PLL + * is rated higher than the hardware. + * + * There is no check on the desired f_cpu frequency, it + * is up to the user to specify something reasonable. + */ + +uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target); + +__END_DECLS + +#endif + diff --git a/raven_spn/bsp/drivers/plic/plic_driver.c b/raven_spn/bsp/drivers/plic/plic_driver.c new file mode 100644 index 0000000..4f41bda --- /dev/null +++ b/raven_spn/bsp/drivers/plic/plic_driver.c @@ -0,0 +1,122 @@ +// See LICENSE for license details. + +#include "sifive/devices/plic.h" +#include "plic/plic_driver.h" +#include "platform.h" +#include "encoding.h" +#include + + +// Note that there are no assertions or bounds checking on these +// parameter values. + +void volatile_memzero(uint8_t * base, unsigned int size) +{ + volatile uint8_t * ptr; + for (ptr = base; ptr < (base + size); ptr++){ + *ptr = 0; + } +} + +void PLIC_init ( + plic_instance_t * this_plic, + uintptr_t base_addr, + uint32_t num_sources, + uint32_t num_priorities, + uint32_t target_hartid + ) +{ + + this_plic->base_addr = base_addr; + this_plic->num_sources = num_sources; + this_plic->num_priorities = num_priorities; + this_plic->target_hartid = target_hartid; + + // Disable all interrupts (don't assume that these registers are reset). + volatile_memzero((uint8_t*) (this_plic->base_addr + + PLIC_ENABLE_OFFSET + + (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET)), + (num_sources + 8) / 8); + + // Set all priorities to 0 (equal priority -- don't assume that these are reset). + volatile_memzero ((uint8_t *)(this_plic->base_addr + + PLIC_PRIORITY_OFFSET), + (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE); + + // Set the threshold to 0. + volatile plic_threshold* threshold = (plic_threshold*) + (this_plic->base_addr + + PLIC_THRESHOLD_OFFSET + + (this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET)); + + *threshold = 0; + +} + +void PLIC_set_threshold (plic_instance_t * this_plic, + plic_threshold threshold){ + + volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr + + PLIC_THRESHOLD_OFFSET + + (this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET)); + + *threshold_ptr = threshold; + +} + + +void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){ + + volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr + + PLIC_ENABLE_OFFSET + + (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) + + (source >> 3)); + uint8_t current = *current_ptr; + current = current | ( 1 << (source & 0x7)); + *current_ptr = current; + +} + +void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){ + + volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr + + PLIC_ENABLE_OFFSET + + (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) + + (source >> 3)); + uint8_t current = *current_ptr; + current = current & ~(( 1 << (source & 0x7))); + *current_ptr = current; + +} + +void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){ + + if (this_plic->num_priorities > 0) { + volatile plic_priority * priority_ptr = (volatile plic_priority *) + (this_plic->base_addr + + PLIC_PRIORITY_OFFSET + + (source << PLIC_PRIORITY_SHIFT_PER_SOURCE)); + *priority_ptr = priority; + } +} + +plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){ + + volatile plic_source * claim_addr = (volatile plic_source * ) + (this_plic->base_addr + + PLIC_CLAIM_OFFSET + + (this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET)); + + return *claim_addr; + +} + +void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){ + + volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr + + PLIC_CLAIM_OFFSET + + (this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET)); + *claim_addr = source; + +} + diff --git a/raven_spn/bsp/drivers/plic/plic_driver.h b/raven_spn/bsp/drivers/plic/plic_driver.h new file mode 100644 index 0000000..f7201ee --- /dev/null +++ b/raven_spn/bsp/drivers/plic/plic_driver.h @@ -0,0 +1,52 @@ +// See LICENSE file for licence details + +#ifndef PLIC_DRIVER_H +#define PLIC_DRIVER_H + + +__BEGIN_DECLS + +#include "platform.h" + +typedef struct __plic_instance_t +{ + uintptr_t base_addr; + + uint32_t num_sources; + uint32_t num_priorities; + uint32_t target_hartid; +} plic_instance_t; + +typedef uint32_t plic_source; +typedef uint32_t plic_priority; +typedef uint32_t plic_threshold; + +void PLIC_init ( + plic_instance_t * this_plic, + uintptr_t base_addr, + uint32_t num_sources, + uint32_t num_priorities, + uint32_t target_hartid + ); + +void PLIC_set_threshold (plic_instance_t * this_plic, + plic_threshold threshold); + +void PLIC_enable_interrupt (plic_instance_t * this_plic, + plic_source source); + +void PLIC_disable_interrupt (plic_instance_t * this_plic, + plic_source source); + +void PLIC_set_priority (plic_instance_t * this_plic, + plic_source source, + plic_priority priority); + +plic_source PLIC_claim_interrupt(plic_instance_t * this_plic); + +void PLIC_complete_interrupt(plic_instance_t * this_plic, + plic_source source); + +__END_DECLS + +#endif diff --git a/raven_spn/bsp/env/common.mk b/raven_spn/bsp/env/common.mk new file mode 100644 index 0000000..0ca2c70 --- /dev/null +++ b/raven_spn/bsp/env/common.mk @@ -0,0 +1,66 @@ +# See LICENSE for license details. + +ifndef _SIFIVE_MK_COMMON +_SIFIVE_MK_COMMON := # defined + +.PHONY: all +all: $(TARGET) + +include $(BSP_BASE)/libwrap/libwrap.mk + +ENV_DIR = $(BSP_BASE)/env +PLATFORM_DIR = $(ENV_DIR)/$(BOARD) + +ASM_SRCS += $(ENV_DIR)/start.S +ASM_SRCS += $(ENV_DIR)/entry.S +C_SRCS += $(PLATFORM_DIR)/init.c + +LINKER_SCRIPT := $(PLATFORM_DIR)/$(LINK_TARGET).lds + +INCLUDES += -I$(BSP_BASE)/include +INCLUDES += -I$(BSP_BASE)/drivers/ +INCLUDES += -I$(ENV_DIR) +INCLUDES += -I$(PLATFORM_DIR) + +TOOL_DIR ?= $(BSP_BASE)/../toolchain/bin + +LDFLAGS += -T $(LINKER_SCRIPT) -nostartfiles +LDFLAGS += -L$(ENV_DIR) --specs=nano.specs + +ASM_OBJS := $(ASM_SRCS:.S=.o) +C_OBJS := $(C_SRCS:.c=.o) +CXX_OBJS := $(CXX_SRCS:.cpp=.o) + +LINK_OBJS += $(ASM_OBJS) $(C_OBJS) $(CXX_OBJS) +LINK_DEPS += $(LINKER_SCRIPT) + +CLEAN_OBJS += $(TARGET) $(LINK_OBJS) + +CFLAGS += -march=$(RISCV_ARCH) +CFLAGS += -mabi=$(RISCV_ABI) +CFLAGS += -mcmodel=medany + +TRIPLET?=riscv64-unknown-elf +CXX=$(TOOL_DIR)/$(TRIPLET)-c++ +CC=$(TOOL_DIR)/$(TRIPLET)-gcc +LD=$(TOOL_DIR)/$(TRIPLET)-gcc +AR=$(TOOL_DIR)/$(TRIPLET)-ar + + +$(TARGET): $(LINK_OBJS) $(LINK_DEPS) + $(LD) $(LINK_OBJS) $(LDFLAGS) $(LIBWRAP) -o $@ + +$(ASM_OBJS): %.o: %.S $(HEADERS) + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +$(C_OBJS): %.o: %.c $(HEADERS) + $(CC) $(CFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $< + +$(CXX_OBJS): %.o: %.cpp $(HEADERS) + $(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $< + +.PHONY: clean +clean: + rm -f $(CLEAN_OBJS) $(LIBWRAP) + +endif # _SIFIVE_MK_COMMON diff --git a/raven_spn/bsp/env/coreip-e2-arty/flash.lds b/raven_spn/bsp/env/coreip-e2-arty/flash.lds new file mode 100644 index 0000000..2d5eb01 --- /dev/null +++ b/raven_spn/bsp/env/coreip-e2-arty/flash.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >flash AT>flash :flash + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreip-e2-arty/init.c b/raven_spn/bsp/env/coreip-e2-arty/init.c new file mode 100644 index 0000000..3a4c77c --- /dev/null +++ b/raven_spn/bsp/env/coreip-e2-arty/init.c @@ -0,0 +1,98 @@ +//See LICENSE for license details. +#include +#include +#include + +#include "platform.h" +#include "encoding.h" + +#define CPU_FREQ 32000000 +#define XSTR(x) #x +#define STR(x) XSTR(x) + +extern int main(int argc, char** argv); + +unsigned long get_cpu_freq() +{ + return CPU_FREQ; +} + +unsigned long get_timer_freq() +{ + return get_cpu_freq(); +} + +uint64_t get_timer_value() +{ +#if __riscv_xlen == 32 + while (1) { + uint32_t hi = read_csr(mcycleh); + uint32_t lo = read_csr(mcycle); + if (hi == read_csr(mcycleh)) + return ((uint64_t)hi << 32) | lo; + } +#else + return read_csr(mcycle); +#endif +} + +static void uart_init(size_t baud_rate) +{ + UART0_REG(UART_REG_DIV) = (get_cpu_freq() ) / baud_rate - 1; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; +} + + +typedef void (*interrupt_function_ptr_t) (void); +interrupt_function_ptr_t localISR[CLIC_NUM_INTERRUPTS] __attribute__((aligned(64))); + + +void trap_entry(void) __attribute__((interrupt, aligned(64))); +void trap_entry(void) +{ + unsigned long mcause = read_csr(mcause); + unsigned long mepc = read_csr(mepc); + if (mcause & MCAUSE_INT) { + localISR[mcause & MCAUSE_CAUSE] (); + } else { + while(1); + } +} + +#ifdef CLIC_DIRECT +#else +void default_handler(void)__attribute__((interrupt));; +#endif +void default_handler(void) +{ + puts("default handler\n"); + while(1); +} + +void _init() +{ +#ifndef NO_INIT + uart_init(115200); + + puts("core freq at " STR(CPU_FREQ) " Hz\n"); + +//initialize vector table + int i=0; + while(iflash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreip-e2-arty/tim.lds b/raven_spn/bsp/env/coreip-e2-arty/tim.lds new file mode 100644 index 0000000..7dfb36b --- /dev/null +++ b/raven_spn/bsp/env/coreip-e2-arty/tim.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K +} + +PHDRS +{ + ram PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >ram AT>ram :ram + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >ram AT>ram :ram + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >ram AT>ram :ram + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >ram AT>ram :ram + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >ram AT>ram :ram + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >ram AT>ram :ram + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >ram AT>ram :ram + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >ram AT>ram :ram + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >ram AT>ram :ram + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >ram AT>ram :ram + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>ram :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>ram :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack : + { + . = ALIGN(8); + . += __stack_size; + PROVIDE( _sp = . ); + PROVIDE( _heap_end = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-arty.h b/raven_spn/bsp/env/coreplexip-arty.h new file mode 100644 index 0000000..eedcaa5 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-arty.h @@ -0,0 +1,102 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_COREPLEXIP_ARTY_H +#define _SIFIVE_COREPLEXIP_ARTY_H + +#include + +/**************************************************************************** + * GPIO Connections + *****************************************************************************/ + +// These are the GPIO bit offsets for the directly driven +// RGB LEDs on the Freedom Exx Coreplex IP Evaluation Arty FPGA Dev Kit. +// Additional RGB LEDs are driven by the 3 PWM outputs. + +#define RED_LED_OFFSET 0 +#define GREEN_LED_OFFSET 1 +#define BLUE_LED_OFFSET 2 + +// Switch 3 is used as a GPIO input. (Switch 0 is used to set +// the reset vector, the other switches are unused). + +#define SW_3_OFFSET 3 + +// These are the buttons which are mapped as inputs. + +#define HAS_BOARD_BUTTONS + +#define BUTTON_0_OFFSET 4 +#define BUTTON_1_OFFSET 5 +#define BUTTON_2_OFFSET 6 +#define BUTTON_3_OFFSET 7 + +// These are the bit offsets for the different GPIO pins +// mapped onto the PMOD A header. + +#define JA_0_OFFSET 8 +#define JA_1_OFFSET 9 +#define JA_2_OFFSET 10 +#define JA_3_OFFSET 11 +#define JA_4_OFFSET 12 +#define JA_5_OFFSET 13 +#define JA_6_OFFSET 14 +#define JA_7_OFFSET 15 + +// The below gives a mapping between global interrupt +// sources and their number. Note that on the coreplex +// deliverable, the io_global_interrupts go directly into +// the PLIC. The evaluation image on the FPGA mimics a +// system with peripheral devices which are driving the +// global interrupt lines. +// So, on this image, in order to get an interrupt from +// e.g. pressing BUTTON_0: +// 1) Steps which are external to the delivery coreplex: +// a) The corresponding GPIO pin must be configured as in input +// b) The "interrupt on fall" bit must be set for the GPIO pin +// 2) Steps which would also need to be performed for the delivery coreplex: +// a) The corresponding global interrupt, priority, and threshold must be configured in the PLIC. +// b) The external interrupt bit must be enabled in MSTATUS +// c) Interrupts must be enabled globally in the core. + +// Any of the above GPIO pins can be used as global interrupt +// sources by adding their offset to the INT_GPIO_BASE. +// For example, the buttons are shown here: + +#define INT_DEVICE_BUTTON_0 (GPIO_INT_BASE + BUTTON_0_OFFSET) +#define INT_DEVICE_BUTTON_1 (GPIO_INT_BASE + BUTTON_1_OFFSET) +#define INT_DEVICE_BUTTON_2 (GPIO_INT_BASE + BUTTON_2_OFFSET) +#define INT_DEVICE_BUTTON_3 (GPIO_INT_BASE + BUTTON_3_OFFSET) + +// In addition, the Switches are mapped directly to +// the PLIC (without going through the GPIO Peripheral). + +#define INT_EXT_DEVICE_SW_0 (EXTERNAL_INT_BASE + 0) +#define INT_EXT_DEVICE_SW_1 (EXTERNAL_INT_BASE + 1) +#define INT_EXT_DEVICE_SW_2 (EXTERNAL_INT_BASE + 2) +#define INT_EXT_DEVICE_SW_3 (EXTERNAL_INT_BASE + 3) + +// This gives the mapping from inputs to LOCAL interrupts. + +#define LOCAL_INT_SW_0 0 +#define LOCAL_INT_SW_1 1 +#define LOCAL_INT_SW_2 2 +#define LOCAL_INT_SW_3 3 +#define LOCAL_INT_BTN_0 4 +#define LOCAL_INT_BTN_1 5 +#define LOCAL_INT_BTN_2 6 +#define LOCAL_INT_BTN_3 7 +#define LOCAL_INT_JA_0 8 +#define LOCAL_INT_JA_1 9 +#define LOCAL_INT_JA_2 10 +#define LOCAL_INT_JA_3 11 +#define LOCAL_INT_JA_4 12 +#define LOCAL_INT_JA_5 13 +#define LOCAL_INT_JA_6 14 +#define LOCAL_INT_JA_7 15 + +#define RTC_FREQ 32768 + +void write_hex(int fd, unsigned long int hex); + +#endif /* _SIFIVE_COREPLEXIP_ARTY_H */ diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/dhrystone.lds b/raven_spn/bsp/env/coreplexip-e31-arty/dhrystone.lds new file mode 100644 index 0000000..8f6527b --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/dhrystone.lds @@ -0,0 +1,157 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/flash.lds b/raven_spn/bsp/env/coreplexip-e31-arty/flash.lds new file mode 100644 index 0000000..590c5b6 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/flash.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >flash AT>flash :flash + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/init.c b/raven_spn/bsp/env/coreplexip-e31-arty/init.c new file mode 100644 index 0000000..1f8b679 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/init.c @@ -0,0 +1,122 @@ +//See LICENSE for license details. +#include +#include +#include + +#include "platform.h" +#include "encoding.h" + +#define CPU_FREQ 65000000 +#define XSTR(x) #x +#define STR(x) XSTR(x) + +#ifndef VECT_IRQ + #define TRAP_ENTRY trap_entry +#else + #define TRAP_ENTRY vtrap_entry +#endif + +extern int main(int argc, char** argv); +extern void TRAP_ENTRY(); + +unsigned long get_cpu_freq() +{ + return CPU_FREQ; +} + +unsigned long get_timer_freq() +{ + return get_cpu_freq(); +} + +uint64_t get_timer_value() +{ +#if __riscv_xlen == 32 + while (1) { + uint32_t hi = read_csr(mcycleh); + uint32_t lo = read_csr(mcycle); + if (hi == read_csr(mcycleh)) + return ((uint64_t)hi << 32) | lo; + } +#else + return read_csr(mcycle); +#endif +} + +static void uart_init(size_t baud_rate) +{ + UART0_REG(UART_REG_DIV) = (get_cpu_freq() / 2) / baud_rate - 1; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; +} + + +#ifdef USE_PLIC +extern void handle_m_ext_interrupt(); +#endif + +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +#ifdef USE_LOCAL_ISR +typedef void (*my_interrupt_function_ptr_t) (void); +extern my_interrupt_function_ptr_t localISR[]; +#endif + +#ifndef VECT_IRQ +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) __attribute__((noinline)); +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + if (0){ +#ifdef USE_PLIC + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { + handle_m_ext_interrupt(); +#endif +#ifdef USE_M_TIME + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif +#ifdef USE_LOCAL_ISR + } else if (mcause & MCAUSE_INT) { + localISR[mcause & MCAUSE_CAUSE] (); +#endif + } + else { + write(1, "Unhandled Trap:\n", 16); + _exit(1 + mcause); + } + return epc; +} +#endif + +#ifdef USE_CLIC +void trap_entry(void) __attribute__((interrupt("SiFive-CLIC-preemptible"), aligned(64))); +void trap_entry(void) +{ + unsigned long mcause = read_csr(mcause); + unsigned long mepc = read_csr(mepc); + handle_trap(mcause, mepc); +} +#endif + +void _init() +{ + #ifndef NO_INIT + uart_init(115200); + + puts("core freq at " STR(CPU_FREQ) " Hz\n"); + +#ifdef USE_CLIC + write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC)); +#else + write_csr(mtvec, ((unsigned long)&TRAP_ENTRY | MTVEC_VECTORED)); +#endif + + #endif +} + +void _fini() +{ +} diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/openocd.cfg b/raven_spn/bsp/env/coreplexip-e31-arty/openocd.cfg new file mode 100644 index 0000000..0481a72 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/openocd.cfg @@ -0,0 +1,31 @@ +# JTAG adapter setup +adapter_khz 10000 + +interface ftdi +ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" +ftdi_vid_pid 0x15ba 0x002a + +ftdi_layout_init 0x0808 0x0a1b +ftdi_layout_signal nSRST -oe 0x0200 +#ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 +ftdi_layout_signal LED -data 0x0800 + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 + +# Un-comment these two flash lines if you have a SPI flash and want to write +# it. +flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000 +init +if {[ info exists pulse_srst]} { + ftdi_set_signal nSRST 0 + ftdi_set_signal nSRST z +} +halt +#flash protect 0 64 last off +echo "Ready for Remote Connections" diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/platform.h b/raven_spn/bsp/env/coreplexip-e31-arty/platform.h new file mode 100644 index 0000000..6fa79ea --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/platform.h @@ -0,0 +1,100 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PLATFORM_H +#define _SIFIVE_PLATFORM_H + +// Some things missing from the official encoding.h + +#if __riscv_xlen == 32 +#define MCAUSE_INT 0x80000000UL +#define MCAUSE_CAUSE 0x000003FFUL +#else +#define MCAUSE_INT 0x8000000000000000UL +#define MCAUSE_CAUSE 0x00000000000003FFUL +#endif + +#ifdef VECT_IRQ + #define MTVEC_VECTORED 0x01 +#else + #define MTVEC_VECTORED 0x00 +#endif +#define MTVEC_CLIC 0x02 +#define IRQ_M_LOCAL 16 +#define MIP_MLIP(x) (1 << (IRQ_M_LOCAL + x)) + +#include "sifive/const.h" +#include "sifive/devices/clint.h" +#include "sifive/devices/gpio.h" +#include "sifive/devices/plic.h" +#include "sifive/devices/pwm.h" +#include "sifive/devices/spi.h" +#include "sifive/devices/uart.h" + +/**************************************************************************** + * Platform definitions + *****************************************************************************/ + +// Memory map +#define CLINT_CTRL_ADDR _AC(0x02000000,UL) +#define GPIO_CTRL_ADDR _AC(0x20002000,UL) +#define PLIC_CTRL_ADDR _AC(0x0C000000,UL) +#define PWM0_CTRL_ADDR _AC(0x20005000,UL) +#define RAM_MEM_ADDR _AC(0x80000000,UL) +#define RAM_MEM_SIZE _AC(0x10000,UL) +#define SPI0_CTRL_ADDR _AC(0x20004000,UL) +#define SPI0_MEM_ADDR _AC(0x40000000,UL) +#define SPI0_MEM_SIZE _AC(0x20000000,UL) +#define TESTBENCH_MEM_ADDR _AC(0x20000000,UL) +#define TESTBENCH_MEM_SIZE _AC(0x10000000,UL) +#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL) +#define UART0_CTRL_ADDR _AC(0x20000000,UL) + +// IOF masks + +// Interrupt numbers +#define RESERVED_INT_BASE 0 +#define UART0_INT_BASE 1 +#define EXTERNAL_INT_BASE 2 +#define SPI0_INT_BASE 6 +#define GPIO_INT_BASE 7 +#define PWM0_INT_BASE 23 + +// Helper functions +#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i))) +#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i))) +#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i))) +// Bulk set bits in `reg` to either 0 or 1. +// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7 +// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7 +#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); } +#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset) +#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset) +#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset) +#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset) +#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset) +#define TRAPVEC_TABLE_REG(offset) _REG32(TRAPVEC_TABLE_CTRL_ADDR, offset) +#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset) +#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset) +#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset) +#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset) +#define PWM0_REG64(offset) _REG64(PWM0_CTRL_ADDR, offset) +#define SPI0_REG64(offset) _REG64(SPI0_CTRL_ADDR, offset) +#define TRAPVEC_TABLE_REG64(offset) _REG64(TRAPVEC_TABLE_CTRL_ADDR, offset) +#define UART0_REG64(offset) _REG64(UART0_CTRL_ADDR, offset) + +// Misc + +#define NUM_GPIO 16 + +#define PLIC_NUM_INTERRUPTS 28 +#define PLIC_NUM_PRIORITIES 7 + +#define HAS_BOARD_BUTTONS + +#include "coreplexip-arty.h" + +unsigned long get_cpu_freq(void); +unsigned long get_timer_freq(void); +uint64_t get_timer_value(void); + +#endif /* _SIFIVE_PLATFORM_H */ diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/scratchpad.lds b/raven_spn/bsp/env/coreplexip-e31-arty/scratchpad.lds new file mode 100644 index 0000000..7887c13 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/scratchpad.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + ram PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >ram AT>ram :ram + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >ram AT>ram :ram + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >ram AT>ram :ram + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >ram AT>ram :ram + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >ram AT>ram :ram + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >ram AT>ram :ram + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >ram AT>ram :ram + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >ram AT>ram :ram + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >ram AT>ram :ram + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >ram AT>ram :ram + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>ram :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>ram :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack : + { + . = ALIGN(8); + . += __stack_size; + PROVIDE( _sp = . ); + PROVIDE( _heap_end = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e31-arty/settings.mk b/raven_spn/bsp/env/coreplexip-e31-arty/settings.mk new file mode 100644 index 0000000..230fccc --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e31-arty/settings.mk @@ -0,0 +1,3 @@ +# Describes the CPU on this board to the rest of the SDK. +RISCV_ARCH := rv32imac +RISCV_ABI := ilp32 diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/dhrystone.lds b/raven_spn/bsp/env/coreplexip-e51-arty/dhrystone.lds new file mode 100644 index 0000000..8f6527b --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/dhrystone.lds @@ -0,0 +1,157 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/flash.lds b/raven_spn/bsp/env/coreplexip-e51-arty/flash.lds new file mode 100644 index 0000000..590c5b6 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/flash.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >flash AT>flash :flash + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/init.c b/raven_spn/bsp/env/coreplexip-e51-arty/init.c new file mode 100644 index 0000000..1f8b679 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/init.c @@ -0,0 +1,122 @@ +//See LICENSE for license details. +#include +#include +#include + +#include "platform.h" +#include "encoding.h" + +#define CPU_FREQ 65000000 +#define XSTR(x) #x +#define STR(x) XSTR(x) + +#ifndef VECT_IRQ + #define TRAP_ENTRY trap_entry +#else + #define TRAP_ENTRY vtrap_entry +#endif + +extern int main(int argc, char** argv); +extern void TRAP_ENTRY(); + +unsigned long get_cpu_freq() +{ + return CPU_FREQ; +} + +unsigned long get_timer_freq() +{ + return get_cpu_freq(); +} + +uint64_t get_timer_value() +{ +#if __riscv_xlen == 32 + while (1) { + uint32_t hi = read_csr(mcycleh); + uint32_t lo = read_csr(mcycle); + if (hi == read_csr(mcycleh)) + return ((uint64_t)hi << 32) | lo; + } +#else + return read_csr(mcycle); +#endif +} + +static void uart_init(size_t baud_rate) +{ + UART0_REG(UART_REG_DIV) = (get_cpu_freq() / 2) / baud_rate - 1; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; +} + + +#ifdef USE_PLIC +extern void handle_m_ext_interrupt(); +#endif + +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +#ifdef USE_LOCAL_ISR +typedef void (*my_interrupt_function_ptr_t) (void); +extern my_interrupt_function_ptr_t localISR[]; +#endif + +#ifndef VECT_IRQ +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) __attribute__((noinline)); +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + if (0){ +#ifdef USE_PLIC + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { + handle_m_ext_interrupt(); +#endif +#ifdef USE_M_TIME + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif +#ifdef USE_LOCAL_ISR + } else if (mcause & MCAUSE_INT) { + localISR[mcause & MCAUSE_CAUSE] (); +#endif + } + else { + write(1, "Unhandled Trap:\n", 16); + _exit(1 + mcause); + } + return epc; +} +#endif + +#ifdef USE_CLIC +void trap_entry(void) __attribute__((interrupt("SiFive-CLIC-preemptible"), aligned(64))); +void trap_entry(void) +{ + unsigned long mcause = read_csr(mcause); + unsigned long mepc = read_csr(mepc); + handle_trap(mcause, mepc); +} +#endif + +void _init() +{ + #ifndef NO_INIT + uart_init(115200); + + puts("core freq at " STR(CPU_FREQ) " Hz\n"); + +#ifdef USE_CLIC + write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC)); +#else + write_csr(mtvec, ((unsigned long)&TRAP_ENTRY | MTVEC_VECTORED)); +#endif + + #endif +} + +void _fini() +{ +} diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/openocd.cfg b/raven_spn/bsp/env/coreplexip-e51-arty/openocd.cfg new file mode 100644 index 0000000..0481a72 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/openocd.cfg @@ -0,0 +1,31 @@ +# JTAG adapter setup +adapter_khz 10000 + +interface ftdi +ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" +ftdi_vid_pid 0x15ba 0x002a + +ftdi_layout_init 0x0808 0x0a1b +ftdi_layout_signal nSRST -oe 0x0200 +#ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 +ftdi_layout_signal LED -data 0x0800 + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 + +# Un-comment these two flash lines if you have a SPI flash and want to write +# it. +flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000 +init +if {[ info exists pulse_srst]} { + ftdi_set_signal nSRST 0 + ftdi_set_signal nSRST z +} +halt +#flash protect 0 64 last off +echo "Ready for Remote Connections" diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/platform.h b/raven_spn/bsp/env/coreplexip-e51-arty/platform.h new file mode 100644 index 0000000..6fa79ea --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/platform.h @@ -0,0 +1,100 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PLATFORM_H +#define _SIFIVE_PLATFORM_H + +// Some things missing from the official encoding.h + +#if __riscv_xlen == 32 +#define MCAUSE_INT 0x80000000UL +#define MCAUSE_CAUSE 0x000003FFUL +#else +#define MCAUSE_INT 0x8000000000000000UL +#define MCAUSE_CAUSE 0x00000000000003FFUL +#endif + +#ifdef VECT_IRQ + #define MTVEC_VECTORED 0x01 +#else + #define MTVEC_VECTORED 0x00 +#endif +#define MTVEC_CLIC 0x02 +#define IRQ_M_LOCAL 16 +#define MIP_MLIP(x) (1 << (IRQ_M_LOCAL + x)) + +#include "sifive/const.h" +#include "sifive/devices/clint.h" +#include "sifive/devices/gpio.h" +#include "sifive/devices/plic.h" +#include "sifive/devices/pwm.h" +#include "sifive/devices/spi.h" +#include "sifive/devices/uart.h" + +/**************************************************************************** + * Platform definitions + *****************************************************************************/ + +// Memory map +#define CLINT_CTRL_ADDR _AC(0x02000000,UL) +#define GPIO_CTRL_ADDR _AC(0x20002000,UL) +#define PLIC_CTRL_ADDR _AC(0x0C000000,UL) +#define PWM0_CTRL_ADDR _AC(0x20005000,UL) +#define RAM_MEM_ADDR _AC(0x80000000,UL) +#define RAM_MEM_SIZE _AC(0x10000,UL) +#define SPI0_CTRL_ADDR _AC(0x20004000,UL) +#define SPI0_MEM_ADDR _AC(0x40000000,UL) +#define SPI0_MEM_SIZE _AC(0x20000000,UL) +#define TESTBENCH_MEM_ADDR _AC(0x20000000,UL) +#define TESTBENCH_MEM_SIZE _AC(0x10000000,UL) +#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL) +#define UART0_CTRL_ADDR _AC(0x20000000,UL) + +// IOF masks + +// Interrupt numbers +#define RESERVED_INT_BASE 0 +#define UART0_INT_BASE 1 +#define EXTERNAL_INT_BASE 2 +#define SPI0_INT_BASE 6 +#define GPIO_INT_BASE 7 +#define PWM0_INT_BASE 23 + +// Helper functions +#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i))) +#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i))) +#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i))) +// Bulk set bits in `reg` to either 0 or 1. +// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7 +// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7 +#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); } +#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset) +#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset) +#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset) +#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset) +#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset) +#define TRAPVEC_TABLE_REG(offset) _REG32(TRAPVEC_TABLE_CTRL_ADDR, offset) +#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset) +#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset) +#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset) +#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset) +#define PWM0_REG64(offset) _REG64(PWM0_CTRL_ADDR, offset) +#define SPI0_REG64(offset) _REG64(SPI0_CTRL_ADDR, offset) +#define TRAPVEC_TABLE_REG64(offset) _REG64(TRAPVEC_TABLE_CTRL_ADDR, offset) +#define UART0_REG64(offset) _REG64(UART0_CTRL_ADDR, offset) + +// Misc + +#define NUM_GPIO 16 + +#define PLIC_NUM_INTERRUPTS 28 +#define PLIC_NUM_PRIORITIES 7 + +#define HAS_BOARD_BUTTONS + +#include "coreplexip-arty.h" + +unsigned long get_cpu_freq(void); +unsigned long get_timer_freq(void); +uint64_t get_timer_value(void); + +#endif /* _SIFIVE_PLATFORM_H */ diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/scratchpad.lds b/raven_spn/bsp/env/coreplexip-e51-arty/scratchpad.lds new file mode 100644 index 0000000..7887c13 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/scratchpad.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + ram PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >ram AT>ram :ram + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >ram AT>ram :ram + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >ram AT>ram :ram + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >ram AT>ram :ram + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >ram AT>ram :ram + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >ram AT>ram :ram + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >ram AT>ram :ram + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >ram AT>ram :ram + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >ram AT>ram :ram + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >ram AT>ram :ram + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>ram :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>ram :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack : + { + . = ALIGN(8); + . += __stack_size; + PROVIDE( _sp = . ); + PROVIDE( _heap_end = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/coreplexip-e51-arty/settings.mk b/raven_spn/bsp/env/coreplexip-e51-arty/settings.mk new file mode 100644 index 0000000..96aea84 --- /dev/null +++ b/raven_spn/bsp/env/coreplexip-e51-arty/settings.mk @@ -0,0 +1,3 @@ +# Describes the CPU on this board to the rest of the SDK. +RISCV_ARCH := rv64imac +RISCV_ABI := lp64 diff --git a/raven_spn/bsp/env/encoding.h b/raven_spn/bsp/env/encoding.h new file mode 100644 index 0000000..35e0f9f --- /dev/null +++ b/raven_spn/bsp/env/encoding.h @@ -0,0 +1,1313 @@ +// See LICENSE for license details. + +#ifndef RISCV_CSR_ENCODING_H +#define RISCV_CSR_ENCODING_H + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_HPP 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_PUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_VM 0x1F000000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_PUM 0x00040000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define VM_MBARE 0 +#define VM_MBB 1 +#define VM_MBBID 2 +#define VM_SV32 8 +#define VM_SV39 9 +#define VM_SV48 10 + +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +#define DEFAULT_RSTVEC 0x00001000 +#define DEFAULT_NMIVEC 0x00001004 +#define DEFAULT_MTVEC 0x00001010 +#define CONFIG_STRING_ADDR 0x0000100C +#define EXT_IO_BASE 0x40000000 +#define DRAM_BASE 0x80000000 + +// page table entry (PTE) fields +#define PTE_V 0x001 // Valid +#define PTE_R 0x002 // Read +#define PTE_W 0x004 // Write +#define PTE_X 0x008 // Execute +#define PTE_U 0x010 // User +#define PTE_G 0x020 // Global +#define PTE_A 0x040 // Accessed +#define PTE_D 0x080 // Dirty +#define PTE_SOFT 0x300 // Reserved for Software + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#ifdef __riscv + +#ifdef __riscv64 +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD +# define RISCV_PGLEVEL_BITS 9 +#else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD +# define RISCV_PGLEVEL_BITS 10 +#endif +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#ifndef __ASSEMBLER__ + +#ifdef __GNUC__ + +#define read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define swap_csr(reg, val) ({ unsigned long __tmp; \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ + else \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + __tmp; }) + +#define set_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define clear_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define rdtime() read_csr(time) +#define rdcycle() read_csr(cycle) +#define rdinstret() read_csr(instret) + +#endif + +#endif + +#endif + +#endif +/* Automatically generated by parse-opcodes */ +#ifndef RISCV_ENCODING_H +#define RISCV_ENCODING_H +#define MATCH_BEQ 0x63 +#define MASK_BEQ 0x707f +#define MATCH_BNE 0x1063 +#define MASK_BNE 0x707f +#define MATCH_BLT 0x4063 +#define MASK_BLT 0x707f +#define MATCH_BGE 0x5063 +#define MASK_BGE 0x707f +#define MATCH_BLTU 0x6063 +#define MASK_BLTU 0x707f +#define MATCH_BGEU 0x7063 +#define MASK_BGEU 0x707f +#define MATCH_JALR 0x67 +#define MASK_JALR 0x707f +#define MATCH_JAL 0x6f +#define MASK_JAL 0x7f +#define MATCH_LUI 0x37 +#define MASK_LUI 0x7f +#define MATCH_AUIPC 0x17 +#define MASK_AUIPC 0x7f +#define MATCH_ADDI 0x13 +#define MASK_ADDI 0x707f +#define MATCH_SLLI 0x1013 +#define MASK_SLLI 0xfc00707f +#define MATCH_SLTI 0x2013 +#define MASK_SLTI 0x707f +#define MATCH_SLTIU 0x3013 +#define MASK_SLTIU 0x707f +#define MATCH_XORI 0x4013 +#define MASK_XORI 0x707f +#define MATCH_SRLI 0x5013 +#define MASK_SRLI 0xfc00707f +#define MATCH_SRAI 0x40005013 +#define MASK_SRAI 0xfc00707f +#define MATCH_ORI 0x6013 +#define MASK_ORI 0x707f +#define MATCH_ANDI 0x7013 +#define MASK_ANDI 0x707f +#define MATCH_ADD 0x33 +#define MASK_ADD 0xfe00707f +#define MATCH_SUB 0x40000033 +#define MASK_SUB 0xfe00707f +#define MATCH_SLL 0x1033 +#define MASK_SLL 0xfe00707f +#define MATCH_SLT 0x2033 +#define MASK_SLT 0xfe00707f +#define MATCH_SLTU 0x3033 +#define MASK_SLTU 0xfe00707f +#define MATCH_XOR 0x4033 +#define MASK_XOR 0xfe00707f +#define MATCH_SRL 0x5033 +#define MASK_SRL 0xfe00707f +#define MATCH_SRA 0x40005033 +#define MASK_SRA 0xfe00707f +#define MATCH_OR 0x6033 +#define MASK_OR 0xfe00707f +#define MATCH_AND 0x7033 +#define MASK_AND 0xfe00707f +#define MATCH_ADDIW 0x1b +#define MASK_ADDIW 0x707f +#define MATCH_SLLIW 0x101b +#define MASK_SLLIW 0xfe00707f +#define MATCH_SRLIW 0x501b +#define MASK_SRLIW 0xfe00707f +#define MATCH_SRAIW 0x4000501b +#define MASK_SRAIW 0xfe00707f +#define MATCH_ADDW 0x3b +#define MASK_ADDW 0xfe00707f +#define MATCH_SUBW 0x4000003b +#define MASK_SUBW 0xfe00707f +#define MATCH_SLLW 0x103b +#define MASK_SLLW 0xfe00707f +#define MATCH_SRLW 0x503b +#define MASK_SRLW 0xfe00707f +#define MATCH_SRAW 0x4000503b +#define MASK_SRAW 0xfe00707f +#define MATCH_LB 0x3 +#define MASK_LB 0x707f +#define MATCH_LH 0x1003 +#define MASK_LH 0x707f +#define MATCH_LW 0x2003 +#define MASK_LW 0x707f +#define MATCH_LD 0x3003 +#define MASK_LD 0x707f +#define MATCH_LBU 0x4003 +#define MASK_LBU 0x707f +#define MATCH_LHU 0x5003 +#define MASK_LHU 0x707f +#define MATCH_LWU 0x6003 +#define MASK_LWU 0x707f +#define MATCH_SB 0x23 +#define MASK_SB 0x707f +#define MATCH_SH 0x1023 +#define MASK_SH 0x707f +#define MATCH_SW 0x2023 +#define MASK_SW 0x707f +#define MATCH_SD 0x3023 +#define MASK_SD 0x707f +#define MATCH_FENCE 0xf +#define MASK_FENCE 0x707f +#define MATCH_FENCE_I 0x100f +#define MASK_FENCE_I 0x707f +#define MATCH_MUL 0x2000033 +#define MASK_MUL 0xfe00707f +#define MATCH_MULH 0x2001033 +#define MASK_MULH 0xfe00707f +#define MATCH_MULHSU 0x2002033 +#define MASK_MULHSU 0xfe00707f +#define MATCH_MULHU 0x2003033 +#define MASK_MULHU 0xfe00707f +#define MATCH_DIV 0x2004033 +#define MASK_DIV 0xfe00707f +#define MATCH_DIVU 0x2005033 +#define MASK_DIVU 0xfe00707f +#define MATCH_REM 0x2006033 +#define MASK_REM 0xfe00707f +#define MATCH_REMU 0x2007033 +#define MASK_REMU 0xfe00707f +#define MATCH_MULW 0x200003b +#define MASK_MULW 0xfe00707f +#define MATCH_DIVW 0x200403b +#define MASK_DIVW 0xfe00707f +#define MATCH_DIVUW 0x200503b +#define MASK_DIVUW 0xfe00707f +#define MATCH_REMW 0x200603b +#define MASK_REMW 0xfe00707f +#define MATCH_REMUW 0x200703b +#define MASK_REMUW 0xfe00707f +#define MATCH_AMOADD_W 0x202f +#define MASK_AMOADD_W 0xf800707f +#define MATCH_AMOXOR_W 0x2000202f +#define MASK_AMOXOR_W 0xf800707f +#define MATCH_AMOOR_W 0x4000202f +#define MASK_AMOOR_W 0xf800707f +#define MATCH_AMOAND_W 0x6000202f +#define MASK_AMOAND_W 0xf800707f +#define MATCH_AMOMIN_W 0x8000202f +#define MASK_AMOMIN_W 0xf800707f +#define MATCH_AMOMAX_W 0xa000202f +#define MASK_AMOMAX_W 0xf800707f +#define MATCH_AMOMINU_W 0xc000202f +#define MASK_AMOMINU_W 0xf800707f +#define MATCH_AMOMAXU_W 0xe000202f +#define MASK_AMOMAXU_W 0xf800707f +#define MATCH_AMOSWAP_W 0x800202f +#define MASK_AMOSWAP_W 0xf800707f +#define MATCH_LR_W 0x1000202f +#define MASK_LR_W 0xf9f0707f +#define MATCH_SC_W 0x1800202f +#define MASK_SC_W 0xf800707f +#define MATCH_AMOADD_D 0x302f +#define MASK_AMOADD_D 0xf800707f +#define MATCH_AMOXOR_D 0x2000302f +#define MASK_AMOXOR_D 0xf800707f +#define MATCH_AMOOR_D 0x4000302f +#define MASK_AMOOR_D 0xf800707f +#define MATCH_AMOAND_D 0x6000302f +#define MASK_AMOAND_D 0xf800707f +#define MATCH_AMOMIN_D 0x8000302f +#define MASK_AMOMIN_D 0xf800707f +#define MATCH_AMOMAX_D 0xa000302f +#define MASK_AMOMAX_D 0xf800707f +#define MATCH_AMOMINU_D 0xc000302f +#define MASK_AMOMINU_D 0xf800707f +#define MATCH_AMOMAXU_D 0xe000302f +#define MASK_AMOMAXU_D 0xf800707f +#define MATCH_AMOSWAP_D 0x800302f +#define MASK_AMOSWAP_D 0xf800707f +#define MATCH_LR_D 0x1000302f +#define MASK_LR_D 0xf9f0707f +#define MATCH_SC_D 0x1800302f +#define MASK_SC_D 0xf800707f +#define MATCH_ECALL 0x73 +#define MASK_ECALL 0xffffffff +#define MATCH_EBREAK 0x100073 +#define MASK_EBREAK 0xffffffff +#define MATCH_URET 0x200073 +#define MASK_URET 0xffffffff +#define MATCH_SRET 0x10200073 +#define MASK_SRET 0xffffffff +#define MATCH_HRET 0x20200073 +#define MASK_HRET 0xffffffff +#define MATCH_MRET 0x30200073 +#define MASK_MRET 0xffffffff +#define MATCH_DRET 0x7b200073 +#define MASK_DRET 0xffffffff +#define MATCH_SFENCE_VM 0x10400073 +#define MASK_SFENCE_VM 0xfff07fff +#define MATCH_WFI 0x10500073 +#define MASK_WFI 0xffffffff +#define MATCH_CSRRW 0x1073 +#define MASK_CSRRW 0x707f +#define MATCH_CSRRS 0x2073 +#define MASK_CSRRS 0x707f +#define MATCH_CSRRC 0x3073 +#define MASK_CSRRC 0x707f +#define MATCH_CSRRWI 0x5073 +#define MASK_CSRRWI 0x707f +#define MATCH_CSRRSI 0x6073 +#define MASK_CSRRSI 0x707f +#define MATCH_CSRRCI 0x7073 +#define MASK_CSRRCI 0x707f +#define MATCH_FADD_S 0x53 +#define MASK_FADD_S 0xfe00007f +#define MATCH_FSUB_S 0x8000053 +#define MASK_FSUB_S 0xfe00007f +#define MATCH_FMUL_S 0x10000053 +#define MASK_FMUL_S 0xfe00007f +#define MATCH_FDIV_S 0x18000053 +#define MASK_FDIV_S 0xfe00007f +#define MATCH_FSGNJ_S 0x20000053 +#define MASK_FSGNJ_S 0xfe00707f +#define MATCH_FSGNJN_S 0x20001053 +#define MASK_FSGNJN_S 0xfe00707f +#define MATCH_FSGNJX_S 0x20002053 +#define MASK_FSGNJX_S 0xfe00707f +#define MATCH_FMIN_S 0x28000053 +#define MASK_FMIN_S 0xfe00707f +#define MATCH_FMAX_S 0x28001053 +#define MASK_FMAX_S 0xfe00707f +#define MATCH_FSQRT_S 0x58000053 +#define MASK_FSQRT_S 0xfff0007f +#define MATCH_FADD_D 0x2000053 +#define MASK_FADD_D 0xfe00007f +#define MATCH_FSUB_D 0xa000053 +#define MASK_FSUB_D 0xfe00007f +#define MATCH_FMUL_D 0x12000053 +#define MASK_FMUL_D 0xfe00007f +#define MATCH_FDIV_D 0x1a000053 +#define MASK_FDIV_D 0xfe00007f +#define MATCH_FSGNJ_D 0x22000053 +#define MASK_FSGNJ_D 0xfe00707f +#define MATCH_FSGNJN_D 0x22001053 +#define MASK_FSGNJN_D 0xfe00707f +#define MATCH_FSGNJX_D 0x22002053 +#define MASK_FSGNJX_D 0xfe00707f +#define MATCH_FMIN_D 0x2a000053 +#define MASK_FMIN_D 0xfe00707f +#define MATCH_FMAX_D 0x2a001053 +#define MASK_FMAX_D 0xfe00707f +#define MATCH_FCVT_S_D 0x40100053 +#define MASK_FCVT_S_D 0xfff0007f +#define MATCH_FCVT_D_S 0x42000053 +#define MASK_FCVT_D_S 0xfff0007f +#define MATCH_FSQRT_D 0x5a000053 +#define MASK_FSQRT_D 0xfff0007f +#define MATCH_FLE_S 0xa0000053 +#define MASK_FLE_S 0xfe00707f +#define MATCH_FLT_S 0xa0001053 +#define MASK_FLT_S 0xfe00707f +#define MATCH_FEQ_S 0xa0002053 +#define MASK_FEQ_S 0xfe00707f +#define MATCH_FLE_D 0xa2000053 +#define MASK_FLE_D 0xfe00707f +#define MATCH_FLT_D 0xa2001053 +#define MASK_FLT_D 0xfe00707f +#define MATCH_FEQ_D 0xa2002053 +#define MASK_FEQ_D 0xfe00707f +#define MATCH_FCVT_W_S 0xc0000053 +#define MASK_FCVT_W_S 0xfff0007f +#define MATCH_FCVT_WU_S 0xc0100053 +#define MASK_FCVT_WU_S 0xfff0007f +#define MATCH_FCVT_L_S 0xc0200053 +#define MASK_FCVT_L_S 0xfff0007f +#define MATCH_FCVT_LU_S 0xc0300053 +#define MASK_FCVT_LU_S 0xfff0007f +#define MATCH_FMV_X_S 0xe0000053 +#define MASK_FMV_X_S 0xfff0707f +#define MATCH_FCLASS_S 0xe0001053 +#define MASK_FCLASS_S 0xfff0707f +#define MATCH_FCVT_W_D 0xc2000053 +#define MASK_FCVT_W_D 0xfff0007f +#define MATCH_FCVT_WU_D 0xc2100053 +#define MASK_FCVT_WU_D 0xfff0007f +#define MATCH_FCVT_L_D 0xc2200053 +#define MASK_FCVT_L_D 0xfff0007f +#define MATCH_FCVT_LU_D 0xc2300053 +#define MASK_FCVT_LU_D 0xfff0007f +#define MATCH_FMV_X_D 0xe2000053 +#define MASK_FMV_X_D 0xfff0707f +#define MATCH_FCLASS_D 0xe2001053 +#define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCVT_S_W 0xd0000053 +#define MASK_FCVT_S_W 0xfff0007f +#define MATCH_FCVT_S_WU 0xd0100053 +#define MASK_FCVT_S_WU 0xfff0007f +#define MATCH_FCVT_S_L 0xd0200053 +#define MASK_FCVT_S_L 0xfff0007f +#define MATCH_FCVT_S_LU 0xd0300053 +#define MASK_FCVT_S_LU 0xfff0007f +#define MATCH_FMV_S_X 0xf0000053 +#define MASK_FMV_S_X 0xfff0707f +#define MATCH_FCVT_D_W 0xd2000053 +#define MASK_FCVT_D_W 0xfff0007f +#define MATCH_FCVT_D_WU 0xd2100053 +#define MASK_FCVT_D_WU 0xfff0007f +#define MATCH_FCVT_D_L 0xd2200053 +#define MASK_FCVT_D_L 0xfff0007f +#define MATCH_FCVT_D_LU 0xd2300053 +#define MASK_FCVT_D_LU 0xfff0007f +#define MATCH_FMV_D_X 0xf2000053 +#define MASK_FMV_D_X 0xfff0707f +#define MATCH_FLW 0x2007 +#define MASK_FLW 0x707f +#define MATCH_FLD 0x3007 +#define MASK_FLD 0x707f +#define MATCH_FSW 0x2027 +#define MASK_FSW 0x707f +#define MATCH_FSD 0x3027 +#define MASK_FSD 0x707f +#define MATCH_FMADD_S 0x43 +#define MASK_FMADD_S 0x600007f +#define MATCH_FMSUB_S 0x47 +#define MASK_FMSUB_S 0x600007f +#define MATCH_FNMSUB_S 0x4b +#define MASK_FNMSUB_S 0x600007f +#define MATCH_FNMADD_S 0x4f +#define MASK_FNMADD_S 0x600007f +#define MATCH_FMADD_D 0x2000043 +#define MASK_FMADD_D 0x600007f +#define MATCH_FMSUB_D 0x2000047 +#define MASK_FMSUB_D 0x600007f +#define MATCH_FNMSUB_D 0x200004b +#define MASK_FNMSUB_D 0x600007f +#define MATCH_FNMADD_D 0x200004f +#define MASK_FNMADD_D 0x600007f +#define MATCH_C_NOP 0x1 +#define MASK_C_NOP 0xffff +#define MATCH_C_ADDI16SP 0x6101 +#define MASK_C_ADDI16SP 0xef83 +#define MATCH_C_JR 0x8002 +#define MASK_C_JR 0xf07f +#define MATCH_C_JALR 0x9002 +#define MASK_C_JALR 0xf07f +#define MATCH_C_EBREAK 0x9002 +#define MASK_C_EBREAK 0xffff +#define MATCH_C_LD 0x6000 +#define MASK_C_LD 0xe003 +#define MATCH_C_SD 0xe000 +#define MASK_C_SD 0xe003 +#define MATCH_C_ADDIW 0x2001 +#define MASK_C_ADDIW 0xe003 +#define MATCH_C_LDSP 0x6002 +#define MASK_C_LDSP 0xe003 +#define MATCH_C_SDSP 0xe002 +#define MASK_C_SDSP 0xe003 +#define MATCH_C_ADDI4SPN 0x0 +#define MASK_C_ADDI4SPN 0xe003 +#define MATCH_C_FLD 0x2000 +#define MASK_C_FLD 0xe003 +#define MATCH_C_LW 0x4000 +#define MASK_C_LW 0xe003 +#define MATCH_C_FLW 0x6000 +#define MASK_C_FLW 0xe003 +#define MATCH_C_FSD 0xa000 +#define MASK_C_FSD 0xe003 +#define MATCH_C_SW 0xc000 +#define MASK_C_SW 0xe003 +#define MATCH_C_FSW 0xe000 +#define MASK_C_FSW 0xe003 +#define MATCH_C_ADDI 0x1 +#define MASK_C_ADDI 0xe003 +#define MATCH_C_JAL 0x2001 +#define MASK_C_JAL 0xe003 +#define MATCH_C_LI 0x4001 +#define MASK_C_LI 0xe003 +#define MATCH_C_LUI 0x6001 +#define MASK_C_LUI 0xe003 +#define MATCH_C_SRLI 0x8001 +#define MASK_C_SRLI 0xec03 +#define MATCH_C_SRAI 0x8401 +#define MASK_C_SRAI 0xec03 +#define MATCH_C_ANDI 0x8801 +#define MASK_C_ANDI 0xec03 +#define MATCH_C_SUB 0x8c01 +#define MASK_C_SUB 0xfc63 +#define MATCH_C_XOR 0x8c21 +#define MASK_C_XOR 0xfc63 +#define MATCH_C_OR 0x8c41 +#define MASK_C_OR 0xfc63 +#define MATCH_C_AND 0x8c61 +#define MASK_C_AND 0xfc63 +#define MATCH_C_SUBW 0x9c01 +#define MASK_C_SUBW 0xfc63 +#define MATCH_C_ADDW 0x9c21 +#define MASK_C_ADDW 0xfc63 +#define MATCH_C_J 0xa001 +#define MASK_C_J 0xe003 +#define MATCH_C_BEQZ 0xc001 +#define MASK_C_BEQZ 0xe003 +#define MATCH_C_BNEZ 0xe001 +#define MASK_C_BNEZ 0xe003 +#define MATCH_C_SLLI 0x2 +#define MASK_C_SLLI 0xe003 +#define MATCH_C_FLDSP 0x2002 +#define MASK_C_FLDSP 0xe003 +#define MATCH_C_LWSP 0x4002 +#define MASK_C_LWSP 0xe003 +#define MATCH_C_FLWSP 0x6002 +#define MASK_C_FLWSP 0xe003 +#define MATCH_C_MV 0x8002 +#define MASK_C_MV 0xf003 +#define MATCH_C_ADD 0x9002 +#define MASK_C_ADD 0xf003 +#define MATCH_C_FSDSP 0xa002 +#define MASK_C_FSDSP 0xe003 +#define MATCH_C_SWSP 0xc002 +#define MASK_C_SWSP 0xe003 +#define MATCH_C_FSWSP 0xe002 +#define MASK_C_FSWSP 0xe003 +#define MATCH_CUSTOM0 0xb +#define MASK_CUSTOM0 0x707f +#define MATCH_CUSTOM0_RS1 0x200b +#define MASK_CUSTOM0_RS1 0x707f +#define MATCH_CUSTOM0_RS1_RS2 0x300b +#define MASK_CUSTOM0_RS1_RS2 0x707f +#define MATCH_CUSTOM0_RD 0x400b +#define MASK_CUSTOM0_RD 0x707f +#define MATCH_CUSTOM0_RD_RS1 0x600b +#define MASK_CUSTOM0_RD_RS1 0x707f +#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b +#define MASK_CUSTOM0_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM1 0x2b +#define MASK_CUSTOM1 0x707f +#define MATCH_CUSTOM1_RS1 0x202b +#define MASK_CUSTOM1_RS1 0x707f +#define MATCH_CUSTOM1_RS1_RS2 0x302b +#define MASK_CUSTOM1_RS1_RS2 0x707f +#define MATCH_CUSTOM1_RD 0x402b +#define MASK_CUSTOM1_RD 0x707f +#define MATCH_CUSTOM1_RD_RS1 0x602b +#define MASK_CUSTOM1_RD_RS1 0x707f +#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b +#define MASK_CUSTOM1_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM2 0x5b +#define MASK_CUSTOM2 0x707f +#define MATCH_CUSTOM2_RS1 0x205b +#define MASK_CUSTOM2_RS1 0x707f +#define MATCH_CUSTOM2_RS1_RS2 0x305b +#define MASK_CUSTOM2_RS1_RS2 0x707f +#define MATCH_CUSTOM2_RD 0x405b +#define MASK_CUSTOM2_RD 0x707f +#define MATCH_CUSTOM2_RD_RS1 0x605b +#define MASK_CUSTOM2_RD_RS1 0x707f +#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b +#define MASK_CUSTOM2_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM3 0x7b +#define MASK_CUSTOM3 0x707f +#define MATCH_CUSTOM3_RS1 0x207b +#define MASK_CUSTOM3_RS1 0x707f +#define MATCH_CUSTOM3_RS1_RS2 0x307b +#define MASK_CUSTOM3_RS1_RS2 0x707f +#define MATCH_CUSTOM3_RD 0x407b +#define MASK_CUSTOM3_RD 0x707f +#define MATCH_CUSTOM3_RD_RS1 0x607b +#define MASK_CUSTOM3_RD_RS1 0x707f +#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b +#define MASK_CUSTOM3_RD_RS1_RS2 0x707f +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_SBADADDR 0x143 +#define CSR_SIP 0x144 +#define CSR_SPTBR 0x180 +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MBADADDR 0x343 +#define CSR_MIP 0x344 +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH 0x7b2 +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MUCOUNTEREN 0x320 +#define CSR_MSCOUNTEREN 0x321 +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_HYPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#endif +#ifdef DECLARE_INSN +DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) +DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) +DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) +DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) +DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) +DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) +DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) +DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) +DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) +DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) +DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) +DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) +DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) +DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) +DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) +DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) +DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) +DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) +DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) +DECLARE_INSN(add, MATCH_ADD, MASK_ADD) +DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) +DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) +DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) +DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) +DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) +DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) +DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) +DECLARE_INSN(or, MATCH_OR, MASK_OR) +DECLARE_INSN(and, MATCH_AND, MASK_AND) +DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) +DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) +DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) +DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) +DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) +DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) +DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) +DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) +DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) +DECLARE_INSN(lb, MATCH_LB, MASK_LB) +DECLARE_INSN(lh, MATCH_LH, MASK_LH) +DECLARE_INSN(lw, MATCH_LW, MASK_LW) +DECLARE_INSN(ld, MATCH_LD, MASK_LD) +DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) +DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) +DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) +DECLARE_INSN(sb, MATCH_SB, MASK_SB) +DECLARE_INSN(sh, MATCH_SH, MASK_SH) +DECLARE_INSN(sw, MATCH_SW, MASK_SW) +DECLARE_INSN(sd, MATCH_SD, MASK_SD) +DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) +DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) +DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) +DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) +DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) +DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) +DECLARE_INSN(div, MATCH_DIV, MASK_DIV) +DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) +DECLARE_INSN(rem, MATCH_REM, MASK_REM) +DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) +DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) +DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) +DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) +DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) +DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) +DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) +DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) +DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) +DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) +DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) +DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) +DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) +DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) +DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) +DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) +DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) +DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) +DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) +DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) +DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) +DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) +DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) +DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) +DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) +DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) +DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) +DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) +DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) +DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) +DECLARE_INSN(uret, MATCH_URET, MASK_URET) +DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) +DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) +DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) +DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) +DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) +DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) +DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) +DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) +DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) +DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) +DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) +DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) +DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) +DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) +DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) +DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) +DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) +DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) +DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) +DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) +DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) +DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) +DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) +DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) +DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) +DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) +DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) +DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) +DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) +DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) +DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) +DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) +DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) +DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) +DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) +DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) +DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) +DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) +DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) +DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) +DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) +DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) +DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) +DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) +DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) +DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) +DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) +DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) +DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) +DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) +DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) +DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) +DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) +DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) +DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) +DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) +DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) +DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) +DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) +DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) +DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) +DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) +DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) +DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) +DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) +DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) +DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) +DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) +DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) +DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) +DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) +DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) +DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) +DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) +DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) +DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) +DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) +DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) +DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) +DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) +DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) +DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) +DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) +DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) +DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) +DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) +DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) +DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) +DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) +DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) +DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) +DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) +DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) +DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) +DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) +DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) +DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) +DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) +DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) +DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) +DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) +DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) +DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) +DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) +DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) +DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) +DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) +DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) +DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) +DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) +DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) +DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) +DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) +DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) +DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) +DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) +DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) +DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) +DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) +DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) +DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) +DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) +DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) +DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) +DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) +DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) +DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) +DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) +DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) +DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) +DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) +DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) +DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) +#endif +#ifdef DECLARE_CSR +DECLARE_CSR(fflags, CSR_FFLAGS) +DECLARE_CSR(frm, CSR_FRM) +DECLARE_CSR(fcsr, CSR_FCSR) +DECLARE_CSR(cycle, CSR_CYCLE) +DECLARE_CSR(time, CSR_TIME) +DECLARE_CSR(instret, CSR_INSTRET) +DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) +DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) +DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) +DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) +DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) +DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) +DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) +DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) +DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) +DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) +DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) +DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) +DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) +DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) +DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) +DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) +DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) +DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) +DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) +DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) +DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) +DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) +DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) +DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) +DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) +DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) +DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) +DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) +DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) +DECLARE_CSR(sstatus, CSR_SSTATUS) +DECLARE_CSR(sie, CSR_SIE) +DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(sscratch, CSR_SSCRATCH) +DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(sbadaddr, CSR_SBADADDR) +DECLARE_CSR(sip, CSR_SIP) +DECLARE_CSR(sptbr, CSR_SPTBR) +DECLARE_CSR(mstatus, CSR_MSTATUS) +DECLARE_CSR(misa, CSR_MISA) +DECLARE_CSR(medeleg, CSR_MEDELEG) +DECLARE_CSR(mideleg, CSR_MIDELEG) +DECLARE_CSR(mie, CSR_MIE) +DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mscratch, CSR_MSCRATCH) +DECLARE_CSR(mepc, CSR_MEPC) +DECLARE_CSR(mcause, CSR_MCAUSE) +DECLARE_CSR(mbadaddr, CSR_MBADADDR) +DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(tselect, CSR_TSELECT) +DECLARE_CSR(tdata1, CSR_TDATA1) +DECLARE_CSR(tdata2, CSR_TDATA2) +DECLARE_CSR(tdata3, CSR_TDATA3) +DECLARE_CSR(dcsr, CSR_DCSR) +DECLARE_CSR(dpc, CSR_DPC) +DECLARE_CSR(dscratch, CSR_DSCRATCH) +DECLARE_CSR(mcycle, CSR_MCYCLE) +DECLARE_CSR(minstret, CSR_MINSTRET) +DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) +DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) +DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) +DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) +DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) +DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) +DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) +DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) +DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) +DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) +DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) +DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) +DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) +DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) +DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) +DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) +DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) +DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) +DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) +DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) +DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) +DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) +DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) +DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) +DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) +DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) +DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) +DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) +DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) +DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) +DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) +DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) +DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) +DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) +DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) +DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) +DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) +DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) +DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) +DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) +DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) +DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) +DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) +DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) +DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) +DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) +DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) +DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) +DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) +DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) +DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) +DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) +DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) +DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) +DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) +DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) +DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) +DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) +DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) +DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) +DECLARE_CSR(mvendorid, CSR_MVENDORID) +DECLARE_CSR(marchid, CSR_MARCHID) +DECLARE_CSR(mimpid, CSR_MIMPID) +DECLARE_CSR(mhartid, CSR_MHARTID) +DECLARE_CSR(cycleh, CSR_CYCLEH) +DECLARE_CSR(timeh, CSR_TIMEH) +DECLARE_CSR(instreth, CSR_INSTRETH) +DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) +DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) +DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) +DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) +DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) +DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) +DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) +DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) +DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) +DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) +DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) +DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) +DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) +DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) +DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) +DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) +DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) +DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) +DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) +DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) +DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) +DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) +DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) +DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) +DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) +DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) +DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) +DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) +DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) +DECLARE_CSR(mcycleh, CSR_MCYCLEH) +DECLARE_CSR(minstreth, CSR_MINSTRETH) +DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) +DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) +DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) +DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) +DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) +DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) +DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) +DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) +DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) +DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) +DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) +DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) +DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) +DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) +DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) +DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) +DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) +DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) +DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) +DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) +DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) +DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) +DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) +DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) +DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) +DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) +DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) +DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) +DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) +#endif +#ifdef DECLARE_CAUSE +DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) +DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) +DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) +DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) +DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) +DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) +DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) +DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) +DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) +DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) +DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) +DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +#endif diff --git a/raven_spn/bsp/env/entry.S b/raven_spn/bsp/env/entry.S new file mode 100644 index 0000000..261b2a4 --- /dev/null +++ b/raven_spn/bsp/env/entry.S @@ -0,0 +1,98 @@ +// See LICENSE for license details + +#ifndef ENTRY_S +#define ENTRY_S + +#include "encoding.h" +#include "sifive/bits.h" + + .section .text.entry + .align 2 + .weak trap_entry + .global trap_entry +trap_entry: + addi sp, sp, -32*REGBYTES + + STORE x1, 1*REGBYTES(sp) + STORE x2, 2*REGBYTES(sp) + STORE x3, 3*REGBYTES(sp) + STORE x4, 4*REGBYTES(sp) + STORE x5, 5*REGBYTES(sp) + STORE x6, 6*REGBYTES(sp) + STORE x7, 7*REGBYTES(sp) + STORE x8, 8*REGBYTES(sp) + STORE x9, 9*REGBYTES(sp) + STORE x10, 10*REGBYTES(sp) + STORE x11, 11*REGBYTES(sp) + STORE x12, 12*REGBYTES(sp) + STORE x13, 13*REGBYTES(sp) + STORE x14, 14*REGBYTES(sp) + STORE x15, 15*REGBYTES(sp) + STORE x16, 16*REGBYTES(sp) + STORE x17, 17*REGBYTES(sp) + STORE x18, 18*REGBYTES(sp) + STORE x19, 19*REGBYTES(sp) + STORE x20, 20*REGBYTES(sp) + STORE x21, 21*REGBYTES(sp) + STORE x22, 22*REGBYTES(sp) + STORE x23, 23*REGBYTES(sp) + STORE x24, 24*REGBYTES(sp) + STORE x25, 25*REGBYTES(sp) + STORE x26, 26*REGBYTES(sp) + STORE x27, 27*REGBYTES(sp) + STORE x28, 28*REGBYTES(sp) + STORE x29, 29*REGBYTES(sp) + STORE x30, 30*REGBYTES(sp) + STORE x31, 31*REGBYTES(sp) + + csrr a0, mcause + csrr a1, mepc + mv a2, sp + call handle_trap + csrw mepc, a0 + + # Remain in M-mode after mret + li t0, MSTATUS_MPP + csrs mstatus, t0 + + LOAD x1, 1*REGBYTES(sp) + LOAD x2, 2*REGBYTES(sp) + LOAD x3, 3*REGBYTES(sp) + LOAD x4, 4*REGBYTES(sp) + LOAD x5, 5*REGBYTES(sp) + LOAD x6, 6*REGBYTES(sp) + LOAD x7, 7*REGBYTES(sp) + LOAD x8, 8*REGBYTES(sp) + LOAD x9, 9*REGBYTES(sp) + LOAD x10, 10*REGBYTES(sp) + LOAD x11, 11*REGBYTES(sp) + LOAD x12, 12*REGBYTES(sp) + LOAD x13, 13*REGBYTES(sp) + LOAD x14, 14*REGBYTES(sp) + LOAD x15, 15*REGBYTES(sp) + LOAD x16, 16*REGBYTES(sp) + LOAD x17, 17*REGBYTES(sp) + LOAD x18, 18*REGBYTES(sp) + LOAD x19, 19*REGBYTES(sp) + LOAD x20, 20*REGBYTES(sp) + LOAD x21, 21*REGBYTES(sp) + LOAD x22, 22*REGBYTES(sp) + LOAD x23, 23*REGBYTES(sp) + LOAD x24, 24*REGBYTES(sp) + LOAD x25, 25*REGBYTES(sp) + LOAD x26, 26*REGBYTES(sp) + LOAD x27, 27*REGBYTES(sp) + LOAD x28, 28*REGBYTES(sp) + LOAD x29, 29*REGBYTES(sp) + LOAD x30, 30*REGBYTES(sp) + LOAD x31, 31*REGBYTES(sp) + + addi sp, sp, 32*REGBYTES + mret + +.weak handle_trap +handle_trap: +1: + j 1b + +#endif diff --git a/raven_spn/bsp/env/freedom-e300-arty/flash.lds b/raven_spn/bsp/env/freedom-e300-arty/flash.lds new file mode 100644 index 0000000..6b37141 --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-arty/flash.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >flash AT>flash :flash + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/freedom-e300-arty/init.c b/raven_spn/bsp/env/freedom-e300-arty/init.c new file mode 100644 index 0000000..a6f4b39 --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-arty/init.c @@ -0,0 +1,87 @@ +//See LICENSE for license details. +#include +#include +#include + +#include "platform.h" +#include "encoding.h" + +extern int main(int argc, char** argv); +extern void trap_entry(); + +static unsigned long get_cpu_freq() +{ + return 65000000; +} + +unsigned long get_timer_freq() +{ + return get_cpu_freq(); +} + +uint64_t get_timer_value() +{ +#if __riscv_xlen == 32 + while (1) { + uint32_t hi = read_csr(mcycleh); + uint32_t lo = read_csr(mcycle); + if (hi == read_csr(mcycleh)) + return ((uint64_t)hi << 32) | lo; + } +#else + return read_csr(mcycle); +#endif +} + +static void uart_init(size_t baud_rate) +{ + GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; + GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; + UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; +} + + +#ifdef USE_PLIC +extern void handle_m_ext_interrupt(); +#endif + +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + if (0){ +#ifdef USE_PLIC + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { + handle_m_ext_interrupt(); +#endif +#ifdef USE_M_TIME + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif + } + else { + write(1, "Unhandled Trap:\n", 16); + _exit(1 + mcause); + } + return epc; +} + +void _init() +{ + #ifndef NO_INIT + uart_init(115200); + + printf("core freq at %d Hz\n", get_cpu_freq()); + + write_csr(mtvec, &trap_entry); + #endif +} + +void _fini() +{ +} diff --git a/raven_spn/bsp/env/freedom-e300-arty/openocd.cfg b/raven_spn/bsp/env/freedom-e300-arty/openocd.cfg new file mode 100644 index 0000000..f4b28ed --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-arty/openocd.cfg @@ -0,0 +1,30 @@ +adapter_khz 10000 + +#source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg] + +interface ftdi +ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" +ftdi_vid_pid 0x15ba 0x002a + +ftdi_layout_init 0x0808 0x0a1b +ftdi_layout_signal nSRST -oe 0x0200 +ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 +ftdi_layout_signal LED -data 0x0800 +# + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME +$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 + +flash bank my_first_flash fespi 0x20000000 0 0 0 $_TARGETNAME +init +#reset +if {[ info exists pulse_srst]} { + ftdi_set_signal nSRST 0 + ftdi_set_signal nSRST z +} +halt +#flash protect 0 64 last off diff --git a/raven_spn/bsp/env/freedom-e300-arty/platform.h b/raven_spn/bsp/env/freedom-e300-arty/platform.h new file mode 100644 index 0000000..8ff7ae6 --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-arty/platform.h @@ -0,0 +1,124 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PLATFORM_H +#define _SIFIVE_PLATFORM_H + +// Some things missing from the official encoding.h +#define MCAUSE_INT 0x80000000 +#define MCAUSE_CAUSE 0x7FFFFFFF + +#include "sifive/const.h" +#include "sifive/devices/aon.h" +#include "sifive/devices/clint.h" +#include "sifive/devices/gpio.h" +#include "sifive/devices/plic.h" +#include "sifive/devices/pwm.h" +#include "sifive/devices/spi.h" +#include "sifive/devices/uart.h" + +/**************************************************************************** + * Platform definitions + *****************************************************************************/ + +#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL) +#define CLINT_CTRL_ADDR _AC(0x02000000,UL) +#define PLIC_CTRL_ADDR _AC(0x0C000000,UL) +#define AON_CTRL_ADDR _AC(0x10000000,UL) +#define GPIO_CTRL_ADDR _AC(0x10012000,UL) +#define UART0_CTRL_ADDR _AC(0x10013000,UL) +#define SPI0_CTRL_ADDR _AC(0x10014000,UL) +#define PWM0_CTRL_ADDR _AC(0x10015000,UL) +#define UART1_CTRL_ADDR _AC(0x10023000,UL) +#define SPI1_CTRL_ADDR _AC(0x10024000,UL) +#define PWM1_CTRL_ADDR _AC(0x10025000,UL) +#define SPI2_CTRL_ADDR _AC(0x10034000,UL) +#define PWM2_CTRL_ADDR _AC(0x10035000,UL) +#define SPI0_MMAP_ADDR _AC(0x20000000,UL) +#define MEM_CTRL_ADDR _AC(0x80000000,UL) + +// IOF Mappings +#define IOF0_SPI1_MASK _AC(0x000007FC,UL) +#define SPI11_NUM_SS (4) +#define IOF_SPI1_SS0 (2u) +#define IOF_SPI1_SS1 (8u) +#define IOF_SPI1_SS2 (9u) +#define IOF_SPI1_SS3 (10u) +#define IOF_SPI1_MOSI (3u) +#define IOF_SPI1_MISO (4u) +#define IOF_SPI1_SCK (5u) +#define IOF_SPI1_DQ0 (3u) +#define IOF_SPI1_DQ1 (4u) +#define IOF_SPI1_DQ2 (6u) +#define IOF_SPI1_DQ3 (7u) + +#define IOF0_SPI2_MASK _AC(0xFC000000,UL) +#define SPI2_NUM_SS (1) +#define IOF_SPI2_SS0 (26u) +#define IOF_SPI2_MOSI (27u) +#define IOF_SPI2_MISO (28u) +#define IOF_SPI2_SCK (29u) +#define IOF_SPI2_DQ0 (27u) +#define IOF_SPI2_DQ1 (28u) +#define IOF_SPI2_DQ2 (30u) +#define IOF_SPI2_DQ3 (31u) + +#define IOF0_UART0_MASK _AC(0x00030000, UL) +#define IOF_UART0_RX (16u) +#define IOF_UART0_TX (17u) + +#define IOF0_UART1_MASK _AC(0x03000000, UL) +#define IOF_UART1_RX (24u) +#define IOF_UART1_TX (25u) + +#define IOF1_PWM0_MASK _AC(0x0000000F, UL) +#define IOF1_PWM1_MASK _AC(0x00780000, UL) +#define IOF1_PWM2_MASK _AC(0x00003C00, UL) + +// Interrupt Numbers +#define INT_RESERVED 0 +#define INT_WDOGCMP 1 +#define INT_RTCCMP 2 +#define INT_UART0_BASE 3 +#define INT_UART1_BASE 4 +#define INT_SPI0_BASE 5 +#define INT_SPI1_BASE 6 +#define INT_SPI2_BASE 7 +#define INT_GPIO_BASE 8 +#define INT_PWM0_BASE 40 +#define INT_PWM1_BASE 44 +#define INT_PWM2_BASE 48 + +// Helper functions +#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i))) +#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i))) +#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset) +#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset) +#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset) +#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset) +#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset) +#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset) +#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset) +#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset) +#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset) +#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset) +#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset) +#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset) +#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset) + +// Misc + +#include + + +#define NUM_GPIO 32 + +#define PLIC_NUM_INTERRUPTS 52 +#define PLIC_NUM_PRIORITIES 7 + +#define HAS_BOARD_BUTTONS +#include "hifive1.h" + +unsigned long get_timer_freq(void); +uint64_t get_timer_value(void); + +#endif /* _SIFIVE_PLATFORM_H */ diff --git a/raven_spn/bsp/env/freedom-e300-arty/settings.mk b/raven_spn/bsp/env/freedom-e300-arty/settings.mk new file mode 100644 index 0000000..230fccc --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-arty/settings.mk @@ -0,0 +1,3 @@ +# Describes the CPU on this board to the rest of the SDK. +RISCV_ARCH := rv32imac +RISCV_ABI := ilp32 diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/dhrystone.lds b/raven_spn/bsp/env/freedom-e300-hifive1/dhrystone.lds new file mode 100644 index 0000000..cc9cd9b --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/dhrystone.lds @@ -0,0 +1,157 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/flash.lds b/raven_spn/bsp/env/freedom-e300-hifive1/flash.lds new file mode 100644 index 0000000..6b37141 --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/flash.lds @@ -0,0 +1,161 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M + ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K +} + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; +} + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash :flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash :flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash :flash + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >flash AT>flash :flash + + . = ALIGN(4); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash :flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash :flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash :flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash :flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash :flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash :flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash :ram_init + + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash :ram_init + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram :ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram :ram +} diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/init.c b/raven_spn/bsp/env/freedom-e300-hifive1/init.c new file mode 100644 index 0000000..621a6e2 --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/init.c @@ -0,0 +1,238 @@ +#include +#include +#include + +#include "platform.h" +#include "encoding.h" + +extern int main(int argc, char** argv); +extern void trap_entry(); + +static unsigned long mtime_lo(void) +{ + return *(volatile unsigned long *)(CLINT_CTRL_ADDR + CLINT_MTIME); +} + +#ifdef __riscv32 + +static uint32_t mtime_hi(void) +{ + return *(volatile uint32_t *)(CLINT_CTRL_ADDR + CLINT_MTIME + 4); +} + +uint64_t get_timer_value() +{ + while (1) { + uint32_t hi = mtime_hi(); + uint32_t lo = mtime_lo(); + if (hi == mtime_hi()) + return ((uint64_t)hi << 32) | lo; + } +} + +#else /* __riscv32 */ + +uint64_t get_timer_value() +{ + return mtime_lo(); +} + +#endif + +unsigned long get_timer_freq() +{ + return 32768; +} + +static void use_hfrosc(int div, int trim) +{ + // Make sure the HFROSC is running at its default setting + PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1)); + while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) ; + PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1); +} + +static void use_pll(int refsel, int bypass, int r, int f, int q) +{ + // Ensure that we aren't running off the PLL before we mess with it. + if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) { + // Make sure the HFROSC is running at its default setting + use_hfrosc(4, 16); + } + + // Set PLL Source to be HFXOSC if available. + uint32_t config_value = 0; + + config_value |= PLL_REFSEL(refsel); + + if (bypass) { + // Bypass + config_value |= PLL_BYPASS(1); + + PRCI_REG(PRCI_PLLCFG) = config_value; + + // If we don't have an HFXTAL, this doesn't really matter. + // Set our Final output divide to divide-by-1: + PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0)); + } else { + // In case we are executing from QSPI, + // (which is quite likely) we need to + // set the QSPI clock divider appropriately + // before boosting the clock frequency. + + // Div = f_sck/2 + SPI0_REG(SPI_REG_SCKDIV) = 8; + + // Set DIV Settings for PLL + // Both HFROSC and HFXOSC are modeled as ideal + // 16MHz sources (assuming dividers are set properly for + // HFROSC). + // (Legal values of f_REF are 6-48MHz) + + // Set DIVR to divide-by-2 to get 8MHz frequency + // (legal values of f_R are 6-12 MHz) + + config_value |= PLL_BYPASS(1); + config_value |= PLL_R(r); + + // Set DIVF to get 512Mhz frequncy + // There is an implied multiply-by-2, 16Mhz. + // So need to write 32-1 + // (legal values of f_F are 384-768 MHz) + config_value |= PLL_F(f); + + // Set DIVQ to divide-by-2 to get 256 MHz frequency + // (legal values of f_Q are 50-400Mhz) + config_value |= PLL_Q(q); + + // Set our Final output divide to divide-by-1: + PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0)); + + PRCI_REG(PRCI_PLLCFG) = config_value; + + // Un-Bypass the PLL. + PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1); + + // Wait for PLL Lock + // Note that the Lock signal can be glitchy. + // Need to wait 100 us + // RTC is running at 32kHz. + // So wait 4 ticks of RTC. + uint32_t now = mtime_lo(); + while (mtime_lo() - now < 4) ; + + // Now it is safe to check for PLL Lock + while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0) ; + } + + // Switch over to PLL Clock source + PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1); +} + +static void use_default_clocks() +{ + // Turn off the LFROSC + AON_REG(AON_LFROSC) &= ~ROSC_EN(1); + + // Use HFROSC + use_hfrosc(4, 16); +} + +static unsigned long __attribute__((noinline)) measure_cpu_freq(size_t n) +{ + unsigned long start_mtime, delta_mtime; + unsigned long mtime_freq = get_timer_freq(); + + // Don't start measuruing until we see an mtime tick + unsigned long tmp = mtime_lo(); + do { + start_mtime = mtime_lo(); + } while (start_mtime == tmp); + + unsigned long start_mcycle = read_csr(mcycle); + + do { + delta_mtime = mtime_lo() - start_mtime; + } while (delta_mtime < n); + + unsigned long delta_mcycle = read_csr(mcycle) - start_mcycle; + + return (delta_mcycle / delta_mtime) * mtime_freq + + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime; +} + +unsigned long get_cpu_freq() +{ + static uint32_t cpu_freq; + + if (!cpu_freq) { + // warm up I$ + measure_cpu_freq(1); + // measure for real + cpu_freq = measure_cpu_freq(10); + } + + return cpu_freq; +} + +static void uart_init(size_t baud_rate) +{ + GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; + GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; + UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; +} + + + +#ifdef USE_PLIC +extern void handle_m_ext_interrupt(); +#endif + +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + if (0){ +#ifdef USE_PLIC + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { + handle_m_ext_interrupt(); +#endif +#ifdef USE_M_TIME + // External Machine-Level interrupt from PLIC + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif + } + else { + write(1, "trap\n", 5); + _exit(1 + mcause); + } + return epc; +} + +void _init() +{ + + #ifndef NO_INIT + use_default_clocks(); + use_pll(0, 0, 1, 31, 1); + uart_init(115200); + + printf("core freq at %d Hz\n", get_cpu_freq()); + + write_csr(mtvec, &trap_entry); + if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present + write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping + write_csr(fcsr, 0); // initialize rounding mode, undefined at reset + } + #endif + +} + +void _fini() +{ +} diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/openocd.cfg b/raven_spn/bsp/env/freedom-e300-hifive1/openocd.cfg new file mode 100644 index 0000000..b531e9c --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/openocd.cfg @@ -0,0 +1,34 @@ +adapter_khz 10000 + +interface ftdi +ftdi_device_desc "Dual RS232-HS" +ftdi_vid_pid 0x0403 0x6010 + +ftdi_layout_init 0x0008 0x001b +ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020 + +#Reset Stretcher logic on FE310 is ~1 second long +#This doesn't apply if you use +# ftdi_set_signal, but still good to document +#adapter_nsrst_delay 1500 + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME +$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 + +flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME +init +#reset -- This type of reset is not implemented yet +if {[ info exists pulse_srst]} { + ftdi_set_signal nSRST 0 + ftdi_set_signal nSRST z + #Wait for the reset stretcher + #It will work without this, but + #will incur lots of delays for later commands. + sleep 1500 +} +halt +#flash protect 0 64 last off diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/platform.h b/raven_spn/bsp/env/freedom-e300-hifive1/platform.h new file mode 100644 index 0000000..806fcfc --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/platform.h @@ -0,0 +1,133 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PLATFORM_H +#define _SIFIVE_PLATFORM_H + +// Some things missing from the official encoding.h +#define MCAUSE_INT 0x80000000 +#define MCAUSE_CAUSE 0x7FFFFFFF + +#include "sifive/const.h" +#include "sifive/devices/aon.h" +#include "sifive/devices/clint.h" +#include "sifive/devices/gpio.h" +#include "sifive/devices/otp.h" +#include "sifive/devices/plic.h" +#include "sifive/devices/prci.h" +#include "sifive/devices/pwm.h" +#include "sifive/devices/spi.h" +#include "sifive/devices/uart.h" + +/**************************************************************************** + * Platform definitions + *****************************************************************************/ + +// Memory map +#define MASKROM_MEM_ADDR _AC(0x00001000,UL) +#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL) +#define OTP_MEM_ADDR _AC(0x00020000,UL) +#define CLINT_CTRL_ADDR _AC(0x02000000,UL) +#define PLIC_CTRL_ADDR _AC(0x0C000000,UL) +#define AON_CTRL_ADDR _AC(0x10000000,UL) +#define PRCI_CTRL_ADDR _AC(0x10008000,UL) +#define OTP_CTRL_ADDR _AC(0x10010000,UL) +#define GPIO_CTRL_ADDR _AC(0x10012000,UL) +#define UART0_CTRL_ADDR _AC(0x10013000,UL) +#define SPI0_CTRL_ADDR _AC(0x10014000,UL) +#define PWM0_CTRL_ADDR _AC(0x10015000,UL) +#define UART1_CTRL_ADDR _AC(0x10023000,UL) +#define SPI1_CTRL_ADDR _AC(0x10024000,UL) +#define PWM1_CTRL_ADDR _AC(0x10025000,UL) +#define SPI2_CTRL_ADDR _AC(0x10034000,UL) +#define PWM2_CTRL_ADDR _AC(0x10035000,UL) +#define SPI0_MEM_ADDR _AC(0x20000000,UL) +#define MEM_CTRL_ADDR _AC(0x80000000,UL) + +// IOF masks +#define IOF0_SPI1_MASK _AC(0x000007FC,UL) +#define SPI11_NUM_SS (4) +#define IOF_SPI1_SS0 (2u) +#define IOF_SPI1_SS1 (8u) +#define IOF_SPI1_SS2 (9u) +#define IOF_SPI1_SS3 (10u) +#define IOF_SPI1_MOSI (3u) +#define IOF_SPI1_MISO (4u) +#define IOF_SPI1_SCK (5u) +#define IOF_SPI1_DQ0 (3u) +#define IOF_SPI1_DQ1 (4u) +#define IOF_SPI1_DQ2 (6u) +#define IOF_SPI1_DQ3 (7u) + +#define IOF0_SPI2_MASK _AC(0xFC000000,UL) +#define SPI2_NUM_SS (1) +#define IOF_SPI2_SS0 (26u) +#define IOF_SPI2_MOSI (27u) +#define IOF_SPI2_MISO (28u) +#define IOF_SPI2_SCK (29u) +#define IOF_SPI2_DQ0 (27u) +#define IOF_SPI2_DQ1 (28u) +#define IOF_SPI2_DQ2 (30u) +#define IOF_SPI2_DQ3 (31u) + +//#define IOF0_I2C_MASK _AC(0x00003000,UL) + +#define IOF0_UART0_MASK _AC(0x00030000, UL) +#define IOF_UART0_RX (16u) +#define IOF_UART0_TX (17u) + +#define IOF0_UART1_MASK _AC(0x03000000, UL) +#define IOF_UART1_RX (24u) +#define IOF_UART1_TX (25u) + +#define IOF1_PWM0_MASK _AC(0x0000000F, UL) +#define IOF1_PWM1_MASK _AC(0x00780000, UL) +#define IOF1_PWM2_MASK _AC(0x00003C00, UL) + +// Interrupt numbers +#define INT_RESERVED 0 +#define INT_WDOGCMP 1 +#define INT_RTCCMP 2 +#define INT_UART0_BASE 3 +#define INT_UART1_BASE 4 +#define INT_SPI0_BASE 5 +#define INT_SPI1_BASE 6 +#define INT_SPI2_BASE 7 +#define INT_GPIO_BASE 8 +#define INT_PWM0_BASE 40 +#define INT_PWM1_BASE 44 +#define INT_PWM2_BASE 48 + +// Helper functions +#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i))) +#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i))) +#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset) +#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset) +#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset) +#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset) +#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset) +#define PRCI_REG(offset) _REG32(PRCI_CTRL_ADDR, offset) +#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset) +#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset) +#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset) +#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset) +#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset) +#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset) +#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset) +#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset) + +// Misc + +#include + +#define NUM_GPIO 32 + +#define PLIC_NUM_INTERRUPTS 52 +#define PLIC_NUM_PRIORITIES 7 + +#include "hifive1.h" + +unsigned long get_cpu_freq(void); +unsigned long get_timer_freq(void); +uint64_t get_timer_value(void); + +#endif /* _SIFIVE_PLATFORM_H */ diff --git a/raven_spn/bsp/env/freedom-e300-hifive1/settings.mk b/raven_spn/bsp/env/freedom-e300-hifive1/settings.mk new file mode 100644 index 0000000..230fccc --- /dev/null +++ b/raven_spn/bsp/env/freedom-e300-hifive1/settings.mk @@ -0,0 +1,3 @@ +# Describes the CPU on this board to the rest of the SDK. +RISCV_ARCH := rv32imac +RISCV_ABI := ilp32 diff --git a/raven_spn/bsp/env/hifive1.h b/raven_spn/bsp/env/hifive1.h new file mode 100644 index 0000000..0db2f0f --- /dev/null +++ b/raven_spn/bsp/env/hifive1.h @@ -0,0 +1,81 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_HIFIVE1_H +#define _SIFIVE_HIFIVE1_H + +#include + +/**************************************************************************** + * GPIO Connections + *****************************************************************************/ + +// These are the GPIO bit offsets for the RGB LED on HiFive1 Board. +// These are also mapped to RGB LEDs on the Freedom E300 Arty +// FPGA +// Dev Kit. + +#define RED_LED_OFFSET 22 +#define GREEN_LED_OFFSET 19 +#define BLUE_LED_OFFSET 21 + +// These are the GPIO bit offsets for the differen digital pins +// on the headers for both the HiFive1 Board and the Freedom E300 Arty FPGA Dev Kit. +#define PIN_0_OFFSET 16 +#define PIN_1_OFFSET 17 +#define PIN_2_OFFSET 18 +#define PIN_3_OFFSET 19 +#define PIN_4_OFFSET 20 +#define PIN_5_OFFSET 21 +#define PIN_6_OFFSET 22 +#define PIN_7_OFFSET 23 +#define PIN_8_OFFSET 0 +#define PIN_9_OFFSET 1 +#define PIN_10_OFFSET 2 +#define PIN_11_OFFSET 3 +#define PIN_12_OFFSET 4 +#define PIN_13_OFFSET 5 +//#define PIN_14_OFFSET 8 //This pin is not connected on either board. +#define PIN_15_OFFSET 9 +#define PIN_16_OFFSET 10 +#define PIN_17_OFFSET 11 +#define PIN_18_OFFSET 12 +#define PIN_19_OFFSET 13 + +// These are *PIN* numbers, not +// GPIO Offset Numbers. +#define PIN_SPI1_SCK (13u) +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SS0 (10u) +#define PIN_SPI1_SS1 (14u) +#define PIN_SPI1_SS2 (15u) +#define PIN_SPI1_SS3 (16u) + +#define SS_PIN_TO_CS_ID(x) \ + ((x==PIN_SPI1_SS0 ? 0 : \ + (x==PIN_SPI1_SS1 ? 1 : \ + (x==PIN_SPI1_SS2 ? 2 : \ + (x==PIN_SPI1_SS3 ? 3 : \ + -1))))) + + +// These buttons are present only on the Freedom E300 Arty Dev Kit. +#ifdef HAS_BOARD_BUTTONS +#define BUTTON_0_OFFSET 15 +#define BUTTON_1_OFFSET 30 +#define BUTTON_2_OFFSET 31 + +#define INT_DEVICE_BUTTON_0 (INT_GPIO_BASE + BUTTON_0_OFFSET) +#define INT_DEVICE_BUTTON_1 (INT_GPIO_BASE + BUTTON_1_OFFSET) +#define INT_DEVICE_BUTTON_2 (INT_GPIO_BASE + BUTTON_2_OFFSET) + +#endif + +#define HAS_HFXOSC 1 +#define HAS_LFROSC_BYPASS 1 + +#define RTC_FREQ 32768 + +void write_hex(int fd, unsigned long int hex); + +#endif /* _SIFIVE_HIFIVE1_H */ diff --git a/raven_spn/bsp/env/start.S b/raven_spn/bsp/env/start.S new file mode 100644 index 0000000..4e9f665 --- /dev/null +++ b/raven_spn/bsp/env/start.S @@ -0,0 +1,111 @@ +// See LICENSE for license details. +#include + +/* This is defined in sifive/platform.h, but that can't be included from + * assembly. */ +#define CLINT_CTRL_ADDR 0x02000000 + + .section .init + .globl _start + .type _start,@function + +_start: + .cfi_startproc + .cfi_undefined ra +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la sp, _sp + +#if defined(ENABLE_SMP) + smp_pause(t0, t1) +#endif + + /* Load data section */ + la a0, _data_lma + la a1, _data + la a2, _edata + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + + /* Clear bss section */ + la a0, __bss_start + la a1, _end + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + + /* Call global constructors */ + la a0, __libc_fini_array + call atexit + call __libc_init_array + +#ifndef __riscv_float_abi_soft + /* Enable FPU */ + li t0, MSTATUS_FS + csrs mstatus, t0 + csrr t1, mstatus + and t1, t1, t0 + beqz t1, 1f + fssr x0 +1: +#endif + +#if defined(ENABLE_SMP) + smp_resume(t0, t1) + + csrr a0, mhartid + bnez a0, 2f +#endif + + auipc ra, 0 + addi sp, sp, -16 +#if __riscv_xlen == 32 + sw ra, 8(sp) +#else + sd ra, 8(sp) +#endif + + /* argc = argv = 0 */ + li a0, 0 + li a1, 0 + call main + tail exit +1: + j 1b + +#if defined(ENABLE_SMP) +2: + la t0, trap_entry + csrw mtvec, t0 + + csrr a0, mhartid + la t1, _sp + slli t0, a0, 10 + sub sp, t1, t0 + + auipc ra, 0 + addi sp, sp, -16 +#if __riscv_xlen == 32 + sw ra, 8(sp) +#else + sd ra, 8(sp) +#endif + + call secondary_main + tail exit + +1: + j 1b +#endif + .cfi_endproc diff --git a/raven_spn/bsp/env/ventry.S b/raven_spn/bsp/env/ventry.S new file mode 100644 index 0000000..5c82c48 --- /dev/null +++ b/raven_spn/bsp/env/ventry.S @@ -0,0 +1,288 @@ +// See LICENSE for license details + +#ifndef VENTRY_S +#define VENTRY_S + +#include "encoding.h" +#include "sifive/bits.h" + +#only save caller registers +.macro TRAP_ENTRY + addi sp, sp, -16*REGBYTES + + STORE x1, 0*REGBYTES(sp) + STORE x5, 1*REGBYTES(sp) + STORE x6, 2*REGBYTES(sp) + STORE x7, 3*REGBYTES(sp) + STORE x10, 4*REGBYTES(sp) + STORE x11, 5*REGBYTES(sp) + STORE x12, 6*REGBYTES(sp) + STORE x13, 7*REGBYTES(sp) + STORE x14, 8*REGBYTES(sp) + STORE x15, 9*REGBYTES(sp) + STORE x16, 10*REGBYTES(sp) + STORE x17, 11*REGBYTES(sp) + STORE x28, 12*REGBYTES(sp) + STORE x29, 13*REGBYTES(sp) + STORE x30, 14*REGBYTES(sp) + STORE x31, 15*REGBYTES(sp) +.endm + +#restore caller registers +.macro TRAP_EXIT +# Remain in M-mode after mret + li t0, MSTATUS_MPP + csrs mstatus, t0 + + LOAD x1, 0*REGBYTES(sp) + LOAD x5, 1*REGBYTES(sp) + LOAD x6, 2*REGBYTES(sp) + LOAD x7, 3*REGBYTES(sp) + LOAD x10, 4*REGBYTES(sp) + LOAD x11, 5*REGBYTES(sp) + LOAD x12, 6*REGBYTES(sp) + LOAD x13, 7*REGBYTES(sp) + LOAD x14, 8*REGBYTES(sp) + LOAD x15, 9*REGBYTES(sp) + LOAD x16, 10*REGBYTES(sp) + LOAD x17, 11*REGBYTES(sp) + LOAD x28, 12*REGBYTES(sp) + LOAD x29, 13*REGBYTES(sp) + LOAD x30, 14*REGBYTES(sp) + LOAD x31, 15*REGBYTES(sp) + + addi sp, sp, 16*REGBYTES + mret +.endm + + + +#Vector table for E31/E51 + + .section .text.entry + .align 8 + .global vtrap_entry +vtrap_entry: + j sync_trap + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j vmsi_Handler + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j vmti_Handler + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j vmei_Handler + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j reserved + .align 2 + j vlip_Handler0 + .align 2 + j vlip_Handler1 + .align 2 + j vlip_Handler2 + .align 2 + j vlip_Handler3 + .align 2 + j vlip_Handler4 + .align 2 + j vlip_Handler5 + .align 2 + j vlip_Handler6 + .align 2 + j vlip_Handler7 + .align 2 + j vlip_Handler8 + .align 2 + j vlip_Handler9 + .align 2 + j vlip_Handler10 + .align 2 + j vlip_Handler11 + .align 2 + j vlip_Handler12 + .align 2 + j vlip_Handler13 + .align 2 + j vlip_Handler14 + .align 2 + j vlip_Handler15 + +#synchronous trap +sync_trap: + TRAP_ENTRY + jal handle_sync_trap + TRAP_EXIT + +#Machine Software Interrupt +vmsi_Handler: + TRAP_ENTRY + jal reserved + TRAP_EXIT + +#Machine Timer Interrupt +vmti_Handler: + TRAP_ENTRY + jal handle_m_time_interrupt + TRAP_EXIT + +#Machine External Interrupt +vmei_Handler: + TRAP_ENTRY + jal handle_m_external_interrupt + TRAP_EXIT + +#LIP0 +vlip_Handler0: + TRAP_ENTRY + jal handle_local_interrupt0 + TRAP_EXIT + +#LIP1 +vlip_Handler1: + TRAP_ENTRY + jal handle_local_interrupt1 + TRAP_EXIT + +#LIP2 +vlip_Handler2: + TRAP_ENTRY + jal handle_local_interrupt2 + TRAP_EXIT + +#LIP3 +vlip_Handler3: + TRAP_ENTRY + jal handle_local_interrupt3 + TRAP_EXIT + +#LIP4 +vlip_Handler4: + TRAP_ENTRY + jal handle_local_interrupt4 + TRAP_EXIT + +#LIP5 +vlip_Handler5: + TRAP_ENTRY + jal handle_local_interrupt5 + TRAP_EXIT + +#LIP6 +vlip_Handler6: + TRAP_ENTRY + jal handle_local_interrupt6 + TRAP_EXIT + +#LIP7 +vlip_Handler7: + TRAP_ENTRY + jal handle_local_interrupt7 + TRAP_EXIT + +#LIP8 +vlip_Handler8: + TRAP_ENTRY + jal handle_local_interrupt8 + TRAP_EXIT + +#LIP9 +vlip_Handler9: + TRAP_ENTRY + jal handle_local_interrupt9 + TRAP_EXIT + +#LIP10 +vlip_Handler10: + TRAP_ENTRY + jal handle_local_interrupt10 + TRAP_EXIT + +#LIP11 +vlip_Handler11: + TRAP_ENTRY + jal handle_local_interrupt11 + TRAP_EXIT + +#LIP12 +vlip_Handler12: + TRAP_ENTRY + jal handle_local_interrupt12 + TRAP_EXIT + +#LIP13 +vlip_Handler13: + TRAP_ENTRY + jal handle_local_interrupt13 + TRAP_EXIT + +#LIP14 +vlip_Handler14: + TRAP_ENTRY + jal handle_local_interrupt14 + TRAP_EXIT + +#LIP15 +vlip_Handler15: + TRAP_ENTRY + jal handle_local_interrupt15 + TRAP_EXIT + +#unimplemented ISRs trap here +.weak reserved +reserved: +.weak handle_local_interrupt0 +handle_local_interrupt0: +.weak handle_local_interrupt1 +handle_local_interrupt1: +.weak handle_local_interrupt2 +handle_local_interrupt2: +.weak handle_local_interrupt3 +handle_local_interrupt3: +.weak handle_local_interrupt4 +handle_local_interrupt4: +.weak handle_local_interrupt5 +handle_local_interrupt5: +.weak handle_local_interrupt6 +handle_local_interrupt6: +.weak handle_local_interrupt7 +handle_local_interrupt7: +.weak handle_local_interrupt8 +handle_local_interrupt8: +.weak handle_local_interrupt9 +handle_local_interrupt9: +.weak handle_local_interrupt10 +handle_local_interrupt10: +.weak handle_local_interrupt11 +handle_local_interrupt11: +.weak handle_local_interrupt12 +handle_local_interrupt12: +.weak handle_local_interrupt13 +handle_local_interrupt13: +.weak handle_local_interrupt14 +handle_local_interrupt14: +.weak handle_local_interrupt15 +handle_local_interrupt15: +1: + j 1b + +#endif diff --git a/raven_spn/bsp/include/sifive/bits.h b/raven_spn/bsp/include/sifive/bits.h new file mode 100644 index 0000000..bfe656f --- /dev/null +++ b/raven_spn/bsp/include/sifive/bits.h @@ -0,0 +1,36 @@ +// See LICENSE for license details. +#ifndef _RISCV_BITS_H +#define _RISCV_BITS_H + +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) + +#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) +#define ROUNDDOWN(a, b) ((a)/(b)*(b)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) + +#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) +#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#define STR(x) XSTR(x) +#define XSTR(x) #x + +#if __riscv_xlen == 64 +# define SLL32 sllw +# define STORE sd +# define LOAD ld +# define LWU lwu +# define LOG_REGBYTES 3 +#else +# define SLL32 sll +# define STORE sw +# define LOAD lw +# define LWU lw +# define LOG_REGBYTES 2 +#endif +#define REGBYTES (1 << LOG_REGBYTES) + +#endif diff --git a/raven_spn/bsp/include/sifive/const.h b/raven_spn/bsp/include/sifive/const.h new file mode 100644 index 0000000..8dcffbb --- /dev/null +++ b/raven_spn/bsp/include/sifive/const.h @@ -0,0 +1,18 @@ +// See LICENSE for license details. +/* Derived from */ + +#ifndef _SIFIVE_CONST_H +#define _SIFIVE_CONST_H + +#ifdef __ASSEMBLER__ +#define _AC(X,Y) X +#define _AT(T,X) X +#else +#define _AC(X,Y) (X##Y) +#define _AT(T,X) ((T)(X)) +#endif /* !__ASSEMBLER__*/ + +#define _BITUL(x) (_AC(1,UL) << (x)) +#define _BITULL(x) (_AC(1,ULL) << (x)) + +#endif /* _SIFIVE_CONST_H */ diff --git a/raven_spn/bsp/include/sifive/devices/aon.h b/raven_spn/bsp/include/sifive/devices/aon.h new file mode 100644 index 0000000..63f1db3 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/aon.h @@ -0,0 +1,88 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_AON_H +#define _SIFIVE_AON_H + +/* Register offsets */ + +#define AON_WDOGCFG 0x000 +#define AON_WDOGCOUNT 0x008 +#define AON_WDOGS 0x010 +#define AON_WDOGFEED 0x018 +#define AON_WDOGKEY 0x01C +#define AON_WDOGCMP 0x020 + +#define AON_RTCCFG 0x040 +#define AON_RTCLO 0x048 +#define AON_RTCHI 0x04C +#define AON_RTCS 0x050 +#define AON_RTCCMP 0x060 + +#define AON_BACKUP0 0x080 +#define AON_BACKUP1 0x084 +#define AON_BACKUP2 0x088 +#define AON_BACKUP3 0x08C +#define AON_BACKUP4 0x090 +#define AON_BACKUP5 0x094 +#define AON_BACKUP6 0x098 +#define AON_BACKUP7 0x09C +#define AON_BACKUP8 0x0A0 +#define AON_BACKUP9 0x0A4 +#define AON_BACKUP10 0x0A8 +#define AON_BACKUP11 0x0AC +#define AON_BACKUP12 0x0B0 +#define AON_BACKUP13 0x0B4 +#define AON_BACKUP14 0x0B8 +#define AON_BACKUP15 0x0BC + +#define AON_PMUWAKEUPI0 0x100 +#define AON_PMUWAKEUPI1 0x104 +#define AON_PMUWAKEUPI2 0x108 +#define AON_PMUWAKEUPI3 0x10C +#define AON_PMUWAKEUPI4 0x110 +#define AON_PMUWAKEUPI5 0x114 +#define AON_PMUWAKEUPI6 0x118 +#define AON_PMUWAKEUPI7 0x11C +#define AON_PMUSLEEPI0 0x120 +#define AON_PMUSLEEPI1 0x124 +#define AON_PMUSLEEPI2 0x128 +#define AON_PMUSLEEPI3 0x12C +#define AON_PMUSLEEPI4 0x130 +#define AON_PMUSLEEPI5 0x134 +#define AON_PMUSLEEPI6 0x138 +#define AON_PMUSLEEPI7 0x13C +#define AON_PMUIE 0x140 +#define AON_PMUCAUSE 0x144 +#define AON_PMUSLEEP 0x148 +#define AON_PMUKEY 0x14C + +#define AON_LFROSC 0x070 +/* Constants */ + +#define AON_WDOGKEY_VALUE 0x51F15E +#define AON_WDOGFEED_VALUE 0xD09F00D + +#define AON_WDOGCFG_SCALE 0x0000000F +#define AON_WDOGCFG_RSTEN 0x00000100 +#define AON_WDOGCFG_ZEROCMP 0x00000200 +#define AON_WDOGCFG_ENALWAYS 0x00001000 +#define AON_WDOGCFG_ENCOREAWAKE 0x00002000 +#define AON_WDOGCFG_CMPIP 0x10000000 + +#define AON_RTCCFG_SCALE 0x0000000F +#define AON_RTCCFG_ENALWAYS 0x00001000 +#define AON_RTCCFG_CMPIP 0x10000000 + +#define AON_WAKEUPCAUSE_RESET 0x00 +#define AON_WAKEUPCAUSE_RTC 0x01 +#define AON_WAKEUPCAUSE_DWAKEUP 0x02 +#define AON_WAKEUPCAUSE_AWAKEUP 0x03 + +#define AON_RESETCAUSE_POWERON 0x0000 +#define AON_RESETCAUSE_EXTERNAL 0x0100 +#define AON_RESETCAUSE_WATCHDOG 0x0200 + +#define AON_PMUCAUSE_WAKEUPCAUSE 0x00FF +#define AON_PMUCAUSE_RESETCAUSE 0xFF00 + +#endif /* _SIFIVE_AON_H */ diff --git a/raven_spn/bsp/include/sifive/devices/clic.h b/raven_spn/bsp/include/sifive/devices/clic.h new file mode 100644 index 0000000..e8dc2df --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/clic.h @@ -0,0 +1,30 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_CLIC_H +#define _SIFIVE_CLIC_H + +#define CLIC_HART0 0x00800000 +#define CLIC_MSIP 0x0000 +#define CLIC_MSIP_size 0x4 +#define CLIC_MTIMECMP 0x4000 +#define CLIC_MTIMECMP_size 0x8 +#define CLIC_MTIME 0xBFF8 +#define CLIC_MTIME_size 0x8 + +#define CLIC_INTIP 0x000 +#define CLIC_INTIE 0x400 +#define CLIC_INTCFG 0x800 +#define CLIC_CFG 0xc00 + +// These interrupt IDs are consistent across old and new mtvec modes +#define SSIPID 1 +#define MSIPID 3 +#define STIPID 5 +#define MTIPID 7 +#define SEIPID 9 +#define MEIPID 11 +#define CSIPID 12 +#define LOCALINTIDBASE 16 + + +#endif /* _SIFIVE_CLIC_H */ diff --git a/raven_spn/bsp/include/sifive/devices/clint.h b/raven_spn/bsp/include/sifive/devices/clint.h new file mode 100644 index 0000000..cd3e0c7 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/clint.h @@ -0,0 +1,14 @@ +// See LICENSE for license details + +#ifndef _SIFIVE_CLINT_H +#define _SIFIVE_CLINT_H + + +#define CLINT_MSIP 0x0000 +#define CLINT_MSIP_size 0x4 +#define CLINT_MTIMECMP 0x4000 +#define CLINT_MTIMECMP_size 0x8 +#define CLINT_MTIME 0xBFF8 +#define CLINT_MTIME_size 0x8 + +#endif /* _SIFIVE_CLINT_H */ diff --git a/raven_spn/bsp/include/sifive/devices/gpio.h b/raven_spn/bsp/include/sifive/devices/gpio.h new file mode 100644 index 0000000..f7f0acb --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/gpio.h @@ -0,0 +1,24 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_GPIO_H +#define _SIFIVE_GPIO_H + +#define GPIO_INPUT_VAL (0x00) +#define GPIO_INPUT_EN (0x04) +#define GPIO_OUTPUT_EN (0x08) +#define GPIO_OUTPUT_VAL (0x0C) +#define GPIO_PULLUP_EN (0x10) +#define GPIO_DRIVE (0x14) +#define GPIO_RISE_IE (0x18) +#define GPIO_RISE_IP (0x1C) +#define GPIO_FALL_IE (0x20) +#define GPIO_FALL_IP (0x24) +#define GPIO_HIGH_IE (0x28) +#define GPIO_HIGH_IP (0x2C) +#define GPIO_LOW_IE (0x30) +#define GPIO_LOW_IP (0x34) +#define GPIO_IOF_EN (0x38) +#define GPIO_IOF_SEL (0x3C) +#define GPIO_OUTPUT_XOR (0x40) + +#endif /* _SIFIVE_GPIO_H */ diff --git a/raven_spn/bsp/include/sifive/devices/otp.h b/raven_spn/bsp/include/sifive/devices/otp.h new file mode 100644 index 0000000..93833e2 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/otp.h @@ -0,0 +1,23 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_OTP_H +#define _SIFIVE_OTP_H + +/* Register offsets */ + +#define OTP_LOCK 0x00 +#define OTP_CK 0x04 +#define OTP_OE 0x08 +#define OTP_SEL 0x0C +#define OTP_WE 0x10 +#define OTP_MR 0x14 +#define OTP_MRR 0x18 +#define OTP_MPP 0x1C +#define OTP_VRREN 0x20 +#define OTP_VPPEN 0x24 +#define OTP_A 0x28 +#define OTP_D 0x2C +#define OTP_Q 0x30 +#define OTP_READ_TIMINGS 0x34 + +#endif diff --git a/raven_spn/bsp/include/sifive/devices/plic.h b/raven_spn/bsp/include/sifive/devices/plic.h new file mode 100644 index 0000000..e1ca5d6 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/plic.h @@ -0,0 +1,31 @@ +// See LICENSE for license details. + +#ifndef PLIC_H +#define PLIC_H + +#include + +// 32 bits per source +#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL) +#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2 +// 1 bit per source (1 address) +#define PLIC_PENDING_OFFSET _AC(0x1000,UL) +#define PLIC_PENDING_SHIFT_PER_SOURCE 0 + +//0x80 per target +#define PLIC_ENABLE_OFFSET _AC(0x2000,UL) +#define PLIC_ENABLE_SHIFT_PER_TARGET 7 + + +#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL) +#define PLIC_CLAIM_OFFSET _AC(0x200004,UL) +#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12 +#define PLIC_CLAIM_SHIFT_PER_TARGET 12 + +#define PLIC_MAX_SOURCE 1023 +#define PLIC_SOURCE_MASK 0x3FF + +#define PLIC_MAX_TARGET 15871 +#define PLIC_TARGET_MASK 0x3FFF + +#endif /* PLIC_H */ diff --git a/raven_spn/bsp/include/sifive/devices/prci.h b/raven_spn/bsp/include/sifive/devices/prci.h new file mode 100644 index 0000000..1a3de58 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/prci.h @@ -0,0 +1,56 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PRCI_H +#define _SIFIVE_PRCI_H + +/* Register offsets */ + +#define PRCI_HFROSCCFG (0x0000) +#define PRCI_HFXOSCCFG (0x0004) +#define PRCI_PLLCFG (0x0008) +#define PRCI_PLLDIV (0x000C) +#define PRCI_PROCMONCFG (0x00F0) + +/* Fields */ +#define ROSC_DIV(x) (((x) & 0x2F) << 0 ) +#define ROSC_TRIM(x) (((x) & 0x1F) << 16) +#define ROSC_EN(x) (((x) & 0x1 ) << 30) +#define ROSC_RDY(x) (((x) & 0x1 ) << 31) + +#define XOSC_EN(x) (((x) & 0x1) << 30) +#define XOSC_RDY(x) (((x) & 0x1) << 31) + +#define PLL_R(x) (((x) & 0x7) << 0) +// single reserved bit for F LSB. +#define PLL_F(x) (((x) & 0x3F) << 4) +#define PLL_Q(x) (((x) & 0x3) << 10) +#define PLL_SEL(x) (((x) & 0x1) << 16) +#define PLL_REFSEL(x) (((x) & 0x1) << 17) +#define PLL_BYPASS(x) (((x) & 0x1) << 18) +#define PLL_LOCK(x) (((x) & 0x1) << 31) + +#define PLL_R_default 0x1 +#define PLL_F_default 0x1F +#define PLL_Q_default 0x3 + +#define PLL_REFSEL_HFROSC 0x0 +#define PLL_REFSEL_HFXOSC 0x1 + +#define PLL_SEL_HFROSC 0x0 +#define PLL_SEL_PLL 0x1 + +#define PLL_FINAL_DIV(x) (((x) & 0x3F) << 0) +#define PLL_FINAL_DIV_BY_1(x) (((x) & 0x1 ) << 8) + +#define PROCMON_DIV(x) (((x) & 0x1F) << 0) +#define PROCMON_TRIM(x) (((x) & 0x1F) << 8) +#define PROCMON_EN(x) (((x) & 0x1) << 16) +#define PROCMON_SEL(x) (((x) & 0x3) << 24) +#define PROCMON_NT_EN(x) (((x) & 0x1) << 28) + +#define PROCMON_SEL_HFCLK 0 +#define PROCMON_SEL_HFXOSCIN 1 +#define PROCMON_SEL_PLLOUTDIV 2 +#define PROCMON_SEL_PROCMON 3 + +#endif // _SIFIVE_PRCI_H diff --git a/raven_spn/bsp/include/sifive/devices/pwm.h b/raven_spn/bsp/include/sifive/devices/pwm.h new file mode 100644 index 0000000..067889a --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/pwm.h @@ -0,0 +1,37 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_PWM_H +#define _SIFIVE_PWM_H + +/* Register offsets */ + +#define PWM_CFG 0x00 +#define PWM_COUNT 0x08 +#define PWM_S 0x10 +#define PWM_CMP0 0x20 +#define PWM_CMP1 0x24 +#define PWM_CMP2 0x28 +#define PWM_CMP3 0x2C + +/* Constants */ + +#define PWM_CFG_SCALE 0x0000000F +#define PWM_CFG_STICKY 0x00000100 +#define PWM_CFG_ZEROCMP 0x00000200 +#define PWM_CFG_DEGLITCH 0x00000400 +#define PWM_CFG_ENALWAYS 0x00001000 +#define PWM_CFG_ONESHOT 0x00002000 +#define PWM_CFG_CMP0CENTER 0x00010000 +#define PWM_CFG_CMP1CENTER 0x00020000 +#define PWM_CFG_CMP2CENTER 0x00040000 +#define PWM_CFG_CMP3CENTER 0x00080000 +#define PWM_CFG_CMP0GANG 0x01000000 +#define PWM_CFG_CMP1GANG 0x02000000 +#define PWM_CFG_CMP2GANG 0x04000000 +#define PWM_CFG_CMP3GANG 0x08000000 +#define PWM_CFG_CMP0IP 0x10000000 +#define PWM_CFG_CMP1IP 0x20000000 +#define PWM_CFG_CMP2IP 0x40000000 +#define PWM_CFG_CMP3IP 0x80000000 + +#endif /* _SIFIVE_PWM_H */ diff --git a/raven_spn/bsp/include/sifive/devices/spi.h b/raven_spn/bsp/include/sifive/devices/spi.h new file mode 100644 index 0000000..80ef345 --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/spi.h @@ -0,0 +1,80 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_SPI_H +#define _SIFIVE_SPI_H + +/* Register offsets */ + +#define SPI_REG_SCKDIV 0x00 +#define SPI_REG_SCKMODE 0x04 +#define SPI_REG_CSID 0x10 +#define SPI_REG_CSDEF 0x14 +#define SPI_REG_CSMODE 0x18 + +#define SPI_REG_DCSSCK 0x28 +#define SPI_REG_DSCKCS 0x2a +#define SPI_REG_DINTERCS 0x2c +#define SPI_REG_DINTERXFR 0x2e + +#define SPI_REG_FMT 0x40 +#define SPI_REG_TXFIFO 0x48 +#define SPI_REG_RXFIFO 0x4c +#define SPI_REG_TXCTRL 0x50 +#define SPI_REG_RXCTRL 0x54 + +#define SPI_REG_FCTRL 0x60 +#define SPI_REG_FFMT 0x64 + +#define SPI_REG_IE 0x70 +#define SPI_REG_IP 0x74 + +/* Fields */ + +#define SPI_SCK_PHA 0x1 +#define SPI_SCK_POL 0x2 + +#define SPI_FMT_PROTO(x) ((x) & 0x3) +#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2) +#define SPI_FMT_DIR(x) (((x) & 0x1) << 3) +#define SPI_FMT_LEN(x) (((x) & 0xf) << 16) + +/* TXCTRL register */ +#define SPI_TXWM(x) ((x) & 0xffff) +/* RXCTRL register */ +#define SPI_RXWM(x) ((x) & 0xffff) + +#define SPI_IP_TXWM 0x1 +#define SPI_IP_RXWM 0x2 + +#define SPI_FCTRL_EN 0x1 + +#define SPI_INSN_CMD_EN 0x1 +#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1) +#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4) +#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8) +#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10) +#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12) +#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16) +#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24) + +#define SPI_TXFIFO_FULL (1 << 31) +#define SPI_RXFIFO_EMPTY (1 << 31) + +/* Values */ + +#define SPI_CSMODE_AUTO 0 +#define SPI_CSMODE_HOLD 2 +#define SPI_CSMODE_OFF 3 + +#define SPI_DIR_RX 0 +#define SPI_DIR_TX 1 + +#define SPI_PROTO_S 0 +#define SPI_PROTO_D 1 +#define SPI_PROTO_Q 2 + +#define SPI_ENDIAN_MSB 0 +#define SPI_ENDIAN_LSB 1 + + +#endif /* _SIFIVE_SPI_H */ diff --git a/raven_spn/bsp/include/sifive/devices/uart.h b/raven_spn/bsp/include/sifive/devices/uart.h new file mode 100644 index 0000000..71bea6f --- /dev/null +++ b/raven_spn/bsp/include/sifive/devices/uart.h @@ -0,0 +1,27 @@ +// See LICENSE for license details. + +#ifndef _SIFIVE_UART_H +#define _SIFIVE_UART_H + +/* Register offsets */ +#define UART_REG_TXFIFO 0x00 +#define UART_REG_RXFIFO 0x04 +#define UART_REG_TXCTRL 0x08 +#define UART_REG_RXCTRL 0x0c +#define UART_REG_IE 0x10 +#define UART_REG_IP 0x14 +#define UART_REG_DIV 0x18 + +/* TXCTRL register */ +#define UART_TXEN 0x1 +#define UART_TXWM(x) (((x) & 0xffff) << 16) + +/* RXCTRL register */ +#define UART_RXEN 0x1 +#define UART_RXWM(x) (((x) & 0xffff) << 16) + +/* IP register */ +#define UART_IP_TXWM 0x1 +#define UART_IP_RXWM 0x2 + +#endif /* _SIFIVE_UART_H */ diff --git a/raven_spn/bsp/include/sifive/sections.h b/raven_spn/bsp/include/sifive/sections.h new file mode 100644 index 0000000..6e1f051 --- /dev/null +++ b/raven_spn/bsp/include/sifive/sections.h @@ -0,0 +1,17 @@ +// See LICENSE for license details. +#ifndef _SECTIONS_H +#define _SECTIONS_H + +extern unsigned char _rom[]; +extern unsigned char _rom_end[]; + +extern unsigned char _ram[]; +extern unsigned char _ram_end[]; + +extern unsigned char _ftext[]; +extern unsigned char _etext[]; +extern unsigned char _fbss[]; +extern unsigned char _ebss[]; +extern unsigned char _end[]; + +#endif /* _SECTIONS_H */ diff --git a/raven_spn/bsp/include/sifive/smp.h b/raven_spn/bsp/include/sifive/smp.h new file mode 100644 index 0000000..8e34388 --- /dev/null +++ b/raven_spn/bsp/include/sifive/smp.h @@ -0,0 +1,65 @@ +#ifndef SIFIVE_SMP +#define SIFIVE_SMP + +// The maximum number of HARTs this code supports +#ifndef MAX_HARTS +#define MAX_HARTS 32 +#endif +#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4) + +// The hart that non-SMP tests should run on +#ifndef NONSMP_HART +#define NONSMP_HART 0 +#endif + +/* If your test cannot handle multiple-threads, use this: + * smp_disable(reg1) + */ +#define smp_disable(reg1, reg2) \ + csrr reg1, mhartid ;\ + li reg2, NONSMP_HART ;\ + beq reg1, reg2, hart0_entry ;\ +42: ;\ + wfi ;\ + j 42b ;\ +hart0_entry: + +/* If your test needs to temporarily block multiple-threads, do this: + * smp_pause(reg1, reg2) + * ... single-threaded work ... + * smp_resume(reg1, reg2) + * ... multi-threaded work ... + */ + +#define smp_pause(reg1, reg2) \ + li reg2, 0x8 ;\ + csrw mie, reg2 ;\ + csrr reg2, mhartid ;\ + bnez reg2, 42f + +#define smp_resume(reg1, reg2) \ + li reg1, CLINT_CTRL_ADDR ;\ +41: ;\ + li reg2, 1 ;\ + sw reg2, 0(reg1) ;\ + addi reg1, reg1, 4 ;\ + li reg2, CLINT_END_HART_IPI ;\ + blt reg1, reg2, 41b ;\ +42: ;\ + wfi ;\ + csrr reg2, mip ;\ + andi reg2, reg2, 0x8 ;\ + beqz reg2, 42b ;\ + li reg1, CLINT_CTRL_ADDR ;\ + csrr reg2, mhartid ;\ + slli reg2, reg2, 2 ;\ + add reg2, reg2, reg1 ;\ + sw zero, 0(reg2) ;\ +41: ;\ + lw reg2, 0(reg1) ;\ + bnez reg2, 41b ;\ + addi reg1, reg1, 4 ;\ + li reg2, CLINT_END_HART_IPI ;\ + blt reg1, reg2, 41b + +#endif diff --git a/raven_spn/bsp/libwrap/libwrap.mk b/raven_spn/bsp/libwrap/libwrap.mk new file mode 100644 index 0000000..71bba3d --- /dev/null +++ b/raven_spn/bsp/libwrap/libwrap.mk @@ -0,0 +1,56 @@ +# See LICENSE for license details. + +ifndef _SIFIVE_MK_LIBWRAP +_SIFIVE_MK_LIBWRAP := # defined + +LIBWRAP_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +LIBWRAP_DIR := $(LIBWRAP_DIR:/=) + +LIBWRAP_SRCS := \ + stdlib/malloc.c \ + sys/open.c \ + sys/lseek.c \ + sys/read.c \ + sys/write.c \ + sys/fstat.c \ + sys/stat.c \ + sys/close.c \ + sys/link.c \ + sys/unlink.c \ + sys/execve.c \ + sys/fork.c \ + sys/getpid.c \ + sys/kill.c \ + sys/wait.c \ + sys/isatty.c \ + sys/times.c \ + sys/sbrk.c \ + sys/_exit.c \ + sys/puts.c \ + misc/write_hex.c + +LIBWRAP_SRCS := $(foreach f,$(LIBWRAP_SRCS),$(LIBWRAP_DIR)/$(f)) +LIBWRAP_OBJS := $(LIBWRAP_SRCS:.c=.o) + +LIBWRAP_SYMS := malloc free \ + open lseek read write fstat stat close link unlink \ + execve fork getpid kill wait \ + isatty times sbrk _exit puts + +LIBWRAP := libwrap.a + +LINK_DEPS += $(LIBWRAP) + +LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=$(s)) +LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=_$(s)) +LDFLAGS += -L. -Wl,--start-group -lwrap -lc -Wl,--end-group + +CLEAN_OBJS += $(LIBWRAP_OBJS) + +$(LIBWRAP_OBJS): %.o: %.c $(HEADERS) + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +$(LIBWRAP): $(LIBWRAP_OBJS) + $(AR) rcs $@ $^ + +endif # _SIFIVE_MK_LIBWRAP diff --git a/raven_spn/bsp/libwrap/misc/write_hex.c b/raven_spn/bsp/libwrap/misc/write_hex.c new file mode 100644 index 0000000..a35ad7a --- /dev/null +++ b/raven_spn/bsp/libwrap/misc/write_hex.c @@ -0,0 +1,19 @@ +/* See LICENSE of license details. */ + +#include +#include +#include "platform.h" + +void write_hex(int fd, unsigned long int hex) +{ + uint8_t ii; + uint8_t jj; + char towrite; + write(fd , "0x", 2); + for (ii = sizeof(unsigned long int) * 2 ; ii > 0; ii--) { + jj = ii - 1; + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + write(fd, &towrite, 1); + } +} diff --git a/raven_spn/bsp/libwrap/stdlib/malloc.c b/raven_spn/bsp/libwrap/stdlib/malloc.c new file mode 100644 index 0000000..8f4f432 --- /dev/null +++ b/raven_spn/bsp/libwrap/stdlib/malloc.c @@ -0,0 +1,17 @@ +/* See LICENSE for license details. */ + +/* These functions are intended for embedded RV32 systems and are + obviously incorrect in general. */ + +void* __wrap_malloc(unsigned long sz) +{ + extern void* sbrk(long); + void* res = sbrk(sz); + if ((long)res == -1) + return 0; + return res; +} + +void __wrap_free(void* ptr) +{ +} diff --git a/raven_spn/bsp/libwrap/sys/_exit.c b/raven_spn/bsp/libwrap/sys/_exit.c new file mode 100644 index 0000000..011464f --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/_exit.c @@ -0,0 +1,17 @@ +/* See LICENSE of license details. */ + +#include +#include "platform.h" +#include "weak_under_alias.h" + +void __wrap_exit(int code) +{ + const char message[] = "\nProgam has exited with code:"; + + write(STDERR_FILENO, message, sizeof(message) - 1); + write_hex(STDERR_FILENO, code); + write(STDERR_FILENO, "\n", 1); + + for (;;); +} +weak_under_alias(exit); diff --git a/raven_spn/bsp/libwrap/sys/close.c b/raven_spn/bsp/libwrap/sys/close.c new file mode 100644 index 0000000..199fe51 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/close.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_close(int fd) +{ + return _stub(EBADF); +} +weak_under_alias(close); diff --git a/raven_spn/bsp/libwrap/sys/execve.c b/raven_spn/bsp/libwrap/sys/execve.c new file mode 100644 index 0000000..f7be25a --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/execve.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_execve(const char* name, char* const argv[], char* const env[]) +{ + return _stub(ENOMEM); +} +weak_under_alias(execve); diff --git a/raven_spn/bsp/libwrap/sys/fork.c b/raven_spn/bsp/libwrap/sys/fork.c new file mode 100644 index 0000000..13a3e65 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/fork.c @@ -0,0 +1,9 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" + +int fork(void) +{ + return _stub(EAGAIN); +} diff --git a/raven_spn/bsp/libwrap/sys/fstat.c b/raven_spn/bsp/libwrap/sys/fstat.c new file mode 100644 index 0000000..ff82bf9 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/fstat.c @@ -0,0 +1,18 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_fstat(int fd, struct stat* st) +{ + if (isatty(fd)) { + st->st_mode = S_IFCHR; + return 0; + } + + return _stub(EBADF); +} +weak_under_alias(fstat); diff --git a/raven_spn/bsp/libwrap/sys/getpid.c b/raven_spn/bsp/libwrap/sys/getpid.c new file mode 100644 index 0000000..195fbec --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/getpid.c @@ -0,0 +1,8 @@ +/* See LICENSE of license details. */ +#include "weak_under_alias.h" + +int __wrap_getpid(void) +{ + return 1; +} +weak_under_alias(getpid); diff --git a/raven_spn/bsp/libwrap/sys/isatty.c b/raven_spn/bsp/libwrap/sys/isatty.c new file mode 100644 index 0000000..7bb82ab --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/isatty.c @@ -0,0 +1,13 @@ +/* See LICENSE of license details. */ + +#include +#include "weak_under_alias.h" + +int __wrap_isatty(int fd) +{ + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) + return 1; + + return 0; +} +weak_under_alias(isatty); diff --git a/raven_spn/bsp/libwrap/sys/kill.c b/raven_spn/bsp/libwrap/sys/kill.c new file mode 100644 index 0000000..18b9bd4 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/kill.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_kill(int pid, int sig) +{ + return _stub(EINVAL); +} +weak_under_alias(kill); diff --git a/raven_spn/bsp/libwrap/sys/link.c b/raven_spn/bsp/libwrap/sys/link.c new file mode 100644 index 0000000..0cad551 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/link.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_link(const char *old_name, const char *new_name) +{ + return _stub(EMLINK); +} +weak_under_alias(link); diff --git a/raven_spn/bsp/libwrap/sys/lseek.c b/raven_spn/bsp/libwrap/sys/lseek.c new file mode 100644 index 0000000..4131449 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/lseek.c @@ -0,0 +1,16 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include "stub.h" +#include "weak_under_alias.h" + +off_t __wrap_lseek(int fd, off_t ptr, int dir) +{ + if (isatty(fd)) + return 0; + + return _stub(EBADF); +} +weak_under_alias(lseek); diff --git a/raven_spn/bsp/libwrap/sys/open.c b/raven_spn/bsp/libwrap/sys/open.c new file mode 100644 index 0000000..c61415a --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/open.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_open(const char* name, int flags, int mode) +{ + return _stub(ENOENT); +} +weak_under_alias(open); diff --git a/raven_spn/bsp/libwrap/sys/openat.c b/raven_spn/bsp/libwrap/sys/openat.c new file mode 100644 index 0000000..227c956 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/openat.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_openat(int dirfd, const char* name, int flags, int mode) +{ + return _stub(ENOENT); +} +weak_under_alias(openat); diff --git a/raven_spn/bsp/libwrap/sys/puts.c b/raven_spn/bsp/libwrap/sys/puts.c new file mode 100644 index 0000000..50d6437 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/puts.c @@ -0,0 +1,28 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include + +#include "platform.h" +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_puts(const char *s) +{ + while (*s != '\0') { + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = *s; + + if (*s == '\n') { + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = '\r'; + } + + ++s; + } + + return 0; +} +weak_under_alias(puts); diff --git a/raven_spn/bsp/libwrap/sys/read.c b/raven_spn/bsp/libwrap/sys/read.c new file mode 100644 index 0000000..3226cdb --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/read.c @@ -0,0 +1,32 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include + +#include "platform.h" +#include "stub.h" +#include "weak_under_alias.h" + +ssize_t __wrap_read(int fd, void* ptr, size_t len) +{ + uint8_t * current = (uint8_t *)ptr; + volatile uint32_t * uart_rx = (uint32_t *)(UART0_CTRL_ADDR + UART_REG_RXFIFO); + volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_CTRL_ADDR + UART_REG_RXCTRL + 2); + + ssize_t result = 0; + + if (isatty(fd)) { + for (current = (uint8_t *)ptr; + (current < ((uint8_t *)ptr) + len) && (*uart_rx_cnt > 0); + current ++) { + *current = *uart_rx; + result++; + } + return result; + } + + return _stub(EBADF); +} +weak_under_alias(read); diff --git a/raven_spn/bsp/libwrap/sys/sbrk.c b/raven_spn/bsp/libwrap/sys/sbrk.c new file mode 100644 index 0000000..12170b4 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/sbrk.c @@ -0,0 +1,18 @@ +/* See LICENSE of license details. */ + +#include +#include "weak_under_alias.h" + +void *__wrap_sbrk(ptrdiff_t incr) +{ + extern char _end[]; + extern char _heap_end[]; + static char *curbrk = _end; + + if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) + return NULL - 1; + + curbrk += incr; + return curbrk - incr; +} +weak_under_alias(sbrk); diff --git a/raven_spn/bsp/libwrap/sys/stat.c b/raven_spn/bsp/libwrap/sys/stat.c new file mode 100644 index 0000000..1576ca1 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/stat.c @@ -0,0 +1,12 @@ +/* See LICENSE of license details. */ + +#include +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_stat(const char* file, struct stat* st) +{ + return _stub(EACCES); +} +weak_under_alias(stat); diff --git a/raven_spn/bsp/libwrap/sys/stub.h b/raven_spn/bsp/libwrap/sys/stub.h new file mode 100644 index 0000000..fb5e5be --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/stub.h @@ -0,0 +1,10 @@ +/* See LICENSE of license details. */ +#ifndef _SIFIVE_SYS_STUB_H +#define _SIFIVE_SYS_STUB_H + +static inline int _stub(int err) +{ + return -1; +} + +#endif /* _SIFIVE_SYS_STUB_H */ diff --git a/raven_spn/bsp/libwrap/sys/times.c b/raven_spn/bsp/libwrap/sys/times.c new file mode 100644 index 0000000..55969a7 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/times.c @@ -0,0 +1,12 @@ +/* See LICENSE of license details. */ + +#include +#include +#include "stub.h" +#include "weak_under_alias.h" + +clock_t __wrap_times(struct tms* buf) +{ + return _stub(EACCES); +} +weak_under_alias(times); diff --git a/raven_spn/bsp/libwrap/sys/unlink.c b/raven_spn/bsp/libwrap/sys/unlink.c new file mode 100644 index 0000000..09f4da7 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/unlink.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" +#include "weak_under_alias.h" + +int __wrap_unlink(const char* name) +{ + return _stub(ENOENT); +} +weak_under_alias(unlink); diff --git a/raven_spn/bsp/libwrap/sys/wait.c b/raven_spn/bsp/libwrap/sys/wait.c new file mode 100644 index 0000000..ea3225b --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/wait.c @@ -0,0 +1,9 @@ +/* See LICENSE of license details. */ + +#include +#include "stub.h" + +int wait(int* status) +{ + return _stub(ECHILD); +} diff --git a/raven_spn/bsp/libwrap/sys/weak_under_alias.h b/raven_spn/bsp/libwrap/sys/weak_under_alias.h new file mode 100644 index 0000000..7629353 --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/weak_under_alias.h @@ -0,0 +1,7 @@ +#ifndef _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H +#define _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H + +#define weak_under_alias(name) \ + extern __typeof (__wrap_##name) __wrap__##name __attribute__ ((weak, alias ("__wrap_"#name))) + +#endif diff --git a/raven_spn/bsp/libwrap/sys/write.c b/raven_spn/bsp/libwrap/sys/write.c new file mode 100644 index 0000000..b1e9a7e --- /dev/null +++ b/raven_spn/bsp/libwrap/sys/write.c @@ -0,0 +1,31 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include + +#include "platform.h" +#include "stub.h" +#include "weak_under_alias.h" + +ssize_t __wrap_write(int fd, const void* ptr, size_t len) +{ + const uint8_t * current = (const char *)ptr; + + if (isatty(fd)) { + for (size_t jj = 0; jj < len; jj++) { + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = current[jj]; + + if (current[jj] == '\n') { + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = '\r'; + } + } + return len; + } + + return _stub(EBADF); +} +weak_under_alias(write); diff --git a/raven_spn/raven_spn b/raven_spn/raven_spn new file mode 100755 index 0000000000000000000000000000000000000000..f426bcbf8c20006a53d8a304662195771fa8a705 GIT binary patch literal 118788 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 O51%U~S1b`nyYBz8QP5ie literal 0 HcmV?d00001 diff --git a/raven_spn/src/bsp.h b/raven_spn/src/bsp.h new file mode 100644 index 0000000..f04f4f4 --- /dev/null +++ b/raven_spn/src/bsp.h @@ -0,0 +1,22 @@ +/* + * bsp.h + * + * Created on: 30.07.2018 + * Author: eyck + */ + +#ifndef BSP_H_ +#define BSP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +extern void trap_entry(); +#ifdef __cplusplus +} +#endif + +#endif /* BSP_H_ */ diff --git a/raven_spn/src/delay.c b/raven_spn/src/delay.c new file mode 100644 index 0000000..24070b4 --- /dev/null +++ b/raven_spn/src/delay.c @@ -0,0 +1,123 @@ +/* + * delay.c + * + * Created on: 30.07.2018 + * Author: eyck + */ + +#include "delay.h" + +#define rdmcycle(x) { \ + uint32_t lo, hi, hi2; \ + __asm__ __volatile__ ("1:\n\t" \ + "csrr %0, mcycleh\n\t" \ + "csrr %1, mcycle\n\t" \ + "csrr %2, mcycleh\n\t" \ + "bne %0, %2, 1b\n\t" \ + : "=r" (hi), "=r" (lo), "=r" (hi2)) ; \ + *(x) = lo | ((uint64_t) hi << 32); \ + } + +typedef struct { + uint32_t n; + uint32_t mult; + uint32_t shift; +} int_inverse ; + +int_inverse f_cpu_1000_inv; +int_inverse f_cpu_1000000_inv; + +uint32_t F_CPU=1000000; + +void calc_inv(uint32_t n, int_inverse * res){ + uint32_t one = ~0; + uint32_t d = one/n; + uint32_t r = one%n + 1; + if (r >= n) ++d; + if (d == 0) --d; + uint32_t shift = 0; + while ((d & 0x80000000) == 0){ + d <<= 1; + ++shift; + } + res->n = n; + res->mult = d; + res->shift = shift; +} + +uint32_t divide32_using_inverse(uint32_t n, int_inverse *inv){ + uint32_t d = (uint32_t)(((uint64_t)n * inv->mult) >> 32); + d >>= inv->shift; + if (n - d*inv->n >= inv->n) ++d; + return d; +} + +// Almost full-range 64/32 divide. +// If divisor-1 has i bits, then the answer is exact for n of up to 64-i bits +// e.g. for divisors up to a million, n can have up to 45 bits +// On RV32IM with divide32_using_inverse inlines this uses 5 multiplies, +// 33 instructions, zero branches, 3 loads, 0 stores. +uint64_t divide64_using_inverse(uint64_t n, int_inverse *inv){ + uint32_t preshift = (31 - inv->shift) & 31; + uint64_t d = (uint64_t)divide32_using_inverse(n >> preshift, inv) << preshift; + uint32_t r = n - d * inv->n; + d += divide32_using_inverse(r, inv); + return d; +} + + +uint32_t millis(){ + uint64_t x; + rdmcycle(&x); + x = divide64_using_inverse(x, &f_cpu_1000_inv); + return((uint32_t) (x & 0xFFFFFFFF)); +} + +uint32_t micros(void){ + uint64_t x; + rdmcycle(&x); + // For Power-of-two MHz F_CPU, + // this compiles into a simple shift, + // and is faster than the general solution. +#if F_CPU==16000000 + x = x / (F_CPU / 1000000); +#else +#if F_CPU==256000000 + x = x / (F_CPU / 1000000); +#else + x = divide64_using_inverse(x, &f_cpu_1000000_inv); +#endif +#endif + return((uint32_t) (x & 0xFFFFFFFF)); +} + + +void delayMS(uint32_t dwMs){ + uint64_t current, later; + rdmcycle(¤t); + later = current + dwMs * (F_CPU/1000); + if (later > current){ // usual case + while (later > current) + rdmcycle(¤t); + } else { // wrap. Though this is unlikely to be hit w/ 64-bit mcycle + while (later < current) + rdmcycle(¤t); + while (current < later) + rdmcycle(¤t); + } +} + +void delayUS(uint32_t dwUs){ + uint64_t current, later; + rdmcycle(¤t); + later = current + dwUs * (F_CPU/1000000); + if (later > current){ // usual case + while (later > current) + rdmcycle(¤t); + } else {// wrap. Though this is unlikely to be hit w/ 64-bit mcycle + while (later < current) + rdmcycle(¤t); + while (current < later) + rdmcycle(¤t); + } +} diff --git a/raven_spn/src/delay.h b/raven_spn/src/delay.h new file mode 100644 index 0000000..36ce098 --- /dev/null +++ b/raven_spn/src/delay.h @@ -0,0 +1,25 @@ +/* + * delay.h + * + * Created on: 30.07.2018 + * Author: eyck + */ + +#ifndef DELAY_H_ +#define DELAY_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern uint32_t F_CPU; + +void delayMS(uint32_t dwMs); +void delayUS(uint32_t dwUs); + +#ifdef __cplusplus +} +#endif + +#endif /* DELAY_H_ */ diff --git a/raven_spn/src/io/gpio.h b/raven_spn/src/io/gpio.h new file mode 100644 index 0000000..466f2d2 --- /dev/null +++ b/raven_spn/src/io/gpio.h @@ -0,0 +1,89 @@ +/* + * gpio.h + * + * Created on: 29.07.2018 + * Author: eyck + */ + +#ifndef GPIO_H_ +#define GPIO_H_ + +#include +#include + +template +class gpio_regs { +public: + static inline uint32_t& value_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_INPUT_VAL); + } + + static inline uint32_t& input_en_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_INPUT_EN); + } + + static inline uint32_t& output_en_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_OUTPUT_EN); + } + + static inline uint32_t& port_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_OUTPUT_VAL); + } + + static inline uint32_t& pue_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_PULLUP_EN); + } + + static inline uint32_t& ds_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_DRIVE); + } + + static inline uint32_t& rise_ie_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_RISE_IE); + } + + static inline uint32_t& rise_ip_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_RISE_IP); + } + + static inline uint32_t& fall_ie_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_FALL_IE); + } + + static inline uint32_t& fall_ip_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_FALL_IP); + } + + static inline uint32_t& high_ie_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_HIGH_IE); + } + + static inline uint32_t& high_ip_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_HIGH_IP); + } + + static inline uint32_t& low_ie_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_LOW_IE); + } + + static inline uint32_t& low_ip_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_LOW_IP); + } + + static inline uint32_t& iof_en_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_IOF_EN); + } + + static inline uint32_t& iof_sel_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_IOF_SEL); + } + + static inline uint32_t& out_xor_reg(){ + return *reinterpret_cast(BASE_ADDR+GPIO_OUTPUT_XOR); + } + +}; + + + +#endif /* GPIO_H_ */ diff --git a/raven_spn/src/io/pwm.h b/raven_spn/src/io/pwm.h new file mode 100644 index 0000000..2aab61b --- /dev/null +++ b/raven_spn/src/io/pwm.h @@ -0,0 +1,122 @@ +/* + * pwm.h + * + * Created on: 29.07.2018 + * Author: eyck + */ + +#ifndef PWM_H_ +#define PWM_H_ + +#include +#include "util/bit_field.h" +#include +#include + +template +class pwm_regs { +public: + BEGIN_BF_DECL(pwmcfg_t, uint32_t); + BF_FIELD(scale, 0, 4); + BF_FIELD(sticky, 8, 1); + BF_FIELD(zerocmp, 9, 1); + BF_FIELD(deglitch, 10, 1); + BF_FIELD(enalways, 12, 1); + BF_FIELD(enoneshot, 13, 1); + BF_FIELD(cmp0center, 16, 1); + BF_FIELD(cmp1center, 17, 1); + BF_FIELD(cmp2center, 18, 1); + BF_FIELD(cmp3center, 19, 1); + BF_FIELD(cmp0gang, 24, 1); + BF_FIELD(cmp1gang, 25, 1); + BF_FIELD(cmp2gang, 26, 1); + BF_FIELD(cmp3gang, 27, 1); + BF_FIELD(cmp0ip, 28, 1); + BF_FIELD(cmp1ip, 29, 1); + BF_FIELD(cmp2ip, 30, 1); + BF_FIELD(cmp3ip, 31, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(pwms_t, uint32_t); + BF_FIELD(s, 0, 16); + END_BF_DECL() r_pwms; + + BEGIN_BF_DECL(pwmcmp0_t, uint32_t); + BF_FIELD(cmp0, 0, 16); + END_BF_DECL() r_pwmcmp0; + + BEGIN_BF_DECL(pwmcmp1_t, uint32_t); + BF_FIELD(cmp0, 0, 16); + END_BF_DECL() r_pwmcmp1; + + BEGIN_BF_DECL(pwmcmp2_t, uint32_t); + BF_FIELD(cmp0, 0, 16); + END_BF_DECL() r_pwmcmp2; + + BEGIN_BF_DECL(pwmcmp3_t, uint32_t); + BF_FIELD(cmp0, 0, 16); + END_BF_DECL() r_pwmcmp3; + + static inline pwmcfg_t& cfg_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_CFG); + } + + static inline uint32_t& count_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_COUNT); + } + + static inline pwms_t& s_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_S); + } + + static inline pwmcmp0_t& cmp0_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_CMP0); + } + + static inline pwmcmp1_t& cmp1_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_CMP1); + } + + static inline pwmcmp2_t& cmp2_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_CMP2); + } + + static inline pwmcmp3_t& cmp3_reg(){ + return *reinterpret_cast(BASE_ADDR+PWM_CMP3); + } + + static inline bool oneshot_delay(long delay_us){ + auto scaling_factor=0; + while(delay_us/(1< std::numeric_limits::max()){ + scaling_factor++; + } + cfg_reg()=0; + count_reg()=0; + cfg_reg().scale=4+scaling_factor; // divide by 16 so we get 1us per pwm clock + cmp0_reg().cmp0 = delay_us/(1< +#include "util/bit_field.h" +#include +#include + +template +class spi_regs { +public: + // storage declarations + BEGIN_BF_DECL(sckdiv_t, uint32_t); + BF_FIELD(div, 0, 12); + END_BF_DECL(); + + BEGIN_BF_DECL(sckmode_t, uint32_t); + BF_FIELD(pha, 0, 1); + BF_FIELD(pol, 1, 1); + END_BF_DECL(); + + uint32_t r_csid; + + uint32_t r_csdef; + + BEGIN_BF_DECL(csmode_t, uint32_t); + BF_FIELD(mode, 0, 2); + END_BF_DECL(); + + BEGIN_BF_DECL(delay0_t, uint32_t); + BF_FIELD(cssck, 0, 8); + BF_FIELD(sckcs, 16, 8); + END_BF_DECL(); + + BEGIN_BF_DECL(delay1_t, uint32_t); + BF_FIELD(intercs, 0, 16); + BF_FIELD(interxfr, 16, 8); + END_BF_DECL(); + + BEGIN_BF_DECL(fmt_t, uint32_t); + BF_FIELD(proto, 0, 2); + BF_FIELD(endian, 2, 1); + BF_FIELD(dir, 3, 1); + BF_FIELD(len, 16, 4); + END_BF_DECL(); + + BEGIN_BF_DECL(txdata_t, uint32_t); + BF_FIELD(data, 0, 8); + BF_FIELD(full, 31, 1); + END_BF_DECL() r_txdata; + + BEGIN_BF_DECL(rxdata_t, uint32_t); + BF_FIELD(data, 0, 8); + BF_FIELD(empty, 31, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(txmark_t, uint32_t); + BF_FIELD(txmark, 0, 3); + END_BF_DECL(); + + BEGIN_BF_DECL(rxmark_t, uint32_t); + BF_FIELD(rxmark, 0, 3); + END_BF_DECL(); + + BEGIN_BF_DECL(fctrl_t, uint32_t); + BF_FIELD(en, 0, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(ffmt_t, uint32_t); + BF_FIELD(cmd_en, 0, 1); + BF_FIELD(addr_len, 1, 2); + BF_FIELD(pad_cnt, 3, 4); + BF_FIELD(cmd_proto, 7, 2); + BF_FIELD(addr_proto, 9, 2); + BF_FIELD(data_proto, 11, 2); + BF_FIELD(cmd_code, 16, 8); + BF_FIELD(pad_code, 24, 8); + END_BF_DECL(); + + BEGIN_BF_DECL(ie_t, uint32_t); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(ip_t, uint32_t); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); + END_BF_DECL(); + + static inline sckdiv_t& sckdiv_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_SCKDIV); + } + + static inline sckmode_t& sckmode_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_SCKMODE); + } + + static inline uint32_t& csid_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_CSID); + } + + static inline uint32_t& csdef_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_CSDEF); + } + + static inline csmode_t& csmode_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_CSMODE); + } + + static inline delay0_t& dcssck_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_DCSSCK); + } + + static inline uint32_t& dsckcs_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_DSCKCS); + } + + static inline delay1_t& dintercs_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_DINTERCS); + } + + static inline uint32_t& dinterxfr_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_DINTERXFR); + } + + static inline fmt_t& fmt_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_FMT); + } + + static inline txdata_t& txfifo_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_TXFIFO); + } + + static inline rxdata_t& rxfifo_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_RXFIFO); + } + + static inline txmark_t& txctrl_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_TXCTRL); + } + + static inline rxmark_t& rxctrl_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_RXCTRL); + } + + static inline fctrl_t& fctrl_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_FCTRL); + } + + static inline ffmt_t& ffmt_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_FFMT); + } + + static inline ie_t& ie_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_IE); + } + + static inline ip_t& ip_reg(){ + return *reinterpret_cast(BASE_ADDR+SPI_REG_IP); + } + + template + static bool transfer(std::array& bytes){ + csmode_reg().mode=2; // HOLD mode + rxctrl_reg().rxmark=bytes.size()-1; // trigger irq if more than 2 bytes are received; + ie_reg().rxwm=1; + // write data bytes + for(size_t i=0; i +#include "util/bit_field.h" +#include + +template +class uart_regs { +public: + BEGIN_BF_DECL(txdata_t, uint32_t); + BF_FIELD(data, 0, 8); + BF_FIELD(full, 31, 1); + END_BF_DECL() ; + + BEGIN_BF_DECL(rxdata_t, uint32_t); + BF_FIELD(data, 0, 8); + BF_FIELD(empty, 31, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(txctrl_t, uint32_t); + BF_FIELD(txen, 0, 1); + BF_FIELD(nstop, 1, 1); + BF_FIELD(txcnt, 16, 3); + END_BF_DECL(); + + BEGIN_BF_DECL(rxctrl_t, uint32_t); + BF_FIELD(rxen, 0, 1); + BF_FIELD(rxcnt, 16, 3); + END_BF_DECL(); + + BEGIN_BF_DECL(ie_t, uint32_t); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(ip_t, uint32_t); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); + END_BF_DECL(); + + BEGIN_BF_DECL(div_t, uint32_t); + BF_FIELD(div, 0, 16); + END_BF_DECL(); + + static inline txdata_t& txdata_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_TXFIFO); + } + + static inline rxdata_t& rxdata_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_RXFIFO); + } + + static inline txctrl_t& txctrl_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_TXCTRL); + } + + static inline rxctrl_t& rxctrl_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_RXCTRL); + } + + static inline ie_t& ie_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_IE); + } + + static inline ip_t& ip_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_IP); + } + + static inline div_t& div_reg(){ + return *reinterpret_cast(BASE_ADDR+UART_REG_DIV); + } + +}; + +#endif /* SPI_H_ */ diff --git a/raven_spn/src/raven_spn.cpp b/raven_spn/src/raven_spn.cpp new file mode 100644 index 0000000..178fb5b --- /dev/null +++ b/raven_spn/src/raven_spn.cpp @@ -0,0 +1,105 @@ +#include "raven_spn.h" +#include "spn_regs.h" +#include "delay.h" +#include "bsp.h" +#include "plic/plic_driver.h" + +#include +#include +#include + +using spn =spn_regs<0x90000000>; + +#define IOF_ENABLE_TERMINAL (0x30000) + + +typedef void (*function_ptr_t) (void); +//! Instance data for the PLIC. +plic_instance_t g_plic; +std::array g_ext_interrupt_handlers; + + +/*! \brief external interrupt handler + * + * routes the peripheral interrupts to the the respective handler + * + */ +extern "C" void handle_m_ext_interrupt() { + plic_source int_num = PLIC_claim_interrupt(&g_plic); + if ((int_num >=1 ) && (int_num < PLIC_NUM_INTERRUPTS)) + g_ext_interrupt_handlers[int_num](); + else + exit(1 + (uintptr_t) int_num); + PLIC_complete_interrupt(&g_plic, int_num); +} +/*! \brief dummy interrupt handler + * + */ +void no_interrupt_handler (void) {}; +/*! \brief configure the per-interrupt handler + * + */ +void configure_irq(size_t irq_num, function_ptr_t handler, unsigned char prio=1) { + g_ext_interrupt_handlers[irq_num] = handler; + // Priority must be set > 0 to trigger the interrupt. + PLIC_set_priority(&g_plic, irq_num, prio); + // Have to enable the interrupt both at the GPIO level, and at the PLIC level. + PLIC_enable_interrupt(&g_plic, irq_num); +} + +static void msi_interrupt_handler(){ + int * local_mem_base = (int *) 0x80000100; + int hartid = read_csr(mhartid); + + int val_a = *local_mem_base; + int val_b = *(local_mem_base+1); + int sum = val_a + val_b; + *(local_mem_base+100) = sum; + if (sum == 0xF) + printf("HW thread ID %d: sum of A+B=0x%x\n", hartid, sum); + else { + printf("HW thread ID %d: sum of A+B is not 0x%x. Test FAILED!!!\n", hartid, sum); + } +} + +/*!\brief initializes platform + * + */ +void platform_init(){ + // UART init section TODO: clarify how to get the functions from init.c? + GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; + GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; + UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; + + F_CPU=PRCI_measure_mcycle_freq(20, RTC_FREQ); + printf("core freq at %d Hz\n", F_CPU); + // initialie interupt & trap handling + write_csr(mtvec, &trap_entry); + + PLIC_init(&g_plic, PLIC_CTRL_ADDR, PLIC_NUM_INTERRUPTS, PLIC_NUM_PRIORITIES, 0); + // Disable the machine & timer interrupts until setup is done. + clear_csr(mie, MIP_MEIP); + clear_csr(mie, MIP_MTIP); + for (auto& h:g_ext_interrupt_handlers) h=no_interrupt_handler; + configure_irq(1, msi_interrupt_handler); + // Enable interrupts in general. + set_csr(mstatus, MSTATUS_MIE); + // Enable the Machine-External bit in MIE + set_csr(mie, MIP_MEIP); +} + +/*! \brief main function + * + */ +int main() { + platform_init(); + + spn::start_reg()=1; + + printf("set SPN Mode: 1\n"); + + delayUS(100); + + printf("End of execution"); + return 0; +} diff --git a/raven_spn/src/raven_spn.h b/raven_spn/src/raven_spn.h new file mode 100644 index 0000000..14ff1a8 --- /dev/null +++ b/raven_spn/src/raven_spn.h @@ -0,0 +1,6 @@ +#ifndef RAVEN_SPN_H_ +#define RAVEN_SPN_H_ + +extern "C" void handle_m_ext_interrupt(); + +#endif /* RAVEN_SPN_H_ */ diff --git a/raven_spn/src/spn_regs.h b/raven_spn/src/spn_regs.h new file mode 100644 index 0000000..9efb417 --- /dev/null +++ b/raven_spn/src/spn_regs.h @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, MINRES Technologies GmbH +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Created on: Thu Oct 01 15:45:55 CEST 2020 +// * spn_regs.h Author: +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _SPN_REGS_H_ +#define _SPN_REGS_H_ + +#include +#include + +#define SPN_REG_START 0x00 +#define SPN_REG_RET_VAL 0x10 +#define SPN_REG_MODE 0x20 +#define SPN_REG_INPUT_LENGTH 0x30 +#define SPN_REG_INPUT_ADDR 0x40 +#define SPN_REG_OUTPUT_ADDR 0x50 +#define SPN_REG_NUM_OF_INPUT_BEATS 0x60 +#define SPN_REG_NUM_OF_OUTPUT_BEATS 0x70 + +template +class spn_regs { +public: + // storage declarations + BEGIN_BF_DECL(start_t, uint32_t); + BF_FIELD(start, 0, 1); + END_BF_DECL() r_start; + + uint32_t r_ret_val; + + uint32_t r_mode; + + uint32_t r_input_length; + + uint32_t r_input_addr; + + uint32_t r_output_addr; + + uint32_t r_num_of_input_beats; + + uint32_t r_num_of_output_beats; + + static inline start_t& start_reg(){ + return *reinterpret_cast(BASE_ADDR+SPN_REG_START); + } +}; + +#endif // _SPN_REGS_H_ diff --git a/raven_spn/src/util/bit_field.h b/raven_spn/src/util/bit_field.h new file mode 100644 index 0000000..d4aff48 --- /dev/null +++ b/raven_spn/src/util/bit_field.h @@ -0,0 +1,179 @@ +/*--------------------------------------------------------- +Copyright (c) 2015 Jeff Preshing + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +---------------------------------------------------------*/ + +#ifndef BIT_FIELD_H_ +#define BIT_FIELD_H_ + +#ifndef __CPP11OM_BITFIELD_H__ +#define __CPP11OM_BITFIELD_H__ + +#include + +//--------------------------------------------------------- +// BitFieldMember<>: Used internally by ADD_BITFIELD_MEMBER macro. +// All members are public to simplify compliance with sections 9.0.7 and +// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior. +//--------------------------------------------------------- +template struct BitFieldMember { + T value; + + static_assert(Offset + Bits <= (int)sizeof(T) * 8, "Member exceeds bitfield boundaries"); + static_assert(Bits < (int)sizeof(T) * 8, "Can't fill entire bitfield with one member"); + + static const T Maximum = (T(1) << Bits) - 1; + static const T Mask = Maximum << Offset; + T maximum() const { return Maximum; } + T one() const { return T(1) << Offset; } + + operator T() const { return (value >> Offset) & Maximum; } + + BitFieldMember &operator=(T v) { + assert(v <= Maximum); // v must fit inside the bitfield member + value = (value & ~Mask) | (v << Offset); + return *this; + } + + BitFieldMember &operator+=(T v) { + assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member + value += v << Offset; + return *this; + } + + BitFieldMember &operator-=(T v) { + assert(T(*this) >= v); // result must not underflow + value -= v << Offset; + return *this; + } + + BitFieldMember &operator++() { return *this += 1; } + BitFieldMember operator++(int) { // postfix form + BitFieldMember tmp(*this); + operator++(); + return tmp; + } + BitFieldMember &operator--() { return *this -= 1; } + BitFieldMember operator--(int) { // postfix form + BitFieldMember tmp(*this); + operator--(); + return tmp; + } +}; + +//--------------------------------------------------------- +// BitFieldArray<>: Used internally by ADD_BITFIELD_ARRAY macro. +// All members are public to simplify compliance with sections 9.0.7 and +// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior. +//--------------------------------------------------------- +template class BitFieldArray { +public: + T value; + + static_assert(BaseOffset + BitsPerItem * NumItems <= (int)sizeof(T) * 8, "Array exceeds bitfield boundaries"); + static_assert(BitsPerItem < (int)sizeof(T) * 8, "Can't fill entire bitfield with one array element"); + + static const T Maximum = (T(1) << BitsPerItem) - 1; + T maximum() const { return Maximum; } + int numItems() const { return NumItems; } + + class Element { + private: + T &value; + int offset; + + public: + Element(T &value, int offset) + : value(value) + , offset(offset) {} + T mask() const { return Maximum << offset; } + + operator T() const { return (value >> offset) & Maximum; } + + Element &operator=(T v) { + assert(v <= Maximum); // v must fit inside the bitfield member + value = (value & ~mask()) | (v << offset); + return *this; + } + + Element &operator+=(T v) { + assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member + value += v << offset; + return *this; + } + + Element &operator-=(T v) { + assert(T(*this) >= v); // result must not underflow + value -= v << offset; + return *this; + } + + Element &operator++() { return *this += 1; } + Element operator++(int) { // postfix form + Element tmp(*this); + operator++(); + return tmp; + } + Element &operator--() { return *this -= 1; } + Element operator--(int) { // postfix form + Element tmp(*this); + operator--(); + return tmp; + } + }; + + Element operator[](int i) { + assert(i >= 0 && i < NumItems); // array index must be in range + return Element(value, BaseOffset + BitsPerItem * i); + } + + const Element operator[](int i) const { + assert(i >= 0 && i < NumItems); // array index must be in range + return Element(value, BaseOffset + BitsPerItem * i); + } +}; + +//--------------------------------------------------------- +// Bitfield definition macros. +// All members are public to simplify compliance with sections 9.0.7 and +// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior. +//--------------------------------------------------------- +#define BEGIN_BF_DECL(typeName, T) \ + union typeName { \ + struct Wrapper { \ + T value; \ + }; \ + Wrapper flat; \ + typeName(T v = 0) { flat.value = v; } \ + typeName &operator=(T v) { \ + flat.value = v; \ + return *this; \ + } \ + operator T &() { return flat.value; } \ + operator T() const { return flat.value; } \ + using StorageType = T; + +#define BF_FIELD(memberName, offset, bits) BitFieldMember memberName; + +#define BF_ARRAY(memberName, offset, bits, numItems) BitFieldArray memberName; + +#define END_BF_DECL() } + +#endif // __CPP11OM_BITFIELD_H__ + +#endif /* BIT_FIELD_H_ */ diff --git a/raven_spn/src/wrap_printf.c b/raven_spn/src/wrap_printf.c new file mode 100644 index 0000000..af23b1a --- /dev/null +++ b/raven_spn/src/wrap_printf.c @@ -0,0 +1,271 @@ +/* The functions in this file are only meant to support Dhrystone on an + * embedded RV32 system and are obviously incorrect in general. */ + +#include +#include +#include +#include +#include +#include + +#undef putchar +int putchar(int ch) +{ + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; +} + +static void sprintf_putch(int ch, void** data) +{ + char** pstr = (char**)data; + **pstr = ch; + (*pstr)++; +} + +static unsigned long getuint(va_list *ap, int lflag) +{ + if (lflag) + return va_arg(*ap, unsigned long); + else + return va_arg(*ap, unsigned int); +} + +static long getint(va_list *ap, int lflag) +{ + if (lflag) + return va_arg(*ap, long); + else + return va_arg(*ap, int); +} + +static inline void printnum(void (*putch)(int, void**), void **putdat, + unsigned long num, unsigned base, int width, int padc) +{ + unsigned digs[sizeof(num)*8]; + int pos = 0; + + while (1) + { + digs[pos++] = num % base; + if (num < base) + break; + num /= base; + } + + while (width-- > pos) + putch(padc, putdat); + + while (pos-- > 0) + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); +} + +static inline void print_double(void (*putch)(int, void**), void **putdat, + double num, int width, int prec) +{ + union { + double d; + uint64_t u; + } u; + u.d = num; + + if (u.u & (1ULL << 63)) { + putch('-', putdat); + u.u &= ~(1ULL << 63); + } + + for (int i = 0; i < prec; i++) + u.d *= 10; + + char buf[32], *pbuf = buf; + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + if (prec > 0) { + for (int i = 0; i < prec; i++) { + pbuf[-i] = pbuf[-i-1]; + } + pbuf[-prec] = '.'; + pbuf++; + } + + for (char* p = buf; p < pbuf; p++) + putch(*p, putdat); +} + +static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + register const char* p; + const char* last_fmt; + register int ch, err; + unsigned long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + if (ch == '\0') + return; + fmt++; + putch(ch, putdat); + } + fmt++; + + // Process a %-escape sequence + last_fmt = fmt; + padc = ' '; + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + + // flag to pad on the right + case '-': + padc = '-'; + goto reswitch; + + // flag to pad with 0's instead of spaces + case '0': + padc = '0'; + goto reswitch; + + // width field + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + goto process_precision; + + case '*': + precision = va_arg(ap, int); + goto process_precision; + + case '.': + if (width < 0) + width = 0; + goto reswitch; + + case '#': + altflag = 1; + goto reswitch; + + process_precision: + if (width < 0) + width = precision, precision = -1; + goto reswitch; + + // long flag + case 'l': + if (lflag) + goto bad; + goto reswitch; + + // character + case 'c': + putch(va_arg(ap, int), putdat); + break; + + // double + case 'f': + print_double(putch, putdat, va_arg(ap, double), width, precision); + break; + + // string + case 's': + if ((p = va_arg(ap, char *)) == NULL) + p = "(null)"; + if (width > 0 && padc != '-') + for (width -= strnlen(p, precision); width > 0; width--) + putch(padc, putdat); + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + putch(ch, putdat); + p++; + } + for (; width > 0; width--) + putch(' ', putdat); + break; + + // (signed) decimal + case 'd': + num = getint(&ap, lflag); + if ((long) num < 0) { + putch('-', putdat); + num = -(long) num; + } + base = 10; + goto signed_number; + + // unsigned decimal + case 'u': + base = 10; + goto unsigned_number; + + // (unsigned) octal + case 'o': + // should do something with padding so it's always 3 octits + base = 8; + goto unsigned_number; + + // pointer + case 'p': + lflag = 1; + putch('0', putdat); + putch('x', putdat); + /* fall through to 'x' */ + + // (unsigned) hexadecimal + case 'x': + base = 16; + unsigned_number: + num = getuint(&ap, lflag); + signed_number: + printnum(putch, putdat, num, base, width, padc); + break; + + // escaped '%' character + case '%': + putch(ch, putdat); + break; + + // unrecognized escape sequence - just print it literally + default: + bad: + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + +int __wrap_printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vprintfmt((void*)putchar, 0, fmt, ap); + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} + +int __wrap_sprintf(char* str, const char* fmt, ...) +{ + va_list ap; + char* str0 = str; + va_start(ap, fmt); + + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + *str = 0; + + va_end(ap); + return str - str0; +} diff --git a/raven_spn/toolchain-rv32.cmake b/raven_spn/toolchain-rv32.cmake new file mode 100644 index 0000000..bd5ee3b --- /dev/null +++ b/raven_spn/toolchain-rv32.cmake @@ -0,0 +1,33 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR riscv) + +set(TOOLCHAIN_DIR /opt/riscv/tools) +set(ARCHITECTURE riscv64-unknown-elf) + +set(CMAKE_C_COMPILER ${ARCHITECTURE}-gcc +set(CMAKE_CXX_COMPILER ${ARCHITECTURE}-g++ +set(RISCV_LINUX_SYSROOT /opt/riscv/tools CACHE PATH "RISC-V cross compilation system root") # search path for the cross compile toolchain + +set(CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags") +set(CMAKE_C_FLAGS "" CACHE STRING "c flags") +set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags") +set(CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags") +set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "executable linker flags") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv32imac -mabi=ilp32") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv32imac -mabi=ilp32") +#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") +#set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -march=rv32imac -mabi=ilp32") + +set(COMPILER_IS_RV32 "1") #flags for the CMakeList.txt +#add_definitions(-D_ARM_TEGRA3) # C/C++ preprocessor macro, which will be used in many many files + +set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR}/${ARCHITECTURE}) + +include_directories(${TOOLCHAIN_DIR}/${ARCHITECTURE}/include) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) \ No newline at end of file diff --git a/riscv-bldc-forced-commutation/.project b/riscv-bldc-forced-commutation/.project new file mode 100644 index 0000000..fe384e6 --- /dev/null +++ b/riscv-bldc-forced-commutation/.project @@ -0,0 +1,28 @@ + + + bldc-forced-commutation + + + bsp + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + +