riscv

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 0abd4fab15a9fd01d804d4e250147434520af696
parent af4786689df0090d6e7bfc136b73b5a71d352893
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat,  2 Nov 2019 16:30:16 -0700

rvsim: iocall mechanism

- provide syscall-like traps for dputc, open, close, read, write
- header (system.h) and stubs (start.S) for iocalls
- remove dedicated dputc instruction
- provide a mechanism to ask the sim for direct memory access

Diffstat:
Minstab.txt | 2+-
Aiocall.h | 8++++++++
Mrvmain.c | 45+++++++++++++++++++++++++++++++++++++++------
Mrvsim.c | 26+++++++++++++++++---------
Mrvsim.h | 14++++++++++++--
Mstart.S | 40++++++++++++++++------------------------
Asystem.h | 17+++++++++++++++++
7 files changed, 110 insertions(+), 42 deletions(-)

diff --git a/instab.txt b/instab.txt @@ -70,8 +70,8 @@ 0000001----------111-----0110011 remu %d, %1, %2 -----------------000-----0001111 fence -----------------000-----0001011 _exiti %i +-----------------001-----0001011 _iocall %i -----------------100-----0001011 _exit %1 ------------------101-----0001011 _putc %1 -----------------001000001110011 csrw %C, %1 -----------------001-----1110011 csrrw %d, %C, %1 ------------00000010-----1110011 csrr %d, %C diff --git a/iocall.h b/iocall.h @@ -0,0 +1,8 @@ +#pragma once + +#define IOCALL_DPUTC 0x00 + +#define IOCALL_OPEN 0x10 +#define IOCALL_CLOSE 0x11 +#define IOCALL_READ 0x12 +#define IOCALL_WRITE 0x13 diff --git a/rvmain.c b/rvmain.c @@ -10,6 +10,7 @@ #include <sys/stat.h> #include "rvsim.h" +#include "iocall.h" uint32_t ior32(uint32_t addr) { return 0xffffffff; @@ -18,9 +19,36 @@ uint32_t ior32(uint32_t addr) { void iow32(uint32_t addr, uint32_t val) { } -void ioputc(uint32_t c) { - uint8_t x = c; - if (write(1, &x, 1)) {} // appease warning +uint32_t iocall(void* ctx, uint32_t n, const uint32_t args[8]) { + rvstate_t* s = ctx; + switch (n) { + case IOCALL_DPUTC: { + uint8_t x = args[0]; + if (write(1, &x, 1)) { return -1; } + return 0; + } + case IOCALL_OPEN: { // (path, flags, mode) -> fd/error + void* ptr = rvsim_dma(s, args[0], 1024); + if (ptr == NULL) return -1; + if (memchr(ptr, 0, 1024) == NULL) return -1; + return open(ptr, args[1], args[2]); + } + case IOCALL_CLOSE: { // (fd) -> 0/error + return close(args[0]); + } + case IOCALL_READ: { // (fd, ptr, len) -> len/error + void* ptr = rvsim_dma(s, args[1], args[2]); + if (ptr == NULL) return -1; + return read(args[0], ptr, args[2]); + } + case IOCALL_WRITE: { // (fd, ptr, len) -> len/error + void* ptr = rvsim_dma(s, args[1], args[2]); + if (ptr == NULL) return -1; + return write(args[0], ptr, args[2]); + } + default: + return -1; + } } int load_image(const char* fn, uint8_t* ptr, size_t sz) { @@ -75,18 +103,23 @@ int main(int argc, char** argv) { return -1; } void* memory; - uint32_t memsize = 0; + uint32_t membase = 0x80000000; + uint32_t memsize = 32768; rvstate_t* s; - if (rvsim_init(&s, &memory, &memsize)) { + if (rvsim_init(&s, NULL)) { fprintf(stderr, "error: cannot initialize simulator\n"); return -1; } + if ((memory = rvsim_dma(s, membase, memsize)) == NULL) { + fprintf(stderr, "error: cannot access sim memory\n"); + return -1; + } if (load_image(fn, memory, memsize) < 0) { fprintf(stderr, "error: failed to load '%s'\n", fn); return -1; } - rvsim_exec(s, 0x80000000); + rvsim_exec(s, membase); if (dumpfn && (dumpto > dumpfrom)) { FILE* fp; diff --git a/rvsim.c b/rvsim.c @@ -9,10 +9,10 @@ #include "riscv.h" #include "rvsim.h" -#define DO_TRACE_INS 1 -#define DO_TRACE_TRAPS 1 -#define DO_TRACE_MEM_WR 1 -#define DO_TRACE_REG_WR 1 +#define DO_TRACE_INS 0 +#define DO_TRACE_TRAPS 0 +#define DO_TRACE_MEM_WR 0 +#define DO_TRACE_REG_WR 0 #define RVMEMBASE 0x80000000 #define RVMEMSIZE 32768 @@ -26,8 +26,17 @@ typedef struct rvstate { uint32_t mtval; uint32_t mepc; uint32_t mcause; + void* ctx; } rvstate_t; +void* rvsim_dma(rvstate_t* s, uint32_t va, uint32_t len) { + if (va < RVMEMBASE) return NULL; + va -= RVMEMBASE; + if (va >= RVMEMSIZE) return NULL; + if (len > (RVMEMSIZE - va)) return NULL; + return s->memory + va; +} + static uint32_t rd32(uint8_t* memory, uint32_t addr) { if (addr < RVMEMBASE) { return ior32(addr); @@ -77,7 +86,7 @@ uint32_t rvsim_rd32(rvstate_t* s, uint32_t addr) { return rd32(s->memory, addr); } -int rvsim_init(rvstate_t** _s, void** _memory, uint32_t* _memsize) { +int rvsim_init(rvstate_t** _s, void* ctx) { rvstate_t *s; if ((s = malloc(sizeof(rvstate_t))) == NULL) { return -1; @@ -89,9 +98,8 @@ int rvsim_init(rvstate_t** _s, void** _memory, uint32_t* _memsize) { } memset(s->memory, 0, RVMEMSIZE); s->mtvec = 0x80000000; + s->ctx = ctx ? ctx : s; *_s = s; - *_memory = s->memory; - *_memsize = RVMEMSIZE; return 0; } @@ -206,8 +214,8 @@ int rvsim_exec(rvstate_t* s, uint32_t _pc) { case 0b100: // _exit fprintf(stderr, "CCOUNT %lu\n", ccount); return RdR1(); - case 0b101: // _putc - ioputc(RdR1()); + case 0b001: // _iocall + s->x[10] = iocall(s->ctx, get_ii(ins), s->x + 10); break; default: goto inval; diff --git a/rvsim.h b/rvsim.h @@ -5,13 +5,23 @@ typedef struct rvstate rvstate_t; -int rvsim_init(rvstate_t** s, void** memory, uint32_t* memsize); +// initialize simulator +int rvsim_init(rvstate_t** s, void* ctx); +// start simulator running at pc int rvsim_exec(rvstate_t* s, uint32_t pc); +// obtain a pointer for direct memory access +void* rvsim_dma(rvstate_t* s, uint32_t va, uint32_t len); + +// read a word from memory uint32_t rvsim_rd32(rvstate_t* s, uint32_t addr); + +// hook for "syscalls" +uint32_t iocall(void* ctx, uint32_t n, const uint32_t args[8]); + +// hooks to implement io read/write access uint32_t ior32(uint32_t addr); void iow32(uint32_t addr, uint32_t val); -void ioputc(uint32_t c); diff --git a/start.S b/start.S @@ -1,29 +1,21 @@ -#define PASS .long 0x0000000b // _exiti 0 -#define FAIL .long 0xFFF0000b // _exiti -1 -#define PUTC .long 0x0005500b // _putc a0 +#include "iocall.h" -.globl _start +#define EXITI_0 .long 0x0000000b // _exiti 0 +#define IOCALL(n) .long 0x0000100b | ((n) << 20) // iocall n + +#define MKIOCALL(a,b) .globl a; a: IOCALL(IOCALL_##b); ret +.globl _start _start: -#if 0 - li t1, 0x87654FFF - PASS - FAIL - PUTC - beqz t1, main0 - bnez t1, main0 - blez t1, main0 - bgez t1, main0 - bltz t1, main0 - bgtz t1, main0 - sltz s1, s2 - sgtz s1, s2 - snez s1, s2 - seqz s1, s2 - not s3, s5 - neg s5, s6 -#endif -main0: jal main - PASS + +.globl exit +exit: + EXITI_0 + +MKIOCALL(dputc,DPUTC) +MKIOCALL(open,OPEN) +MKIOCALL(close,CLOSE) +MKIOCALL(read,READ) +MKIOCALL(write,WRITE) diff --git a/system.h b/system.h @@ -0,0 +1,17 @@ +#pragma once + +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 + +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_RUNC 01000 + +int dputc(unsigned ch); + +int open(const char* path, unsigned flags, unsigned mode); +int close(int fd); +int read(int fd, void* ptr, int len); +int write(int fd, void* ptr, int len); +