Giter Site home page Giter Site logo

Comments (2)

twitchyliquid64 avatar twitchyliquid64 commented on July 18, 2024

This is what I've come up with so far.

Some comments:

  1. 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?
  2. 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 a blocked() 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.

cnlohr avatar cnlohr commented on July 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.