Comments (2)
This is what I've come up with so far.
Some comments:
mini-rv32ima.h
is perfect for embedding with one exception: I had to move the struct def outside. Can we add an ifndef for that?- This might be my new-ness to risc-v, but its really hard to tell when its okay to call
MiniRV32IMAStep
or when some state needs to be handled. Can we add ablocked()
function or something like that?
Main sketch:
#include "Arduino.h"
#include "emulator.h"
#define LED_PIN 38
static uint8_t static_ram[] = {
0x6f, 0x00, 0xC0, 0x00, //jal 8
0x48, 0x69, 0x20, 0x3A, // "Hi :"
0x29, 0x00, 0x00, 0x00, // ")"
0x13, 0x01, 0x10, 0x00, //addi x2, x0, 1 - syscall number 1
0x13, 0x02, 0x40, 0x00, //addi x4, x0, 4 - addr 0x04
0x73, 0x00, 0x00, 0x00, //ecall
};
Emulator myEmu((void*) static_ram, sizeof(static_ram));
void setup() {
Serial.begin(5000000);
Serial.println("Hello T-Display-S3");
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
myEmu.step(20);
myEmu.step(20);
digitalWrite(LED_PIN, LOW);
delay(100);
}
void loop() {
}
emulator.cpp
#include "Arduino.h"
#include "emulator.h"
// configures mini-rv32ima.h
#define MINIRV32_DECORATE
#define MINIRV32_IMPLEMENTATION
#define MINIRV32_STEPPROTO MINIRV32_DECORATE int32_t Emulator::MiniRV32IMAStep( struct MiniRV32IMAState * state, uint8_t * image, uint32_t elapsedUs, int count )
#define MINI_RV32_RAM_SIZE this->_ramSize
#define MINIRV32_RAM_IMAGE_OFFSET 0x0
#define MINIRV32_POSTEXEC(pc, ir, trap) this->dumpState(state, image, pc);
#include "mini-rv32ima.h"
Emulator::Emulator(void* ram, uint32_t ramSize) {
_ram = ram;
_ramSize = ramSize;
memset((void*) &_m, 0, sizeof(MiniRV32IMAState));
}
void Emulator::step(int numSteps) {
if (this->noTrap()) {
uint32_t ret = MiniRV32IMAStep(&this->_m, (uint8_t*) this->_ram, micros(), numSteps);
Serial.printf("got return: %08x\n", ret);
dumpState(&this->_m, (uint8_t*) this->_ram, this->_m.pc);
}
// Handle any fault or exception.
switch (this->_m.mcause) {
case 0x08: // ECALL (syscall) - U-Mode
handleSyscall();
break;
}
}
void Emulator::handleSyscall() {
uint8_t fault = 0;
uint32_t retval = 0;
switch (this->_m.regs[2]) { // syscall number in x2
case 1: // print null-terminated string
// TODO(tom): Check memory bounds
{
void* base = this->_ram + this->_m.regs[4];
Serial.println((const char*) base);
}
break;
default:
fault = 1;
retval = -1;
break;
}
if (!fault) {
this->_m.regs[2] = retval;
} else {
this->_m.regs[7] = retval; // error code
}
this->_m.pc = this->_m.mtval;
this->_m.mtval = 0;
this->_m.mcause = 0;
}
bool Emulator::noTrap() {
return this->_m.mcause == 0;
}
void Emulator::dumpState( struct MiniRV32IMAState * core, uint8_t * ram_image, uint32_t pc )
{
uint32_t pc_offset = pc - MINIRV32_RAM_IMAGE_OFFSET;
uint32_t ir = 0;
Serial.printf( "PC: %08x ", pc );
if( pc_offset >= 0 && pc_offset < MINI_RV32_RAM_SIZE - 3 )
{
ir = *((uint32_t*)(&((uint8_t*)ram_image)[pc_offset]));
Serial.printf( "[0x%08x]", ir );
}
else
Serial.printf( "[xxxxxxxxxx]" );
Serial.println();
delay(100);
uint32_t * regs = core->regs;
Serial.printf( "\tZ:%08x ra:%08x sp:%08x gp:%08x tp:%08x\n\tt0:%08x t1:%08x t2:%08x s0:%08x s1:%08x a0:%08x a1:%08x a2:%08x",
regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7],
regs[8], regs[9], regs[10], regs[11], regs[12]);
Serial.println();
delay(100);
Serial.printf( "\ta3:%08x a4:%08x a5:%08x a6:%08x a7:%08x",
regs[13], regs[14], regs[15], regs[16], regs[17]);
Serial.println();
delay(100);
Serial.printf("\tmstatus=%08x mcause=%08x mtval=%08x", core->mstatus, core->mcause, core->mtval);
Serial.println();
}
emulator.h
#ifndef Emulator_h
#define Emulator_h
// As a note: We quouple-ify these, because in HLSL, we will be operating with
// uint4's. We are going to uint4 data to/from system RAM.
//
// We're going to try to keep the full processor state to 12 x uint4.
struct MiniRV32IMAState
{
uint32_t regs[32];
uint32_t pc;
uint32_t mstatus;
uint32_t cyclel;
uint32_t cycleh;
uint32_t timerl;
uint32_t timerh;
uint32_t timermatchl;
uint32_t timermatchh;
uint32_t mscratch;
uint32_t mtvec;
uint32_t mie;
uint32_t mip;
uint32_t mepc;
uint32_t mtval;
uint32_t mcause;
// Note: only a few bits are used. (Machine = 3, User = 0)
// Bits 0..1 = privilege.
// Bit 2 = WFI (Wait for interrupt)
// Bit 3+ = Load/Store reservation LSBs.
uint32_t extraflags;
};
class Emulator {
public:
Emulator(void* _ram, uint32_t _ramSize);
// step executes at most numStep instructions or one syscall.
void step(int numSteps);
bool noTrap();
private:
void* _ram;
uint32_t _ramSize;
MiniRV32IMAState _m;
// defined in mini-rv32ima.h
int32_t MiniRV32IMAStep( struct MiniRV32IMAState * state, uint8_t * image, uint32_t elapsedUs, int count );
void dumpState( struct MiniRV32IMAState * core, uint8_t * ram_image, uint32_t pc );
void handleSyscall();
};
#endif
from mini-rv32ima.
You can do this. If you are on Discord, feel free to discuss on the mini-rv32ima channel on my Discord. But, I believe this is possible, though it feels a little odd to me. I can't put my finger on a better way to do it instead though.
from mini-rv32ima.
Related Issues (20)
- Doom build fails since 32-bit libraries not installed (I think?) HOT 3
- Please express true isa as RV32IMAZicsr_Zifencei HOT 18
- (Suggestion) extension to G(IMAFD)-spec? HOT 4
- vi with no filename faults with access fault HOT 12
- Human readable unit tests for rv64imafdc instructions
- Bare-metal libc HOT 3
- Kernel panics on emulator compiled for ARM (trying to run linux on the Raspberry Pi Pico) HOT 8
- inittab for buildroot HOT 1
- "make testdlimage" => "./mini-rv32ima -f DownloadedImage" ... hangs (tested on 3 different platforms). HOT 4
- I Made it! esp32c3 can run linux with this wonderful emulator HOT 10
- Test page trimming
- U-BOOT HOT 5
- Can it run OpenSBI? HOT 9
- Customizing allowed instruction set? HOT 1
- Possible to get a full debian running on this? HOT 1
- Virtual Graphical interface HOT 1
- Invalid Discord Invite HOT 3
- Integrating Kernel on FPGA HOT 3
- Simplify sign-extension of immediates during instruction decoding HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mini-rv32ima.