gmod-lcpu/native/projects/lcpu/src/LuaCpu.cpp

146 lines
3.2 KiB
C++
Raw Normal View History

2023-07-24 06:50:18 -04:00
#include "LuaCpu.hpp"
#include <lucore/Logger.hpp>
#include "LuaDevice.hpp"
#include "LuaHelpers.hpp"
2023-07-24 06:50:18 -04:00
// this is temporary from the thing
/// simple 16550 UART implementation
struct SimpleUartDevice : public riscv::Bus::MmioDevice {
constexpr static riscv::Address BASE_ADDRESS = 0x10000000;
riscv::Address Base() const override { return BASE_ADDRESS; }
riscv::Address Size() const override { return 12; } // for now
u32 Peek(riscv::Address address) override {
switch(address) {
case BASE_ADDRESS: return '\0'; // just return 0 for the input register
case BASE_ADDRESS + 5: return 0x60; // active, but no keyboard input
}
return 0;
}
void Poke(riscv::Address address, u32 value) override {
if(address == BASE_ADDRESS) {
char c = value & 0x000000ff;
std::fputc(c, stderr);
2023-07-24 06:50:18 -04:00
}
}
};
LUA_CLASS_BIND_VARIABLES_IMPLEMENT(LuaCpu);
2023-07-24 06:50:18 -04:00
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PoweredOn) {
LUA_CLASS_GET(LuaCpu, self, 1);
LUA->PushBool(self->poweredOn);
return 1;
2023-07-24 06:50:18 -04:00
}
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Cycle) {
LUA_CLASS_GET(LuaCpu, self, 1);
[&self]() {
if(!self->poweredOn)
return;
self->system->Step();
}();
return 0;
2023-07-24 06:50:18 -04:00
}
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOff) {
LUA_CLASS_GET(LuaCpu, self, 1);
[&self]() {
if(!self->poweredOn)
return;
2023-07-24 06:50:18 -04:00
self->poweredOn = false;
self->system->bus->Reset();
}();
2023-07-24 06:50:18 -04:00
return 0;
2023-07-24 06:50:18 -04:00
}
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOn) {
LUA_CLASS_GET(LuaCpu, self, 1);
[&self]() {
if(self->poweredOn)
return;
self->poweredOn = true;
self->system->bus->Reset();
}();
return 0;
2023-07-24 06:50:18 -04:00
}
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Reset) {
LUA_CLASS_GET(LuaCpu, self, 1);
[&self]() { self->system->bus->Reset(); }();
return 0;
}
2023-07-24 06:50:18 -04:00
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, AttachDevice) {
LUA_CLASS_GET(LuaCpu, self, 1);
bool result = false;
#if 0
[&]() {
LUA_CLASS_GET(LuaDevice, device, 2);
if(!device)
return; // the bus is safe against this possibility, but
// I'd rather be doubly-safe tbh
// Attach it
result = self->system->bus->AttachDevice(static_cast<riscv::Bus::Device*>(device));
}();
#endif
LUA->PushBool(result);
return 1;
2023-07-24 06:50:18 -04:00
}
void LuaCpu::Bind(GarrysMod::Lua::ILuaBase* LUA) {
// clang-format off
LUA_CLASS_BIND_BEGIN(LuaCpu);
LUA_SET_C_FUNCTION(PoweredOn);
LUA_SET_C_FUNCTION(Cycle);
LUA_SET_C_FUNCTION(PowerOff);
LUA_SET_C_FUNCTION(PowerOn);
LUA_SET_C_FUNCTION(Reset);
LUA_SET_C_FUNCTION(AttachDevice);
LUA_CLASS_BIND_END();
// clang-format on
2023-07-24 06:50:18 -04:00
}
void LuaCpu::Create(GarrysMod::Lua::ILuaBase* LUA, u32 memorySize) {
auto cpuWrapper = new LuaCpu(memorySize);
// lame test code. this WILL be removed, I just want this for a quick test
cpuWrapper->system->bus->AttachDevice(new SimpleUartDevice);
auto fp = std::fopen("/home/lily/test.bin", "rb");
if(fp) {
std::fseek(fp, 0, SEEK_END);
auto len = std::ftell(fp);
std::fseek(fp, 0, SEEK_SET);
std::fread(cpuWrapper->system->ram->Raw(), 1, len, fp);
std::fclose(fp);
2023-07-24 06:50:18 -04:00
}
LUA->PushUserType(cpuWrapper, __lua_typeid);
2023-07-24 06:50:18 -04:00
}
LuaCpu::LuaCpu(u32 memorySize) {
lucore::LogInfo("in LuaCpu::LuaCpu(0x{:08x})\n", memorySize);
2023-07-24 06:50:18 -04:00
poweredOn = true;
system = riscv::System::Create(memorySize);
system->OnPowerOff = [&]() {
poweredOn = false;
system->bus->Reset();
};
}
LuaCpu::~LuaCpu() {
delete system;
2023-07-24 06:50:18 -04:00
}