├── sw ├── .gitignore ├── sys-read │ ├── test-ignore │ ├── Makefile │ └── main.c ├── basic-debug │ ├── test-ignore │ ├── bootstrap.S │ ├── Makefile │ ├── main.c │ ├── remote-debug-readme.txt │ └── eclipse-remote-debug-readme.txt ├── basic-gcov │ ├── test-ignore │ ├── main.c │ └── Makefile ├── flashTest │ ├── test-ignore │ ├── Makefile │ └── main.cpp ├── simple-display │ ├── test-ignore │ ├── Makefile │ ├── libDisplay.hpp │ └── libDisplay.cpp ├── peripheral-in-the-loop │ ├── irq.c │ ├── irq.h │ ├── bootstrap.S │ ├── Makefile │ └── main.c ├── basic-gpio │ ├── gpio.h │ ├── uart.h │ ├── util.h │ ├── Makefile │ ├── link.ld │ ├── main.c │ ├── uart.c │ ├── bootstrap.S │ ├── util.c │ └── platform.h ├── basic-c │ ├── sum.c │ ├── Makefile │ ├── bootstrap.S │ └── main.c ├── simple-scheduler │ ├── Makefile │ ├── no-clib │ │ ├── Makefile │ │ ├── bootstrap.S │ │ └── cor.S │ └── cor.S ├── crc8 │ ├── uart.h │ ├── util.h │ ├── Makefile │ ├── link.ld │ ├── platform.h │ ├── uart.c │ ├── bootstrap.S │ ├── util.c │ └── main.c ├── mramTest │ ├── Makefile │ └── main.cpp ├── mrv32-uart │ ├── uart.h │ ├── util.h │ ├── Makefile │ ├── link.ld │ ├── uart.c │ ├── main.c │ ├── bootstrap.S │ ├── util.c │ └── platform.h ├── c++-lib │ ├── Makefile │ └── main.cpp ├── basic-dma │ ├── Makefile │ ├── irq.h │ ├── main.c │ └── bootstrap.S ├── clock-ticks │ ├── Makefile │ ├── irq.h │ ├── main.c │ └── bootstrap.S ├── simple-sensor │ ├── Makefile │ ├── irq.h │ └── main.c ├── basic-multicore │ ├── main.c │ ├── Makefile │ └── bootstrap.S ├── Makefile ├── printf │ ├── Makefile │ ├── entry.S │ └── main.c ├── basic-asm │ ├── Makefile │ └── sum.S ├── busy-wait-sleep │ ├── Makefile │ ├── bootstrap.S │ └── main.c ├── blocking-sleep │ ├── Makefile │ ├── bootstrap.S │ ├── main.c │ └── irq.S ├── basic-e │ ├── Makefile │ └── sum.S ├── test.sh ├── README.md └── Makefile.common ├── vp ├── .gitignore ├── src │ ├── util │ │ ├── gtkwave_riscv-filter │ │ │ ├── .gitignore │ │ │ └── CMakeLists.txt │ │ ├── elegantEnums.cpp │ │ ├── options.h │ │ ├── common.h │ │ └── gtkwave_riscv-filter.py │ ├── platform │ │ ├── common │ │ │ ├── fe310_plic.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── slip.h │ │ │ ├── terminal.h │ │ │ ├── fd_abstract_uart.h │ │ │ ├── uart.h │ │ │ ├── options.h │ │ │ ├── async_event.h │ │ │ └── uart.cpp │ │ ├── hifive │ │ │ ├── can │ │ │ │ ├── slcan_remove.sh │ │ │ │ ├── slcan_add.sh │ │ │ │ ├── 90-slcan.rules │ │ │ │ ├── CAN-Howto.md │ │ │ │ └── cantest.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── otp.h │ │ │ ├── tunnel-uart.hpp │ │ │ ├── oled │ │ │ │ ├── oled.hpp │ │ │ │ ├── common.cpp │ │ │ │ └── common.hpp │ │ │ ├── prci.h │ │ │ ├── tunnel-uart.cpp │ │ │ ├── maskROM.h │ │ │ └── can.h │ │ ├── CMakeLists.txt │ │ ├── linux │ │ │ ├── CMakeLists.txt │ │ │ └── prci.h │ │ ├── test32 │ │ │ ├── CMakeLists.txt │ │ │ └── htif.h │ │ ├── tiny64 │ │ │ └── CMakeLists.txt │ │ ├── linux32 │ │ │ ├── CMakeLists.txt │ │ │ └── prci.h │ │ ├── microrv32 │ │ │ ├── CMakeLists.txt │ │ │ ├── microrv32_led.h │ │ │ └── microrv32_gpio.h │ │ ├── tiny32-mc │ │ │ └── CMakeLists.txt │ │ ├── tiny32 │ │ │ └── CMakeLists.txt │ │ ├── tiny64-mc │ │ │ └── CMakeLists.txt │ │ ├── hwitl │ │ │ ├── CMakeLists.txt │ │ │ └── virtual_bus_tlm_connector.hpp │ │ └── basic │ │ │ ├── CMakeLists.txt │ │ │ ├── basic_timer.h │ │ │ ├── random_source.h │ │ │ └── display.hpp │ ├── core │ │ ├── CMakeLists.txt │ │ ├── common │ │ │ ├── rawmode.h │ │ │ ├── clint_if.h │ │ │ ├── gdb-mc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── register_format.h │ │ │ │ ├── gdb_runner.h │ │ │ │ ├── libgdb │ │ │ │ │ ├── CMakeLists.txt │ │ │ │ │ ├── internal.h │ │ │ │ │ ├── include │ │ │ │ │ │ └── libgdb │ │ │ │ │ │ │ ├── response.h │ │ │ │ │ │ │ ├── parser1.h │ │ │ │ │ │ │ └── parser2.h │ │ │ │ │ ├── response.c │ │ │ │ │ └── README.md │ │ │ │ ├── register_format.cpp │ │ │ │ └── gdb_runner.cpp │ │ │ ├── load_if.h │ │ │ ├── CMakeLists.txt │ │ │ ├── core_defs.h │ │ │ ├── bus_lock_if.h │ │ │ ├── mmu_mem_if.h │ │ │ ├── debug_memory.h │ │ │ ├── timer.h │ │ │ ├── debug.h │ │ │ ├── irq_if.h │ │ │ ├── trap.h │ │ │ ├── dmi.h │ │ │ └── real_clint.h │ │ ├── rv32 │ │ │ ├── mmu.h │ │ │ ├── CMakeLists.txt │ │ │ ├── syscall_if.h │ │ │ ├── mem_if.h │ │ │ ├── timing │ │ │ │ ├── timing_simple.h │ │ │ │ └── timing_external.h │ │ │ └── elf_loader.h │ │ └── rv64 │ │ │ ├── mmu.h │ │ │ ├── CMakeLists.txt │ │ │ ├── syscall_if.h │ │ │ └── mem_if.h │ ├── CMakeLists.txt │ └── vendor │ │ ├── softfloat │ │ ├── include │ │ │ └── softfloat │ │ │ │ └── softfloat.hpp │ │ ├── s_commonNaNToF16UI.c │ │ ├── s_commonNaNToF32UI.c │ │ ├── s_commonNaNToF64UI.c │ │ ├── s_f128UIToCommonNaN.c │ │ ├── s_f16UIToCommonNaN.c │ │ ├── s_f32UIToCommonNaN.c │ │ ├── s_f64UIToCommonNaN.c │ │ ├── f32_classify.c │ │ ├── f64_classify.c │ │ ├── f128_classify.c │ │ ├── s_eq128.c │ │ ├── s_le128.c │ │ ├── s_lt128.c │ │ ├── f32_isSignalingNaN.c │ │ ├── f64_isSignalingNaN.c │ │ ├── f16_isSignalingNaN.c │ │ ├── s_shortShiftRightJam64.c │ │ ├── f128_isSignalingNaN.c │ │ ├── s_shiftRightJam32.c │ │ ├── s_shiftRightJam64.c │ │ ├── s_add128.c │ │ └── s_sub128.c │ │ └── CMakeLists.txt ├── cmake │ └── AddGitSubmodule.cmake └── CMakeLists.txt ├── img ├── riscv-vp_logo.pdf ├── riscv-vp_logo.png └── riscv-vp_logo.svg ├── env └── basic │ └── vp-display │ ├── VP-Display-layout.svg.png │ ├── main.cpp │ ├── vpdisplayserver.h │ ├── mainwindow.h │ ├── mainwindow.ui │ ├── CMakeLists.txt │ ├── VP-Display.pro │ ├── vpdisplayserver.cpp │ ├── mainwindow.cpp │ └── framebuffer.h ├── .clang-format ├── .gitignore ├── .gitmodules ├── Dockerfile ├── .gitlab-ci.yml ├── LICENSE ├── Makefile └── CITATION.cff /sw/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | -------------------------------------------------------------------------------- /sw/sys-read/test-ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vp/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /sw/basic-debug/test-ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sw/basic-gcov/test-ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sw/flashTest/test-ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sw/simple-display/test-ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sw/peripheral-in-the-loop/irq.c: -------------------------------------------------------------------------------- 1 | ../simple-sensor/irq.c -------------------------------------------------------------------------------- /sw/peripheral-in-the-loop/irq.h: -------------------------------------------------------------------------------- 1 | ../simple-sensor/irq.h -------------------------------------------------------------------------------- /vp/src/util/gtkwave_riscv-filter/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /sw/peripheral-in-the-loop/bootstrap.S: -------------------------------------------------------------------------------- 1 | ../simple-sensor/bootstrap.S -------------------------------------------------------------------------------- /vp/src/platform/common/fe310_plic.cpp: -------------------------------------------------------------------------------- 1 | #include "fe310_plic.h" 2 | -------------------------------------------------------------------------------- /vp/src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | subdirs(common) 2 | subdirs(rv32) 3 | subdirs(rv64) 4 | -------------------------------------------------------------------------------- /sw/basic-gpio/gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef GPIO_H 2 | #define GPIO_H 3 | 4 | 5 | #endif /* GPIO_H */ -------------------------------------------------------------------------------- /img/riscv-vp_logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agra-uni-bremen/riscv-vp/HEAD/img/riscv-vp_logo.pdf -------------------------------------------------------------------------------- /img/riscv-vp_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agra-uni-bremen/riscv-vp/HEAD/img/riscv-vp_logo.png -------------------------------------------------------------------------------- /vp/src/platform/hifive/can/slcan_remove.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Remove the USBCAN device 3 | pkill slcand 4 | -------------------------------------------------------------------------------- /vp/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(.) 2 | 3 | subdirs(vendor) 4 | subdirs(core) 5 | subdirs(platform) 6 | -------------------------------------------------------------------------------- /sw/sys-read/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o 2 | CFLAGS = -march=rv32ima -mabi=ilp32 3 | 4 | include ../Makefile.common 5 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/include/softfloat/softfloat.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | extern "C" { 3 | #include "softfloat.h" 4 | } 5 | -------------------------------------------------------------------------------- /sw/basic-c/sum.c: -------------------------------------------------------------------------------- 1 | int sum(int end) { 2 | int ans = end; 3 | for (int i=1; i 4 | 5 | int sendString(char* str, long len); 6 | void putChr(char chr); 7 | 8 | #endif /* UART_H */ -------------------------------------------------------------------------------- /sw/flashTest/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o 2 | CXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32 3 | 4 | include ../Makefile.common 5 | override LD = $(CXX) 6 | -------------------------------------------------------------------------------- /sw/mramTest/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o 2 | CXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32 3 | 4 | include ../Makefile.common 5 | override LD = $(CXX) 6 | -------------------------------------------------------------------------------- /sw/basic-gpio/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef UART_H 2 | 3 | #include 4 | 5 | int sendString(char* str, long len); 6 | void putChr(char chr); 7 | 8 | #endif /* UART_H */ -------------------------------------------------------------------------------- /sw/mrv32-uart/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef UART_H 2 | 3 | #include 4 | 5 | int sendString(char* str, long len); 6 | void putChr(char chr); 7 | 8 | #endif /* UART_H */ -------------------------------------------------------------------------------- /vp/src/platform/hifive/can/slcan_add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Bind the USBCAN device 3 | slcand -o -c -f -s6 /dev/ttyUSB_CAN slcan0 4 | sleep 1 5 | ifconfig slcan0 up 6 | -------------------------------------------------------------------------------- /vp/src/core/common/rawmode.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_RAWMODE_H 2 | #define RISCV_VP_RAWMODE_H 3 | 4 | void enableRawMode(int); 5 | void disableRawMode(int); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /sw/c++-lib/Makefile: -------------------------------------------------------------------------------- 1 | LD = $(CXX) 2 | OBJECTS = main.o 3 | CXXFLAGS = -std=c++14 -march=rv32imac -mabi=ilp32 4 | 5 | include ../Makefile.common 6 | override LD = $(CXX) 7 | -------------------------------------------------------------------------------- /sw/basic-c/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o sum.o bootstrap.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | include ../Makefile.common 6 | -------------------------------------------------------------------------------- /sw/basic-dma/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o irq.o bootstrap.o 2 | CFLAGS = -march=rv32imac -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | include ../Makefile.common 6 | -------------------------------------------------------------------------------- /sw/clock-ticks/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o irq.o bootstrap.o 2 | CFLAGS = -march=rv32imac -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | include ../Makefile.common 6 | -------------------------------------------------------------------------------- /sw/simple-sensor/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o irq.o bootstrap.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | include ../Makefile.common 6 | -------------------------------------------------------------------------------- /vp/src/core/common/clint_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct clint_if { 6 | virtual ~clint_if() {} 7 | 8 | virtual uint64_t update_and_get_mtime() = 0; 9 | }; -------------------------------------------------------------------------------- /sw/basic-multicore/main.c: -------------------------------------------------------------------------------- 1 | int main(unsigned hart_id) { 2 | // behave differently based on the core (i.e. hart) id 3 | for (unsigned i=0; i<100*hart_id; ++i) 4 | ; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /sw/crc8/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | 3 | void swap(char *x, char *y); 4 | char* reverse(char *buffer, int i, int j); 5 | char* itoa(int value, char* buffer, int base); 6 | 7 | #endif /* UTIL_H */ -------------------------------------------------------------------------------- /sw/basic-c/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | _start: 5 | jal main 6 | 7 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 8 | li a7,93 9 | li a0,0 10 | ecall 11 | -------------------------------------------------------------------------------- /sw/basic-c/main.c: -------------------------------------------------------------------------------- 1 | int sum(int end); 2 | 3 | int x = 5; 4 | int y; 5 | 6 | int main() { 7 | int a = 6; 8 | int b = 7; 9 | a = a + b + x + y; 10 | a = sum(a); 11 | return a; 12 | } 13 | -------------------------------------------------------------------------------- /sw/basic-gpio/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | 3 | void swap(char *x, char *y); 4 | char* reverse(char *buffer, int i, int j); 5 | char* itoa(int value, char* buffer, int base); 6 | 7 | #endif /* UTIL_H */ -------------------------------------------------------------------------------- /sw/mrv32-uart/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | 3 | void swap(char *x, char *y); 4 | char* reverse(char *buffer, int i, int j); 5 | char* itoa(int value, char* buffer, int base); 6 | 7 | #endif /* UTIL_H */ -------------------------------------------------------------------------------- /vp/src/core/rv32/mmu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iss.h" 4 | #include "core/common/mmu.h" 5 | 6 | namespace rv32 { 7 | 8 | typedef GenericMMU MMU; 9 | 10 | } // namespace rv64 -------------------------------------------------------------------------------- /vp/src/core/rv64/mmu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iss.h" 4 | #include "core/common/mmu.h" 5 | 6 | namespace rv64 { 7 | 8 | typedef GenericMMU MMU; 9 | 10 | } // namespace rv64 -------------------------------------------------------------------------------- /sw/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && make" \; 3 | 4 | clean: 5 | find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && make clean" \; 6 | -------------------------------------------------------------------------------- /sw/printf/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o entry.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -Wl,-e_reset_vector 4 | VP_FLAGS = --error-on-zero-traphandler=true 5 | 6 | include ../Makefile.common 7 | -------------------------------------------------------------------------------- /sw/basic-asm/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = sum.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | VP_FLAGS = --error-on-zero-traphandler=true 5 | 6 | include ../Makefile.common 7 | -------------------------------------------------------------------------------- /sw/busy-wait-sleep/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o bootstrap.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | VP = tiny32-vp 6 | 7 | include ../Makefile.common 8 | -------------------------------------------------------------------------------- /sw/busy-wait-sleep/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | _start: 5 | jal main 6 | 7 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 8 | li a7,93 9 | li a0,0 10 | ecall 11 | -------------------------------------------------------------------------------- /sw/basic-debug/bootstrap.S: -------------------------------------------------------------------------------- 1 | .align 6 2 | .globl _start 3 | .globl main 4 | 5 | _start: 6 | jal main 7 | 8 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 9 | li a7,93 10 | li a0,0 11 | ecall 12 | -------------------------------------------------------------------------------- /sw/blocking-sleep/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o irq.o bootstrap.o 2 | CFLAGS = -march=rv32imac -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | VP = tiny32-vp 6 | 7 | include ../Makefile.common 8 | -------------------------------------------------------------------------------- /sw/basic-e/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = sum.o 2 | CFLAGS = -march=rv32e -mabi=ilp32e 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | VP_FLAGS = --use-E-base-isa --error-on-zero-traphandler=true 5 | 6 | include ../Makefile.common 7 | -------------------------------------------------------------------------------- /env/basic/vp-display/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mainwindow.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | QApplication a(argc, argv); 6 | VPDisplay w; 7 | w.show(); 8 | 9 | return a.exec(); 10 | } 11 | -------------------------------------------------------------------------------- /sw/simple-display/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o libDisplay.o 2 | CXXFLAGS = -std=c++14 -march=rv32ima -mabi=ilp32 3 | 4 | removeSHMEM: 5 | ipcrm --shmem-key 0x0000053a || true 6 | 7 | include ../Makefile.common 8 | override LD = $(CXX) 9 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(libgdb) 2 | 3 | add_library(gdb-mc 4 | gdb_server.cpp 5 | gdb_runner.cpp 6 | register_format.cpp 7 | handler.cpp) 8 | 9 | target_link_libraries(gdb-mc gdb core-common systemc) 10 | -------------------------------------------------------------------------------- /vp/src/platform/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources_list LIST_DIRECTORIES true *) 2 | foreach(dir ${sources_list}) 3 | IF(IS_DIRECTORY ${dir}) 4 | add_subdirectory(${dir}) 5 | ELSE() 6 | CONTINUE() 7 | ENDIF() 8 | endforeach() -------------------------------------------------------------------------------- /sw/basic-multicore/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o bootstrap.o 2 | CFLAGS = -march=rv32ima -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | VP = tiny32-mc 6 | VP_FLAGS = --error-on-zero-traphandler=true 7 | 8 | include ../Makefile.common 9 | -------------------------------------------------------------------------------- /sw/basic-debug/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o bootstrap.o 2 | CFLAGS = -g3 -march=rv32im -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | VP_FLAGS = --intercept-syscalls --error-on-zero-traphandler=true --debug-mode 5 | 6 | include ../Makefile.common 7 | -------------------------------------------------------------------------------- /sw/blocking-sleep/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl register_handler 3 | .globl main 4 | 5 | _start: 6 | call register_handler 7 | jal main 8 | 9 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 10 | li a7,93 11 | li a0,0 12 | ecall 13 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_commonNaNToF16UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_commonNaNToF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_commonNaNToF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_f128UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_f16UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_f32UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_f64UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*---------------------------------------------------------------------------- 3 | | This file intentionally contains no code. 4 | *----------------------------------------------------------------------------*/ 5 | 6 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | ColumnLimit: '120' 4 | AllowShortCaseLabelsOnASingleLine: 'false' 5 | AllowShortFunctionsOnASingleLine: Empty 6 | AllowShortIfStatementsOnASingleLine: 'false' 7 | IndentWidth: '4' 8 | TabWidth: '4' 9 | UseTab: ForIndentation 10 | ... 11 | -------------------------------------------------------------------------------- /sw/crc8/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o uart.o bootstrap.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax -T link.ld 4 | 5 | VP = microrv32-vp 6 | VP_FLAGS = 7 | 8 | hex: all 9 | ../elf2bin.py ./main crc.hex 0x4020 10 | 11 | include ../Makefile.common 12 | -------------------------------------------------------------------------------- /sw/basic-gpio/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = bootstrap.o main.o uart.o 2 | CFLAGS = -g3 -march=rv32i -mabi=ilp32 3 | LDLIBS = -Tlink.ld -nostartfiles -Wl,--no-relax 4 | 5 | VP = microrv32-vp 6 | VP_FLAGS = 7 | 8 | hex: $(EXECUTABLE) 9 | ../elf2bin.py ./main gpio.hex 0x4020 10 | 11 | include ../Makefile.common 12 | -------------------------------------------------------------------------------- /sw/mrv32-uart/Makefile: -------------------------------------------------------------------------------- 1 | rvArch?=rv32i 2 | 3 | OBJECTS = bootstrap.o main.o uart.o util.o 4 | CFLAGS = -march=$(rvArch) -mabi=ilp32 -mno-strict-align 5 | LDFLAGS = -nostartfiles -Wl,--no-relax,--print-memory-usage -T link.ld 6 | 7 | VP = microrv32-vp 8 | VP_FLAGS = 9 | 10 | include ../Makefile.common 11 | -------------------------------------------------------------------------------- /sw/basic-debug/main.c: -------------------------------------------------------------------------------- 1 | int x = 5; 2 | int y; 3 | 4 | int f(int a, int b) { 5 | if (a > 0) { 6 | int ans = a + b; 7 | return ans; 8 | } 9 | a = -a; 10 | return b + a; 11 | } 12 | 13 | int main() { 14 | int a = 5; 15 | int b = 3; 16 | b--; 17 | a = a / b; 18 | a = a * 2; 19 | a = f(x, y); 20 | return a; 21 | } 22 | -------------------------------------------------------------------------------- /sw/printf/entry.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl _reset_vector 3 | .equ SYSCALL_ADDR, 0x02010000 4 | 5 | trap_handler: 6 | li t0, SYSCALL_ADDR 7 | csrr t1, mhartid 8 | sw t1, 0(t0) 9 | csrr t0, mepc 10 | addi t0, t0, 4 11 | csrw mepc, t0 12 | mret 13 | 14 | _reset_vector: 15 | la t0, trap_handler 16 | csrw mtvec, t0 17 | j _start 18 | -------------------------------------------------------------------------------- /vp/src/core/common/load_if.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_LOAD_IF_H 2 | #define RISCV_VP_LOAD_IF_H 3 | 4 | #include 5 | #include 6 | 7 | class load_if { 8 | public: 9 | virtual void load_data(const char *src, uint64_t dst_addr, size_t n) = 0; 10 | virtual void load_zero(uint64_t dst_addr, size_t n) = 0; 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /vp/src/platform/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(linux-vp 4 | linux_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(linux-vp rv64 platform-common gdb-mc 8 | ${Boost_LIBRARIES} systemc pthread) 9 | 10 | INSTALL(TARGETS linux-vp RUNTIME DESTINATION bin) 11 | -------------------------------------------------------------------------------- /vp/src/platform/test32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(test32-vp 4 | test32_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(test32-vp rv32 platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 8 | 9 | INSTALL(TARGETS test32-vp RUNTIME DESTINATION bin) 10 | -------------------------------------------------------------------------------- /vp/src/platform/tiny64/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(tiny64-vp 4 | tiny64_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(tiny64-vp rv64 platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 8 | 9 | INSTALL(TARGETS tiny64-vp RUNTIME DESTINATION bin) 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | .settings/ 4 | main 5 | build/ 6 | vp/dependencies/systemc-dist/ 7 | *.bin 8 | systemc-* 9 | *.asm 10 | **/nbproject/private/ 11 | **/nbproject/Makefile-*.mk 12 | **/nbproject/Package-*.bash 13 | build/ 14 | nbbuild/ 15 | dist/ 16 | nbdist/ 17 | .nb-gradle/ 18 | nbproject/ 19 | sw/basic-gcov/main.* 20 | sw/**/*.o 21 | -------------------------------------------------------------------------------- /sw/basic-gcov/main.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int main() { 4 | int i = 0; 5 | 6 | while (i < 10) { 7 | if (i < 5) { 8 | printf("i < 5\n"); 9 | } 10 | 11 | if (i % 2 == 0) { 12 | printf("i mod 2 == 0\n"); 13 | } 14 | 15 | if (i == 10) { 16 | printf("i == 10\n"); 17 | } 18 | 19 | ++i; 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/can/90-slcan.rules: -------------------------------------------------------------------------------- 1 | # Lawicel CANUSB module 2 | 3 | SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{product}=="CANUSB", SYMLINK+="ttyUSB_CAN" 4 | ACTION=="add", ATTRS{product}=="CANUSB", RUN+="/usr/local/bin/slcan_add.sh" 5 | ACTION=="remove", ATTRS{product}=="CANUSB", RUN+="/usr/local/bin/slcan_remove.sh" 6 | -------------------------------------------------------------------------------- /vp/src/platform/linux32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(linux32-vp 4 | linux32_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(linux32-vp rv32 platform-common gdb-mc 8 | ${Boost_LIBRARIES} systemc pthread) 9 | 10 | INSTALL(TARGETS linux32-vp RUNTIME DESTINATION bin) 11 | -------------------------------------------------------------------------------- /vp/src/platform/microrv32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(microrv32-vp 4 | ${HEADERS} 5 | main.cpp) 6 | 7 | target_link_libraries(microrv32-vp rv32 platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 8 | 9 | INSTALL(TARGETS microrv32-vp RUNTIME DESTINATION bin) 10 | -------------------------------------------------------------------------------- /vp/src/platform/tiny32-mc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(tiny32-mc 4 | mc_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(tiny32-mc rv32 platform-common gdb-mc 8 | ${Boost_LIBRARIES} systemc pthread) 9 | 10 | INSTALL(TARGETS tiny32-mc RUNTIME DESTINATION bin) 11 | -------------------------------------------------------------------------------- /vp/src/platform/tiny32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(tiny32-vp 4 | tiny32_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(tiny32-vp rv32 platform-common gdb-mc 8 | ${Boost_LIBRARIES} systemc pthread) 9 | 10 | INSTALL(TARGETS tiny32-vp RUNTIME DESTINATION bin) 11 | -------------------------------------------------------------------------------- /vp/src/platform/tiny64-mc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_executable(tiny64-mc 4 | mc_main.cpp 5 | ${HEADERS}) 6 | 7 | target_link_libraries(tiny64-mc rv64 platform-common gdb-mc 8 | ${Boost_LIBRARIES} systemc pthread) 9 | 10 | INSTALL(TARGETS tiny64-mc RUNTIME DESTINATION bin) 11 | -------------------------------------------------------------------------------- /sw/crc8/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .bss : { *(.bss) } 15 | _end = .; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /sw/basic-gpio/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .bss : { *(.bss) } 15 | _end = .; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /sw/simple-scheduler/no-clib/Makefile: -------------------------------------------------------------------------------- 1 | all : main.c 2 | riscv32-unknown-elf-gcc main.c cor.S bootstrap.S -o main -march=rv32ima -mabi=ilp32 -nostartfiles 3 | 4 | sim: all 5 | riscv-vp --intercept-syscalls main 6 | 7 | dump-elf: all 8 | riscv32-unknown-elf-readelf -a main 9 | 10 | dump-code: all 11 | riscv32-unknown-elf-objdump -D main 12 | 13 | clean: 14 | rm -f main 15 | -------------------------------------------------------------------------------- /sw/sys-read/main.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int main(int argc, char **argv) { 4 | printf("Enter a number: "); 5 | 6 | int c,n = 0; 7 | while (!scanf("%d", &n)) { 8 | printf("Error: unable to parse number\n"); 9 | while((c = getchar()) != '\n' && c != EOF); 10 | printf("Enter a number: "); 11 | } 12 | 13 | printf("Success, you entered %i\n", n); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /sw/basic-dma/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef __RISCV_IRQ_H__ 2 | #define __RISCV_IRQ_H__ 3 | 4 | #include "stdint.h" 5 | 6 | typedef void (*irq_handler_t)(void); 7 | 8 | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn); 9 | 10 | void register_timer_interrupt_handler(irq_handler_t fn); 11 | 12 | extern volatile uint64_t* mtime; 13 | extern volatile uint64_t* mtimecmp; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /sw/clock-ticks/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef __RISCV_IRQ_H__ 2 | #define __RISCV_IRQ_H__ 3 | 4 | #include "stdint.h" 5 | 6 | typedef void (*irq_handler_t)(void); 7 | 8 | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn); 9 | 10 | void register_timer_interrupt_handler(irq_handler_t fn); 11 | 12 | extern volatile uint64_t* mtime; 13 | extern volatile uint64_t* mtimecmp; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /sw/simple-sensor/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef __RISCV_IRQ_H__ 2 | #define __RISCV_IRQ_H__ 3 | 4 | #include "stdint.h" 5 | 6 | typedef void (*irq_handler_t)(void); 7 | 8 | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn); 9 | 10 | void register_timer_interrupt_handler(irq_handler_t fn); 11 | 12 | extern volatile uint64_t* mtime; 13 | extern volatile uint64_t* mtimecmp; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /vp/src/platform/hwitl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h*) 2 | file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c*) 3 | 4 | add_git_submodule(virtual-bus) 5 | 6 | add_executable(hwitl-vp 7 | ${SOURCES} 8 | ) 9 | 10 | target_link_libraries(hwitl-vp rv32 virtual-bus platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 11 | 12 | INSTALL(TARGETS hwitl-vp RUNTIME DESTINATION bin) -------------------------------------------------------------------------------- /sw/simple-scheduler/no-clib/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | 5 | _start: 6 | 7 | # Initialize global pointer 8 | .option push 9 | .option norelax 10 | 1:auipc gp, %pcrel_hi(__global_pointer$) 11 | addi gp, gp, %pcrel_lo(1b) 12 | .option pop 13 | 14 | li sp, 8000000 15 | 16 | jal main 17 | 18 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 19 | li a7,93 20 | li a0,0 21 | ecall 22 | -------------------------------------------------------------------------------- /vp/src/core/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_library(core-common 4 | timer.cpp 5 | real_clint.cpp 6 | instr.cpp 7 | debug_memory.cpp 8 | rawmode.cpp 9 | ${HEADERS}) 10 | 11 | target_include_directories(core-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 12 | target_link_libraries(core-common PRIVATE pthread systemc) 13 | 14 | add_subdirectory(gdb-mc) 15 | -------------------------------------------------------------------------------- /vp/src/platform/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_library(platform-common 4 | fe310_plic.cpp 5 | fu540_plic.cpp 6 | uart_if.cpp 7 | fd_abstract_uart.cpp 8 | slip.cpp 9 | uart.cpp 10 | options.cpp 11 | ${HEADERS}) 12 | 13 | target_include_directories(platform-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 14 | target_link_libraries(platform-common systemc) 15 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/register_format.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_GDB_REGISTER 2 | #define RISCV_GDB_REGISTER 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "core_defs.h" 9 | 10 | class RegisterFormater { 11 | private: 12 | Architecture arch; 13 | std::ostringstream stream; 14 | 15 | public: 16 | RegisterFormater(Architecture); 17 | void formatRegister(uint64_t); 18 | std::string str(void); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /sw/mrv32-uart/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(_start) 3 | 4 | MEMORY { 5 | RAM (rwx): ORIGIN = 0x80000000, LENGTH = 8k 6 | } 7 | 8 | SECTIONS 9 | { 10 | . = 0x80000000; 11 | .text.init : { *(.text.init) } > RAM 12 | . = ALIGN(0x1000); 13 | .tohost : { *(.tohost) } > RAM 14 | . = ALIGN(0x1000); 15 | .text : { *(.text) } > RAM 16 | . = ALIGN(0x1000); 17 | .data : { *(.data) } > RAM 18 | .bss : { *(.bss) } > RAM 19 | _end = .; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /vp/src/util/gtkwave_riscv-filter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | project(GTKWAVE_RISCV_INSTR_FILTER CXX) 3 | 4 | SET(INSTR ${CMAKE_CURRENT_SOURCE_DIR}/../../core/common) 5 | 6 | add_executable(gtkwave_riscv-filter 7 | riscv-filter.cpp 8 | ${INSTR}/instr.cpp 9 | ) 10 | target_include_directories(gtkwave_riscv-filter PRIVATE 11 | ${INSTR} 12 | ${CMAKE_CURRENT_SOURCE_DIR}/../.. 13 | ) 14 | target_compile_features(gtkwave_riscv-filter PRIVATE cxx_std_20) -------------------------------------------------------------------------------- /vp/src/core/common/core_defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum Architecture { 4 | RV32 = 1, 5 | RV64 = 2, 6 | RV128 = 3, 7 | }; 8 | 9 | enum class CoreExecStatus { 10 | Runnable, 11 | HitBreakpoint, 12 | Terminated, 13 | }; 14 | 15 | constexpr unsigned SATP_MODE_BARE = 0; 16 | constexpr unsigned SATP_MODE_SV32 = 1; 17 | constexpr unsigned SATP_MODE_SV39 = 8; 18 | constexpr unsigned SATP_MODE_SV48 = 9; 19 | constexpr unsigned SATP_MODE_SV57 = 10; 20 | constexpr unsigned SATP_MODE_SV64 = 11; -------------------------------------------------------------------------------- /vp/src/util/elegantEnums.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * elegantEnums.hpp 3 | * 4 | * Created on: 14 Mar 2019 5 | * Author: dwd 6 | */ 7 | 8 | #include "elegantEnums.hpp" 9 | 10 | std::vector splitString(std::string str, char sep) { 11 | std::vector vecString; 12 | std::string item; 13 | 14 | std::stringstream stringStream(str); 15 | 16 | while (std::getline(stringStream, item, sep)) { 17 | vecString.push_back(item); 18 | } 19 | 20 | return vecString; 21 | } 22 | -------------------------------------------------------------------------------- /sw/basic-e/sum.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .equ SYSCALL_ADDR, 0x02010000 3 | 4 | .macro SYS_EXIT, exit_code 5 | li a5, 93 6 | li a0, \exit_code 7 | li t0, SYSCALL_ADDR 8 | csrr t1, mhartid 9 | sw t1, 0(t0) 10 | .endm 11 | 12 | 13 | # program entry-point 14 | _start: 15 | 16 | li a0,50 17 | li a1,100 18 | 19 | li a2,0 20 | loop: 21 | bgt a0,a1,end 22 | add a2,a2,a0 23 | addi a0,a0,1 24 | j loop 25 | end: 26 | 27 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 28 | SYS_EXIT 0 29 | -------------------------------------------------------------------------------- /sw/basic-asm/sum.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .equ SYSCALL_ADDR, 0x02010000 3 | 4 | .macro SYS_EXIT, exit_code 5 | li a7, 93 6 | li a0, \exit_code 7 | li t0, SYSCALL_ADDR 8 | csrr a6, mhartid 9 | sw a6, 0(t0) 10 | .endm 11 | 12 | 13 | # program entry-point 14 | _start: 15 | 16 | li a0,50 17 | li a1,100 18 | 19 | li a2,0 20 | loop: 21 | bgt a0,a1,end 22 | add a2,a2,a0 23 | addi a0,a0,1 24 | j loop 25 | end: 26 | 27 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 28 | SYS_EXIT 0 29 | -------------------------------------------------------------------------------- /env/basic/vp-display/vpdisplayserver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "framebuffer.h" 6 | 7 | class VPDisplayserver { 8 | unsigned int mSharedMemoryKey; 9 | Framebuffer* framebuffer; 10 | std::atomic stop; 11 | std::thread active_watch; 12 | 13 | public: 14 | VPDisplayserver(unsigned int sharedMemoryKey = 1338); 15 | ~VPDisplayserver(); 16 | Framebuffer* createSM(); 17 | void startListening(std::function notifyChange); 18 | }; 19 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(hifive-vp 2 | hifive_main.cpp 3 | can.cpp 4 | oled/common.cpp 5 | oled/oled.cpp 6 | gpio.cpp 7 | tunnel-uart.cpp 8 | ../../util/elegantEnums.cpp #sorry :( 9 | ${HEADERS}) 10 | 11 | add_git_submodule(vbb-protocol) 12 | 13 | target_link_libraries(hifive-vp virtual-breadboard-server rv32 platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 14 | 15 | INSTALL(TARGETS hifive-vp RUNTIME DESTINATION bin) 16 | -------------------------------------------------------------------------------- /vp/src/core/common/bus_lock_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct bus_lock_if { 4 | virtual ~bus_lock_if() {} 5 | 6 | virtual void lock(unsigned hart_id) = 0; 7 | 8 | virtual void unlock(unsigned hart_id) = 0; 9 | 10 | virtual bool is_locked() = 0; // by any hart 11 | 12 | virtual bool is_locked(unsigned hart_id) = 0; 13 | 14 | virtual void wait_until_unlocked() = 0; 15 | 16 | inline void wait_for_access_rights(unsigned hart_id) { 17 | if (is_locked() && !is_locked(hart_id)) 18 | wait_until_unlocked(); 19 | } 20 | }; -------------------------------------------------------------------------------- /sw/printf/main.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "errno.h" 3 | #include "string.h" 4 | #include "unistd.h" 5 | 6 | int main(int argc, char **argv) { 7 | int n = printf("ABCDEFX %s\n", "Done"); 8 | int e = errno; 9 | puts(strerror(e)); 10 | 11 | puts ("Hello World!"); 12 | puts (" Hello World!"); 13 | puts (" X A "); 14 | putchar('a'); 15 | putchar('b'); 16 | putchar('c'); 17 | putchar('\n'); 18 | printf(" X Test\n"); 19 | printf("%d\n", 12); 20 | 21 | printf("Should print 1.2: %f\n", 1.2f); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/gdb_runner.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_GDB_RUNNER 2 | #define RISCV_GDB_RUNNER 3 | 4 | #include 5 | 6 | #include "debug.h" 7 | #include "gdb_server.h" 8 | 9 | SC_MODULE(GDBServerRunner) { 10 | public: 11 | SC_HAS_PROCESS(GDBServerRunner); 12 | 13 | GDBServerRunner(sc_core::sc_module_name, GDBServer *, debug_target_if *); 14 | private: 15 | GDBServer *server; 16 | debug_target_if *hart; 17 | sc_core::sc_event run_event; 18 | sc_core::sc_event *stop_event; 19 | 20 | void run(void); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /vp/src/platform/basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_library(platform-basic 4 | ethernet.cpp 5 | display.cpp 6 | ${HEADERS}) 7 | 8 | target_include_directories(platform-basic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 9 | target_link_libraries(platform-basic systemc) 10 | 11 | add_executable(riscv-vp 12 | main.cpp) 13 | 14 | target_link_libraries(riscv-vp rv32 platform-basic platform-common gdb-mc ${Boost_LIBRARIES} systemc pthread) 15 | 16 | INSTALL(TARGETS riscv-vp RUNTIME DESTINATION bin) 17 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/otp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "irq_if.h" 8 | #include "tlm_map.h" 9 | 10 | struct OTP : public sc_core::sc_module { 11 | tlm_utils::simple_target_socket tsock; 12 | 13 | OTP(sc_core::sc_module_name) { 14 | tsock.register_b_transport(this, &OTP::transport); 15 | } 16 | 17 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 18 | assert(false && "OTP not yet implemented"); 19 | return; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(gdb 2 | mpc/mpc.c 3 | parser1.c 4 | parser2.c 5 | response.c 6 | util.c) 7 | 8 | target_compile_options(gdb PRIVATE 9 | -Wpedantic -Wall -Wextra -Wconversion -Wmissing-prototypes 10 | -Wpointer-arith -Wstrict-prototypes -Wshadow -Wcast-align) 11 | 12 | set_source_files_properties(mpc/mpc.c 13 | PROPERTIES COMPILE_FLAGS "-w -ansi") 14 | target_include_directories(gdb PRIVATE 15 | ${CMAKE_CURRENT_SOURCE_DIR}/mpc) 16 | target_include_directories(gdb PUBLIC 17 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 18 | -------------------------------------------------------------------------------- /vp/src/core/common/mmu_mem_if.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_MMU_MEM_IF_H 2 | #define RISCV_VP_MMU_MEM_IF_H 3 | 4 | #include 5 | 6 | enum MemoryAccessType { FETCH, LOAD, STORE }; 7 | 8 | struct mmu_memory_if { 9 | virtual ~mmu_memory_if() {} 10 | 11 | virtual uint64_t v2p(uint64_t vaddr, MemoryAccessType type) = 0; 12 | virtual uint64_t mmu_load_pte64(uint64_t addr) = 0; 13 | virtual uint64_t mmu_load_pte32(uint64_t addr) = 0; 14 | virtual void mmu_store_pte32(uint64_t addr, uint32_t value) = 0; 15 | }; 16 | 17 | #endif //RISCV_VP_MMU_MEM_IF_H 18 | -------------------------------------------------------------------------------- /env/basic/vp-display/mainwindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "vpdisplayserver.h" 5 | 6 | namespace Ui { 7 | class VPDisplay; 8 | } 9 | 10 | class VPDisplay : public QWidget { 11 | Q_OBJECT 12 | Framebuffer* framebuffer; 13 | QImage* frame; 14 | VPDisplayserver server; 15 | 16 | public: 17 | VPDisplay(QWidget* mparent = 0); 18 | ~VPDisplay(); 19 | void paintEvent(QPaintEvent*); 20 | // void keyPressEvent(QKeyEvent *e); 21 | void drawMainPage(QImage* mem); 22 | 23 | void notifyChange(bool success); 24 | }; 25 | -------------------------------------------------------------------------------- /sw/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export SYSTEMC_DISABLE_COPYRIGHT_MESSAGE=1 4 | 5 | handle_exit() { 6 | [ $# -eq 1 ] || exit 1 7 | 8 | if [ "${1}" -eq 0 ]; then 9 | printf "OK.\n" 10 | else 11 | printf "FAIL.\n" 12 | exit 1 13 | fi 14 | } 15 | 16 | for test in *; do 17 | [ -e "${test}/test-ignore" -o -f "${test}" ] && continue 18 | 19 | name=${test##*/} 20 | 21 | printf "Building sw '%s': " "${name}" 22 | make -C "${test}" >/dev/null 23 | handle_exit $? 24 | 25 | printf "Running sw '%s': " "${name}" 26 | make -C "${test}" sim >/dev/null 27 | handle_exit $? 28 | done 29 | -------------------------------------------------------------------------------- /sw/busy-wait-sleep/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x2004000; 4 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x200bff8; 5 | 6 | enum { 7 | SLEEP_TIME = 5, // In seconds 8 | US_PER_SEC = 1000000, 9 | }; 10 | 11 | /* This is used to quantize a 1MHz value to the closest 32768Hz value */ 12 | #define DIVIDEND ((uint64_t)15625/(uint64_t)512) 13 | 14 | int main() { 15 | uint64_t usec = SLEEP_TIME * US_PER_SEC; 16 | uint64_t ticks = usec / DIVIDEND; 17 | 18 | uint64_t target = *MTIME_REG + ticks; 19 | while (*MTIME_REG < target) 20 | ; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /vp/src/platform/common/slip.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_SLIP_H 2 | #define RISCV_VP_SLIP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class SLIP : public FD_ABSTRACT_UART { 9 | public: 10 | SLIP(const sc_core::sc_module_name &, uint32_t, std::string); 11 | ~SLIP(void); 12 | 13 | private: 14 | int get_mtu(const char *); 15 | void send_packet(void); 16 | void write_data(uint8_t) override; 17 | void handle_input(int fd) override; 18 | 19 | int tunfd; 20 | 21 | uint8_t *sndbuf = NULL, *rcvbuf = NULL; 22 | size_t sndsiz, rcvsiz; 23 | 24 | }; 25 | 26 | #endif // RISCV_VP_SLIP_H 27 | -------------------------------------------------------------------------------- /vp/src/core/rv32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_library(rv32 4 | iss.cpp 5 | syscall.cpp 6 | ${HEADERS}) 7 | 8 | target_link_libraries(rv32 systemc core-common softfloat) 9 | 10 | 11 | if(COLOR_THEME STREQUAL "LIGHT") 12 | message("> using color theme LIGHT") 13 | target_compile_definitions(rv32 PRIVATE COLOR_THEME_LIGHT) 14 | elseif(COLOR_THEME STREQUAL "DARK") 15 | message("> using color theme DARK") 16 | target_compile_definitions(rv32 PRIVATE COLOR_THEME_DARK) 17 | endif() 18 | 19 | 20 | target_include_directories(rv32 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 21 | -------------------------------------------------------------------------------- /vp/src/core/rv64/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 2 | 3 | add_library(rv64 4 | iss.cpp 5 | syscall.cpp 6 | ${HEADERS}) 7 | 8 | target_link_libraries(rv64 systemc core-common softfloat) 9 | 10 | 11 | if(COLOR_THEME STREQUAL "LIGHT") 12 | message("> using color theme LIGHT") 13 | target_compile_definitions(rv64 PRIVATE COLOR_THEME_LIGHT) 14 | elseif(COLOR_THEME STREQUAL "DARK") 15 | message("> using color theme DARK") 16 | target_compile_definitions(rv64 PRIVATE COLOR_THEME_DARK) 17 | endif() 18 | 19 | 20 | target_include_directories(rv64 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 21 | -------------------------------------------------------------------------------- /sw/basic-gcov/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o 2 | CFLAGS = --coverage -march=rv32ima -mabi=ilp32 3 | LDFLAGS = --coverage 4 | VP_FLAGS = --error-on-zero-traphandler=true 5 | 6 | CLEAN_EXTRA = main.c.gcov main.gcda main.gcno cov*.html 7 | 8 | main.gcda: main 9 | riscv-vp --intercept-syscalls --error-on-zero-traphandler=true main 10 | 11 | # use -b option to display branch coverage too 12 | dump-coverage: main.gcda 13 | $(RISCV_PREFIX)gcov main.c 14 | 15 | dump-html-coverage: main.gcda 16 | gcovr --gcov-executable $(RISCV_PREFIX)gcov -b -r . --html-details -o cov.html 17 | 18 | include ../Makefile.common 19 | .DEFAULT_GOAL := main.gcda 20 | -------------------------------------------------------------------------------- /sw/mrv32-uart/uart.c: -------------------------------------------------------------------------------- 1 | #include "uart.h" 2 | #include "platform.h" 3 | #include 4 | 5 | int sendString(char* str, long len) { 6 | long cnt = len; 7 | const char *s = (const char *)str; 8 | while (cnt > 0) { 9 | --cnt; 10 | putChr(*s); 11 | s++; 12 | } 13 | return len; 14 | } 15 | 16 | void putChr(char chr) { 17 | uint32_t tx_rdy = 0; 18 | UART->TXDATA = chr; 19 | // send character stored in uart_tx_addr 20 | UART->TXCTRL = 1; 21 | // wait until tx is ready again for sening another character 22 | do { 23 | // read uart tx status 24 | tx_rdy = UART->TXCTRL; 25 | asm volatile ("nop"); 26 | } while(!tx_rdy); 27 | return; 28 | } -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/internal.h: -------------------------------------------------------------------------------- 1 | #ifndef GDB_PROTOCOL_FNS 2 | #define GDB_PROTOCOL_FNS 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #ifdef NDEBUG 10 | #define xassert(X) ((void)(X)) /* prevent -Wunused-parameter warning */ 11 | #else 12 | #define xassert(X) (assert(X)) 13 | #endif 14 | 15 | void *xrealloc(void *, size_t); 16 | void *xmalloc(size_t); 17 | char *xstrdup(char *); 18 | 19 | gdb_command_t *gdb_new_cmd(char *, gdb_argument_t); 20 | 21 | int calc_csum(const char *); 22 | bool gdb_is_valid(gdb_packet_t *); 23 | char *gdb_unescape(char *); 24 | char *gdb_decode_runlen(char *); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/include/libgdb/response.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGDB_RESPONSE_H 2 | #define LIBGDB_RESPONSE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* Copied from QEMU 9 | * See: https://github.com/qemu/qemu/blob/d37147997/gdbstub.c#L103-L113 */ 10 | typedef enum { 11 | GDB_SIGNAL_0 = 0, 12 | GDB_SIGNAL_INT = 2, 13 | GDB_SIGNAL_QUIT = 3, 14 | GDB_SIGNAL_TRAP = 5, 15 | GDB_SIGNAL_ABRT = 6, 16 | GDB_SIGNAL_ALRM = 14, 17 | GDB_SIGNAL_IO = 23, 18 | GDB_SIGNAL_XCPU = 24, 19 | GDB_SIGNAL_UNKNOWN = 143 20 | } gdb_signal_t; 21 | 22 | char *gdb_serialize(gdb_kind_t, const char *); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser1.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGDB_PARSER1_H 2 | #define LIBGDB_PARSER1_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define GDB_CSUM_LEN 2 13 | 14 | typedef enum { 15 | GDB_KIND_NOTIFY, 16 | GDB_KIND_PACKET, 17 | GDB_KIND_NACK, 18 | GDB_KIND_ACK, 19 | } gdb_kind_t; 20 | 21 | typedef struct { 22 | gdb_kind_t kind; 23 | char *data; 24 | char csum[GDB_CSUM_LEN]; 25 | } gdb_packet_t; 26 | 27 | void gdb_free_packet(gdb_packet_t *); 28 | gdb_packet_t *gdb_parse_pkt(FILE *); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /vp/src/core/rv64/syscall_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rv64 { 6 | 7 | /* The syscall handler is using this interface to access and control the ISS. */ 8 | struct iss_syscall_if { 9 | virtual ~iss_syscall_if() {} 10 | 11 | virtual void sys_exit() = 0; 12 | 13 | virtual uint64_t read_register(unsigned idx) = 0; 14 | virtual void write_register(unsigned idx, uint64_t value) = 0; 15 | }; 16 | 17 | /* Using this interface, the ISS supports to intercept and delegate syscalls. */ 18 | struct syscall_emulator_if { 19 | virtual ~syscall_emulator_if() {} 20 | 21 | virtual void execute_syscall(iss_syscall_if *core) = 0; 22 | }; 23 | 24 | } // namespace rv64 -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/register_format.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "register_format.h" 6 | 7 | RegisterFormater::RegisterFormater(Architecture arch) { 8 | this->arch = arch; 9 | this->stream << std::setfill('0') << std::hex; 10 | } 11 | 12 | void RegisterFormater::formatRegister(uint64_t value) { 13 | switch (arch) { 14 | case RV32: 15 | stream << std::setw(8) << bswap_32(value); 16 | break; 17 | case RV64: 18 | stream << std::setw(16) << bswap_64(value); 19 | break; 20 | default: 21 | throw std::invalid_argument("Architecture not implemented"); 22 | } 23 | } 24 | 25 | std::string RegisterFormater::str(void) { 26 | return this->stream.str(); 27 | } 28 | -------------------------------------------------------------------------------- /sw/c++-lib/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct A { 7 | int a; 8 | int b; 9 | 10 | A(int a, int b) : a(a), b(b) {} 11 | 12 | virtual int foo() = 0; 13 | 14 | virtual int bar() { 15 | return a + b; 16 | } 17 | }; 18 | 19 | struct B : public A { 20 | using A::A; 21 | 22 | virtual int foo() override { 23 | return a - b; 24 | } 25 | }; 26 | 27 | int main() { 28 | std::cout << "Hello World\n"; 29 | B x(5, 2); 30 | auto a = x.foo(); 31 | auto b = x.bar(); 32 | std::cout << a << "\n"; 33 | std::cout << b << "\n"; 34 | std::vector v; 35 | v.push_back(1); 36 | v.push_back(2); 37 | for (auto e : v) std::cout << e << std::endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /vp/src/platform/basic/basic_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_ISA_BASIC_TIMER_H 2 | #define RISCV_ISA_BASIC_TIMER_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "core/common/irq_if.h" 9 | 10 | struct BasicTimer : public sc_core::sc_module { 11 | interrupt_gateway *plic = 0; 12 | uint32_t irq_number = 0; 13 | 14 | SC_HAS_PROCESS(BasicTimer); 15 | 16 | BasicTimer(sc_core::sc_module_name, uint32_t irq_number) : irq_number(irq_number) { 17 | SC_THREAD(run); 18 | } 19 | 20 | void run() { 21 | while (true) { 22 | sc_core::wait(sc_core::sc_time(1, sc_core::SC_MS)); 23 | 24 | plic->gateway_trigger_interrupt(irq_number); 25 | } 26 | } 27 | }; 28 | 29 | #endif // RISCV_ISA_BASIC_TIMER_H 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vp/src/core/common/gdb-mc/parser/mpc"] 2 | path = vp/src/core/common/gdb-mc/libgdb/mpc 3 | url = https://github.com/orangeduck/mpc 4 | [submodule "tests/integration"] 5 | path = vp/tests 6 | url = https://github.com/agra-uni-bremen/vp-integration-tests.git 7 | [submodule "vp/src/platform/hwitl/virtual-bus"] 8 | path = vp/src/platform/hwitl/virtual-bus 9 | url = https://github.com/agra-uni-bremen/virtual-bus 10 | [submodule "vp/src/platform/hifive/vbb-protocol"] 11 | path = vp/src/platform/hifive/vbb-protocol 12 | url = https://github.com/agra-uni-bremen/virtual-breadboard-protocol.git 13 | [submodule "vp/src/vendor/systemc"] 14 | path = vp/src/vendor/systemc 15 | url = https://github.com/accellera-official/systemc.git 16 | -------------------------------------------------------------------------------- /sw/clock-ticks/main.c: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | #include "irq.h" 3 | #include "stdio.h" 4 | #include "assert.h" 5 | 6 | static void set_next_timer_interrupt() { 7 | assert (mtime && mtimecmp); 8 | *mtimecmp = *mtime + 1000; // 1000 timer ticks, corresponds to 1 MS delay with current CLINT configuration 9 | } 10 | 11 | unsigned int num_ticks = 0; 12 | 13 | void timer_irq_handler() { 14 | set_next_timer_interrupt(); 15 | ++num_ticks; 16 | } 17 | 18 | int main() { 19 | printf("num_ticks %d\n", num_ticks); 20 | register_timer_interrupt_handler(timer_irq_handler); 21 | set_next_timer_interrupt(); 22 | while (num_ticks < 10) { 23 | printf("num_ticks %d\n", num_ticks); 24 | } 25 | printf("num_ticks %d\n", num_ticks); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /env/basic/vp-display/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | MainWindow 3 | 4 | 5 | 6 | 0 7 | 0 8 | 400 9 | 300 10 | 11 | 12 | 13 | MainWindow 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /env/basic/vp-display/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0) 2 | project(vp-display) # Your project name 3 | 4 | set(CMAKE_CXX_STANDARD 11) # This is equal to QMAKE_CXX_FLAGS += -std=c++0x 5 | 6 | 7 | # Find includes in corresponding build directories 8 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 9 | set(CMAKE_AUTOMOC ON) 10 | set(CMAKE_AUTOUIC ON) 11 | 12 | 13 | find_package(Qt5Widgets CONFIG REQUIRED) 14 | 15 | set(SOURCES 16 | main.cpp 17 | mainwindow.cpp 18 | vpdisplayserver.cpp 19 | ) 20 | 21 | set(HEADERS 22 | mainwindow.h 23 | vpdisplayserver.h 24 | framebuffer.h 25 | ) 26 | 27 | set(UI mainwindow.ui) 28 | 29 | add_executable(vp-display ${SOURCES} ${HEADERS} ${UI}) 30 | 31 | target_link_libraries(vp-display Qt5::Widgets pthread) 32 | 33 | -------------------------------------------------------------------------------- /sw/basic-debug/remote-debug-readme.txt: -------------------------------------------------------------------------------- 1 | In the first terminal run our VP in debug mode (wraps the core iss in a debug stub): 2 | 3 | riscv-vp --debug-mode --intercept-syscalls main 4 | 5 | 6 | In the other terminal run: 7 | 8 | riscv32-unknown-elf-gdb 9 | 10 | Inside of gdb then (for example): 11 | 12 | file main 13 | target remote :5005 14 | b main.c:14 15 | continue 16 | p x 17 | p y 18 | step 19 | continue 20 | 21 | This will load the symbols from the *main* elf file (note: this one should match the one loaded in our VP). The *target remote* command is passed host and port number. In this case localhost is used. 22 | 23 | Note: you can use 'set debug remote 1' in gdb to observe the packets send and received by gdb (might be useful for debugging). 24 | -------------------------------------------------------------------------------- /vp/src/platform/common/terminal.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_ISA_TERMINAL_H 2 | #define RISCV_ISA_TERMINAL_H 3 | 4 | #include 5 | #include 6 | 7 | struct SimpleTerminal : public sc_core::sc_module { 8 | tlm_utils::simple_target_socket tsock; 9 | 10 | SimpleTerminal(sc_core::sc_module_name) { 11 | tsock.register_b_transport(this, &SimpleTerminal::transport); 12 | } 13 | 14 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 15 | sc_assert(trans.get_command() == tlm::TLM_WRITE_COMMAND); 16 | sc_assert(trans.get_data_length() == 1); 17 | 18 | std::cout << (char)*trans.get_data_ptr(); 19 | delay += (sc_core::sc_time(1, sc_core::sc_time_unit::SC_US)); 20 | } 21 | }; 22 | 23 | #endif // RISCV_ISA_TERMINAL_H 24 | -------------------------------------------------------------------------------- /vp/src/core/common/debug_memory.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_ISA_DEBUG_MEMORY_H 2 | #define RISCV_ISA_DEBUG_MEMORY_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "core_defs.h" 11 | #include "trap.h" 12 | 13 | struct DebugMemoryInterface : public sc_core::sc_module { 14 | tlm_utils::simple_initiator_socket isock; 15 | 16 | DebugMemoryInterface(sc_core::sc_module_name) {} 17 | 18 | unsigned _do_dbg_transaction(tlm::tlm_command cmd, uint64_t addr, uint8_t *data, unsigned num_bytes); 19 | 20 | std::string read_memory(uint64_t start, unsigned nbytes); 21 | 22 | void write_memory(uint64_t start, unsigned nbytes, const std::string &data); 23 | }; 24 | 25 | #endif // RISCV_ISA_GDB_STUB_H 26 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # XXX: Need Alpine Linux Edge since the latest release (3.19) 2 | # only ships SystemC 2.3.3 and does hence not support aarch64. 3 | FROM alpine:edge 4 | 5 | RUN apk update && apk add --no-cache build-base cmake boost-dev \ 6 | systemc-dev systemc-static git gcc-riscv-none-elf \ 7 | g++-riscv-none-elf newlib-riscv-none-elf gdb-multiarch 8 | 9 | RUN adduser -G users -g 'RISC-V VP User' -D riscv-vp 10 | ADD --chown=riscv-vp:users . /home/riscv-vp/riscv-vp 11 | RUN su - riscv-vp -c 'env USE_SYSTEM_SYSTEMC=ON MAKEFLAGS="-j$(nproc)" make -C /home/riscv-vp/riscv-vp' 12 | RUN su - riscv-vp -c 'echo export RISCV_PREFIX=\"riscv-none-elf-\" >> /home/riscv-vp/.profile' 13 | RUN su - riscv-vp -c 'echo export PATH=\"$PATH:/home/riscv-vp/riscv-vp/vp/build/bin\" >> /home/riscv-vp/.profile' 14 | CMD su - riscv-vp 15 | -------------------------------------------------------------------------------- /vp/src/platform/basic/random_source.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_ISA_RANDOM_SOURCE_H 2 | #define RISCV_ISA_RANDOM_SOURCE_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | struct RandomSource : public sc_core::sc_module { 11 | tlm_utils::simple_target_socket tsock; 12 | 13 | RandomSource(sc_core::sc_module_name) { 14 | tsock.register_b_transport(this, &RandomSource::transport); 15 | } 16 | 17 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 18 | assert(trans.get_command() == tlm::TLM_READ_COMMAND); 19 | 20 | auto *p = trans.get_data_ptr(); 21 | for (unsigned i = 0; i < trans.get_data_length(); ++i) { 22 | *(p + i) = rand(); 23 | } 24 | } 25 | }; 26 | 27 | #endif // RISCV_ISA_RANDOM_SOURCE_H 28 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: alpine:3.19 2 | 3 | variables: 4 | GIT_SUBMODULE_STRATEGY: recursive 5 | 6 | cache: 7 | key: $CI_COMMIT_REF_SLUG 8 | paths: 9 | - vp/build 10 | 11 | default: 12 | before_script: 13 | - apk update && apk add --no-cache build-base git boost-dev cmake git gdb-multiarch g++-riscv-none-elf gcc-riscv-none-elf newlib-riscv-none-elf valgrind socat 14 | - export RISCV_PREFIX=riscv-none-elf- 15 | 16 | build-vp: 17 | stage: build 18 | script: 19 | - sh -c 'env MAKEFLAGS=-j$(nproc) make' 20 | artifacts: 21 | paths: 22 | - vp/build/bin 23 | expire_in: 24h 24 | only: 25 | - master 26 | - merge_requests 27 | 28 | test-vp: 29 | stage: test 30 | script: 31 | - cd vp/build 32 | - ctest -V 33 | only: 34 | - master 35 | - merge_requests 36 | -------------------------------------------------------------------------------- /sw/mramTest/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stdio.h" 3 | 4 | static char* const MRAM_START_ADDR = reinterpret_cast(0x60000000); 5 | static const unsigned int MRAM_SIZE = 0x0FFFFFFF; 6 | 7 | int main() { 8 | unsigned long counter = 0; 9 | char buffer[10] = {0}; 10 | 11 | memcpy(&counter, MRAM_START_ADDR, sizeof(unsigned long)); 12 | memcpy(buffer, MRAM_START_ADDR + 10, 10); 13 | 14 | printf("Before:\n"); 15 | printf("%lu, %0.*s\n", counter, 10, buffer); 16 | 17 | memcpy(MRAM_START_ADDR, &(++counter), sizeof(unsigned long)); 18 | memcpy(MRAM_START_ADDR + 10, "Kokosnuss", 10); 19 | 20 | memcpy(&counter, MRAM_START_ADDR, sizeof(unsigned long)); 21 | memcpy(buffer, MRAM_START_ADDR + 10, 10); 22 | 23 | printf("After:\n"); 24 | printf("%lu, %0.*s\n", counter, 10, buffer); 25 | } 26 | -------------------------------------------------------------------------------- /vp/src/platform/common/fd_abstract_uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "uart_if.h" 11 | 12 | class FD_ABSTRACT_UART : public UART_IF { 13 | public: 14 | FD_ABSTRACT_UART(sc_core::sc_module_name, uint32_t); 15 | virtual ~FD_ABSTRACT_UART(void); 16 | 17 | protected: 18 | void start_threads(int fd, bool write_only = false); 19 | void stop_threads(void); 20 | 21 | private: 22 | virtual void write_data(uint8_t) = 0; 23 | virtual void handle_input(int fd) = 0; 24 | 25 | void transmit(); 26 | void receive(); 27 | 28 | std::thread *rcvthr = NULL, *txthr = NULL; 29 | 30 | bool stop; 31 | int stop_pipe[2]; 32 | 33 | enum { 34 | NFDS = 2, 35 | }; 36 | struct pollfd fds[NFDS]; 37 | }; 38 | -------------------------------------------------------------------------------- /vp/src/core/rv32/syscall_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rv32 { 6 | 7 | /* The syscall handler is using this interface to access and control the ISS. */ 8 | struct iss_syscall_if { 9 | virtual ~iss_syscall_if() {} 10 | 11 | virtual void sys_exit() = 0; 12 | // virtual void sys_break() = 0; 13 | 14 | virtual unsigned get_syscall_register_index() = 0; 15 | 16 | virtual uint64_t read_register(unsigned idx) = 0; 17 | virtual void write_register(unsigned idx, uint64_t value) = 0; 18 | 19 | // virtual uint32_t get_hart_id() = 0; 20 | }; 21 | 22 | /* Using this interface, the ISS supports to intercept and delegate syscalls. */ 23 | struct syscall_emulator_if { 24 | virtual ~syscall_emulator_if() {} 25 | 26 | virtual void execute_syscall(iss_syscall_if *core) = 0; 27 | }; 28 | 29 | } // namespace rv32 -------------------------------------------------------------------------------- /vp/src/core/common/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_TIMER_H 2 | #define RISCV_VP_TIMER_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class Timer { 12 | public: 13 | typedef std::chrono::duration usecs; 14 | 15 | typedef void (*Callback) (void*); 16 | class Context { 17 | public: 18 | Timer::usecs duration; 19 | Callback fn; 20 | void *arg; 21 | 22 | Context(usecs _duration, Callback _fn, void *_arg) 23 | : duration(_duration), fn(_fn), arg(_arg) {}; 24 | }; 25 | 26 | Timer(Callback fn, void *arg); 27 | ~Timer(void); 28 | 29 | void pause(void); 30 | void start(usecs duration); 31 | 32 | private: 33 | Context ctx; 34 | pthread_t thread; 35 | bool running; 36 | 37 | void stop_thread(void); 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/gdb_runner.cpp: -------------------------------------------------------------------------------- 1 | #include "gdb_runner.h" 2 | 3 | GDBServerRunner::GDBServerRunner(sc_core::sc_module_name name, GDBServer *server, debug_target_if *hart) { 4 | (void)name; 5 | 6 | this->hart = hart; 7 | this->server = server; 8 | 9 | this->stop_event = server->get_stop_event(hart); 10 | server->set_run_event(hart, &this->run_event); 11 | 12 | hart->enable_debug(); 13 | SC_THREAD(run); 14 | } 15 | 16 | void GDBServerRunner::run(void) { 17 | for (;;) { 18 | sc_core::wait(run_event); 19 | if (server->single_run) { 20 | hart->run_step(); 21 | if (hart->get_status() == CoreExecStatus::Runnable) 22 | hart->set_status(CoreExecStatus::HitBreakpoint); 23 | } else { 24 | hart->run(); 25 | } 26 | stop_event->notify(); 27 | 28 | if (hart->get_status() == CoreExecStatus::Terminated) 29 | break; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vp/src/platform/common/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_UART_H 2 | #define RISCV_VP_UART_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class UART : public FD_ABSTRACT_UART { 9 | public: 10 | UART(const sc_core::sc_module_name&, uint32_t); 11 | virtual ~UART(void); 12 | 13 | private: 14 | typedef enum { 15 | STATE_COMMAND, 16 | STATE_NORMAL, 17 | } uart_state; 18 | 19 | /** 20 | * State of the input handling state machine. In normal mode 21 | * (STATE_NORMAL) the next input character is forwarded to the 22 | * guest. In command mode (STATE_COMMAND) the next input 23 | * character is interpreted by ::handle_cmd. 24 | */ 25 | uart_state state = STATE_NORMAL; 26 | void handle_cmd(uint8_t); 27 | 28 | void handle_input(int fd) override; 29 | void write_data(uint8_t) override; 30 | }; 31 | 32 | #endif // RISCV_VP_UART_H 33 | -------------------------------------------------------------------------------- /vp/src/util/options.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | struct OptionValue { 9 | bool available = false; 10 | T value{}; 11 | std::string option; 12 | 13 | bool finalize(std::function parser) { 14 | if (!option.empty()) { 15 | value = parser(option); 16 | available = true; 17 | } 18 | return available; 19 | } 20 | }; 21 | 22 | unsigned long parse_ulong_option(const std::string &s) { 23 | bool is_hex = false; 24 | if (s.size() >= 2) { 25 | if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) 26 | is_hex = true; 27 | } 28 | 29 | try { 30 | if (is_hex) 31 | return stoul(s, 0, 16); 32 | return stoul(s); 33 | } catch (std::exception &e) { 34 | throw std::runtime_error(std::string("unable to parse option '") + s + "' into a number"); 35 | } 36 | } -------------------------------------------------------------------------------- /sw/basic-gpio/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "platform.h" 4 | #include "uart.h" 5 | #include "util.h" 6 | //#include "gpio.h" 7 | void wait(uint32_t nOps) { 8 | /* 9 | * TODO correlate nOps to clocks/time waited 10 | */ 11 | for(uint32_t i = 0; i < nOps; i++) { 12 | asm("nop"); 13 | } 14 | } 15 | 16 | int main(int argc, char **argv) { 17 | uint8_t val = 1; 18 | 19 | *GPIO_BANK_A_DIRECTION_ADDR = 0x000000ff; // set all pins to output 20 | *GPIO_BANK_A_OUTPUT_ADDR = 0x01; // output 0x01 to all 8 pins of gpio bank A 21 | wait(10); 22 | *LED_ADDR = 0x05; 23 | wait(10); 24 | *LED_ADDR = 0x0A; 25 | wait(10); 26 | // bit shift pattern until only 0x55 and 0xAA are present 27 | for(uint8_t i=0; i<10; i++) { 28 | *GPIO_BANK_A_OUTPUT_ADDR = val; 29 | wait(10); 30 | val = (val << 1) | (i & 1); 31 | } 32 | *LED_ADDR = 0x0A; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /vp/src/platform/common/options.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_OPTIONS_H 2 | #define RISCV_VP_OPTIONS_H 3 | 4 | #include 5 | #include 6 | 7 | class Options : public boost::program_options::options_description { 8 | public: 9 | Options(void); 10 | virtual ~Options(); 11 | virtual void parse(int argc, char **argv); 12 | 13 | std::string input_program; 14 | 15 | bool intercept_syscalls = false; 16 | bool error_on_zero_traphandler = false; 17 | bool use_debug_runner = false; 18 | unsigned int debug_port = 5005; 19 | bool trace_mode = false; 20 | unsigned int tlm_global_quantum = 10; 21 | bool use_instr_dmi = false; 22 | bool use_data_dmi = false; 23 | 24 | virtual void printValues(std::ostream& os = std::cout) const; 25 | 26 | private: 27 | 28 | boost::program_options::positional_options_description pos; 29 | boost::program_options::variables_map vm; 30 | }; 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /vp/src/core/common/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_DEBUG 2 | #define RISCV_DEBUG 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "core_defs.h" 10 | 11 | 12 | struct debug_target_if { 13 | virtual ~debug_target_if() {} 14 | 15 | virtual void enable_debug(void) = 0; 16 | virtual CoreExecStatus get_status(void) = 0; 17 | virtual void set_status(CoreExecStatus) = 0; 18 | virtual void block_on_wfi(bool) = 0; 19 | 20 | virtual void insert_breakpoint(uint64_t) = 0; 21 | virtual void remove_breakpoint(uint64_t) = 0; 22 | 23 | virtual Architecture get_architecture(void) = 0; 24 | virtual uint64_t get_hart_id(void) = 0; 25 | 26 | virtual uint64_t get_progam_counter(void) = 0; 27 | virtual std::vector get_registers(void) = 0; 28 | virtual uint64_t read_register(unsigned) = 0; 29 | 30 | virtual void run(void) = 0; 31 | virtual void run_step(void) = 0; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /vp/cmake/AddGitSubmodule.cmake: -------------------------------------------------------------------------------- 1 | #thanks @ https://gist.github.com/scivision/bb1d47a9529e153617414e91ff5390af 2 | 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | function(add_git_submodule dir) 6 | # add a Git submodule directory to CMake, assuming the 7 | # Git submodule directory is a CMake project. 8 | # 9 | # Usage: in CMakeLists.txt 10 | # 11 | # include(AddGitSubmodule.cmake) 12 | # add_git_submodule(mysubmod_dir) 13 | 14 | find_package(Git REQUIRED) 15 | if(NOT EXISTS ${dir}) 16 | set(dir ${CMAKE_CURRENT_SOURCE_DIR}/${dir}) 17 | endif() 18 | 19 | if(NOT EXISTS "${dir}/CMakeLists.txt") 20 | message("checking out submodule ${dir}") 21 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${abs_dir} 22 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 23 | #COMMAND_ERROR_IS_FATAL # cmake 3.19+ 24 | #ANY # cmake 3.19+ 25 | ) 26 | endif() 27 | 28 | add_subdirectory(${dir}) 29 | 30 | endfunction(add_git_submodule) -------------------------------------------------------------------------------- /vp/src/util/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define likely(x) __builtin_expect((x), 1) 6 | #define unlikely(x) __builtin_expect((x), 0) 7 | 8 | #define UNUSED(x) (void)(x) 9 | 10 | inline void ensure(bool cond) { 11 | if (unlikely(!cond)) 12 | throw std::runtime_error("runtime assertion failed"); 13 | } 14 | 15 | inline void ensure(bool cond, const std::string &reason) { 16 | if (unlikely(!cond)) 17 | throw std::runtime_error(reason); 18 | } 19 | 20 | inline uint64_t rv64_align_address(uint64_t addr) { 21 | return addr - addr % 8; 22 | } 23 | 24 | inline uint32_t rv32_align_address(uint32_t addr) { 25 | return addr - addr % 4; 26 | } 27 | 28 | /* Allow to provide a custom function name for a SystemC thread to avoid duplicate name warning in case the same 29 | * SystemC module is instantiated multiple times. */ 30 | #define SC_NAMED_THREAD(func, name) declare_thread_process(func##_handle, name, SC_CURRENT_USER_MODULE, func) 31 | -------------------------------------------------------------------------------- /vp/src/vendor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | subdirs(softfloat) 2 | if(NOT USE_SYSTEM_SYSTEMC) 3 | include(ExternalProject) 4 | ExternalProject_Add( 5 | systemc_project 6 | URL ${CMAKE_CURRENT_SOURCE_DIR}/systemc 7 | CMAKE_ARGS 8 | -DCMAKE_CXX_FLAGS_NO_WARNINGS="-w" 9 | -DCMAKE_BUILD_TYPE=NO_WARNINGS 10 | -DCMAKE_INSTALL_LIBDIR=lib #don't use lib64 11 | -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} 12 | -DBUILD_SHARED_LIBS=OFF 13 | INSTALL_COMMAND "" 14 | BINARY_DIR ${CMAKE_BINARY_DIR}/systemc 15 | BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/systemc/src/libsystemc.a 16 | ) 17 | 18 | add_library(systemc STATIC IMPORTED GLOBAL) 19 | set_target_properties(systemc PROPERTIES 20 | INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/systemc/src 21 | IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/systemc/src/libsystemc.a) 22 | add_dependencies(systemc systemc_project) 23 | endif() 24 | -------------------------------------------------------------------------------- /sw/mrv32-uart/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // #include 4 | #include "platform.h" 5 | #include "uart.h" 6 | #include "util.h" 7 | 8 | void delay(uint32_t loops) { 9 | for(uint32_t i = 0; i < loops; i++) { 10 | asm volatile("nop"); 11 | } 12 | } 13 | 14 | int main() { 15 | delay(10000); 16 | char buf[3]; 17 | char *txt1 = "uart rx failed?!\n"; 18 | delay(5000); 19 | // delay(7000); 20 | // delay(2000); 21 | // delay(10000); 22 | 23 | char rxBuf[5]; 24 | int rxEmpty = 1; 25 | int maxCnt = 30; 26 | int cnt = 0; 27 | rxEmpty = UART->RXEMPT; 28 | int occ; 29 | if(!rxEmpty) { 30 | // read rx data register from uart peripheral 31 | do { 32 | rxBuf[0] = UART->RXDATA; 33 | putChr(rxBuf[0]); 34 | cnt++; 35 | occ = UART->RXOCCU; 36 | // sendString() 37 | } while(UART->RXEMPT || cnt <= maxCnt); 38 | putChr('\n'); 39 | putChr('\n'); 40 | } else { 41 | sendString(txt1,1600); 42 | putChr('\n'); 43 | } 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /sw/crc8/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H 2 | #define PLATFORM_H 3 | 4 | //#define MICRORV 5 | 6 | #ifdef MICRORV 7 | // LED 8 | static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000; 9 | // UART 10 | static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 11 | static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 12 | static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 13 | // CLIC 14 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 15 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 16 | #else 17 | // UART 18 | static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 19 | static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 20 | static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 21 | // CLIC 22 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 23 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 24 | #endif 25 | 26 | #endif /* PLATFORM_H */ -------------------------------------------------------------------------------- /vp/src/platform/basic/display.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * display.hpp 3 | * 4 | * Created on: Sep 11, 2018 5 | * Author: dwd 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include "../../../../env/basic/vp-display/framebuffer.h" 13 | 14 | using namespace std; 15 | using namespace sc_core; 16 | using namespace tlm_utils; 17 | 18 | struct Display : public sc_core::sc_module { 19 | static const size_t addressRange = sizeof(Framebuffer); 20 | 21 | simple_target_socket tsock; 22 | 23 | union { 24 | uint8_t* raw; 25 | Framebuffer* buf; 26 | } frame; 27 | 28 | void createSM(); 29 | 30 | Display(sc_module_name); 31 | void transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay); 32 | 33 | // graphics acceleration functions 34 | void fillFrame(Framebuffer::Type frame, Framebuffer::Color color); 35 | void drawLine(Framebuffer::Type frame, Framebuffer::PointF from, Framebuffer::PointF to, Framebuffer::Color color); 36 | }; 37 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/can/CAN-Howto.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | sudo apt-get install can-utils 3 | ``` 4 | Check if the kernel modules „can“, „can_raw“ and „slcan“ are already loaded: 5 | 6 | ```bash 7 | lsmod | grep can 8 | ``` 9 | if not, load them manually: 10 | 11 | ```bash 12 | sudo modprobe can 13 | sudo modprobe can_raw 14 | sudo modprobe slcan 15 | ```` 16 | 17 | If modprobe says „Module not found“ at this point, your linux distribution is missing the can modules. If modprobe says nothing, the modules exist. 18 | To autoload these modules, insert into new file `/etc/modules-load.d/can` following lines: 19 | 20 | ``` 21 | can 22 | can_raw 23 | slcan 24 | ``` 25 | 26 | (perhaps test by restart, haha) 27 | 28 | 29 | ```bash 30 | sudo cp 90-slcan.rules /etc/udev/rules.d/90-slcan.rules 31 | sudo cp slcan* /usr/local/bin/ 32 | ``` 33 | 34 | You may plug in the CAN-Controller now. *kiss* 35 | 36 | - If `ip link` does not show a _slcan0_, execute the `sudo slcan_add.sh` 37 | - To see can traffic, run `candump slcan0` 38 | -------------------------------------------------------------------------------- /sw/crc8/uart.c: -------------------------------------------------------------------------------- 1 | #include "uart.h" 2 | #include "platform.h" 3 | #include 4 | 5 | int sendString(char* str, long len) { 6 | long cnt = len; 7 | const char *s = (const char *)str; 8 | while (cnt > 0) { 9 | --cnt; 10 | putChr(*s); 11 | s++; 12 | } 13 | return len; 14 | } 15 | 16 | void putChr(char chr) { 17 | #ifdef MICRORV 18 | uint32_t tx_rdy = 0; 19 | *UART_TX_ADDR = chr; 20 | // send character stored in uart_tx_addr 21 | *UART_TX_CTRL = 1; 22 | // wait until tx is ready again for sening another character 23 | do { 24 | // read uart tx status 25 | tx_rdy = *UART_TX_CTRL; 26 | asm volatile ("nop"); 27 | } while(!tx_rdy); 28 | #else 29 | uint32_t tx_rdy = 0; 30 | *UART_TX_DATA_ADDR = chr; 31 | // send character stored in uart_tx_addr 32 | *UART_TX_CTRL_ADDR = 1; 33 | // wait until tx is ready again for sening another character 34 | do { 35 | // read uart tx status 36 | tx_rdy = *UART_TX_CTRL_ADDR; 37 | asm volatile ("nop"); 38 | } while(!tx_rdy); 39 | #endif 40 | return; 41 | } -------------------------------------------------------------------------------- /sw/peripheral-in-the-loop/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS = main.o irq.o bootstrap.o 2 | CFLAGS = -march=rv32i -mabi=ilp32 3 | LDFLAGS = -nostartfiles -Wl,--no-relax 4 | 5 | virtual-bus-path=../../vp/src/platform/hwitl/virtual-bus 6 | simple-sensor-path=../simple-sensor 7 | tty=/dev/ttyUSB2 8 | 9 | $(virtual-bus-path)/responder-cli: 10 | make -C $(virtual-bus-path) responder-cli 11 | 12 | sim-bus: $(EXECUTABLE) $(virtual-bus-path)/responder-cli 13 | make -C $(virtual-bus-path) pipe_left 14 | sleep 1 #needed sometimes as pipe is not immediately there 15 | $(virtual-bus-path)/responder-cli $(virtual-bus-path)/pipe_right & 16 | hwitl-vp $(EXECUTABLE) --error-on-zero-traphandler=true --virtual-bus-device $(virtual-bus-path)/pipe_left 17 | killall responder-cli 18 | killall socat 19 | 20 | real: $(EXECUTABLE) 21 | hwitl-vp $(EXECUTABLE) --error-on-zero-traphandler=true --virtual-bus-device $(tty) 22 | 23 | clearpipes: 24 | killall responder-cli || true 25 | killall socat || true 26 | 27 | SIM_TARGET = sim-bus 28 | include ../Makefile.common 29 | -------------------------------------------------------------------------------- /sw/simple-sensor/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "irq.h" 3 | 4 | static volatile char * const TERMINAL_ADDR = (char * const)0x20000000; 5 | static volatile char * const SENSOR_INPUT_ADDR = (char * const)0x50000000; 6 | static volatile uint32_t * const SENSOR_SCALER_REG_ADDR = (uint32_t * const)0x50000080; 7 | static volatile uint32_t * const SENSOR_FILTER_REG_ADDR = (uint32_t * const)0x50000084; 8 | 9 | volatile _Bool has_sensor_data = 0; 10 | 11 | void sensor_irq_handler() { 12 | has_sensor_data = 1; 13 | } 14 | 15 | void dump_sensor_data() { 16 | while (!has_sensor_data) { 17 | asm volatile ("wfi"); 18 | } 19 | has_sensor_data = 0; 20 | 21 | for (int i=0; i<64; ++i) { 22 | *TERMINAL_ADDR = *(SENSOR_INPUT_ADDR + i) % 92 + 32; 23 | } 24 | *TERMINAL_ADDR = '\n'; 25 | } 26 | 27 | int main() { 28 | register_interrupt_handler(2, sensor_irq_handler); 29 | 30 | *SENSOR_SCALER_REG_ADDR = 5; 31 | *SENSOR_FILTER_REG_ADDR = 2; 32 | 33 | for (int i=0; i<3; ++i) 34 | dump_sensor_data(); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/tunnel-uart.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "uart_if.h" 4 | #include // For UART_Byte types 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef std::function UartRXFunction; // from server to peripheral 11 | typedef std::function UartTXFunction; // from peripheral to server 12 | 13 | class Tunnel_UART : public UART_IF { 14 | static constexpr unsigned DROP_AT_FIFO_DEPTH = 1600; 15 | public: 16 | Tunnel_UART(sc_core::sc_module_name, uint32_t irqsrc); 17 | virtual ~Tunnel_UART(void); 18 | 19 | 20 | void nonblock_receive(gpio::UART_Bytes bytes); 21 | void register_transmit_function(UartTXFunction fun); 22 | 23 | private: 24 | std::queue nonblocking_rx_queue; 25 | std::mutex nonblock_rx_mutex; 26 | 27 | bool stop; 28 | std::thread rx_worker; 29 | void rx_dequeue(); 30 | 31 | std::thread tx_worker; 32 | void tx_dequeue(UartTXFunction fun); 33 | }; 34 | 35 | 36 | -------------------------------------------------------------------------------- /vp/src/platform/test32/htif.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct HTIF : public sc_core::sc_module { 6 | uint64_t *to_host; 7 | uint64_t *num_instr; 8 | uint64_t max_instrs; 9 | std::function to_host_callback; 10 | 11 | SC_HAS_PROCESS(HTIF); 12 | HTIF(sc_core::sc_module_name, uint64_t *to_host, uint64_t *num_instr, uint64_t max_instrs, std::function to_host_callback) { 13 | this->to_host = to_host; 14 | this->num_instr = num_instr; 15 | this->max_instrs = max_instrs; 16 | this->to_host_callback = to_host_callback; 17 | SC_THREAD(run); 18 | } 19 | 20 | void run() { 21 | while (true) { 22 | sc_core::wait(10, sc_core::SC_US); 23 | auto x = *to_host; 24 | to_host_callback(x); 25 | x = *num_instr; 26 | if (x >= max_instrs) 27 | throw std::runtime_error("reached >= max #instrs: " + std::to_string(x)); 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /sw/basic-gpio/uart.c: -------------------------------------------------------------------------------- 1 | #include "uart.h" 2 | #include "platform.h" 3 | #include 4 | 5 | int sendString(char* str, long len) { 6 | long cnt = len; 7 | const char *s = (const char *)str; 8 | while (cnt > 0) { 9 | --cnt; 10 | putChr(*s); 11 | s++; 12 | } 13 | return len; 14 | } 15 | 16 | void putChr(char chr) { 17 | #ifdef MICRORV 18 | uint32_t tx_rdy = 0; 19 | *UART_TX_DATA_ADDR = chr; 20 | // send character stored in uart_tx_addr 21 | *UART_TX_CTRL_ADDR = 1; 22 | // wait until tx is ready again for sening another character 23 | do { 24 | // read uart tx status 25 | tx_rdy = *UART_TX_CTRL_ADDR; 26 | asm volatile ("nop"); 27 | } while(!tx_rdy); 28 | #else 29 | uint32_t tx_rdy = 0; 30 | *UART_TX_DATA_ADDR = chr; 31 | // send character stored in uart_tx_addr 32 | *UART_TX_CTRL_ADDR = 1; 33 | // wait until tx is ready again for sening another character 34 | do { 35 | // read uart tx status 36 | tx_rdy = *UART_TX_CTRL_ADDR; 37 | asm volatile ("nop"); 38 | } while(!tx_rdy); 39 | #endif 40 | return; 41 | } -------------------------------------------------------------------------------- /sw/crc8/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | .equ SYSCALL_ADDR, 0x02010000 5 | 6 | .macro INIT_HW_PLATFORM 7 | and x1,x0,x0 8 | and x2,x0,x0 9 | and x3,x0,x0 10 | and x4,x0,x0 11 | and x5,x0,x0 12 | and x6,x0,x0 13 | and x7,x0,x0 14 | and x8,x0,x0 15 | and x9,x0,x0 16 | and x10,x0,x0 17 | and x11,x0,x0 18 | and x12,x0,x0 19 | and x13,x0,x0 20 | and x14,x0,x0 21 | and x15,x0,x0 22 | and x16,x0,x0 23 | and x17,x0,x0 24 | and x18,x0,x0 25 | and x19,x0,x0 26 | and x20,x0,x0 27 | and x21,x0,x0 28 | and x22,x0,x0 29 | and x23,x0,x0 30 | and x24,x0,x0 31 | and x25,x0,x0 32 | and x26,x0,x0 33 | and x27,x0,x0 34 | and x28,x0,x0 35 | and x29,x0,x0 36 | and x30,x0,x0 37 | and x31,x0,x0 38 | .endm 39 | 40 | .macro SYS_EXIT 41 | li a7, 93 42 | li t0, SYSCALL_ADDR 43 | csrr a6, mhartid 44 | sw a6, 0(t0) 45 | .endm 46 | 47 | _start: 48 | # initialize hw-platform 49 | INIT_HW_PLATFORM 50 | la sp, stack_end 51 | jal main 52 | 53 | # call exit (SYS_EXIT=93) with exit code in a0 54 | SYS_EXIT 55 | 56 | stack_begin: 57 | .zero 1024 58 | stack_end: 59 | -------------------------------------------------------------------------------- /sw/basic-debug/eclipse-remote-debug-readme.txt: -------------------------------------------------------------------------------- 1 | Start Eclipse 2 | 3 | File -> New -> Makefile Project with Existing Code 4 | 5 | Select the software folder containing the Makefile 6 | 7 | Run -> Debug Configurations ... 8 | 9 | C/C++ Remote Application (List Entry on the left side): Click "New" Button 10 | 11 | Main Tab 12 | - C/C++ Application Name: Enter name, typically "main" 13 | - Using GDB (DSF) Automatic Remote Launcher: Click "Select other" 14 | -> Use configuration specific settings 15 | -> GDB (DSF) Manual Remote Debug Launcher 16 | 17 | Debugger Tab 18 | - GDB debugger: riscv32-unknown-elf-gdb [Sub-tab Main] 19 | - Connection: Port Number 5005 [Sub-tab Connection] 20 | 21 | Click "Debug" Button (lower right corner) to start debugging 22 | -> Launch the VP in debug mode first: riscv-vp --debug-mode main 23 | -> Perhaps it is necessary to refresh the Eclipse project view in case the executable (typically main) cannot be found (the "Debug" button is greyed out in this case) 24 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/oled/oled.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * oled.hpp 3 | * 4 | * Created on: 20 Sep 2019 5 | * Author: dwd 6 | * 7 | * This class models the SH1106 oled Display driver. 8 | */ 9 | 10 | #pragma once 11 | #include "common.hpp" 12 | 13 | #include 14 | #include 15 | 16 | class SS1106 { 17 | public: 18 | typedef std::function GetDCPin_function; 19 | private: 20 | 21 | static const std::map opcode; 22 | 23 | struct Command 24 | { 25 | ss1106::Operator op; 26 | uint8_t payload; 27 | }; 28 | 29 | enum class Mode : uint_fast8_t 30 | { 31 | normal, 32 | second_arg 33 | } mode = Mode::normal; 34 | 35 | void *sharedSegment = nullptr; 36 | ss1106::State* state; 37 | 38 | Command last_cmd = Command{ss1106::Operator::NOP, 0}; 39 | 40 | GetDCPin_function getDCPin; 41 | 42 | 43 | uint8_t mask(ss1106::Operator op); 44 | Command match(uint8_t cmd); 45 | 46 | public: 47 | SS1106(GetDCPin_function getDCPin, ss1106::State* state_memory_override = nullptr); 48 | ~SS1106(); 49 | 50 | uint8_t write(uint8_t byte); 51 | }; 52 | -------------------------------------------------------------------------------- /vp/src/core/common/irq_if.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_ISA_IRQ_IF_H 2 | #define RISCV_ISA_IRQ_IF_H 3 | 4 | #include 5 | 6 | typedef uint32_t PrivilegeLevel; 7 | 8 | constexpr uint32_t MachineMode = 0b11; 9 | constexpr uint32_t HypervisorMode = 0b10; 10 | constexpr uint32_t SupervisorMode = 0b01; 11 | constexpr uint32_t UserMode = 0b00; 12 | constexpr uint32_t NoneMode = -1; // invalid sentinel to avoid passing a boolean alongside a privilege level 13 | 14 | struct external_interrupt_target { 15 | virtual ~external_interrupt_target() {} 16 | 17 | virtual void trigger_external_interrupt(PrivilegeLevel level) = 0; 18 | virtual void clear_external_interrupt(PrivilegeLevel level) = 0; 19 | }; 20 | 21 | struct clint_interrupt_target { 22 | virtual ~clint_interrupt_target() {} 23 | 24 | virtual void trigger_timer_interrupt(bool status) = 0; 25 | virtual void trigger_software_interrupt(bool status) = 0; 26 | }; 27 | 28 | struct interrupt_gateway { 29 | virtual ~interrupt_gateway() {} 30 | 31 | virtual void gateway_trigger_interrupt(uint32_t irq_id) = 0; 32 | }; 33 | 34 | #endif // RISCV_ISA_IRQ_IF_H 35 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/oled/common.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * common.cpp 3 | * 4 | * Created on: 24 Sep 2019 5 | * Author: dwd 6 | */ 7 | 8 | #include "common.hpp" 9 | #include 10 | #include 11 | #include 12 | 13 | namespace ss1106 14 | { 15 | 16 | IMPL_ENUM(Operator); 17 | 18 | State* getSharedState() 19 | { 20 | int shmid; 21 | for(unsigned i = 0; i < 2; i++) 22 | { 23 | if ((shmid = shmget(shm_key, sizeof(State), IPC_CREAT | 0660)) >= 0) 24 | continue; 25 | 26 | std::cerr << "Could not get " << sizeof(State) << " Byte of shared Memory " << int(shm_key) 27 | << " for oled display" << std::endl; 28 | perror("shmget"); 29 | std::cerr << "Trying again...\n" << std::endl; 30 | 31 | if(-1 == (shmctl(shm_key, IPC_RMID, nullptr))) 32 | { 33 | std::cerr << "Could not destroy SHM" << std::endl; 34 | perror("shmctl"); 35 | return nullptr; 36 | } 37 | } 38 | 39 | void *addr = shmat(shmid, nullptr, 0); 40 | if (addr == nullptr) { 41 | perror("shmat"); 42 | return nullptr; 43 | } 44 | 45 | return reinterpret_cast(addr); 46 | } 47 | 48 | 49 | }; 50 | 51 | 52 | -------------------------------------------------------------------------------- /sw/simple-display/libDisplay.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * libDisplay.hpp 3 | * 4 | * Created on: Oct 5, 2018 5 | * Author: dwd 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "../../env/basic/vp-display/framebuffer.h" 11 | 12 | extern Framebuffer* volatile const framebuffer; 13 | 14 | inline Framebuffer::Color fromRGB(uint8_t r, uint8_t g, uint8_t b) { 15 | Framebuffer::Color ret = 0; 16 | ret |= (b & 0x0F); 17 | ret |= (g & 0x0F) << 4; 18 | ret |= (r & 0x0F) << 8; 19 | return ret; 20 | } 21 | 22 | namespace display { 23 | void setPixel(Framebuffer::Type frame, Framebuffer::Point pixel, Framebuffer::Color color); 24 | 25 | void drawLine(Framebuffer::Type frame, Framebuffer::PointF from, Framebuffer::PointF to, Framebuffer::Color color); 26 | 27 | void drawRect(Framebuffer::Type frame, Framebuffer::PointF ol, Framebuffer::PointF ur, Framebuffer::Color color); 28 | 29 | void fillRect(Framebuffer::Type frame, Framebuffer::PointF ol, Framebuffer::PointF ur, Framebuffer::Color color); 30 | 31 | void applyFrame(); 32 | 33 | void fillFrame(Framebuffer::Type frame = Framebuffer::Type::foreground, Framebuffer::Color color = 0); 34 | }; // namespace display 35 | -------------------------------------------------------------------------------- /vp/src/platform/microrv32/microrv32_led.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | struct MicroRV32LED : public sc_core::sc_module { 11 | tlm_utils::simple_target_socket tsock; 12 | 13 | sc_core::sc_event run_event; 14 | uint8_t led_vals = 0; 15 | 16 | SC_HAS_PROCESS(MicroRV32LED); 17 | 18 | MicroRV32LED(sc_core::sc_module_name) { 19 | tsock.register_b_transport(this, &MicroRV32LED::transport); 20 | } 21 | 22 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 23 | auto addr = trans.get_address(); 24 | auto cmd = trans.get_command(); 25 | // auto len = trans.get_data_length(); 26 | auto ptr = trans.get_data_ptr(); 27 | 28 | if (cmd == tlm::TLM_WRITE_COMMAND) { 29 | if (addr == 0) { 30 | led_vals = *ptr; 31 | // printf("\n[TLM] LED write : %X \n", *ptr); 32 | } 33 | } else if (cmd == tlm::TLM_READ_COMMAND) { 34 | if (addr == 0) { 35 | *((uint32_t*)ptr) = led_vals; 36 | } 37 | } 38 | 39 | (void)delay; // zero delay 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /sw/mrv32-uart/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | .equ SYSCALL_ADDR, 0x02010000 5 | 6 | .macro INIT_HW_PLATFORM 7 | and x1,x0,x0 8 | and x2,x0,x0 9 | and x3,x0,x0 10 | and x4,x0,x0 11 | and x5,x0,x0 12 | and x6,x0,x0 13 | and x7,x0,x0 14 | and x8,x0,x0 15 | and x9,x0,x0 16 | and x10,x0,x0 17 | and x11,x0,x0 18 | and x12,x0,x0 19 | and x13,x0,x0 20 | and x14,x0,x0 21 | and x15,x0,x0 22 | and x16,x0,x0 23 | and x17,x0,x0 24 | and x18,x0,x0 25 | and x19,x0,x0 26 | and x20,x0,x0 27 | and x21,x0,x0 28 | and x22,x0,x0 29 | and x23,x0,x0 30 | and x24,x0,x0 31 | and x25,x0,x0 32 | and x26,x0,x0 33 | and x27,x0,x0 34 | and x28,x0,x0 35 | and x29,x0,x0 36 | and x30,x0,x0 37 | and x31,x0,x0 38 | .endm 39 | 40 | .macro SYS_EXIT, exit_code 41 | li a7, 93 42 | li a0, \exit_code 43 | li t0, SYSCALL_ADDR 44 | csrr a6, mhartid 45 | sw a6, 0(t0) 46 | sw a7, 0(t0) 47 | .endm 48 | 49 | .align 4 50 | _start: 51 | # initialize hw-platform 52 | INIT_HW_PLATFORM 53 | la sp, stack_end 54 | jal main 55 | 56 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 57 | 1: SYS_EXIT 0 58 | j 1b 59 | 60 | .align 4 61 | stack_begin: 62 | .zero 2048 63 | stack_end: 64 | -------------------------------------------------------------------------------- /img/riscv-vp_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | RISC V 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /vp/src/core/common/trap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum ExceptionCode { 4 | // interrupt exception codes (mcause) 5 | EXC_U_SOFTWARE_INTERRUPT = 0, 6 | EXC_S_SOFTWARE_INTERRUPT = 1, 7 | EXC_M_SOFTWARE_INTERRUPT = 3, 8 | 9 | EXC_U_TIMER_INTERRUPT = 4, 10 | EXC_S_TIMER_INTERRUPT = 5, 11 | EXC_M_TIMER_INTERRUPT = 7, 12 | 13 | EXC_U_EXTERNAL_INTERRUPT = 8, 14 | EXC_S_EXTERNAL_INTERRUPT = 9, 15 | EXC_M_EXTERNAL_INTERRUPT = 11, 16 | 17 | // non-interrupt exception codes (mcause) 18 | EXC_INSTR_ADDR_MISALIGNED = 0, 19 | EXC_INSTR_ACCESS_FAULT = 1, 20 | EXC_ILLEGAL_INSTR = 2, 21 | EXC_BREAKPOINT = 3, 22 | EXC_LOAD_ADDR_MISALIGNED = 4, 23 | EXC_LOAD_ACCESS_FAULT = 5, 24 | EXC_STORE_AMO_ADDR_MISALIGNED = 6, 25 | EXC_STORE_AMO_ACCESS_FAULT = 7, 26 | 27 | EXC_ECALL_U_MODE = 8, 28 | EXC_ECALL_S_MODE = 9, 29 | EXC_ECALL_M_MODE = 11, 30 | 31 | EXC_INSTR_PAGE_FAULT = 12, 32 | EXC_LOAD_PAGE_FAULT = 13, 33 | EXC_STORE_AMO_PAGE_FAULT = 15, 34 | }; 35 | 36 | struct SimulationTrap { 37 | ExceptionCode reason; 38 | unsigned long mtval; 39 | }; 40 | 41 | inline void raise_trap(ExceptionCode exc, unsigned long mtval) { 42 | throw SimulationTrap({exc, mtval}); 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2018 Group of Computer Architecture, University of Bremen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /vp/src/util/gtkwave_riscv-filter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import tempfile 4 | import subprocess 5 | 6 | def main(): 7 | fh_in = sys.stdin 8 | fh_out = sys.stdout 9 | 10 | while True: 11 | l = fh_in.readline() 12 | if not l: 13 | return 0 14 | 15 | if "x" in l: 16 | fh_out.write(l) 17 | fh_out.flush() 18 | continue 19 | 20 | obj_temp = tempfile.NamedTemporaryFile(delete=False, mode='w') 21 | with tempfile.NamedTemporaryFile(delete=False, mode='w') as asm_temp: 22 | asm_temp.write(".word 0x%s\n" % l) 23 | asm_temp.flush() 24 | subprocess.run(["riscv64-unknown-elf-as", "-march=rv32i", "-o", obj_temp.name, asm_temp.name]) 25 | result = subprocess.run(["riscv64-unknown-elf-objdump", "-d", obj_temp.name], capture_output=True) 26 | lastline = result.stdout.splitlines()[-1] 27 | chunks = lastline.decode().split('\t') 28 | 29 | opcodes = " ".join(chunks[2:]) 30 | 31 | fh_out.write("%s\n" % opcodes) 32 | fh_out.flush() 33 | 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main()) 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --no-print-directory 2 | 3 | # Whether to use a system-wide SystemC library instead of the vendored one. 4 | USE_SYSTEM_SYSTEMC ?= OFF 5 | 6 | vps: vp/src/core/common/gdb-mc/libgdb/mpc/mpc.c vp/build/Makefile 7 | $(MAKE) install -C vp/build 8 | 9 | vp/src/core/common/gdb-mc/libgdb/mpc/mpc.c: 10 | git submodule update --init vp/src/core/common/gdb-mc/libgdb/mpc 11 | 12 | all: vps vp-display 13 | 14 | vp/build/Makefile: 15 | mkdir -p vp/build 16 | cd vp/build && cmake -DUSE_SYSTEM_SYSTEMC=$(USE_SYSTEM_SYSTEMC) .. 17 | 18 | vp-eclipse: 19 | mkdir -p vp-eclipse 20 | cd vp-eclipse && cmake ../vp/ -G "Eclipse CDT4 - Unix Makefiles" 21 | 22 | env/basic/vp-display/build/Makefile: 23 | mkdir -p env/basic/vp-display/build 24 | cd env/basic/vp-display/build && cmake .. 25 | 26 | vp-display: env/basic/vp-display/build/Makefile 27 | $(MAKE) -C env/basic/vp-display/build 28 | 29 | vp-clean: 30 | rm -rf vp/build 31 | 32 | qt-clean: 33 | rm -rf env/basic/vp-display/build 34 | 35 | clean-all: vp-clean qt-clean 36 | 37 | clean: vp-clean 38 | 39 | codestyle: 40 | find . -type d \( -name .git -o -name dependencies \) -prune -o -name '*.h' -o -name '*.hpp' -o -name '*.cpp' -print | xargs clang-format -i -style=file 41 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # This CITATION.cff file was generated with cffinit. 2 | # Visit https://bit.ly/cffinit to generate yours today! 3 | 4 | cff-version: 1.2.0 5 | title: RISC-V VP 6 | message: >- 7 | If you want to cite this software, please use the metadata from this file. 8 | type: software 9 | authors: 10 | - given-names: Vladimir 11 | family-names: Herdt 12 | email: riscv@informatik.uni-bremen.de 13 | affiliation: University of Bremen 14 | orcid: 'https://orcid.org/0000-0002-4481-057X' 15 | - given-names: Group of Computer Architecture 16 | email: riscv@informatik.uni-bremen.de 17 | affiliation: University of Bremen 18 | - given-names: Rolf 19 | family-names: Drechsler 20 | email: drechsler@uni-bremen.de 21 | affiliation: University of Bremen 22 | orcid: 'https://orcid.org/0000-0002-9872-1740' 23 | identifiers: 24 | - type: doi 25 | value: 10.1016/j.sysarc.2020.101756 26 | description: >- 27 | RISC-V based virtual prototype: An extensible and configurable platform for the system-level 28 | repository-code: 'hhttps://github.com/agra-uni-bremen/riscv-vp' 29 | abstract: >- 30 | RISC-V based virtual prototype: An extensible and configurable platform for the system-level 31 | license: MIT 32 | -------------------------------------------------------------------------------- /sw/basic-gpio/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | .equ SYSCALL_ADDR, 0x02010000 5 | 6 | .macro INIT_HW_PLATFORM 7 | and x1,x0,x0 8 | and x2,x0,x0 9 | and x3,x0,x0 10 | and x4,x0,x0 11 | and x5,x0,x0 12 | and x6,x0,x0 13 | and x7,x0,x0 14 | and x8,x0,x0 15 | and x9,x0,x0 16 | and x10,x0,x0 17 | and x11,x0,x0 18 | and x12,x0,x0 19 | and x13,x0,x0 20 | and x14,x0,x0 21 | and x15,x0,x0 22 | and x16,x0,x0 23 | and x17,x0,x0 24 | and x18,x0,x0 25 | and x19,x0,x0 26 | and x20,x0,x0 27 | and x21,x0,x0 28 | and x22,x0,x0 29 | and x23,x0,x0 30 | and x24,x0,x0 31 | and x25,x0,x0 32 | and x26,x0,x0 33 | and x27,x0,x0 34 | and x28,x0,x0 35 | and x29,x0,x0 36 | and x30,x0,x0 37 | and x31,x0,x0 38 | .endm 39 | 40 | .macro SYS_EXIT, exit_code 41 | li a7, 93 42 | li a0, \exit_code 43 | li t0, SYSCALL_ADDR 44 | csrr a6, mhartid 45 | sw a6, 0(t0) 46 | .endm 47 | 48 | # .macro SYS_EXIT, exit_code 49 | # li a7, 93 50 | # li a0, \exit_code 51 | # li t0, SYSCALL_ADDR 52 | # sw a7, 0(t0) 53 | # .endm 54 | 55 | _start: 56 | # initialize hw-platform 57 | INIT_HW_PLATFORM 58 | la sp, stack_end 59 | jal main 60 | 61 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 62 | SYS_EXIT 0 63 | 64 | .align 4 65 | stack_begin: 66 | .zero 1024 67 | stack_end: 68 | -------------------------------------------------------------------------------- /env/basic/vp-display/VP-Display.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-09-10T15:30:06 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = VP-Display 12 | TEMPLATE = app 13 | CONFIG += c++11 14 | 15 | # The following define makes your compiler emit warnings if you use 16 | # any feature of Qt which has been marked as deprecated (the exact warnings 17 | # depend on your compiler). Please consult the documentation of the 18 | # deprecated API in order to know how to port your code away from it. 19 | DEFINES += QT_DEPRECATED_WARNINGS 20 | 21 | # You can also make your code fail to compile if you use deprecated APIs. 22 | # In order to do so, uncomment the following line. 23 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 | 26 | 27 | SOURCES += \ 28 | main.cpp \ 29 | mainwindow.cpp \ 30 | vpdisplayserver.cpp 31 | 32 | HEADERS += \ 33 | mainwindow.h \ 34 | vpdisplayserver.h \ 35 | framebuffer.h 36 | 37 | FORMS += \ 38 | mainwindow.ui 39 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f32_classify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast16_t f32_classify( float32_t a ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | 14 | uA.f = a; 15 | uiA = uA.ui; 16 | 17 | uint_fast16_t infOrNaN = expF32UI( uiA ) == 0xFF; 18 | uint_fast16_t subnormalOrZero = expF32UI( uiA ) == 0; 19 | bool sign = signF32UI( uiA ); 20 | bool fracZero = fracF32UI( uiA ) == 0; 21 | bool isNaN = isNaNF32UI( uiA ); 22 | bool isSNaN = softfloat_isSigNaNF32UI( uiA ); 23 | 24 | return 25 | ( sign && infOrNaN && fracZero ) << 0 | 26 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | 27 | ( sign && subnormalOrZero && !fracZero ) << 2 | 28 | ( sign && subnormalOrZero && fracZero ) << 3 | 29 | ( !sign && infOrNaN && fracZero ) << 7 | 30 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | 31 | ( !sign && subnormalOrZero && !fracZero ) << 5 | 32 | ( !sign && subnormalOrZero && fracZero ) << 4 | 33 | ( isNaN && isSNaN ) << 8 | 34 | ( isNaN && !isSNaN ) << 9; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f64_classify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast16_t f64_classify( float64_t a ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | 14 | uA.f = a; 15 | uiA = uA.ui; 16 | 17 | uint_fast16_t infOrNaN = expF64UI( uiA ) == 0x7FF; 18 | uint_fast16_t subnormalOrZero = expF64UI( uiA ) == 0; 19 | bool sign = signF64UI( uiA ); 20 | bool fracZero = fracF64UI( uiA ) == 0; 21 | bool isNaN = isNaNF64UI( uiA ); 22 | bool isSNaN = softfloat_isSigNaNF64UI( uiA ); 23 | 24 | return 25 | ( sign && infOrNaN && fracZero ) << 0 | 26 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | 27 | ( sign && subnormalOrZero && !fracZero ) << 2 | 28 | ( sign && subnormalOrZero && fracZero ) << 3 | 29 | ( !sign && infOrNaN && fracZero ) << 7 | 30 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | 31 | ( !sign && subnormalOrZero && !fracZero ) << 5 | 32 | ( !sign && subnormalOrZero && fracZero ) << 4 | 33 | ( isNaN && isSNaN ) << 8 | 34 | ( isNaN && !isSNaN ) << 9; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /sw/basic-dma/main.c: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | 3 | #include "irq.h" 4 | 5 | 6 | static volatile char * const TERMINAL_ADDR = (char * const)0x20000000; 7 | 8 | static volatile uint32_t * const DMA_SRC_ADDR = (uint32_t * const)0x70000000; 9 | static volatile uint32_t * const DMA_DST_ADDR = (uint32_t * const)0x70000004; 10 | static volatile uint32_t * const DMA_LEN_ADDR = (uint32_t * const)0x70000008; 11 | static volatile uint32_t * const DMA_OP_ADDR = (uint32_t * const)0x7000000C; 12 | static volatile uint32_t * const DMA_STAT_ADDR = (uint32_t * const)0x70000010; 13 | 14 | static const uint32_t DMA_OP_NOP = 0; 15 | static const uint32_t DMA_OP_MEMCPY = 1; 16 | 17 | 18 | volatile _Bool dma_completed = 0; 19 | 20 | void dma_irq_handler() { 21 | dma_completed = 1; 22 | } 23 | 24 | void init() { 25 | register_interrupt_handler(4, dma_irq_handler); 26 | } 27 | 28 | int main() { 29 | uint8_t src[32] = { [ 0 ... 31 ] = 70 }; 30 | uint8_t dst[32] = { 0 }; 31 | 32 | dma_completed = 0; 33 | *DMA_SRC_ADDR = (uint32_t)(&src[0]); 34 | *DMA_DST_ADDR = (uint32_t)(&dst[0]); 35 | *DMA_LEN_ADDR = sizeof(src); 36 | *DMA_OP_ADDR = DMA_OP_MEMCPY; 37 | 38 | while (!dma_completed) { 39 | asm volatile ("wfi"); 40 | } 41 | 42 | for (int i=0; i<32; ++i) { 43 | *TERMINAL_ADDR = dst[i]; 44 | } 45 | *TERMINAL_ADDR = '\n'; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /vp/src/core/rv32/mem_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rv32 { 6 | 7 | struct instr_memory_if { 8 | virtual ~instr_memory_if() {} 9 | 10 | virtual uint32_t load_instr(uint64_t pc) = 0; 11 | }; 12 | 13 | //NOTE: load/store double is used for floating point D extension 14 | struct data_memory_if { 15 | virtual ~data_memory_if() {} 16 | 17 | virtual int64_t load_double(uint64_t addr) = 0; 18 | virtual int32_t load_word(uint64_t addr) = 0; 19 | virtual int32_t load_half(uint64_t addr) = 0; 20 | virtual int32_t load_byte(uint64_t addr) = 0; 21 | virtual uint32_t load_uhalf(uint64_t addr) = 0; 22 | virtual uint32_t load_ubyte(uint64_t addr) = 0; 23 | 24 | virtual void store_double(uint64_t addr, uint64_t value) = 0; 25 | virtual void store_word(uint64_t addr, uint32_t value) = 0; 26 | virtual void store_half(uint64_t addr, uint16_t value) = 0; 27 | virtual void store_byte(uint64_t addr, uint8_t value) = 0; 28 | 29 | virtual int32_t atomic_load_word(uint64_t addr) = 0; 30 | virtual void atomic_store_word(uint64_t addr, uint32_t value) = 0; 31 | virtual int32_t atomic_load_reserved_word(uint64_t addr) = 0; 32 | virtual bool atomic_store_conditional_word(uint64_t addr, uint32_t value) = 0; 33 | virtual void atomic_unlock() = 0; 34 | 35 | virtual void flush_tlb() = 0; 36 | }; 37 | 38 | } // namespace rv32 -------------------------------------------------------------------------------- /sw/basic-multicore/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | 4 | .equ SYSCALL_ADDR, 0x02010000 5 | 6 | # NOTE: this will exit the whole simulation, i.e. stop all harts 7 | .macro SYS_EXIT, exit_code 8 | li a7, 93 9 | li a0, \exit_code 10 | li t0, SYSCALL_ADDR 11 | csrr a6, mhartid 12 | sw a6, 0(t0) 13 | .endm 14 | 15 | 16 | # NOTE: each core will start here with execution 17 | _start: 18 | 19 | # initialize global pointer (see crt0.S of the RISC-V newlib C-library port) 20 | .option push 21 | .option norelax 22 | 1:auipc gp, %pcrel_hi(__global_pointer$) 23 | addi gp, gp, %pcrel_lo(1b) 24 | .option pop 25 | 26 | csrr a0, mhartid # return a core specific number 0 or 1 27 | li t0, 0 28 | beq a0, t0, core0 29 | li t0, 1 30 | beq a0, t0, core1 31 | core0: 32 | la sp, stack0_end # code executed only by core0 33 | j end 34 | core1: 35 | la sp, stack1_end # code executed only by core1 36 | j end 37 | end: 38 | 39 | jal main 40 | 41 | # wait until all two cores have finished 42 | la t0, exit_counter 43 | li t1, 1 44 | li t2, 1 45 | amoadd.w a0, t1, 0(t0) 46 | 1: 47 | blt a0, t2, 1b 48 | 49 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 50 | SYS_EXIT 0 51 | 52 | .align 8 53 | stack0_begin: 54 | .zero 32768 55 | stack0_end: 56 | 57 | .align 8 58 | stack1_begin: 59 | .zero 32768 60 | stack1_end: 61 | exit_counter: 62 | .word 0 63 | -------------------------------------------------------------------------------- /vp/src/platform/hwitl/virtual_bus_tlm_connector.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * virtual_bus_tlm_connector.cpp 3 | * 4 | * Created on: Oct 20, 2022 5 | * Author: dwd 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "bus.h" 14 | #include "virtual-bus/initiator.hpp" 15 | 16 | struct VirtualBusMember : public sc_core::sc_module { 17 | tlm_utils::simple_target_socket tsock; 18 | 19 | Initiator& virtual_bus; 20 | const hwitl::Address base_address; 21 | sc_core::sc_time m_read_delay; 22 | sc_core::sc_time m_write_delay; 23 | 24 | // interrupt stuff 25 | sc_core::sc_time m_interrupt_polling_delay; 26 | std::function trigger_interrupt_callback; 27 | sc_core::sc_event m_interrupt_event; 28 | 29 | /** 30 | * @input base_address will be added to the local (!) address 31 | */ 32 | VirtualBusMember(sc_core::sc_module_name, Initiator& virtual_bus_connector, 33 | hwitl::Address base_address = 0); 34 | 35 | void setDelayTimes(sc_core::sc_time read_delay, sc_core::sc_time write_delay); 36 | void setInterruptRoutine(std::function trigger_target, sc_core::sc_time polling_time = sc_core::sc_time(10, sc_core::SC_MS)); 37 | 38 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay); 39 | 40 | SC_HAS_PROCESS(VirtualBusMember); 41 | void interrupt_service(); 42 | }; 43 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f128_classify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast16_t f128_classify( float128_t a ) 10 | { 11 | union ui128_f128 uA; 12 | uint_fast64_t uiA64, uiA0; 13 | 14 | uA.f = a; 15 | uiA64 = uA.ui.v64; 16 | uiA0 = uA.ui.v0; 17 | 18 | uint_fast16_t infOrNaN = expF128UI64( uiA64 ) == 0x7FFF; 19 | uint_fast16_t subnormalOrZero = expF128UI64( uiA64 ) == 0; 20 | bool sign = signF128UI64( uiA64 ); 21 | bool fracZero = fracF128UI64( uiA64 ) == 0 && uiA0 == 0; 22 | bool isNaN = isNaNF128UI( uiA64, uiA0 ); 23 | bool isSNaN = softfloat_isSigNaNF128UI( uiA64, uiA0 ); 24 | 25 | return 26 | ( sign && infOrNaN && fracZero ) << 0 | 27 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | 28 | ( sign && subnormalOrZero && !fracZero ) << 2 | 29 | ( sign && subnormalOrZero && fracZero ) << 3 | 30 | ( !sign && infOrNaN && fracZero ) << 7 | 31 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | 32 | ( !sign && subnormalOrZero && !fracZero ) << 5 | 33 | ( !sign && subnormalOrZero && fracZero ) << 4 | 34 | ( isNaN && isSNaN ) << 8 | 35 | ( isNaN && !isSNaN ) << 9; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /env/basic/vp-display/vpdisplayserver.cpp: -------------------------------------------------------------------------------- 1 | #include "vpdisplayserver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | VPDisplayserver::VPDisplayserver(unsigned int sharedMemoryKey) : mSharedMemoryKey(sharedMemoryKey), stop(false) {} 10 | 11 | VPDisplayserver::~VPDisplayserver() { 12 | stop.store(true); 13 | active_watch.join(); 14 | } 15 | 16 | Framebuffer* VPDisplayserver::createSM() { 17 | int shmid; 18 | // TODO: Dont create, but check if exists 19 | if ((shmid = shmget(mSharedMemoryKey, sizeof(Framebuffer), 0666)) < 0) { 20 | perror("shmget"); 21 | exit(1); 22 | } 23 | std::cout << "SHMID: " << shmid << std::endl; 24 | framebuffer = reinterpret_cast(shmat(shmid, nullptr, 0)); 25 | if (framebuffer == (Framebuffer*)-1) { 26 | perror("shmat"); 27 | exit(1); 28 | } 29 | return framebuffer; 30 | } 31 | 32 | void VPDisplayserver::startListening(std::function notifyChange) { 33 | // TODO: While loop around buffer changer 34 | active_watch = std::thread([=]() { 35 | uint8_t lastFrame = -1; 36 | while (!stop.load()) { 37 | if (framebuffer->activeFrame != lastFrame) { 38 | notifyChange(true); 39 | lastFrame = framebuffer->activeFrame; 40 | } 41 | // std::this_thread::sleep_for(std::chrono::milliseconds(100)); 42 | } 43 | }); 44 | notifyChange(true); 45 | } 46 | -------------------------------------------------------------------------------- /sw/blocking-sleep/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | enum { 5 | SLEEP_TIME = 5, // In seconds 6 | US_PER_SEC = 1000000, 7 | }; 8 | 9 | /* This is used to quantize a 1MHz value to the closest 32768Hz value */ 10 | #define DIVIDEND ((uint64_t)15625/(uint64_t)512) 11 | 12 | /* Bitmask to extract exception code from mcause register */ 13 | #define MCAUSE_CAUSE 0x7FFFFFFF 14 | 15 | /* Exception code for timer interrupts */ 16 | #define MACHINE_TIMER 7 17 | 18 | /* Set after timer interrupt was received */ 19 | static volatile bool terminate = false; 20 | 21 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x2004000; 22 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x200bff8; 23 | 24 | void irq_handler(void) { 25 | uint32_t mcause; 26 | uint32_t code; 27 | 28 | mcause = 0; 29 | __asm__ volatile ("csrr %[ret], mcause" 30 | : [ret] "=r" (mcause)); 31 | 32 | code = mcause & MCAUSE_CAUSE; 33 | if (code != MACHINE_TIMER || terminate) 34 | __asm__ volatile ("ebreak"); 35 | 36 | // Attempt to clear timer interrupt 37 | *MTIMECMP_REG = UINT64_MAX; 38 | 39 | terminate = true; 40 | return; 41 | } 42 | 43 | int main() { 44 | uint64_t usec = SLEEP_TIME * US_PER_SEC; 45 | uint64_t ticks = usec / DIVIDEND; 46 | 47 | uint64_t target = *MTIME_REG + ticks; 48 | *MTIMECMP_REG = target; 49 | 50 | while (!terminate) 51 | __asm__ volatile ("wfi"); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /sw/crc8/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * utility functions for embedded usage where c-libs are too big 3 | */ 4 | 5 | //---------------------------- 6 | // integer to ascii (itoa) with util functions 7 | //---------------------------- 8 | 9 | // function to swap two numbers 10 | void swap(char *x, char *y) { 11 | char t = *x; 12 | *x = *y; 13 | *y = t; 14 | } 15 | 16 | // function to reverse buffer[i..j] 17 | char* reverse(char *buffer, int i, int j) { 18 | while (i < j) 19 | swap(&buffer[i++], &buffer[j--]); 20 | return buffer; 21 | } 22 | 23 | // Iterative function to implement itoa() function in C 24 | char* itoa(int value, char* buffer, int base) { 25 | // invalid input 26 | if (base < 2 || base > 32) 27 | return buffer; 28 | // consider absolute value of number 29 | int n = (value < 0) ? -value : value; 30 | int i = 0; 31 | while (n) { 32 | int r = n % base; 33 | if (r >= 10) 34 | buffer[i++] = 65 + (r - 10); 35 | else 36 | buffer[i++] = 48 + r; 37 | n = n / base; 38 | } 39 | 40 | // if number is 0 41 | if (i == 0) 42 | buffer[i++] = '0'; 43 | 44 | // If base is 10 and value is negative, the resulting string 45 | // is preceded with a minus sign (-) 46 | // With any other base, value is always considered unsigned 47 | if (value < 0 && base == 10) 48 | buffer[i++] = '-'; 49 | 50 | buffer[i] = '\0'; // null terminate string 51 | 52 | // reverse the string and return it 53 | return reverse(buffer, 0, i - 1); 54 | } 55 | -------------------------------------------------------------------------------- /sw/basic-gpio/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * utility functions for embedded usage where c-libs are too big 3 | */ 4 | 5 | //---------------------------- 6 | // integer to ascii (itoa) with util functions 7 | //---------------------------- 8 | 9 | // function to swap two numbers 10 | void swap(char *x, char *y) { 11 | char t = *x; 12 | *x = *y; 13 | *y = t; 14 | } 15 | 16 | // function to reverse buffer[i..j] 17 | char* reverse(char *buffer, int i, int j) { 18 | while (i < j) 19 | swap(&buffer[i++], &buffer[j--]); 20 | return buffer; 21 | } 22 | 23 | // Iterative function to implement itoa() function in C 24 | char* itoa(int value, char* buffer, int base) { 25 | // invalid input 26 | if (base < 2 || base > 32) 27 | return buffer; 28 | // consider absolute value of number 29 | int n = (value < 0) ? -value : value; 30 | int i = 0; 31 | while (n) { 32 | int r = n % base; 33 | if (r >= 10) 34 | buffer[i++] = 65 + (r - 10); 35 | else 36 | buffer[i++] = 48 + r; 37 | n = n / base; 38 | } 39 | 40 | // if number is 0 41 | if (i == 0) 42 | buffer[i++] = '0'; 43 | 44 | // If base is 10 and value is negative, the resulting string 45 | // is preceded with a minus sign (-) 46 | // With any other base, value is always considered unsigned 47 | if (value < 0 && base == 10) 48 | buffer[i++] = '-'; 49 | 50 | buffer[i] = '\0'; // null terminate string 51 | 52 | // reverse the string and return it 53 | return reverse(buffer, 0, i - 1); 54 | } 55 | -------------------------------------------------------------------------------- /sw/mrv32-uart/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * utility functions for embedded usage where c-libs are too big 3 | */ 4 | 5 | //---------------------------- 6 | // integer to ascii (itoa) with util functions 7 | //---------------------------- 8 | 9 | // function to swap two numbers 10 | void swap(char *x, char *y) { 11 | char t = *x; 12 | *x = *y; 13 | *y = t; 14 | } 15 | 16 | // function to reverse buffer[i..j] 17 | char* reverse(char *buffer, int i, int j) { 18 | while (i < j) 19 | swap(&buffer[i++], &buffer[j--]); 20 | return buffer; 21 | } 22 | 23 | // Iterative function to implement itoa() function in C 24 | char* itoa(int value, char* buffer, int base) { 25 | // invalid input 26 | if (base < 2 || base > 32) 27 | return buffer; 28 | // consider absolute value of number 29 | int n = (value < 0) ? -value : value; 30 | int i = 0; 31 | while (n) { 32 | int r = n % base; 33 | if (r >= 10) 34 | buffer[i++] = 65 + (r - 10); 35 | else 36 | buffer[i++] = 48 + r; 37 | n = n / base; 38 | } 39 | 40 | // if number is 0 41 | if (i == 0) 42 | buffer[i++] = '0'; 43 | 44 | // If base is 10 and value is negative, the resulting string 45 | // is preceded with a minus sign (-) 46 | // With any other base, value is always considered unsigned 47 | if (value < 0 && base == 10) 48 | buffer[i++] = '-'; 49 | 50 | buffer[i] = '\0'; // null terminate string 51 | 52 | // reverse the string and return it 53 | return reverse(buffer, 0, i - 1); 54 | } 55 | -------------------------------------------------------------------------------- /sw/README.md: -------------------------------------------------------------------------------- 1 | These SW examples demonstrate basic bare-metal applications and applications that use the C-library. In particular, the applications using the C-library require support for system calls (syscalls). Syscalls are handled in one of two ways in the VP: 2 | 3 | 1) By default the VP will trigger a trap and thus jump to the trap/interrupt handler. The handler will detect that the reason is a syscall and re-direct the syscall to the syscall handler (or some other peripheral) through memory mapped I/O. This requires to provide and setup a trap handler. This can be done by providing a custom entry-point that performs the required setup and then jumps to the crt0.S entry code of the C-library (which in turn will call the main function). The *printf* SW example demonstrates this case. 4 | 5 | 2) With the "--intercept-syscalls" command line argument, the VP will directly intercept and handle syscalls, hence it is not necessary to setup a trap handler. Thus, no designated startup code (i.e. bootstrap.S) is required to run applications that use the C-library. For example see the *c++-lib* SW example. 6 | 7 | The provided SW examples demonstrate both approaches for dealing with syscalls. 8 | 9 | The VP also supports the FreeRTOS (see https://github.com/agra-uni-bremen/riscv-freertos) and Zephyr (see https://www.zephyrproject.org/ - use the Zephyr *hifive* board option when building Zephyr applications and use the *hifive-vp* configuration for executing them) operating systems. 10 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/response.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "internal.h" 11 | 12 | static char 13 | kind_to_char(gdb_kind_t kind) 14 | { 15 | switch (kind) { 16 | case GDB_KIND_NOTIFY: 17 | return '#'; 18 | case GDB_KIND_PACKET: 19 | return '$'; 20 | case GDB_KIND_NACK: 21 | return '-'; 22 | case GDB_KIND_ACK: 23 | return '+'; 24 | default: 25 | xassert(0); 26 | return -1; 27 | } 28 | } 29 | 30 | char * 31 | gdb_serialize(gdb_kind_t kind, const char *data) 32 | { 33 | size_t pktlen; 34 | char *serialized; 35 | char pktkind; 36 | int csum, ret; 37 | 38 | pktkind = kind_to_char(kind); 39 | if (kind == GDB_KIND_NACK || kind == GDB_KIND_ACK) { 40 | xassert(data == NULL); 41 | serialized = xmalloc(2); /* kind + nullbyte */ 42 | 43 | serialized[0] = pktkind; 44 | serialized[1] = '\0'; 45 | 46 | return serialized; 47 | } 48 | 49 | csum = calc_csum(data); 50 | 51 | /* + 3 → nullbyte, checksum delimiter, kind */ 52 | pktlen = strlen(data) + GDB_CSUM_LEN + 3; 53 | serialized = xmalloc(pktlen); 54 | 55 | ret = snprintf(serialized, pktlen, "%c%s#%.2x", pktkind, data, csum); 56 | if (ret < 0) 57 | err(EXIT_FAILURE, "snprintf failed"); 58 | else if ((size_t)ret >= pktlen) 59 | errx(EXIT_FAILURE, "insufficient snprintf buffer size"); 60 | 61 | return serialized; 62 | } 63 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/oled/common.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * common.hpp 3 | * 4 | * Created on: 24 Sep 2019 5 | * Author: dwd 6 | */ 7 | 8 | #pragma once 9 | #include 10 | #include "util/elegantEnums.hpp" 11 | 12 | namespace ss1106 13 | { 14 | 15 | static constexpr uint8_t width = 132; 16 | static constexpr uint8_t padding_lr = 2; 17 | static constexpr uint8_t height = 64; 18 | static_assert(height%8 == 0, "invalid height"); 19 | static constexpr uint16_t shm_key = 1339; 20 | 21 | struct State 22 | { 23 | uint8_t changed:1; //beh, this is for syncing 24 | 25 | uint8_t column; 26 | uint8_t page; 27 | uint8_t pump_voltage:2; 28 | uint8_t display_startline:6; 29 | uint8_t contrast; 30 | uint8_t segment_remap:1; 31 | uint8_t entire_disp_on:1; 32 | uint8_t invert_color:1; 33 | uint8_t multiplex_whatever:6; 34 | uint8_t display_on:1; 35 | uint8_t frame[(height / 8)][width]; 36 | }; 37 | 38 | State* getSharedState(); 39 | 40 | DECLARE_ENUM(Operator, 41 | COL_LOW, 42 | COL_HIGH, 43 | PUMP_VOLTAGE, 44 | DISPLAY_START_LINE, 45 | CONTRAST_MODE_SET, //Double Command 46 | SEGMENT_REMAP, 47 | ENTIRE_DISPLAY, 48 | NORMAL_INVERSE, 49 | MULTIPLEX_RATIO, //Double command 50 | DC_DC_VOLTAGE, 51 | DISPLAY_ON, 52 | PAGE_ADDR, 53 | COMMON_OUTPUT_DIR, 54 | DISPLAY_OFFSET, //Double command 55 | DISPLAY_DIVIDE_RATIO, //Double command 56 | DIS_PRE_CHARGE_PERIOD, //Double command 57 | COMMON_PADS_STUFF, //DC 58 | VCOM_DESELECT, //DC 59 | RMW, 60 | RMW_END, 61 | NOP 62 | ); 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /sw/basic-gpio/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H 2 | #define PLATFORM_H 3 | 4 | //#define MICRORV 5 | 6 | #ifdef MICRORV 7 | // LED 8 | static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000; 9 | // UART 10 | static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 11 | static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 12 | static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 13 | // CLIC 14 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 15 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 16 | // GPIO 17 | static volatile uint32_t *GPIO_BANK_A_DIRECTION_ADDR = (uint32_t *)0x83000000; 18 | static volatile uint32_t *GPIO_BANK_A_OUTPUT_ADDR = (uint32_t *)0x83000004; 19 | static volatile uint32_t *GPIO_BANK_A_INPUT_ADDR = (uint32_t *)0x83000008; 20 | #else 21 | // LED 22 | static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000; 23 | // UART 24 | static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 25 | static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 26 | static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 27 | // CLIC 28 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 29 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 30 | // GPIO 31 | static volatile uint32_t *GPIO_BANK_A_DIRECTION_ADDR = (uint32_t *)0x83000000; 32 | static volatile uint32_t *GPIO_BANK_A_OUTPUT_ADDR = (uint32_t *)0x83000004; 33 | static volatile uint32_t *GPIO_BANK_A_INPUT_ADDR = (uint32_t *)0x83000008; 34 | #endif 35 | 36 | #endif /* PLATFORM_H */ -------------------------------------------------------------------------------- /env/basic/vp-display/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | #include 4 | #include "framebuffer.h" 5 | #include "ui_mainwindow.h" 6 | 7 | VPDisplay::VPDisplay(QWidget* mparent) : QWidget(mparent) { 8 | framebuffer = server.createSM(); 9 | frame = new QImage(Framebuffer::screenWidth, Framebuffer::screenHeight, 10 | QImage::Format_RGB444); // two bytes per pixel 11 | resize(Framebuffer::screenWidth, Framebuffer::screenHeight); 12 | setFixedSize(size()); 13 | server.startListening(std::bind(&VPDisplay::notifyChange, this, std::placeholders::_1)); 14 | } 15 | 16 | VPDisplay::~VPDisplay() { 17 | delete frame; 18 | } 19 | 20 | void VPDisplay::drawMainPage(QImage* mem) { 21 | Framebuffer::Frame activeFrame = framebuffer->getActiveFrame(); 22 | Framebuffer::Frame background = framebuffer->getBackground(); 23 | for (int row = 0; row < mem->height(); row++) { 24 | uint16_t* line = reinterpret_cast(mem->scanLine(row)); // Two bytes per pixel 25 | for (int x = 0; x < mem->width(); x++) { 26 | line[x] = activeFrame.raw[row][x] == 0 ? background.raw[row][x] : activeFrame.raw[row][x]; 27 | } 28 | } 29 | } 30 | 31 | void VPDisplay::paintEvent(QPaintEvent*) { 32 | QPainter painter(this); 33 | 34 | // painter.scale(size_factor, size_factor); 35 | 36 | // Draw Header 37 | // QPainter mempaint(&memory); 38 | 39 | drawMainPage(frame); 40 | painter.drawImage(QPoint(0, 0), *frame); 41 | painter.end(); 42 | } 43 | 44 | void VPDisplay::notifyChange(bool success) { 45 | assert(success); 46 | update(); 47 | } 48 | -------------------------------------------------------------------------------- /sw/mrv32-uart/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H 2 | #define PLATFORM_H 3 | 4 | /* #define MICRORV 5 | 6 | // #ifdef MICRORV */ 7 | // LED 8 | static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000; 9 | // UART 10 | static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 11 | static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 12 | static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 13 | // CLIC 14 | static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 15 | static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 16 | 17 | typedef struct { 18 | volatile uint32_t TXDATA; 19 | volatile uint32_t TXCTRL; 20 | volatile uint32_t RXDATA; 21 | volatile uint32_t RXOCCU; 22 | volatile uint32_t RXALEM; 23 | volatile uint32_t RXEMPT; 24 | } UART_REGS; 25 | 26 | #define UART ((UART_REGS *)0x82000000) 27 | 28 | /* #else 29 | // // UART 30 | // static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000; 31 | // static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004; 32 | // static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008; 33 | // static volatile uint32_t *UART_RX_FIFO_OCC_ADDR = (uint32_t *)0x8200000c; 34 | // static volatile uint32_t *UART_RX_FIFO_ALMOST_EMPTY_ADDR = (uint32_t *)0x82000010; 35 | // static volatile uint32_t *UART_RX_FIFO_EMPTY_ADDR = (uint32_t *)0x82000014; 36 | 37 | // // CLIC 38 | // static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000; 39 | // static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8; 40 | // #endif */ 41 | 42 | #endif /* PLATFORM_H */ -------------------------------------------------------------------------------- /sw/blocking-sleep/irq.S: -------------------------------------------------------------------------------- 1 | .globl register_handler 2 | .globl lvl0_handler 3 | 4 | .align 4 5 | lvl0_handler: 6 | # Store all register values on the stack 7 | addi sp, sp, -4 * 32 8 | sw x1, 0x0(sp) 9 | sw x4, 3 * 4(sp) 10 | sw x5, 4 * 4(sp) 11 | sw x6, 5 * 4(sp) 12 | sw x7, 6 * 4(sp) 13 | sw x10, 9 * 4(sp) 14 | sw x11, 10 * 4(sp) 15 | sw x12, 11 * 4(sp) 16 | sw x13, 12 * 4(sp) 17 | sw x14, 13 * 4(sp) 18 | sw x15, 14 * 4(sp) 19 | sw x16, 15 * 4(sp) 20 | sw x17, 16 * 4(sp) 21 | sw x28, 27 * 4(sp) 22 | sw x29, 28 * 4(sp) 23 | sw x30, 29 * 4(sp) 24 | sw x31, 30 * 4(sp) 25 | 26 | jal irq_handler 27 | 28 | # Load all register values from the stack and return 29 | lw x1, 0x0(sp) 30 | lw x4, 3 * 4(sp) 31 | lw x5, 4 * 4(sp) 32 | lw x6, 5 * 4(sp) 33 | lw x7, 6 * 4(sp) 34 | lw x10, 9 * 4(sp) 35 | lw x11, 10 * 4(sp) 36 | lw x12, 11 * 4(sp) 37 | lw x13, 12 * 4(sp) 38 | lw x14, 13 * 4(sp) 39 | lw x15, 14 * 4(sp) 40 | lw x16, 15 * 4(sp) 41 | lw x17, 16 * 4(sp) 42 | lw x28, 27 * 4(sp) 43 | lw x29, 28 * 4(sp) 44 | lw x30, 29 * 4(sp) 45 | lw x31, 30 * 4(sp) 46 | addi sp, sp, 4 * 32 47 | mret 48 | 49 | register_handler: 50 | # Use lvl0_handler as the trap handler 51 | la t0, lvl0_handler 52 | csrw mtvec, t0 53 | 54 | # Enable machine external interrupts (MIE bit) 55 | li t1, 0x888 56 | csrw mie, t1 57 | 58 | # Globally enable machine mode interrupts (MIE bit) 59 | li t1, 8 60 | csrw mstatus, t1 61 | 62 | # Return 63 | ret 64 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/README.md: -------------------------------------------------------------------------------- 1 | # libgdb 2 | 3 | Utility library for implementing the [GDB protocol][gdb protocol]. 4 | 5 | ## Design 6 | 7 | Unfortunately, the GDB protocol doesn't use delimiters for protocol 8 | messages. For this reason, a state machine is required to read packets 9 | from a stream. This library implements such a state machine using a 10 | parser combinator library. This state machine only returns a generic 11 | package structure and doesn't perform any further canonicalization. 12 | 13 | Since proper canonicalization of GDB packets is desirable this utility 14 | library provides two parser stages. The first stage is the 15 | aforementioned state machine, the second parser stages performs packet 16 | specific validations and uses the most restrictive input definition on a 17 | per packet basis. 18 | 19 | This library attempts to follow some of the [langsec][langsec website] 20 | principles outlined in [\[1\]][curing the vulnerable parsers]. 21 | Unfortunately, the second stage parser is unfinished at the moment and 22 | has a fallback for accepting arbitrary inputs currently, thereby 23 | circumventing the "most restrictive input definition". 24 | 25 | Additionally, some utility functions for creating responses to received 26 | GDB packets are provided by `libgdb/response.h`. However, this part of 27 | the library is in very early stages of development. 28 | 29 | [gdb protocol]: https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html 30 | [langsec website]: http://langsec.org/ 31 | [curing the vulnerable parsers]: https://www.usenix.org/publications/login/spring2017/bratus 32 | -------------------------------------------------------------------------------- /vp/src/core/rv32/timing/timing_simple.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../iss.h" 4 | 5 | struct SimpleTimingDecorator : public timing_if { 6 | std::array instr_cycles; 7 | sc_core::sc_time cycle_time = sc_core::sc_time(10, sc_core::SC_NS); 8 | 9 | SimpleTimingDecorator() { 10 | for (int i = 0; i < Opcode::NUMBER_OF_INSTRUCTIONS; ++i) instr_cycles[i] = cycle_time; 11 | 12 | const sc_core::sc_time memory_access_cycles = 4 * cycle_time; 13 | const sc_core::sc_time mul_div_cycles = 8 * cycle_time; 14 | 15 | instr_cycles[Opcode::LB] = memory_access_cycles; 16 | instr_cycles[Opcode::LBU] = memory_access_cycles; 17 | instr_cycles[Opcode::LH] = memory_access_cycles; 18 | instr_cycles[Opcode::LHU] = memory_access_cycles; 19 | instr_cycles[Opcode::LW] = memory_access_cycles; 20 | instr_cycles[Opcode::SB] = memory_access_cycles; 21 | instr_cycles[Opcode::SH] = memory_access_cycles; 22 | instr_cycles[Opcode::SW] = memory_access_cycles; 23 | instr_cycles[Opcode::MUL] = mul_div_cycles; 24 | instr_cycles[Opcode::MULH] = mul_div_cycles; 25 | instr_cycles[Opcode::MULHU] = mul_div_cycles; 26 | instr_cycles[Opcode::MULHSU] = mul_div_cycles; 27 | instr_cycles[Opcode::DIV] = mul_div_cycles; 28 | instr_cycles[Opcode::DIVU] = mul_div_cycles; 29 | instr_cycles[Opcode::REM] = mul_div_cycles; 30 | instr_cycles[Opcode::REMU] = mul_div_cycles; 31 | } 32 | 33 | void on_begin_exec_step(Instruction instr, Opcode::mapping op, ISS &iss) override { 34 | auto new_cycles = instr_cycles[op]; 35 | 36 | iss.quantum_keeper.inc(new_cycles); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /vp/src/core/rv64/mem_if.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rv64 { 6 | 7 | struct instr_memory_if { 8 | virtual ~instr_memory_if() {} 9 | 10 | virtual uint32_t load_instr(uint64_t pc) = 0; 11 | }; 12 | 13 | struct data_memory_if { 14 | virtual ~data_memory_if() {} 15 | 16 | virtual int64_t load_double(uint64_t addr) = 0; 17 | virtual int64_t load_word(uint64_t addr) = 0; 18 | virtual int64_t load_half(uint64_t addr) = 0; 19 | virtual int64_t load_byte(uint64_t addr) = 0; 20 | virtual uint64_t load_uword(uint64_t addr) = 0; 21 | virtual uint64_t load_uhalf(uint64_t addr) = 0; 22 | virtual uint64_t load_ubyte(uint64_t addr) = 0; 23 | 24 | virtual void store_double(uint64_t addr, uint64_t value) = 0; 25 | virtual void store_word(uint64_t addr, uint32_t value) = 0; 26 | virtual void store_half(uint64_t addr, uint16_t value) = 0; 27 | virtual void store_byte(uint64_t addr, uint8_t value) = 0; 28 | 29 | virtual int64_t atomic_load_word(uint64_t addr) = 0; 30 | virtual void atomic_store_word(uint64_t addr, uint32_t value) = 0; 31 | virtual int64_t atomic_load_reserved_word(uint64_t addr) = 0; 32 | virtual bool atomic_store_conditional_word(uint64_t addr, uint32_t value) = 0; 33 | virtual void atomic_unlock() = 0; 34 | 35 | virtual int64_t atomic_load_double(uint64_t addr) = 0; 36 | virtual void atomic_store_double(uint64_t addr, uint64_t value) = 0; 37 | virtual int64_t atomic_load_reserved_double(uint64_t addr) = 0; 38 | virtual bool atomic_store_conditional_double(uint64_t addr, uint64_t value) = 0; 39 | 40 | virtual void flush_tlb() = 0; 41 | }; 42 | 43 | } // namespace rv64 -------------------------------------------------------------------------------- /sw/Makefile.common: -------------------------------------------------------------------------------- 1 | RISCV_PREFIX ?= riscv32-unknown-elf- 2 | 3 | override CC = $(RISCV_PREFIX)gcc 4 | override CXX = $(RISCV_PREFIX)g++ 5 | override LD = $(RISCV_PREFIX)gcc 6 | 7 | ASFLAGS ?= $(CFLAGS) 8 | SIM_TARGET ?= sim-default 9 | 10 | # ISA Version 2.2 is the last version where zicsr is still 11 | # supported as part of the base ISA. Use that for now until 12 | # _zicsr is widely supported by existing cross-compilers. 13 | SUPPORTS_MISA ?= $(shell echo "typedef int dont_be_pedantic;" | $(RISCV_PREFIX)gcc -march=rv32imac -mabi=ilp32 -misa-spec=2.2 -E - > /dev/null 2>&1 && echo 1 || echo 0) 14 | ifeq (1,$(SUPPORTS_MISA)) 15 | CFLAGS += -misa-spec=2.2 16 | CXXFLAGS += -misa-spec=2.2 17 | endif 18 | 19 | VP ?= riscv-vp 20 | VP_FLAGS ?= --intercept-syscalls --error-on-zero-traphandler=true 21 | 22 | EXECUTABLE ?= main 23 | OBJECTS ?= main.o 24 | 25 | ######################################################################## 26 | 27 | $(EXECUTABLE): $(OBJECTS) 28 | $(LD) $(CXXFLAGS) $(CFLAGS) -o $@ $(LDFLAGS) $^ $(LDLIBS) 29 | 30 | %.o: %.S 31 | $(CC) $(CPPFLAGS) $(ASFLAGS) -c $< 32 | %.o: %.c 33 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $< 34 | %.o: %.cpp 35 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< 36 | 37 | ######################################################################## 38 | 39 | sim: $(SIM_TARGET) 40 | sim-default: $(EXECUTABLE) 41 | $(VP) $(VP_FLAGS) $< 42 | 43 | dump-elf: $(EXECUTABLE) 44 | $(RISCV_PREFIX)readelf -a main 45 | 46 | dump-code: $(EXECUTABLE) 47 | $(RISCV_PREFIX)objdump -D main 48 | 49 | clean: 50 | rm -f $(OBJECTS) $(EXECUTABLE) $(CLEAN_EXTRA) 51 | 52 | .PHONY: sim sim-default dump-elf dump-code clean 53 | .DEFAULT_GOAL := $(EXECUTABLE) 54 | -------------------------------------------------------------------------------- /vp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | project(riscv-vp 3 | VERSION 1.2.2 4 | ) 5 | 6 | option(USE_SYSTEM_SYSTEMC "use systemc version provided by the system" OFF) 7 | 8 | if(NOT CMAKE_BUILD_TYPE) 9 | set(CMAKE_BUILD_TYPE Debug) 10 | endif() 11 | 12 | set(CMAKE_CXX_STANDARD 17) 13 | set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wpedantic") 14 | set(CMAKE_CXX_FLAGS_DEBUG "-g3") #"-fsanitize=address -fno-omit-frame-pointer" 15 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 16 | 17 | # Allows running tests without invoking `make install` first. 18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 19 | 20 | set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) 21 | 22 | include(cmake/AddGitSubmodule.cmake) 23 | 24 | find_package( Boost REQUIRED COMPONENTS iostreams program_options log) 25 | 26 | if(USE_SYSTEM_SYSTEMC) 27 | find_library(SystemC libsystemc.a) 28 | endif() 29 | 30 | subdirs(src) 31 | 32 | enable_testing() 33 | list(APPEND CMAKE_CTEST_ARGUMENTS "--verbose") 34 | 35 | add_test(NAME libgdb 36 | COMMAND ./test.sh 37 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/libgdb") 38 | add_test(NAME gdb 39 | COMMAND ./test.sh 40 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/gdb") 41 | add_test(NAME integration 42 | COMMAND ./test.sh 43 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/integration") 44 | add_test(NAME sw 45 | COMMAND ./test.sh 46 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/../sw") 47 | 48 | set_tests_properties(gdb integration sw PROPERTIES ENVIRONMENT 49 | PATH=$ENV{PATH}:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) 50 | set_tests_properties(libgdb PROPERTIES ENVIRONMENT 51 | RISCV_VP_BASE=${CMAKE_CURRENT_SOURCE_DIR}/..) 52 | -------------------------------------------------------------------------------- /sw/peripheral-in-the-loop/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../simple-sensor/irq.h" 3 | 4 | typedef uint32_t BUS_BRIDGE_TYPE; 5 | static volatile BUS_BRIDGE_TYPE * const BUS_BRIDGE_START = (BUS_BRIDGE_TYPE * const) 0x50000000; 6 | static volatile BUS_BRIDGE_TYPE * const BUS_BRIDGE_END = (BUS_BRIDGE_TYPE * const) 0x5000000F; // INCLUSIVE 7 | static const unsigned BUS_BRIDGE_ITR = 2; 8 | static volatile char * const TERMINAL_ADDR = (char * const)0x20000000; 9 | 10 | static const unsigned num_words = (BUS_BRIDGE_END - BUS_BRIDGE_START) + 1; // INCLUSIVE 11 | 12 | void read_stuff() { 13 | for (int i = 0; i < num_words; i++) { 14 | const BUS_BRIDGE_TYPE datum = BUS_BRIDGE_START[i]; 15 | for(int c = 0; c < sizeof(BUS_BRIDGE_TYPE); c++) { 16 | *TERMINAL_ADDR = ((uint8_t*)&datum)[c]; 17 | } 18 | *TERMINAL_ADDR = '\n'; 19 | } 20 | } 21 | 22 | void write_stuff() { 23 | for (int i = 0; i < num_words; i++) { 24 | BUS_BRIDGE_TYPE datum; 25 | for(int c = 0; c < sizeof(BUS_BRIDGE_TYPE); c++) { 26 | ((uint8_t*)&datum)[c] = 'a' + (i+c); 27 | *TERMINAL_ADDR = ((uint8_t*)&datum)[c]; 28 | } 29 | BUS_BRIDGE_START[i] = datum; 30 | *TERMINAL_ADDR = '\n'; 31 | } 32 | } 33 | 34 | volatile int was_itr_triggered = 0; 35 | void virtual_bus_irq_handler() { 36 | static const char* hi = "Interrupt was triggered\n"; 37 | was_itr_triggered = 1; 38 | for(int i = 0; hi[i]; i++) 39 | *TERMINAL_ADDR = hi[i]; 40 | } 41 | 42 | int main() { 43 | register_interrupt_handler(BUS_BRIDGE_ITR, virtual_bus_irq_handler); 44 | 45 | read_stuff(); 46 | 47 | /* 48 | while(!was_itr_triggered) 49 | asm volatile ("wfi"); 50 | */ 51 | 52 | write_stuff(); 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/prci.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_PRCI_H 2 | #define RISCV_VP_PRCI_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "core/common/irq_if.h" 9 | #include "util/tlm_map.h" 10 | 11 | struct PRCI : public sc_core::sc_module { 12 | tlm_utils::simple_target_socket tsock; 13 | 14 | // memory mapped configuration registers 15 | uint32_t hfrosccfg = 0; 16 | uint32_t hfxosccfg = 0; 17 | uint32_t pllcfg = 0; 18 | uint32_t plloutdiv = 0; 19 | 20 | enum { 21 | HFROSCCFG_REG_ADDR = 0x0, 22 | HFXOSCCFG_REG_ADDR = 0x4, 23 | PLLCFG_REG_ADDR = 0x8, 24 | PLLOUTDIV_REG_ADDR = 0xC, 25 | }; 26 | 27 | vp::map::LocalRouter router = {"PRCI"}; 28 | 29 | PRCI(sc_core::sc_module_name) { 30 | tsock.register_b_transport(this, &PRCI::transport); 31 | 32 | router 33 | .add_register_bank({ 34 | {HFROSCCFG_REG_ADDR, &hfrosccfg}, 35 | {HFXOSCCFG_REG_ADDR, &hfxosccfg}, 36 | {PLLCFG_REG_ADDR, &pllcfg}, 37 | {PLLOUTDIV_REG_ADDR, &plloutdiv}, 38 | }) 39 | .register_handler(this, &PRCI::register_access_callback); 40 | } 41 | 42 | void register_access_callback(const vp::map::register_access_t &r) { 43 | /* Pretend that the crystal oscillator output is always ready. */ 44 | if (r.read && r.vptr == &hfxosccfg) 45 | hfxosccfg = 1 << 31; 46 | 47 | r.fn(); 48 | 49 | if ((r.vptr == &hfrosccfg) && r.nv) 50 | hfrosccfg |= 1 << 31; 51 | 52 | if ((r.vptr == &pllcfg) && r.nv) 53 | pllcfg |= 1 << 31; 54 | } 55 | 56 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 57 | router.transport(trans, delay); 58 | } 59 | }; 60 | 61 | #endif // RISCV_VP_PRCI_H 62 | -------------------------------------------------------------------------------- /sw/simple-scheduler/cor.S: -------------------------------------------------------------------------------- 1 | .globl contextswitch 2 | .globl coroutine_entry 3 | .globl launch_coroutine 4 | 5 | 6 | coroutine_entry: 7 | // move the launch argument to the a0 register (i.e. first argument of the following function) 8 | mv a0,s0 9 | call launch_coroutine 10 | 11 | // the above call should not return (i.e the scheduler should not call a finished coroutine) 12 | ebreak 13 | 14 | 15 | /* 16 | * registers a0 and a1 point to the current and next context, respectively 17 | * 18 | * 1) store all current registers and pc in the current context 19 | * 2) load register values from next context 20 | * 3) jump to pc in the next context 21 | */ 22 | contextswitch: 23 | // store registers 24 | sw x1,4(a0) // ra 25 | sw x2,8(a0) // sp 26 | sw x8,32(a0) // s0 27 | sw x9,36(a0) // s1 28 | sw x18,72(a0) // s2 29 | sw x19,76(a0) // s3 30 | sw x20,80(a0) // s4 31 | sw x21,84(a0) // s5 32 | sw x22,88(a0) // s6 33 | sw x23,92(a0) // s7 34 | sw x24,96(a0) // s8 35 | sw x25,100(a0) // s9 36 | sw x26,104(a0) // s10 37 | sw x27,108(a0) // s11 38 | 39 | // store pc 40 | la t0,_resume 41 | sw t0,0(a0) 42 | 43 | // restore other registers (NOTE: callee saved only + ra) 44 | lw x1,4(a1) // ra 45 | lw x2,8(a1) // sp 46 | lw x8,32(a1) // s0 47 | lw x9,36(a1) // s1 48 | lw x18,72(a1) // s2 49 | lw x19,76(a1) // s3 50 | lw x20,80(a1) // s4 51 | lw x21,84(a1) // s5 52 | lw x22,88(a1) // s6 53 | lw x23,92(a1) // s7 54 | lw x24,96(a1) // s8 55 | lw x25,100(a1) // s9 56 | lw x26,104(a1) // s10 57 | lw x27,108(a1) // s11 58 | 59 | // load new program counter and perform context switch 60 | lw t0,0(a1) 61 | jr t0 62 | 63 | _resume: 64 | 65 | ret 66 | 67 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/can/cantest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * cantest.cpp 3 | * 4 | * Created on: 22 Mar 2019 5 | * Author: dwd 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | int main(int argc, char* argv[]) { 22 | int s; 23 | struct sockaddr_can addr; 24 | struct ifreq ifr; 25 | 26 | s = socket(PF_CAN, SOCK_RAW, CAN_RAW); 27 | if (s < 0) { 28 | perror("Could not open socket!"); 29 | } 30 | 31 | memset(&ifr, 0, sizeof(struct ifreq)); 32 | strcpy(ifr.ifr_name, "slcan0"); 33 | if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 34 | perror("Could not ctl to device"); 35 | } 36 | 37 | addr.can_family = AF_CAN; 38 | addr.can_ifindex = ifr.ifr_ifindex; 39 | 40 | if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 41 | perror("Could not bind to can family"); 42 | } 43 | 44 | // while(true) 45 | { 46 | struct can_frame frame; 47 | 48 | int nbytes = read(s, &frame, sizeof(struct can_frame)); 49 | 50 | if (nbytes < 0) { 51 | perror("can raw socket read"); 52 | return 1; 53 | } 54 | 55 | /* paranoid check ... */ 56 | if (nbytes < sizeof(struct can_frame)) { 57 | fprintf(stderr, "read: incomplete CAN frame\n"); 58 | return 1; 59 | } 60 | 61 | /* do something with the received CAN frame */ 62 | 63 | cout << "received id " << frame.can_id << " len " << unsigned(frame.can_dlc) << endl; 64 | 65 | for (uint8_t i = 0; i < frame.can_dlc; i++) { 66 | printf("%s%02X", i > 0 ? " " : "", frame.data[i]); 67 | } 68 | cout << endl; 69 | 70 | nbytes = write(s, &frame, sizeof(struct can_frame)); 71 | } 72 | close(s); 73 | } 74 | -------------------------------------------------------------------------------- /vp/src/platform/microrv32/microrv32_gpio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | struct MicroRV32GPIO : public sc_core::sc_module { 11 | tlm_utils::simple_target_socket tsock; 12 | 13 | sc_core::sc_event run_event; 14 | // each bit represents a pin in each register 15 | uint8_t direction = 0; // direction of pins, 0: input (read pin), 1: output (write pin) 16 | uint8_t input = 0; // incomming, read pin values 17 | uint8_t output = 0; // outgoing pin values 18 | 19 | SC_HAS_PROCESS(MicroRV32GPIO); 20 | 21 | MicroRV32GPIO(sc_core::sc_module_name) { 22 | tsock.register_b_transport(this, &MicroRV32GPIO::transport); 23 | } 24 | 25 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 26 | auto addr = trans.get_address(); 27 | auto cmd = trans.get_command(); 28 | // auto len = trans.get_data_length(); 29 | auto ptr = trans.get_data_ptr(); 30 | 31 | if (cmd == tlm::TLM_WRITE_COMMAND) { 32 | if (addr == 0) { 33 | direction = *ptr; 34 | // printf("\n[TLM] GPIO direction write: %X\n", *ptr); 35 | } else if (addr == 4) { 36 | output = *ptr; 37 | // printf("\n[TLM] GPIO output write: %X\n", *ptr); 38 | } 39 | } else if (cmd == tlm::TLM_READ_COMMAND) { 40 | if (addr == 0) { 41 | *((uint32_t*)ptr) = direction; 42 | } else if (addr == 4) { 43 | *((uint32_t*)ptr) = output; 44 | } else if (addr == 8) { 45 | *((uint32_t*)ptr) = input; 46 | } 47 | } 48 | 49 | (void)delay; // zero delay 50 | } 51 | /* 52 | * TODO for future : generate data for GPIO input register 53 | * a) generate random data 54 | * b) read file with timestamp and value for input register 55 | * c) accept values for input register from socket/outside vp 56 | */ 57 | }; 58 | -------------------------------------------------------------------------------- /sw/clock-ticks/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl main 3 | .globl level_1_interrupt_handler 4 | 5 | _start: 6 | la t0, level_0_interrupt_handler 7 | csrw mtvec, t0 8 | li t1, 0x888 9 | csrw mie, t1 10 | csrwi mstatus, 8 11 | jal main 12 | 13 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 14 | li a7,93 15 | li a0,0 16 | ecall 17 | 18 | 19 | /* 20 | * Interrupt handler for non-nested interrupts. Only selected registers are stored/re-stored, i.e. those not preserved on function calls. 21 | */ 22 | #define STORE sw 23 | #define LOAD lw 24 | #define REGBYTES 4 25 | 26 | .align 4 27 | level_0_interrupt_handler: 28 | // store execution context on the stack (register content) 29 | addi sp, sp, -REGBYTES * 32 30 | STORE x1, 0x0(sp) 31 | STORE x4, 3 * REGBYTES(sp) 32 | STORE x5, 4 * REGBYTES(sp) 33 | STORE x6, 5 * REGBYTES(sp) 34 | STORE x7, 6 * REGBYTES(sp) 35 | STORE x10, 9 * REGBYTES(sp) 36 | STORE x11, 10 * REGBYTES(sp) 37 | STORE x12, 11 * REGBYTES(sp) 38 | STORE x13, 12 * REGBYTES(sp) 39 | STORE x14, 13 * REGBYTES(sp) 40 | STORE x15, 14 * REGBYTES(sp) 41 | STORE x16, 15 * REGBYTES(sp) 42 | STORE x17, 16 * REGBYTES(sp) 43 | STORE x28, 27 * REGBYTES(sp) 44 | STORE x29, 28 * REGBYTES(sp) 45 | STORE x30, 29 * REGBYTES(sp) 46 | STORE x31, 30 * REGBYTES(sp) 47 | 48 | // load interrupt/trap reason and call external C function to handle it 49 | csrr a0, mcause 50 | jal level_1_interrupt_handler 51 | 52 | // re-store the saved context 53 | LOAD x1, 0x0(sp) 54 | LOAD x4, 3 * REGBYTES(sp) 55 | LOAD x5, 4 * REGBYTES(sp) 56 | LOAD x6, 5 * REGBYTES(sp) 57 | LOAD x7, 6 * REGBYTES(sp) 58 | LOAD x10, 9 * REGBYTES(sp) 59 | LOAD x11, 10 * REGBYTES(sp) 60 | LOAD x12, 11 * REGBYTES(sp) 61 | LOAD x13, 12 * REGBYTES(sp) 62 | LOAD x14, 13 * REGBYTES(sp) 63 | LOAD x15, 14 * REGBYTES(sp) 64 | LOAD x16, 15 * REGBYTES(sp) 65 | LOAD x17, 16 * REGBYTES(sp) 66 | LOAD x28, 27 * REGBYTES(sp) 67 | LOAD x29, 28 * REGBYTES(sp) 68 | LOAD x30, 29 * REGBYTES(sp) 69 | LOAD x31, 30 * REGBYTES(sp) 70 | addi sp, sp, REGBYTES * 32 71 | mret 72 | 73 | -------------------------------------------------------------------------------- /vp/src/platform/linux/prci.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_PRCI_H 2 | #define RISCV_VP_PRCI_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "core/common/irq_if.h" 9 | #include "util/tlm_map.h" 10 | 11 | struct PRCI : public sc_core::sc_module { 12 | tlm_utils::simple_target_socket tsock; 13 | 14 | // memory mapped configuration registers 15 | uint32_t hfrosccfg = 0; 16 | uint32_t core_pllcfg0 = 0; 17 | uint32_t ddr_pllcfg0 = 0; 18 | uint32_t core_pllcfg1 = 0; 19 | uint32_t gemgxl_pllcfg0 = 0; 20 | uint32_t gemgxl_pllcfg1 = 0; 21 | uint32_t core_clksel = 0; 22 | uint32_t reset = 0; 23 | uint32_t clkmux_status = 0; 24 | 25 | enum { 26 | HFROSCCFG_REG_ADDR = 0x0, 27 | CORE_PLLCFG0_REG_ADDR = 0x4, 28 | DDR_PLLCFG0_REG_ADDR = 0x8, 29 | CORE_PLLCFG1_REG_ADDR = 0x10, 30 | GEMGXL_PLLCFG0_REG_ADDR = 0x1C, 31 | GEMGXL_PLLCFG1_REG_ADDR = 0x20, 32 | CORE_CLKSEL_REG_ADDR = 0x24, 33 | RESET_REG_ADDR = 0x28, 34 | CLKMUX_STATUS_REG_ADDR = 0x2C, 35 | }; 36 | 37 | vp::map::LocalRouter router = {"PRCI"}; 38 | 39 | PRCI(sc_core::sc_module_name) { 40 | tsock.register_b_transport(this, &PRCI::transport); 41 | 42 | router 43 | .add_register_bank({ 44 | {HFROSCCFG_REG_ADDR, &hfrosccfg}, 45 | {CORE_PLLCFG0_REG_ADDR, &core_pllcfg0}, 46 | {DDR_PLLCFG0_REG_ADDR, &ddr_pllcfg0}, 47 | {CORE_PLLCFG1_REG_ADDR, &core_pllcfg1}, 48 | {GEMGXL_PLLCFG0_REG_ADDR, &gemgxl_pllcfg0}, 49 | {GEMGXL_PLLCFG1_REG_ADDR, &gemgxl_pllcfg1}, 50 | {CORE_CLKSEL_REG_ADDR, &core_clksel}, 51 | {RESET_REG_ADDR, &reset}, 52 | {CLKMUX_STATUS_REG_ADDR, &clkmux_status}, 53 | }) 54 | .register_handler(this, &PRCI::register_access_callback); 55 | } 56 | 57 | void register_access_callback(const vp::map::register_access_t &r) { 58 | r.fn(); 59 | 60 | /* TODO: not implemented yet, this is a stub */ 61 | } 62 | 63 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 64 | router.transport(trans, delay); 65 | } 66 | }; 67 | 68 | #endif // RISCV_VP_PRCI_H 69 | -------------------------------------------------------------------------------- /vp/src/platform/hifive/tunnel-uart.cpp: -------------------------------------------------------------------------------- 1 | #include "tunnel-uart.hpp" 2 | 3 | #include 4 | 5 | Tunnel_UART::Tunnel_UART(sc_core::sc_module_name name, uint32_t irqsrc) : UART_IF(name, irqsrc) 6 | { 7 | stop = false; 8 | rx_worker = std::thread(std::bind(&Tunnel_UART::rx_dequeue, this)); 9 | }; 10 | 11 | Tunnel_UART::~Tunnel_UART(){ 12 | stop = true; 13 | if(rx_worker.joinable()) { 14 | spost(&rxempty); // unblock receive thread 15 | rx_worker.join(); 16 | } 17 | if(tx_worker.joinable()) { 18 | spost(&txfull); // unblock transmit thread 19 | } 20 | } 21 | 22 | void Tunnel_UART::nonblock_receive(gpio::UART_Bytes bytes) { 23 | const std::lock_guard lock(nonblock_rx_mutex); 24 | if(nonblocking_rx_queue.size() > DROP_AT_FIFO_DEPTH - UART_FIFO_DEPTH) { 25 | std::cerr << "[tunnel-uart] Warn: pre-rx_queue growing to " << nonblocking_rx_queue.size() << " byte." << std::endl; 26 | std::cerr << " The VP can probably not keep up with the remote." << std::endl; 27 | } 28 | if(nonblocking_rx_queue.size() > DROP_AT_FIFO_DEPTH) { 29 | // Dropping elements 30 | return; 31 | } 32 | for(const auto& byte : bytes) { 33 | nonblocking_rx_queue.push(byte); 34 | } 35 | } 36 | 37 | void Tunnel_UART::register_transmit_function(UartTXFunction fun) { 38 | tx_worker = std::thread(std::bind(&Tunnel_UART::tx_dequeue, this, fun)); 39 | } 40 | 41 | void Tunnel_UART::rx_dequeue() { 42 | while(!stop) { 43 | nonblock_rx_mutex.lock(); 44 | if(!nonblocking_rx_queue.empty() && !stop){ 45 | gpio::UART_Byte byte = nonblocking_rx_queue.front(); 46 | nonblocking_rx_queue.pop(); 47 | nonblock_rx_mutex.unlock(); 48 | rxpush(byte); // may block 49 | } else { 50 | nonblock_rx_mutex.unlock(); 51 | } 52 | } 53 | } 54 | 55 | void Tunnel_UART::tx_dequeue(UartTXFunction fun) { 56 | while(!stop) { 57 | // TODO: Perhaps make this a SysC-Thread for more realism? 58 | const auto data = txpull(); // TODO: Optimize if more elems are in tx queue 59 | if(stop) 60 | break; 61 | fun(gpio::UART_Bytes{data}); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vp/src/platform/linux32/prci.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_PRCI_H 2 | #define RISCV_VP_PRCI_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "core/common/irq_if.h" 9 | #include "util/tlm_map.h" 10 | 11 | struct PRCI : public sc_core::sc_module { 12 | tlm_utils::simple_target_socket tsock; 13 | 14 | // memory mapped configuration registers 15 | uint32_t hfrosccfg = 0; 16 | uint32_t core_pllcfg0 = 0; 17 | uint32_t ddr_pllcfg0 = 0; 18 | uint32_t core_pllcfg1 = 0; 19 | uint32_t gemgxl_pllcfg0 = 0; 20 | uint32_t gemgxl_pllcfg1 = 0; 21 | uint32_t core_clksel = 0; 22 | uint32_t reset = 0; 23 | uint32_t clkmux_status = 0; 24 | 25 | enum { 26 | HFROSCCFG_REG_ADDR = 0x0, 27 | CORE_PLLCFG0_REG_ADDR = 0x4, 28 | DDR_PLLCFG0_REG_ADDR = 0x8, 29 | CORE_PLLCFG1_REG_ADDR = 0x10, 30 | GEMGXL_PLLCFG0_REG_ADDR = 0x1C, 31 | GEMGXL_PLLCFG1_REG_ADDR = 0x20, 32 | CORE_CLKSEL_REG_ADDR = 0x24, 33 | RESET_REG_ADDR = 0x28, 34 | CLKMUX_STATUS_REG_ADDR = 0x2C, 35 | }; 36 | 37 | vp::map::LocalRouter router = {"PRCI"}; 38 | 39 | PRCI(sc_core::sc_module_name) { 40 | tsock.register_b_transport(this, &PRCI::transport); 41 | 42 | router 43 | .add_register_bank({ 44 | {HFROSCCFG_REG_ADDR, &hfrosccfg}, 45 | {CORE_PLLCFG0_REG_ADDR, &core_pllcfg0}, 46 | {DDR_PLLCFG0_REG_ADDR, &ddr_pllcfg0}, 47 | {CORE_PLLCFG1_REG_ADDR, &core_pllcfg1}, 48 | {GEMGXL_PLLCFG0_REG_ADDR, &gemgxl_pllcfg0}, 49 | {GEMGXL_PLLCFG1_REG_ADDR, &gemgxl_pllcfg1}, 50 | {CORE_CLKSEL_REG_ADDR, &core_clksel}, 51 | {RESET_REG_ADDR, &reset}, 52 | {CLKMUX_STATUS_REG_ADDR, &clkmux_status}, 53 | }) 54 | .register_handler(this, &PRCI::register_access_callback); 55 | } 56 | 57 | void register_access_callback(const vp::map::register_access_t &r) { 58 | r.fn(); 59 | 60 | /* TODO: not implemented yet, this is a stub */ 61 | } 62 | 63 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 64 | router.transport(trans, delay); 65 | } 66 | }; 67 | 68 | #endif // RISCV_VP_PRCI_H 69 | -------------------------------------------------------------------------------- /sw/flashTest/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // From flash.h 6 | static constexpr unsigned int BLOCKSIZE = 512; 7 | static constexpr unsigned int FLASH_ADDR_REG = 0; 8 | static constexpr unsigned int FLASH_SIZE_REG = sizeof(uint64_t); 9 | static constexpr unsigned int DATA_ADDR = FLASH_SIZE_REG + sizeof(uint64_t); 10 | // static constexpr unsigned int ADDR_SPACE = DATA_ADDR + BLOCKSIZE; 11 | 12 | static uint8_t* volatile const FLASH_CONTROLLER = (uint8_t * volatile const)(0x71000000); 13 | 14 | using namespace std; 15 | 16 | void setTargetBlock(uint64_t addr); 17 | void readFlash(char* dst, uint64_t addr, size_t len); 18 | void writeFlash(const char* src, uint64_t addr, size_t len); 19 | 20 | int main() { 21 | unsigned long counter = 0; 22 | uint64_t flashNumOfBlocks = 0; 23 | memcpy(&flashNumOfBlocks, FLASH_CONTROLLER + FLASH_SIZE_REG, sizeof(uint64_t)); 24 | 25 | cout << "Flash size: " << flashNumOfBlocks * BLOCKSIZE << " (" << flashNumOfBlocks << " Blocks)" << endl; 26 | 27 | readFlash(reinterpret_cast(&counter), 0, sizeof(unsigned long)); 28 | 29 | cout << " Counter before: " << counter << endl; 30 | 31 | writeFlash(reinterpret_cast(&++counter), 0, sizeof(unsigned long)); 32 | 33 | cout << " Counter after: " << counter << endl; 34 | } 35 | 36 | void setTargetBlock(uint64_t addr) { 37 | uint64_t targetBlock = addr % BLOCKSIZE; 38 | memcpy(FLASH_CONTROLLER + FLASH_ADDR_REG, &targetBlock, sizeof(uint64_t)); 39 | } 40 | 41 | void readFlash(char* dst, uint64_t addr, size_t len) { 42 | if (addr / BLOCKSIZE != (addr + len) / BLOCKSIZE) { 43 | cerr << "Unaligned read, currently not supported" << endl; 44 | return; 45 | } 46 | setTargetBlock(addr); 47 | memcpy(dst, FLASH_CONTROLLER + DATA_ADDR, len); 48 | } 49 | 50 | void writeFlash(const char* src, uint64_t addr, size_t len) { 51 | if (addr / BLOCKSIZE != (addr + len) / BLOCKSIZE) { 52 | cerr << "Unaligned read, currently not supported" << endl; 53 | return; 54 | } 55 | setTargetBlock(addr); 56 | memcpy(FLASH_CONTROLLER + DATA_ADDR, src, len); 57 | } 58 | -------------------------------------------------------------------------------- /env/basic/vp-display/framebuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #define SHMKEY 1338 7 | 8 | struct Framebuffer { 9 | static constexpr uint16_t screenWidth = 800; 10 | static constexpr uint16_t screenHeight = 600; 11 | 12 | typedef uint16_t Color; 13 | 14 | struct Point { 15 | uint32_t x; 16 | uint32_t y; 17 | inline Point() : x(0), y(0){}; 18 | inline Point(uint32_t x, uint32_t y) : x(x), y(y){}; 19 | }; 20 | 21 | struct PointF { 22 | float x; 23 | float y; 24 | inline PointF() : x(0), y(0){}; 25 | inline PointF(float x, float y) : x(x), y(y){}; 26 | inline PointF(Point p) : x(p.x), y(p.y){}; 27 | }; 28 | 29 | struct Frame { 30 | Color raw[screenHeight][screenWidth]; // Notice: Screen is on side 31 | }; 32 | 33 | enum class Type : uint8_t { foreground, background }; 34 | uint8_t activeFrame; 35 | enum class Command : uint8_t { 36 | none = 0, 37 | clearAll, 38 | fillFrame, 39 | applyFrame, 40 | drawLine, 41 | } volatile command; 42 | union Parameter { 43 | struct { 44 | //fillframe 45 | Type frame; 46 | Color color; 47 | } fill; 48 | struct { 49 | //drawLine 50 | Type frame; 51 | PointF from; 52 | PointF to; 53 | Color color; 54 | } line; 55 | inline Parameter(){}; 56 | } parameter; 57 | Frame frames[2]; 58 | Frame background; 59 | 60 | Framebuffer() : activeFrame(0), command(Command::none){}; 61 | 62 | Frame& getActiveFrame() { 63 | return frames[activeFrame % 2]; 64 | } 65 | Frame& getInactiveFrame() { 66 | return frames[(activeFrame + 1) % 2]; 67 | } 68 | Frame& getBackground() { 69 | return background; 70 | } 71 | Frame& getFrame(Type type) { 72 | if (type == Type::foreground) 73 | return getInactiveFrame(); 74 | else if (type == Type::background) 75 | return getBackground(); 76 | 77 | assert(false && "Get invalid frame type"); 78 | return background; 79 | } 80 | }; 81 | 82 | 83 | inline Framebuffer::PointF operator+(const Framebuffer::PointF l, Framebuffer::PointF const r) { 84 | return Framebuffer::PointF(l.x + r.x, l.y + r.y); 85 | } 86 | -------------------------------------------------------------------------------- /vp/src/core/common/dmi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class MemoryDMI { 6 | uint8_t *mem; 7 | uint64_t start; 8 | uint64_t size; 9 | uint64_t end; 10 | 11 | MemoryDMI(uint8_t *mem, uint64_t start, uint64_t size) : mem(mem), start(start), size(size), end(start + size) {} 12 | 13 | public: 14 | static MemoryDMI create_start_end_mapping(uint8_t *mem, uint64_t start, uint64_t end) { 15 | assert(end > start); 16 | return create_start_size_mapping(mem, start, end - start); 17 | } 18 | 19 | static MemoryDMI create_start_size_mapping(uint8_t *mem, uint64_t start, uint64_t size) { 20 | assert(start + size > start); 21 | return MemoryDMI(mem, start, size); 22 | } 23 | 24 | uint8_t *get_raw_mem_ptr() { 25 | return mem; 26 | } 27 | 28 | template 29 | T *get_mem_ptr_to_global_addr(uint64_t addr) { 30 | assert(contains(addr)); 31 | assert((addr + sizeof(T)) <= end); 32 | // assert ((addr % sizeof(T)) == 0 && "unaligned access"); //NOTE: due to compressed instructions, fetching 33 | // can be unaligned 34 | return reinterpret_cast(mem + (addr - start)); 35 | } 36 | 37 | template 38 | T load(uint64_t addr) { 39 | static_assert(std::is_integral::value, "integer type required"); 40 | T ans; 41 | T *src = get_mem_ptr_to_global_addr(addr); 42 | // use memcpy to avoid problems with unaligned loads into standard C++ data types 43 | // see: https://blog.quarkslab.com/unaligned-accesses-in-cc-what-why-and-solutions-to-do-it-properly.html 44 | memcpy(&ans, src, sizeof(T)); 45 | return ans; 46 | } 47 | 48 | template 49 | void store(uint64_t addr, T value) { 50 | static_assert(std::is_integral::value, "integer type required"); 51 | T *dst = get_mem_ptr_to_global_addr(addr); 52 | memcpy(dst, &value, sizeof(value)); 53 | } 54 | 55 | uint64_t get_start() { 56 | return start; 57 | } 58 | 59 | uint64_t get_end() { 60 | return start + size; 61 | } 62 | 63 | uint64_t get_size() { 64 | return size; 65 | } 66 | 67 | bool contains(uint64_t addr) { 68 | return addr >= start && addr < end; 69 | } 70 | }; -------------------------------------------------------------------------------- /vp/src/platform/hifive/maskROM.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "core/common/irq_if.h" 8 | #include "util/tlm_map.h" 9 | 10 | #include 11 | 12 | struct MaskROM : public sc_core::sc_module { 13 | tlm_utils::simple_target_socket tsock; 14 | 15 | const uint32_t baseAddr = 0x1000; 16 | const uint32_t configStringOffs = 0x03b0; 17 | const char *configString = 18 | "/cs-v1/;" 19 | "/{" 20 | "model = \"SiFive,FE310G-0000-Z0\";" 21 | "compatible = \"sifive,fe300\";" 22 | "/include/ 0x20004;" 23 | "};"; 24 | 25 | MaskROM(sc_core::sc_module_name) { 26 | tsock.register_b_transport(this, &MaskROM::transport); 27 | } 28 | 29 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) { 30 | tlm::tlm_command cmd = trans.get_command(); 31 | unsigned addr = trans.get_address(); 32 | auto *ptr = trans.get_data_ptr(); 33 | auto len = trans.get_data_length(); 34 | 35 | if (cmd != tlm::TLM_READ_COMMAND) { 36 | throw(std::runtime_error("invalid write to MROM")); 37 | } 38 | 39 | if (addr < 0x000C) { // should contain jump to OTP 40 | memset(ptr, 0, len); 41 | return; 42 | } 43 | 44 | if (addr + len <= 0x000C + sizeof(uint32_t)) { 45 | uint32_t buf = baseAddr + configStringOffs; 46 | memcpy(ptr, &buf, sizeof(uint32_t)); 47 | delay += sc_core::sc_time(len * 5, sc_core::SC_NS); 48 | return; 49 | } 50 | 51 | if (addr < configStringOffs) { 52 | std::cerr << "invalid access to Mask-ROM at " << std::hex << addr << std::endl; 53 | assert(false); 54 | return; 55 | } 56 | 57 | if (addr < configStringOffs + strlen(configString)) { 58 | uint32_t offs = addr - configStringOffs; 59 | uint8_t cut = offs + len <= strlen(configString) ? len : (offs + len) - strlen(configString); 60 | memcpy(ptr, &configString[offs], cut); 61 | if (cut != len) { 62 | memset(&ptr[cut], 0, len - cut); 63 | } 64 | return; 65 | } 66 | 67 | memset(ptr, 0, len); 68 | delay += sc_core::sc_time(len * 5, sc_core::SC_NS); 69 | 70 | return; 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /vp/src/core/common/real_clint.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_VP_REAL_CLINT_H 2 | #define RISCV_VP_REAL_CLINT_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "platform/common/async_event.h" 12 | #include "util/memory_map.h" 13 | #include "clint_if.h" 14 | #include "irq_if.h" 15 | #include "timer.h" 16 | 17 | // This class implements a CLINT as specified in the FE310-G000 manual 18 | // and the RISC-V Privileged Specification. As per the FE310-G000 19 | // manual, this CLINT uses an input clock which runs at a frequency of 20 | // 32.768 kHz. Currently, this frequency cannot be configured. 21 | // 22 | // Contrary to the CLINT class, also provided in this directory, this 23 | // CLINT is based on "real time" instead of SystemC simulation time. 24 | class RealCLINT : public clint_if, public sc_core::sc_module { 25 | public: 26 | RealCLINT(sc_core::sc_module_name, std::vector&); 27 | ~RealCLINT(void); 28 | 29 | tlm_utils::simple_target_socket tsock; 30 | uint64_t update_and_get_mtime(void) override; 31 | 32 | SC_HAS_PROCESS(RealCLINT); 33 | public: 34 | typedef std::chrono::high_resolution_clock::time_point time_point; 35 | typedef Timer::usecs usecs; 36 | 37 | RegisterRange regs_msip; 38 | RegisterRange regs_mtimecmp; 39 | RegisterRange regs_mtime; 40 | 41 | ArrayView msip; 42 | ArrayView mtimecmp; 43 | IntegerView mtime; 44 | 45 | std::vector register_ranges; 46 | std::vector &harts; 47 | 48 | AsyncEvent event; 49 | std::vector timers; 50 | 51 | time_point first_mtime; 52 | 53 | void post_write_mtimecmp(RegisterRange::WriteInfo info); 54 | void post_write_msip(RegisterRange::WriteInfo info); 55 | void post_write_mtime(RegisterRange::WriteInfo info); 56 | bool pre_read_mtime(RegisterRange::ReadInfo info); 57 | 58 | uint64_t usec_to_ticks(usecs usec); 59 | usecs ticks_to_usec(uint64_t ticks); 60 | 61 | void interrupt(void); 62 | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay); 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /vp/src/core/rv32/elf_loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/common/elf_loader.h" 4 | 5 | namespace rv32 { 6 | 7 | // see: http://wiki.osdev.org/ELF_Tutorial for ELF definitions 8 | 9 | typedef uint16_t Elf32_Half; // Unsigned half int 10 | typedef uint32_t Elf32_Off; // Unsigned offset 11 | typedef uint32_t Elf32_Addr; // Unsigned address 12 | typedef uint32_t Elf32_Word; // Unsigned int 13 | typedef int32_t Elf32_Sword; // Signed int 14 | 15 | constexpr unsigned ELF_NIDENT = 16; 16 | 17 | typedef struct { 18 | uint8_t e_ident[ELF_NIDENT]; 19 | Elf32_Half e_type; 20 | Elf32_Half e_machine; 21 | Elf32_Word e_version; 22 | Elf32_Addr e_entry; 23 | Elf32_Off e_phoff; 24 | Elf32_Off e_shoff; 25 | Elf32_Word e_flags; 26 | Elf32_Half e_ehsize; 27 | Elf32_Half e_phentsize; 28 | Elf32_Half e_phnum; 29 | Elf32_Half e_shentsize; 30 | Elf32_Half e_shnum; 31 | Elf32_Half e_shstrndx; 32 | } Elf32_Ehdr; 33 | 34 | typedef struct { 35 | Elf32_Word p_type; 36 | Elf32_Off p_offset; 37 | Elf32_Addr p_vaddr; 38 | Elf32_Addr p_paddr; 39 | Elf32_Word p_filesz; 40 | Elf32_Word p_memsz; 41 | Elf32_Word p_flags; 42 | Elf32_Word p_align; 43 | } Elf32_Phdr; 44 | 45 | typedef struct { 46 | Elf32_Word sh_name; 47 | Elf32_Word sh_type; 48 | Elf32_Word sh_flags; 49 | Elf32_Addr sh_addr; 50 | Elf32_Off sh_offset; 51 | Elf32_Word sh_size; 52 | Elf32_Word sh_link; 53 | Elf32_Word sh_info; 54 | Elf32_Word sh_addralign; 55 | Elf32_Word sh_entsize; 56 | } Elf32_Shdr; 57 | 58 | typedef struct { 59 | Elf32_Word st_name; 60 | Elf32_Addr st_value; 61 | Elf32_Word st_size; 62 | unsigned char st_info; 63 | unsigned char st_other; 64 | Elf32_Half st_shndx; 65 | } Elf32_Sym; 66 | 67 | enum Elf32_PhdrType { PT_NULL = 0, PT_LOAD = 1, PT_DYNAMIC = 2, PT_INTERP = 3, PT_NOTE = 4, PT_SHLIB = 5, PT_PHDR = 6 }; 68 | 69 | struct Elf32Types { 70 | typedef uint32_t addr_t; 71 | typedef Elf32_Ehdr Elf_Ehdr; 72 | typedef Elf32_Phdr Elf_Phdr; 73 | typedef Elf32_Shdr Elf_Shdr; 74 | typedef Elf32_Sym Elf_Sym; 75 | static constexpr unsigned PT_LOAD = Elf32_PhdrType::PT_LOAD; 76 | }; 77 | 78 | typedef GenericElfLoader ELFLoader; 79 | 80 | } // namespace rv32 81 | -------------------------------------------------------------------------------- /vp/src/platform/common/async_event.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 | more contributor license agreements. See the NOTICE file distributed 5 | with this work for additional information regarding copyright ownership. 6 | Accellera licenses this file to you under the Apache License, Version 2.0 7 | (the "License"); you may not use this file except in compliance with the 8 | License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 | implied. See the License for the specific language governing 16 | permissions and limitations under the License. 17 | 18 | *****************************************************************************/ 19 | /* 20 | * thread_safe_event.h 21 | * 22 | * Copyright (C) 2017, GreenSocs Ltd. 23 | * 24 | * Developed by Mark Burton mark@greensocs.com 25 | */ 26 | 27 | #pragma once 28 | #include 29 | 30 | class AsyncEvent : public sc_core::sc_prim_channel { 31 | sc_core::sc_time m_delay; 32 | sc_core::sc_event m_event; 33 | 34 | public: 35 | AsyncEvent(const char* name = sc_core::sc_gen_unique_name("async_event")) 36 | : sc_core::sc_prim_channel(name), m_event((std::string(this->basename()) + "_event").c_str()) { 37 | // register this channel as "suspending", to not end the simulation 38 | // when we're running out of internal events 39 | async_attach_suspending(); 40 | } 41 | 42 | // THREADSAFE METHOD: 43 | void notify(sc_core::sc_time delay = sc_core::SC_ZERO_TIME) { 44 | m_delay = delay; 45 | async_request_update(); 46 | } 47 | 48 | // only allow waiting for the event 49 | operator const sc_core::sc_event&() const { 50 | return m_event; 51 | } 52 | 53 | protected: 54 | void update(void) { 55 | // we're in the update phase of the SystemC kernel (thread) 56 | m_event.notify(m_delay); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /sw/basic-dma/bootstrap.S: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl init 3 | .globl main 4 | .globl level_1_interrupt_handler 5 | 6 | .equ PLIC_ENABLED_IRQ_ADDR, 0x40002000 7 | 8 | _start: 9 | jal init 10 | la t0, level_0_interrupt_handler 11 | csrw mtvec, t0 12 | li t1, 0x888 13 | csrw mie, t1 14 | csrwi mstatus, 8 15 | li t0, PLIC_ENABLED_IRQ_ADDR 16 | li t1, -1 17 | sw t1, 0(t0) 18 | sw t1, 4(t0) 19 | jal main 20 | 21 | # call exit (SYS_EXIT=93) with exit code 0 (argument in a0) 22 | li a7,93 23 | li a0,0 24 | ecall 25 | 26 | 27 | /* 28 | * Interrupt handler for non-nested interrupts. Only selected registers are stored/re-stored, i.e. those not preserved on function calls. 29 | */ 30 | #define STORE sw 31 | #define LOAD lw 32 | #define REGBYTES 4 33 | 34 | .align 4 35 | level_0_interrupt_handler: 36 | // store execution context on the stack (register content) 37 | addi sp, sp, -REGBYTES * 32 38 | STORE x1, 0x0(sp) 39 | STORE x4, 3 * REGBYTES(sp) 40 | STORE x5, 4 * REGBYTES(sp) 41 | STORE x6, 5 * REGBYTES(sp) 42 | STORE x7, 6 * REGBYTES(sp) 43 | STORE x10, 9 * REGBYTES(sp) 44 | STORE x11, 10 * REGBYTES(sp) 45 | STORE x12, 11 * REGBYTES(sp) 46 | STORE x13, 12 * REGBYTES(sp) 47 | STORE x14, 13 * REGBYTES(sp) 48 | STORE x15, 14 * REGBYTES(sp) 49 | STORE x16, 15 * REGBYTES(sp) 50 | STORE x17, 16 * REGBYTES(sp) 51 | STORE x28, 27 * REGBYTES(sp) 52 | STORE x29, 28 * REGBYTES(sp) 53 | STORE x30, 29 * REGBYTES(sp) 54 | STORE x31, 30 * REGBYTES(sp) 55 | 56 | // load interrupt/trap reason and call external C function to handle it 57 | csrr a0, mcause 58 | jal level_1_interrupt_handler 59 | 60 | // re-store the saved context 61 | LOAD x1, 0x0(sp) 62 | LOAD x4, 3 * REGBYTES(sp) 63 | LOAD x5, 4 * REGBYTES(sp) 64 | LOAD x6, 5 * REGBYTES(sp) 65 | LOAD x7, 6 * REGBYTES(sp) 66 | LOAD x10, 9 * REGBYTES(sp) 67 | LOAD x11, 10 * REGBYTES(sp) 68 | LOAD x12, 11 * REGBYTES(sp) 69 | LOAD x13, 12 * REGBYTES(sp) 70 | LOAD x14, 13 * REGBYTES(sp) 71 | LOAD x15, 14 * REGBYTES(sp) 72 | LOAD x16, 15 * REGBYTES(sp) 73 | LOAD x17, 16 * REGBYTES(sp) 74 | LOAD x28, 27 * REGBYTES(sp) 75 | LOAD x29, 28 * REGBYTES(sp) 76 | LOAD x30, 29 * REGBYTES(sp) 77 | LOAD x31, 30 * REGBYTES(sp) 78 | addi sp, sp, REGBYTES * 32 79 | mret 80 | 81 | -------------------------------------------------------------------------------- /vp/src/core/rv32/timing/timing_external.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../iss.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | std::string RISCV_TIMING_SIM_LIB = "riscv-timing-sim.so"; 10 | std::string RISCV_TIMING_DB = "riscv-timing-db.xml"; 11 | 12 | // NOTE: the interface inside the library has to match this one exactly, don't 13 | // forget the *virtual* attribute 14 | struct SimTimingInterface { 15 | virtual uint64_t get_cycles_for_instruction(uint64_t pc); 16 | 17 | // only to detect errors in loading the shared library 18 | virtual uint64_t get_magic_number(); 19 | }; 20 | 21 | struct ExternalTimingDecorator : public timing_if { 22 | SimTimingInterface *timing_sim = 0; 23 | void *lib_handle = 0; 24 | SimTimingInterface *(*create)(const char *) = 0; 25 | void (*destroy)(SimTimingInterface *) = 0; 26 | 27 | void initialize() { 28 | lib_handle = dlopen(RISCV_TIMING_SIM_LIB.c_str(), RTLD_LAZY); 29 | if (!lib_handle) 30 | throw std::runtime_error("unable to open shared library '" + RISCV_TIMING_SIM_LIB + "'"); 31 | 32 | create = (SimTimingInterface * (*)(const char *)) dlsym(lib_handle, "create_riscv_vp_timing_interface"); 33 | if (!create) 34 | throw std::runtime_error("unable to load 'create_riscv_vp_timing_interface' function"); 35 | 36 | destroy = (void (*)(SimTimingInterface *))dlsym(lib_handle, "destroy_riscv_vp_timing_interface"); 37 | if (!destroy) 38 | throw std::runtime_error("unable to load 'destroy_riscv_vp_timing_interface' function"); 39 | 40 | timing_sim = (SimTimingInterface *)create(RISCV_TIMING_DB.c_str()); 41 | } 42 | 43 | ExternalTimingDecorator() { 44 | initialize(); 45 | } 46 | 47 | ~ExternalTimingDecorator() { 48 | assert(timing_sim != 0); 49 | destroy(timing_sim); 50 | assert(lib_handle != 0); 51 | dlclose(lib_handle); 52 | } 53 | 54 | void on_begin_exec_step(Instruction instr, Opcode::mapping op, ISS &iss) override { 55 | uint64_t cycles = timing_sim->get_cycles_for_instruction(iss.last_pc); 56 | 57 | assert(timing_sim->get_magic_number() == 0x5E5E5E5E5E5E5E5E); 58 | 59 | sc_core::sc_time delay = iss.cycle_time * cycles; 60 | 61 | iss.quantum_keeper.inc(delay); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_eq128.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include 39 | #include "platform.h" 40 | 41 | #ifndef softfloat_eq128 42 | 43 | bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 44 | { 45 | 46 | return (a64 == b64) && (a0 == b0); 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /sw/simple-display/libDisplay.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * libDisplay.cpp 3 | * 4 | * Created on: Oct 5, 2018 5 | * Author: dwd 6 | */ 7 | 8 | #include "libDisplay.hpp" 9 | #include 10 | #include 11 | 12 | typedef Framebuffer::Point Point; 13 | typedef Framebuffer::PointF PointF; 14 | typedef Framebuffer::Color Color; 15 | 16 | 17 | namespace display { 18 | 19 | void setPixel(Framebuffer::Type frame, Point pixel, Color color) { 20 | framebuffer->getFrame(frame).raw[pixel.y][pixel.x] = color; 21 | } 22 | 23 | void drawLine(Framebuffer::Type frame, PointF from, PointF to, Color color) { 24 | framebuffer->parameter.line.frame = frame; 25 | framebuffer->parameter.line.from = from; 26 | framebuffer->parameter.line.to = to; 27 | framebuffer->parameter.line.color = color; 28 | framebuffer->command = Framebuffer::Command::drawLine; 29 | } 30 | 31 | void drawRect(Framebuffer::Type frame, PointF ol, PointF ur, Color color) { 32 | if (ol.x > ur.x) { 33 | std::swap(ol.x, ur.x); 34 | } 35 | if (ol.y > ur.y) { 36 | std::swap(ol.y, ur.y); 37 | } 38 | drawLine(frame, ol, PointF(ur.x, ol.y), color); 39 | drawLine(frame, PointF(ur.x, ol.y), ur, color); 40 | drawLine(frame, ur, PointF(ol.x, ur.y), color); 41 | drawLine(frame, PointF(ol.x, ur.y), ol, color); 42 | } 43 | 44 | void fillRect(Framebuffer::Type frame, PointF ol, PointF ur, Color color) { 45 | if (ol.x == ur.x || ol.y == ur.y) { // No dimension 46 | return; 47 | } 48 | if (ol.x > ur.x) { 49 | std::swap(ol.x, ur.x); 50 | } 51 | if (ol.y > ur.y) { 52 | std::swap(ol.y, ur.y); 53 | } 54 | if (ur.x - ol.x > ur.y - ol.y) { 55 | // Horizontal 56 | for (uint16_t y = ol.y; y <= ur.y; y++) { 57 | drawLine(frame, PointF(ol.x, y), PointF(ur.x, y), color); 58 | } 59 | } else { 60 | // Vertical 61 | for (uint16_t x = ol.x; x <= ur.x; x++) { 62 | drawLine(frame, PointF(x, ol.y), PointF(x, ur.y), color); 63 | } 64 | } 65 | } 66 | 67 | void applyFrame() { 68 | framebuffer->command = Framebuffer::Command::applyFrame; 69 | } 70 | 71 | void fillFrame(Framebuffer::Type frame, Color color) { 72 | framebuffer->parameter.fill.frame = frame; 73 | framebuffer->parameter.fill.color = color; 74 | framebuffer->command = Framebuffer::Command::fillFrame; 75 | } 76 | 77 | } // namespace display 78 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_le128.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include 39 | #include "platform.h" 40 | 41 | #ifndef softfloat_le128 42 | 43 | bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 44 | { 45 | 46 | return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_lt128.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include 39 | #include "platform.h" 40 | 41 | #ifndef softfloat_lt128 42 | 43 | bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 44 | { 45 | 46 | return (a64 < b64) || ((a64 == b64) && (a0 < b0)); 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f32_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | #include "internals.h" 40 | #include "specialize.h" 41 | #include "softfloat.h" 42 | 43 | bool f32_isSignalingNaN( float32_t a ) 44 | { 45 | union ui32_f32 uA; 46 | 47 | uA.f = a; 48 | return softfloat_isSigNaNF32UI( uA.ui ); 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f64_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | #include "internals.h" 40 | #include "specialize.h" 41 | #include "softfloat.h" 42 | 43 | bool f64_isSignalingNaN( float64_t a ) 44 | { 45 | union ui64_f64 uA; 46 | 47 | uA.f = a; 48 | return softfloat_isSigNaNF64UI( uA.ui ); 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f16_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | #include "internals.h" 40 | #include "specialize.h" 41 | #include "softfloat.h" 42 | 43 | bool f16_isSignalingNaN( float16_t a ) 44 | { 45 | union ui16_f16 uA; 46 | 47 | uA.f = a; 48 | return softfloat_isSigNaNF16UI( uA.ui ); 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_shortShiftRightJam64.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | 40 | #ifndef softfloat_shortShiftRightJam64 41 | 42 | uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) 43 | { 44 | 45 | return a>>dist | ((a & (((uint_fast64_t) 1< 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class CAN { 13 | enum class State { 14 | init, 15 | readRegister, 16 | writeRegister, 17 | bitmod, 18 | 19 | loadTX0, 20 | loadTX1, 21 | loadTX2, 22 | 23 | sendTX0, 24 | sendTX1, 25 | sendTX2, 26 | sendALL, 27 | 28 | readRX0, 29 | readRX1, 30 | 31 | getStatus, 32 | 33 | shit, 34 | wank, 35 | fuck, 36 | arse, 37 | crap, 38 | dick, 39 | } state; 40 | 41 | std::thread listener; 42 | 43 | uint8_t registers[MCP_RXB1SIDH + 1]; 44 | 45 | struct MCPFrame { 46 | union { 47 | uint8_t raw[5 + CANFD_MAX_DLEN]; 48 | struct { 49 | union { 50 | uint8_t id[4]; 51 | struct { 52 | /* 53 | MCP_SIDH 0 54 | MCP_SIDL 1 55 | MCP_EID8 2 56 | MCP_EID0 3 57 | */ 58 | uint16_t sid; 59 | uint16_t eid; 60 | } fields; 61 | }; 62 | uint8_t length; 63 | uint8_t payload[CANFD_MAX_DLEN]; 64 | } fields; 65 | }; 66 | }; 67 | 68 | MCPFrame txBuf[3]; 69 | MCPFrame rxBuf[2]; 70 | 71 | uint8_t status; 72 | 73 | int s; 74 | struct sockaddr_can addr; 75 | struct ifreq ifr; 76 | 77 | volatile bool stop; 78 | 79 | public: 80 | CAN(); 81 | ~CAN(); 82 | 83 | uint8_t write(uint8_t byte); 84 | 85 | const char* registerName(uint8_t id); 86 | const char* regValueName(uint8_t id); 87 | const char* spiInstName(uint8_t id); 88 | 89 | void command(uint8_t byte); 90 | uint8_t readRegister(uint8_t byte); 91 | uint8_t writeRegister(uint8_t byte); 92 | uint8_t modifyRegister(uint8_t byte); 93 | 94 | uint8_t loadTxBuf(uint8_t no, uint8_t byte); 95 | uint8_t sendTxBuf(uint8_t no, uint8_t byte); 96 | 97 | uint8_t readRxBuf(uint8_t no, uint8_t byte); 98 | 99 | void mcp2515_id_to_buf(const unsigned long id, uint8_t* idField, const bool extended = false); 100 | void mcp2515_buf_to_id(unsigned& id, bool& extended, uint8_t* idField); 101 | 102 | void enqueueIncomingCanFrame(const struct can_frame& frame); 103 | void listen(); 104 | }; 105 | -------------------------------------------------------------------------------- /sw/simple-scheduler/no-clib/cor.S: -------------------------------------------------------------------------------- 1 | .globl contextswitch 2 | .globl coroutine_entry 3 | .globl launch_coroutine 4 | 5 | 6 | coroutine_entry: 7 | // move the launch argument to the a0 register (i.e. first argument of the following function) 8 | mv a0,s0 9 | call launch_coroutine 10 | 11 | // the above call should not return (i.e the scheduler should not call a finished coroutine) 12 | ebreak 13 | 14 | 15 | /* 16 | * registers a0 and a1 point to the current and next context, respectively 17 | * 18 | * 1) store all current registers and pc in the current context 19 | * 2) load register values from next context 20 | * 3) jump to pc in the next context 21 | */ 22 | contextswitch: 23 | // store registers 24 | sw x1,4(a0) // ra 25 | sw x2,8(a0) // sp 26 | //sw x3,12(a0) // gp 27 | //sw x4,16(a0) // tp 28 | //sw x5,20(a0) // t0 29 | //sw x6,24(a0) // t1 30 | //sw x7,28(a0) // t2 31 | sw x8,32(a0) // s0 32 | sw x9,36(a0) // s1 33 | //sw x10,40(a0) // a0 34 | //sw x11,44(a0) // a1 35 | //sw x12,48(a0) // a2 36 | //sw x13,52(a0) // a3 37 | //sw x14,56(a0) // a4 38 | //sw x15,60(a0) // a5 39 | //sw x16,64(a0) // a6 40 | //sw x17,68(a0) // a7 41 | sw x18,72(a0) // s2 42 | sw x19,76(a0) // s3 43 | sw x20,80(a0) // s4 44 | sw x21,84(a0) // s5 45 | sw x22,88(a0) // s6 46 | sw x23,92(a0) // s7 47 | sw x24,96(a0) // s8 48 | sw x25,100(a0) // s9 49 | sw x26,104(a0) // s10 50 | sw x27,108(a0) // s11 51 | //sw x28,112(a0) // t3 52 | //sw x29,116(a0) // t4 53 | //sw x30,120(a0) // t5 54 | //sw x31,124(a0) // t6 55 | 56 | // store pc 57 | la t0,_resume 58 | sw t0,0(a0) 59 | 60 | // restore other registers (NOTE: callee saved only + ra) 61 | lw x1,4(a1) // ra 62 | lw x2,8(a1) // sp 63 | lw x8,32(a1) // s0 64 | lw x9,36(a1) // s1 65 | lw x18,72(a1) // s2 66 | lw x19,76(a1) // s3 67 | lw x20,80(a1) // s4 68 | lw x21,84(a1) // s5 69 | lw x22,88(a1) // s6 70 | lw x23,92(a1) // s7 71 | lw x24,96(a1) // s8 72 | lw x25,100(a1) // s9 73 | lw x26,104(a1) // s10 74 | lw x27,108(a1) // s11 75 | 76 | // load new program counter and perform context switch 77 | lw t0,0(a1) 78 | jr t0 79 | 80 | _resume: 81 | 82 | ret 83 | 84 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/f128_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | #include "internals.h" 40 | #include "specialize.h" 41 | #include "softfloat.h" 42 | 43 | bool f128_isSignalingNaN( float128_t a ) 44 | { 45 | union ui128_f128 uA; 46 | 47 | uA.f = a; 48 | return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 ); 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_shiftRightJam32.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | 40 | #ifndef softfloat_shiftRightJam32 41 | 42 | uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) 43 | { 44 | 45 | return 46 | (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_shiftRightJam64.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | 40 | #ifndef softfloat_shiftRightJam64 41 | 42 | uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) 43 | { 44 | 45 | return 46 | (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser2.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGDB_PARSER2_H 2 | #define LIBGDB_PARSER2_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #ifndef LIBGDB_ADDR_TYPE 15 | #define LIBGDB_ADDR_TYPE uint64_t 16 | #endif 17 | #ifndef LIBGDB_ADDR_FORMAT 18 | #define LIBGDB_ADDR_FORMAT SCNx64 19 | #endif 20 | 21 | typedef LIBGDB_ADDR_TYPE gdb_addr_t; 22 | #undef LIBGDB_ADDR_TYPE 23 | 24 | enum { 25 | GDB_THREAD_UNSET = -2, 26 | GDB_THREAD_ANY = 0, 27 | GDB_THREAD_ALL = -1, 28 | }; 29 | 30 | typedef struct { 31 | int pid; /* requires multiprocess feature */ 32 | int tid; 33 | } gdb_thread_t; 34 | 35 | typedef enum { 36 | GDB_ZKIND_SOFT = 0, 37 | GDB_ZKIND_HARD, 38 | GDB_ZKIND_WATCHW, 39 | GDB_ZKIND_WATCHR, 40 | GDB_ZKIND_WATCHA, 41 | } gdb_ztype_t; 42 | 43 | typedef struct { 44 | gdb_ztype_t type; 45 | gdb_addr_t address; 46 | size_t kind; 47 | } gdb_breakpoint_t; 48 | 49 | typedef struct { 50 | gdb_addr_t addr; 51 | size_t length; 52 | } gdb_memory_t; 53 | 54 | typedef struct { 55 | gdb_memory_t location; 56 | char *data; /* null-terminated hexstring */ 57 | } gdb_memory_write_t; 58 | 59 | typedef struct { 60 | char op; 61 | gdb_thread_t id; 62 | } gdb_cmd_h_t; 63 | 64 | typedef struct _gdb_vcont_t gdb_vcont_t; 65 | 66 | struct _gdb_vcont_t { 67 | char action; 68 | int sig; /* -1 if unset */ 69 | gdb_thread_t thread; 70 | 71 | gdb_vcont_t *next; /* NULL on end */ 72 | }; 73 | 74 | typedef enum { 75 | GDB_ARG_NONE, 76 | GDB_ARG_VCONT, 77 | GDB_ARG_H, 78 | GDB_ARG_INT, 79 | GDB_ARG_MEMORY, 80 | GDB_ARG_MEMORYW, 81 | GDB_ARG_BREAK, 82 | GDB_ARG_THREAD, 83 | } gdb_argument_t; 84 | 85 | typedef struct { 86 | char *name; 87 | gdb_argument_t type; 88 | 89 | union { 90 | gdb_vcont_t *vval; 91 | gdb_cmd_h_t hcmd; 92 | int ival; 93 | gdb_memory_t mem; 94 | gdb_memory_write_t memw; 95 | gdb_breakpoint_t bval; 96 | gdb_thread_t tval; 97 | } v; 98 | } gdb_command_t; 99 | 100 | void gdb_free_cmd(gdb_command_t *); 101 | gdb_command_t *gdb_parse_cmd(gdb_packet_t *); 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /vp/src/platform/common/uart.cpp: -------------------------------------------------------------------------------- 1 | #include "uart.h" 2 | #include "core/common/rawmode.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /* character → control key */ 12 | #define CTRL(c) ((c) & 0x1f) 13 | 14 | #define KEY_ESC CTRL('a') /* Ctrl-a (character to enter command mode) */ 15 | #define KEY_EXIT 'x' /* x (character to exit in command mode) */ 16 | #define KEY_CEXIT CTRL(KEY_EXIT) /* Ctrl-x (character to exit in command mode) */ 17 | 18 | UART::UART(const sc_core::sc_module_name& name, uint32_t irqsrc) 19 | : FD_ABSTRACT_UART(name, irqsrc) { 20 | // If stdin isn't a tty, it doesn't make much sense to poll from it. 21 | // In this case, we will run the UART in write-only mode. 22 | bool write_only = !isatty(STDIN_FILENO); 23 | 24 | enableRawMode(STDIN_FILENO); 25 | start_threads(STDIN_FILENO, write_only); 26 | } 27 | 28 | UART::~UART(void) { 29 | stop_threads(); 30 | disableRawMode(STDIN_FILENO); 31 | } 32 | 33 | void UART::handle_input(int fd) { 34 | uint8_t buf; 35 | ssize_t nread; 36 | 37 | nread = read(fd, &buf, sizeof(buf)); 38 | if (nread == -1) 39 | throw std::system_error(errno, std::generic_category()); 40 | else if (nread != sizeof(buf)) 41 | throw std::runtime_error("short read"); 42 | 43 | switch (state) { 44 | case STATE_NORMAL: 45 | if(buf != KEY_ESC) // filter out first esc sequence 46 | rxpush(buf); 47 | break; 48 | case STATE_COMMAND: 49 | handle_cmd(buf); 50 | break; 51 | } 52 | 53 | /* update state of input state machine for next run */ 54 | if (buf == KEY_ESC && state != STATE_COMMAND) { 55 | state = STATE_COMMAND; 56 | } else { 57 | state = STATE_NORMAL; 58 | } 59 | } 60 | 61 | void UART::handle_cmd(uint8_t cmd) { 62 | switch (cmd) { 63 | case KEY_ESC: /* double escape */ 64 | rxpush(cmd); 65 | break; 66 | case KEY_EXIT: 67 | case KEY_CEXIT: 68 | exit(EXIT_SUCCESS); 69 | break; 70 | default: 71 | return; /* unknown command → ignore */ 72 | } 73 | } 74 | 75 | void UART::write_data(uint8_t data) { 76 | ssize_t nwritten; 77 | nwritten = write(STDOUT_FILENO, &data, sizeof(data)); 78 | if (nwritten == -1) 79 | throw std::system_error(errno, std::generic_category()); 80 | else if (nwritten != sizeof(data)) 81 | throw std::runtime_error("short write"); 82 | } 83 | -------------------------------------------------------------------------------- /sw/crc8/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "platform.h" 4 | #include "uart.h" 5 | #include "util.h" 6 | 7 | // 8-bit SAE J1850 CRC 8 | unsigned char crc8(unsigned char *data, int length) { 9 | /* 10 | * 8-bit CRC calculation 11 | * polynomial : 0x1D 12 | * initial value : 0xFF 13 | * reflect input : no 14 | * reflect result : no 15 | * XOR value : 0xFF 16 | * check : 0x4B 17 | * magic check : 0xC4 18 | */ 19 | unsigned long crc; 20 | int i,bit; 21 | crc = 0xFF; 22 | for(i=0; i 38 | #include "platform.h" 39 | #include "primitiveTypes.h" 40 | 41 | #ifndef softfloat_add128 42 | 43 | struct uint128 44 | softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 45 | { 46 | struct uint128 z; 47 | 48 | z.v0 = a0 + b0; 49 | z.v64 = a64 + b64 + (z.v0 < a0); 50 | return z; 51 | 52 | } 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /vp/src/vendor/softfloat/s_sub128.c: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 | Package, Release 3d, by John R. Hauser. 6 | 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 8 | California. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions, and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions, and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the University nor the names of its contributors may 21 | be used to endorse or promote products derived from this software without 22 | specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | =============================================================================*/ 36 | 37 | #include 38 | #include "platform.h" 39 | #include "primitiveTypes.h" 40 | 41 | #ifndef softfloat_sub128 42 | 43 | struct uint128 44 | softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 45 | { 46 | struct uint128 z; 47 | 48 | z.v0 = a0 - b0; 49 | z.v64 = a64 - b64 - (a0 < b0); 50 | return z; 51 | 52 | } 53 | 54 | #endif 55 | 56 | --------------------------------------------------------------------------------