lcpu: Lua devices now work!!
now i can like, actually finish this thing i will probably commonize all the stuff the luadevice class is doing right now into its own object, since I think that it would be very useful to have elsewhere. but for now it's not common :(
This commit is contained in:
parent
b6d41d33fa
commit
40c539bf22
|
@ -1,15 +1,59 @@
|
|||
AddCSLuaFile()
|
||||
|
||||
-- prime the native lua module & add clientside files to send
|
||||
-- if running on the server
|
||||
if SERVER then
|
||||
require("lcpu_native")
|
||||
|
||||
if LCPUNative.ModuleVersion != 1 then
|
||||
if LCPUNative.ModuleVersion ~= 1 then
|
||||
print("Your LCPU native module is somehow lagging behind the Lua code. Please rebuild it.")
|
||||
LCPUNative = nil
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- rapid iteration requires rapid solutions
|
||||
--[[
|
||||
device = LCPUNative.CreateDevice(0x100000f0, 0x10)
|
||||
device.a = 12
|
||||
device.apple = {}
|
||||
|
||||
--print(device)
|
||||
--print(device.a)
|
||||
--print(device.apple)
|
||||
|
||||
function device:Clock()
|
||||
print("a")
|
||||
end
|
||||
|
||||
function device:Peek(address)
|
||||
print("peek @ " .. address)
|
||||
if address == 0x100000f0 then return 0x1010 end -- it a test!
|
||||
|
||||
return 0x10000
|
||||
end
|
||||
|
||||
function device:Poke(address, value)
|
||||
if address == 0x100000f0 then
|
||||
print("What you doing?")
|
||||
end
|
||||
end
|
||||
|
||||
function device:Reset()
|
||||
print("device was reset")
|
||||
end
|
||||
|
||||
cpu = LCPUNative.CreateCPU(64*1024)
|
||||
|
||||
cpu:AttachDevice(device)
|
||||
|
||||
print(device.Clock)
|
||||
|
||||
print(cpu)
|
||||
|
||||
-- unrolled test loops ftw
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
]]
|
||||
AddCSLuaFile("entities/gmod_lcpu_cpu.lua")
|
||||
end
|
||||
|
|
|
@ -4,46 +4,51 @@ ENT.PrintName = "LCPU"
|
|||
ENT.Author = "Lily <3"
|
||||
-- no more, this deeply uses native APIs
|
||||
if CLIENT then return end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
-- 64 kb of ram for now.
|
||||
self.cpu = LCPUNative.CreateCPU(128 * 1024)
|
||||
|
||||
print(self.cpu)
|
||||
-- todo: cpu callbacks? once they become a thing
|
||||
-- test device framework
|
||||
-- this is how I ideally want to do things,
|
||||
-- dunno if it's possible
|
||||
self.test_device = LCPUNative.CreateDevice()
|
||||
print(self.test_device)
|
||||
self.test_device:SetBase(0x12000000)
|
||||
self.test_device:SetSize(0x10)
|
||||
function self.test_device:Clock()
|
||||
print("TestDevice Clock()")
|
||||
end
|
||||
-- (for once something works out how I wanted it to..)
|
||||
self.test_device = LCPUNative.CreateDevice(0x11300000, 0x8)
|
||||
self.test_device.register = 0x0
|
||||
|
||||
--function self.test_device:Clock()
|
||||
--print("TestDevice Clock()")
|
||||
--end
|
||||
|
||||
function self.test_device:Peek(address)
|
||||
if address == 0x12000000 then
|
||||
-- it a test!
|
||||
return CurTime()
|
||||
end
|
||||
return 0x10000
|
||||
--print("peek @ " .. address)
|
||||
if address == self.Base then return CurTime() end -- it a test!
|
||||
if address == self.Base + 4 then return self.register end
|
||||
|
||||
return 0xffffffff
|
||||
end
|
||||
|
||||
function self.test_device:Poke(address, value)
|
||||
if address == 0x12000000 then
|
||||
print("What you doing?")
|
||||
print("poke of address " .. address .. " -> " .. value)
|
||||
if address == self.Base + 4 then
|
||||
print("LUAREG write")
|
||||
self.register = value
|
||||
end
|
||||
end
|
||||
|
||||
function self.test_device:Reset()
|
||||
print("device was reset")
|
||||
-- clear the register
|
||||
self.register = 0
|
||||
end
|
||||
|
||||
self.cpu:AttachDevice(self.test_device)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
--
|
||||
if not self.cpu:PoweredOn() then return end
|
||||
|
||||
self.cpu:Cycle()
|
||||
-- Even though this is gated by tickrate I'm just trying to be nice here
|
||||
self:NextThink(CurTime() + 0.1)
|
||||
|
|
|
@ -8,7 +8,6 @@ add_library(lcpu_native SHARED
|
|||
|
||||
# Support code
|
||||
src/SourceSink.cpp
|
||||
src/LuaShared.cpp
|
||||
)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
@ -22,6 +21,7 @@ endif()
|
|||
|
||||
target_link_libraries(lcpu_native
|
||||
gmod_headers
|
||||
|
||||
lucore::lucore
|
||||
riscv::riscv
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "LcpuGlobals.hpp"
|
||||
|
||||
#include "GarrysMod/Lua/Interface.h"
|
||||
#include "LuaCpu.hpp"
|
||||
#include "LuaDevice.hpp"
|
||||
|
||||
|
||||
#include "LuaHelpers.hpp"
|
||||
|
||||
LUA_FUNCTION(LCPUNative_CreateCPU) {
|
||||
LUA->CheckType(1, GarrysMod::Lua::Type::Number);
|
||||
|
@ -18,13 +18,16 @@ LUA_FUNCTION(LCPUNative_CreateCPU) {
|
|||
}
|
||||
|
||||
LUA_FUNCTION(LCPUNative_CreateDevice) {
|
||||
LuaDevice::Create(LUA);
|
||||
auto base = LUA->CheckNumber(1);
|
||||
auto size = LUA->CheckNumber(2);
|
||||
lucore::LogInfo("Creating Lua device object mapped @ 0x{:08x} with size 0x{:08x}", static_cast<riscv::Address>(base), static_cast<riscv::Address>(size));
|
||||
LuaDevice::Create(LUA, static_cast<riscv::Address>(base), static_cast<riscv::Address>(size));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GlobalsBind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
LuaCpu::Bind(LUA);
|
||||
// LuaDevice::Bind(LUA);
|
||||
LuaDevice::Bind(LUA);
|
||||
|
||||
// clang-format off
|
||||
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);
|
||||
|
|
|
@ -75,12 +75,7 @@ LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Reset) {
|
|||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, AttachDevice) {
|
||||
auto self = LUA_CLASS_GET(LuaCpu)(1);
|
||||
auto device = LUA_CLASS_GET(LuaDevice)(1);
|
||||
|
||||
// the bus is safe against this possibility, but
|
||||
// I'd rather be doubly-safe tbh
|
||||
if(!device)
|
||||
LUA->ThrowError("Null device pointer");
|
||||
auto device = LUA_CLASS_GET(LuaDevice)(2);
|
||||
|
||||
// Attach it
|
||||
LUA->PushBool(self->system->bus->AttachDevice(static_cast<riscv::Bus::Device*>(device)));
|
||||
|
|
|
@ -1,42 +1,23 @@
|
|||
#include "LuaDevice.hpp"
|
||||
|
||||
#include "LuaHelpers.hpp"
|
||||
|
||||
LUA_CLASS_BIND_VARIABLES_IMPLEMENT(LuaDevice);
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, SetBase) {
|
||||
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
||||
if(self->bus)
|
||||
LUA->ThrowError("Do not call this on an attached device");
|
||||
self->base = static_cast<u32>(LUA->CheckNumber(2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, SetSize) {
|
||||
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
||||
if(self->bus)
|
||||
LUA->ThrowError("Do not call this on an attached device");
|
||||
self->size = static_cast<u32>(LUA->CheckNumber(2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LuaDevice::Clocked() const {
|
||||
// Even if Lua devices may not have a clock handler
|
||||
// installed there's no real non-awful way to check,
|
||||
// so just lie and say yes always.
|
||||
// no real good rationale for checking here,
|
||||
// since function calling does bail out properly
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaDevice::Clock() {
|
||||
LuaState->PushUserType(this, __lua_typeid);
|
||||
LuaState->GetField(-2, "Clock");
|
||||
if(!LuaState->IsType(-1, GarrysMod::Lua::Type::Function)) {
|
||||
LuaState->Pop(2);
|
||||
return;
|
||||
}
|
||||
LuaState->Push(-2); // "self"
|
||||
LuaState->ReferencePush(tableReference);
|
||||
LuaState->GetField(-1,"Clock");
|
||||
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
LuaState->Push(-2); // 'self' argument
|
||||
LuaState->Call(1, 0);
|
||||
LuaState->Pop();
|
||||
} else {
|
||||
LuaState->Pop(); // pop the Clock function off the stack
|
||||
}
|
||||
LuaState->Pop(); // pop the reference
|
||||
}
|
||||
|
||||
riscv::Address LuaDevice::Base() const {
|
||||
|
@ -48,60 +29,144 @@ riscv::Address LuaDevice::Size() const {
|
|||
}
|
||||
|
||||
u32 LuaDevice::Peek(riscv::Address address) {
|
||||
LuaState->PushUserType(this, __lua_typeid);
|
||||
LuaState->GetField(-2, "Peek");
|
||||
if(!LuaState->IsType(-1, GarrysMod::Lua::Type::Function)) {
|
||||
LuaState->Pop(2);
|
||||
return -1;
|
||||
}
|
||||
LuaState->Push(-2); // "self"
|
||||
LuaState->PushNumber(address);
|
||||
LuaState->Call(2, 1);
|
||||
/*if(peekHandlerReference != -1) {
|
||||
LuaState->ReferencePush(resetHandlerReference);
|
||||
LuaState->PushNumber(static_cast<double>(address));
|
||||
LuaState->Call(1, 1);
|
||||
auto result = LuaState->GetNumber(-1);
|
||||
LuaState->Pop();
|
||||
return static_cast<u32>(result);
|
||||
}*/
|
||||
|
||||
LuaState->ReferencePush(tableReference);
|
||||
LuaState->GetField(-1,"Peek");
|
||||
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
LuaState->Push(-2); // 'self' argument
|
||||
LuaState->PushNumber(static_cast<double>(address));
|
||||
LuaState->Call(2, 1);
|
||||
|
||||
auto result = static_cast<u32>(LuaState->GetNumber(-1));
|
||||
LuaState->Pop(2); // pop result and the table off
|
||||
return result;
|
||||
} else {
|
||||
LuaState->Pop(); // pop whatever Peek is off the stack
|
||||
}
|
||||
LuaState->Pop(); // pop the table reference
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
void LuaDevice::Poke(riscv::Address address, u32 value) {
|
||||
LuaState->PushUserType(this, __lua_typeid);
|
||||
LuaState->GetField(-2, "Poke");
|
||||
if(!LuaState->IsType(-1, GarrysMod::Lua::Type::Function)) {
|
||||
LuaState->Pop(2);
|
||||
return;
|
||||
}
|
||||
LuaState->Push(-2); // "self"
|
||||
/*if(pokeHandlerReference != -1) {
|
||||
LuaState->ReferencePush(pokeHandlerReference);
|
||||
LuaState->PushNumber(address);
|
||||
LuaState->PushNumber(value);
|
||||
LuaState->Call(2, 0);
|
||||
}*/
|
||||
|
||||
LuaState->ReferencePush(tableReference);
|
||||
LuaState->GetField(-1,"Poke");
|
||||
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
LuaState->Push(-2); // 'self' argument
|
||||
LuaState->PushNumber(static_cast<double>(address));
|
||||
LuaState->PushNumber(static_cast<double>(value));
|
||||
LuaState->Call(3, 0);
|
||||
LuaState->Pop();
|
||||
} else {
|
||||
LuaState->Pop(); // pop whatever Peek is
|
||||
}
|
||||
LuaState->Pop(); // pop the table reference
|
||||
}
|
||||
|
||||
void LuaDevice::Reset() {
|
||||
LuaState->PushUserType(this, __lua_typeid);
|
||||
LuaState->GetField(-2, "Reset");
|
||||
if(!LuaState->IsType(-1, GarrysMod::Lua::Type::Function))
|
||||
return;
|
||||
/*if(resetHandlerReference != -1) {
|
||||
LuaState->ReferencePush(resetHandlerReference);
|
||||
LuaState->Call(0, 0);
|
||||
}*/
|
||||
|
||||
LuaState->Push(-2); // "self"
|
||||
LuaState->ReferencePush(tableReference);
|
||||
LuaState->GetField(-1,"Reset");
|
||||
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
LuaState->Push(-2); // 'self' argument
|
||||
LuaState->Call(1, 0);
|
||||
LuaState->Pop();
|
||||
} else {
|
||||
LuaState->Pop(); // pop whatever reset is
|
||||
}
|
||||
LuaState->Pop(); // pop the reference
|
||||
}
|
||||
|
||||
LuaDevice::~LuaDevice() = default;
|
||||
LuaDevice::LuaDevice(riscv::Address base, riscv::Address size) : base(base), size(size) {
|
||||
}
|
||||
|
||||
LuaDevice::~LuaDevice() {
|
||||
// Free all refererences
|
||||
if(tableReference == -1)
|
||||
LuaState->ReferenceFree(tableReference);
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, __index) {
|
||||
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
||||
//lucore::LogInfo("metamethod __index call");
|
||||
|
||||
// TODO: before moving this to a shared lua object class thing
|
||||
// and moving the CPU class to use this way of doing things
|
||||
// I should probably try and like, add stuff to ensure native
|
||||
// methods can be registered as well,,
|
||||
LUA->ReferencePush(self->tableReference);
|
||||
LUA->Push(2);
|
||||
LUA->GetTable(-2);
|
||||
return 1; // the value
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, __newindex) {
|
||||
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
||||
//lucore::LogInfo("metamethod __newindex call");
|
||||
|
||||
// Always push onto the table.
|
||||
// TODO: This function
|
||||
// should error on attempt to __newindex any native methods
|
||||
// (when moved to a shared place)
|
||||
LUA->ReferencePush(self->tableReference);
|
||||
LUA->Push(2);
|
||||
LUA->Push(3);
|
||||
LUA->SetTable(-3);
|
||||
LUA->Pop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LuaDevice::Bind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
// clang-format off
|
||||
// TODO: I need to figure out how to like, set up metamethod stuff
|
||||
// so it all properly works.
|
||||
LUA_CLASS_BIND_BEGIN(LuaDevice);
|
||||
LUA_SET_C_FUNCTION(SetBase)
|
||||
LUA_SET_C_FUNCTION(SetSize)
|
||||
//LUA_CLASS_BIND_BEGIN(LuaDevice)
|
||||
__lua_typeid = LUA->CreateMetaTable("LuaDevice");
|
||||
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_REG);
|
||||
LUA->PushNumber(__lua_typeid);
|
||||
LUA->SetField(-2, "LuaDevice__typeid");
|
||||
LUA->Pop(); /* pop registry */
|
||||
|
||||
LUA_SET_C_FUNCTION(__gc)
|
||||
LUA_SET_C_FUNCTION(__index)
|
||||
LUA_SET_C_FUNCTION(__newindex)
|
||||
LUA_CLASS_BIND_END();
|
||||
// clang-format on
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LuaDevice::Create(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
auto device = new LuaDevice();
|
||||
void LuaDevice::Create(GarrysMod::Lua::ILuaBase* LUA, riscv::Address base, riscv::Address size) {
|
||||
auto device = new LuaDevice(base, size);
|
||||
device->LuaState = LUA;
|
||||
|
||||
LUA->CreateTable();
|
||||
device->tableReference = LUA->ReferenceCreate();
|
||||
LUA->Pop();
|
||||
|
||||
// push base/size properties for lua to have a looksee at !
|
||||
// ideally these should be handled as metamethods in __index,
|
||||
// but i don't quite feel like making gmod sol2 yet /shrug
|
||||
LUA->ReferencePush(device->tableReference);
|
||||
LUA->PushNumber(static_cast<double>(base));
|
||||
LUA->SetField(-2, "Base");
|
||||
LUA->PushNumber(static_cast<double>(base));
|
||||
LUA->SetField(-2, "Size");
|
||||
LUA->Pop();
|
||||
|
||||
LUA->PushUserType(device, __lua_typeid);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
struct LuaDevice : public riscv::Bus::MmioDevice {
|
||||
/// Lua binding stuff
|
||||
static void Bind(GarrysMod::Lua::ILuaBase* LUA);
|
||||
static void Create(GarrysMod::Lua::ILuaBase* LUA);
|
||||
static void Create(GarrysMod::Lua::ILuaBase* LUA, riscv::Address base, riscv::Address size);
|
||||
|
||||
~LuaDevice();
|
||||
|
||||
|
@ -26,14 +26,15 @@ struct LuaDevice : public riscv::Bus::MmioDevice {
|
|||
// class binding stuff
|
||||
LUA_CLASS_BIND_VARIABLES(private);
|
||||
|
||||
// Do not call these once attached to a bus.
|
||||
LUA_MEMBER_FUNCTION(SetBase);
|
||||
LUA_MEMBER_FUNCTION(SetSize);
|
||||
LUA_MEMBER_FUNCTION(__index);
|
||||
LUA_MEMBER_FUNCTION(__newindex);
|
||||
|
||||
// GetBase/GetSize?
|
||||
LuaDevice(riscv::Address base, riscv::Address size);
|
||||
|
||||
riscv::Address base {};
|
||||
riscv::Address size {};
|
||||
|
||||
GarrysMod::Lua::ILuaBase* LuaState;
|
||||
|
||||
// this should be a common type tbh
|
||||
int tableReference = -1;
|
||||
};
|
||||
|
|
|
@ -43,12 +43,13 @@
|
|||
LUA->CheckType(1, T::__lua_typeid); \
|
||||
auto self = LUA->GetUserType<T>(1, T::__lua_typeid); \
|
||||
if(self != nullptr) { /* GetUserType returns nullptr on failure */ \
|
||||
lucore::LogInfo("GCing {} object", #T); \
|
||||
lucore::LogInfo("GCing {} object @ {:p}", #T, static_cast<void*>(self)); \
|
||||
delete self; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
// Begin the Bind() method of a class. This just sets up boilerplate
|
||||
// and required things to setup a class.
|
||||
#define LUA_CLASS_BIND_BEGIN(T) \
|
||||
|
@ -73,3 +74,14 @@
|
|||
#define LUA_SET_C_FUNCTION_NAME(name, altName) \
|
||||
LUA->PushCFunction(name); \
|
||||
LUA->SetField(-2, altName);
|
||||
|
||||
|
||||
inline std::string GetLuaString(GarrysMod::Lua::ILuaBase* LUA, int stackPos) {
|
||||
unsigned len{};
|
||||
auto ptr = LUA->GetString(stackPos, &len);
|
||||
if(ptr) {
|
||||
return std::string(ptr, len);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
#include "LuaShared.hpp"
|
||||
|
||||
#include <lucore/Assert.hpp>
|
||||
#include <lucore/Library.hpp>
|
||||
|
||||
namespace lcpu::lua {
|
||||
|
||||
// A global pointer to the loaded instance of the lua_shared library.
|
||||
lucore::Library* luaSharedLibrary = nullptr;
|
||||
|
||||
#define LUA_SHARED_FUNC(Retty, name, ...) Retty (*name)(__VA_ARGS__) = nullptr;
|
||||
#include "LuaSharedFunctions.inc"
|
||||
#undef LUA_SHARED_FUNC
|
||||
|
||||
void LoadLuaShared() {
|
||||
// Open the lua_shared library
|
||||
luaSharedLibrary = lucore::Library::OpenExisting("lua_shared");
|
||||
LUCORE_CHECK(luaSharedLibrary != nullptr, "Could not open lua_shared library for some reason.");
|
||||
|
||||
// Load the functions from lua_shared
|
||||
// This is helped quite a bit by using an x-macro
|
||||
#define LUA_SHARED_FUNC(Retty, name, ...) \
|
||||
name = luaSharedLibrary->Symbol<decltype(name)>(#name); \
|
||||
LUCORE_CHECK(name != nullptr, "Could not load lua_shared function \"{}\"", #name);
|
||||
#include "LuaSharedFunctions.inc"
|
||||
#undef LUA_SHARED_FUNC
|
||||
}
|
||||
|
||||
void UnloadLuaShared() {
|
||||
LUCORE_ASSERT(luaSharedLibrary != nullptr, "UnloadLuaShared() should only be called if LoadLuaShared() was called");
|
||||
delete luaSharedLibrary;
|
||||
|
||||
#define LUA_SHARED_FUNC(Retty, name, ...) name = nullptr;
|
||||
#include "LuaSharedFunctions.inc"
|
||||
#undef LUA_SHARED_FUNC
|
||||
}
|
||||
|
||||
} // namespace lcpu::lua
|
|
@ -1,56 +0,0 @@
|
|||
//! Loader/types for lua_shared API. I plan to use this instead of the Garry's Mod
|
||||
//! ILuaBase interface; they are interchangable (and in fact, less friction to use!)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <GarrysMod/Lua/Interface.h>
|
||||
|
||||
namespace lcpu::lua {
|
||||
|
||||
#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */
|
||||
|
||||
struct lua_Debug {
|
||||
int event;
|
||||
const char* name; /* (n) */
|
||||
const char* namewhat; /* (n) `global', `local', `field', `method' */
|
||||
const char* what; /* (S) `Lua', `C', `main', `tail' */
|
||||
const char* source; /* (S) */
|
||||
int currentline; /* (l) */
|
||||
int nups; /* (u) number of upvalues */
|
||||
int linedefined; /* (S) */
|
||||
int lastlinedefined; /* (S) */
|
||||
char short_src[LUA_IDSIZE]; /* (S) */
|
||||
/* private part */
|
||||
int i_ci; /* active function */
|
||||
};
|
||||
|
||||
typedef int (*lua_CFunction)(lua_State* L);
|
||||
typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize);
|
||||
typedef const char* (*lua_Reader)(lua_State* L, void* ud, size_t* sz);
|
||||
typedef int (*lua_Writer)(lua_State* L, const void* p, size_t sz, void* ud);
|
||||
//typedef struct lua_Debug lua_Debug; /* activation record */
|
||||
typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar);
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char* p; /* current position in buffer */
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State* L;
|
||||
char buffer[8192];
|
||||
} luaL_Buffer;
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char* name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
#define LUA_SHARED_FUNC(Retty, name, ...) extern Retty (*name)(__VA_ARGS__);
|
||||
#include "LuaSharedFunctions.inc"
|
||||
#undef LUA_SHARED_FUNC
|
||||
|
||||
/// Load lua_shared
|
||||
void LoadLuaShared();
|
||||
|
||||
/// .. and unload it.
|
||||
void UnloadLuaShared();
|
||||
|
||||
} // namespace lcpu::lua
|
|
@ -1,128 +0,0 @@
|
|||
//! This is an X-Macro file of all the interesting functions in lua_shared
|
||||
LUA_SHARED_FUNC(lua_State*, luaL_newstate, void);
|
||||
LUA_SHARED_FUNC(int, luaL_loadstring, lua_State *L, const char* code);
|
||||
LUA_SHARED_FUNC(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf);
|
||||
LUA_SHARED_FUNC(void, lua_call, lua_State *L, int nargs, int nresults);
|
||||
LUA_SHARED_FUNC(int, lua_checkstack, lua_State *L, int size);
|
||||
LUA_SHARED_FUNC(void, lua_close, lua_State *L);
|
||||
LUA_SHARED_FUNC(void, lua_concat, lua_State*L,int n);
|
||||
LUA_SHARED_FUNC(int, lua_cpcall, lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_SHARED_FUNC(void, lua_createtable, lua_State *L, int narray, int nrec);
|
||||
LUA_SHARED_FUNC(int, lua_dump, lua_State *L, lua_Writer writer, void *data);
|
||||
LUA_SHARED_FUNC(int, lua_equal, lua_State *L, int idx1, int idx2);
|
||||
LUA_SHARED_FUNC(int, lua_error, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, lua_gc, lua_State *L, int what, int data);
|
||||
LUA_SHARED_FUNC(lua_Alloc, lua_getallocf, lua_State *L, void **ud);
|
||||
LUA_SHARED_FUNC(void, lua_getfenv, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_getfield, lua_State *L, int idx, const char *k);
|
||||
LUA_SHARED_FUNC(lua_Hook, lua_gethook, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, lua_gethookcount, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, lua_gethookmask, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar);
|
||||
LUA_SHARED_FUNC(const char*, lua_getlocal, lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_SHARED_FUNC(int, lua_getmetatable, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_getstack, lua_State *L, int level, lua_Debug *ar);
|
||||
LUA_SHARED_FUNC(void, lua_gettable, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_gettop, lua_State *L);
|
||||
LUA_SHARED_FUNC(const char*, lua_getupvalue, lua_State *L, int idx, int n);
|
||||
LUA_SHARED_FUNC(void, lua_insert, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_iscfunction, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_isnumber, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_isstring, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_isuserdata, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_lessthan, lua_State *L, int idx1, int idx2);
|
||||
LUA_SHARED_FUNC(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname);
|
||||
LUA_SHARED_FUNC(int, lua_loadx, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
||||
LUA_SHARED_FUNC(lua_State*, lua_newstate, lua_Alloc f, void *ud);
|
||||
LUA_SHARED_FUNC(lua_State*, lua_newthread, lua_State *L);
|
||||
LUA_SHARED_FUNC(void*, lua_newuserdata, lua_State *L, size_t size);
|
||||
LUA_SHARED_FUNC(int, lua_next, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(size_t, lua_objlen, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_pcall, lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_SHARED_FUNC(void, lua_pushboolean, lua_State *L, int b);
|
||||
LUA_SHARED_FUNC(void, lua_pushcclosure, lua_State *L, lua_CFunction f, int n);
|
||||
LUA_SHARED_FUNC(const char*, lua_pushfstring, lua_State *L, const char *fmt, ...);
|
||||
LUA_SHARED_FUNC(void, lua_pushlightuserdata, lua_State *L, void *p);
|
||||
LUA_SHARED_FUNC(void, lua_pushlstring, lua_State *L, const char *str, size_t len);
|
||||
LUA_SHARED_FUNC(void, lua_pushnil, lua_State *L);
|
||||
LUA_SHARED_FUNC(void, lua_pushnumber, lua_State *L, double n);
|
||||
LUA_SHARED_FUNC(void, lua_pushstring, lua_State *L, const char *str);
|
||||
LUA_SHARED_FUNC(int, lua_pushthread, lua_State *L);
|
||||
LUA_SHARED_FUNC(void, lua_pushvalue, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const char*, lua_pushvfstring, lua_State *L, const char *fmt, char* argp);
|
||||
LUA_SHARED_FUNC(int, lua_rawequal, lua_State *L, int idx1, int idx2);
|
||||
LUA_SHARED_FUNC(void, lua_rawget, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_rawgeti, lua_State *L, int idx, int n);
|
||||
LUA_SHARED_FUNC(void, lua_rawset, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_rawseti, lua_State *L, int idx, int n);
|
||||
LUA_SHARED_FUNC(void, lua_remove, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_replace, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud);
|
||||
LUA_SHARED_FUNC(int, lua_setfenv, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_setfield, lua_State *L, int idx, const char *k);
|
||||
LUA_SHARED_FUNC(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count);
|
||||
LUA_SHARED_FUNC(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_SHARED_FUNC(int, lua_setmetatable, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_settable, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void, lua_settop, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const char*, lua_setupvalue, lua_State *L, int idx, int n);
|
||||
LUA_SHARED_FUNC(int, lua_status, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, lua_toboolean, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(lua_CFunction, lua_tocfunction, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const char*, lua_tolstring, lua_State *L, int idx, size_t *len);
|
||||
LUA_SHARED_FUNC(double, lua_tonumber, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const void*, lua_topointer, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(lua_State*, lua_tothread, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(void*, lua_touserdata, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, lua_type, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const char*, lua_typename, lua_State *L, int t);
|
||||
LUA_SHARED_FUNC(void*, lua_upvalueid, lua_State *L, int idx, int n);
|
||||
LUA_SHARED_FUNC(void, lua_upvaluejoin, lua_State *L, int idx1, int n1, int idx2, int n2);
|
||||
LUA_SHARED_FUNC(void, lua_xmove, lua_State *from, lua_State *to, int n);
|
||||
LUA_SHARED_FUNC(int, lua_yield, lua_State *L, int nresults);
|
||||
LUA_SHARED_FUNC(int, luaJIT_setmode, lua_State *L, int idx, int mode);
|
||||
LUA_SHARED_FUNC(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l);
|
||||
LUA_SHARED_FUNC(void, luaL_addstring, luaL_Buffer *B, const char *s);
|
||||
LUA_SHARED_FUNC(void, luaL_addvalue, luaL_Buffer *B);
|
||||
LUA_SHARED_FUNC(int, luaL_argerror, lua_State *L, int narg, const char *msg);
|
||||
LUA_SHARED_FUNC(void, luaL_buffinit, lua_State *L, luaL_Buffer *B);
|
||||
LUA_SHARED_FUNC(int, luaL_callmeta, lua_State *L, int idx, const char *field);
|
||||
LUA_SHARED_FUNC(void, luaL_checkany, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(const char*, luaL_checklstring, lua_State *L, int idx, size_t *len);
|
||||
LUA_SHARED_FUNC(double, luaL_checknumber, lua_State *L, int idx);
|
||||
LUA_SHARED_FUNC(int, luaL_checkoption, lua_State *L, int idx, const char *def, const char *const lst[]);
|
||||
LUA_SHARED_FUNC(void, luaL_checkstack, lua_State *L, int size, const char *msg);
|
||||
LUA_SHARED_FUNC(void, luaL_checktype, lua_State *L, int idx, int tt);
|
||||
LUA_SHARED_FUNC(void*, luaL_checkudata, lua_State *L, int idx, const char *tname);
|
||||
LUA_SHARED_FUNC(int, luaL_error, lua_State *L, const char *fmt, ...);
|
||||
LUA_SHARED_FUNC(int, luaL_execresult, lua_State *L, int stat);
|
||||
LUA_SHARED_FUNC(int, luaL_fileresult, lua_State *L, int stat, const char *fname);
|
||||
LUA_SHARED_FUNC(const char*, luaL_findtable, lua_State *L, int idx, const char *fname, int szhint);
|
||||
LUA_SHARED_FUNC(int, luaL_getmetafield, lua_State *L, int idx, const char *field);
|
||||
LUA_SHARED_FUNC(const char*, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r);
|
||||
LUA_SHARED_FUNC(int, luaL_loadbuffer, lua_State *L, const char *buff, size_t sz, const char *name);
|
||||
LUA_SHARED_FUNC(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
|
||||
LUA_SHARED_FUNC(int, luaL_loadfile, lua_State *L, const char *filename);
|
||||
LUA_SHARED_FUNC(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode);
|
||||
LUA_SHARED_FUNC(int, luaL_newmetatable, lua_State *L, const char *tname);
|
||||
LUA_SHARED_FUNC(void, luaL_openlib, lua_State *L, const char *libname, const luaL_Reg *l, int nup);
|
||||
LUA_SHARED_FUNC(int, luaL_openlibs, lua_State *L);
|
||||
LUA_SHARED_FUNC(const char*, luaL_optlstring, lua_State *L, int idx, const char *def, size_t *len);
|
||||
LUA_SHARED_FUNC(double, luaL_optnumber, lua_State *L, int idx, double def);
|
||||
LUA_SHARED_FUNC(char*, luaL_prepbuffer, luaL_Buffer *B);
|
||||
LUA_SHARED_FUNC(void, luaL_pushresult, luaL_Buffer *B);
|
||||
LUA_SHARED_FUNC(int, luaL_ref, lua_State *L, int t);
|
||||
LUA_SHARED_FUNC(void, luaL_register, lua_State *L, const char *libname, const luaL_Reg *l);
|
||||
LUA_SHARED_FUNC(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level);
|
||||
LUA_SHARED_FUNC(int, luaL_typerror, lua_State *L, int narg, const char *tname);
|
||||
LUA_SHARED_FUNC(void, luaL_unref, lua_State *L, int t, int ref);
|
||||
LUA_SHARED_FUNC(void, luaL_where, lua_State *L, int lvl);
|
||||
LUA_SHARED_FUNC(int, luaopen_base, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_bit, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_debug, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_jit, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_math, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_os, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_package, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_string, lua_State *L);
|
||||
LUA_SHARED_FUNC(int, luaopen_table, lua_State *L);
|
|
@ -6,19 +6,15 @@
|
|||
|
||||
#include "LcpuGlobals.hpp"
|
||||
|
||||
#include "LuaShared.hpp"
|
||||
|
||||
GMOD_MODULE_OPEN() {
|
||||
// Initialize our lua_shared binding. It is important we ca
|
||||
lucore::Logger::The().AttachSink(lcpu::SourceSink::The());
|
||||
lucore::LogInfo("LCPU Native Module! (ModuleVersion {})", LCPU_MODULE_VERSION);
|
||||
|
||||
lcpu::lua::LoadLuaShared();
|
||||
|
||||
GlobalsBind(LUA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GMOD_MODULE_CLOSE() {
|
||||
lcpu::lua::UnloadLuaShared();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -105,14 +105,10 @@ namespace riscv {
|
|||
virtual void Poke(Address address, u32 value) = 0;
|
||||
};
|
||||
|
||||
/// Bus destructor.
|
||||
/// This frees the memory for all devices.
|
||||
~Bus();
|
||||
|
||||
/// Attach a device to the bus.
|
||||
///
|
||||
/// Note that once this function is called (and the device is successfully added),
|
||||
/// the object pointed to by [device] is owned by the Bus object, and should not be deleted.
|
||||
/// the object pointed to by [device] should last at least as long as the bus.
|
||||
///
|
||||
/// # Returns
|
||||
/// This function returns true if the device was able to be put on the bus.
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
|
||||
namespace riscv {
|
||||
|
||||
Bus::~Bus() {
|
||||
// Free all devices
|
||||
for(auto device : devices)
|
||||
delete device;
|
||||
}
|
||||
|
||||
bool Bus::AttachDevice(Device* device) {
|
||||
if(!device)
|
||||
return false;
|
||||
|
|
|
@ -30,7 +30,13 @@ namespace riscv {
|
|||
|
||||
System::~System() {
|
||||
delete cpu;
|
||||
delete bus; // the rest of the device pointers will be deleted by the bus.
|
||||
delete bus;
|
||||
|
||||
// delete our devices
|
||||
// externally bound devices should clean themselves up
|
||||
delete clnt;
|
||||
delete syscon;
|
||||
delete ram;
|
||||
}
|
||||
|
||||
void System::Step() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// a simple test program - this version would talk to a device
|
||||
// written in GLua
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t strlen(const char* str) {
|
||||
if(!str)
|
||||
|
@ -12,7 +12,9 @@ uint32_t strlen(const char* str) {
|
|||
return c - str;
|
||||
}
|
||||
|
||||
#define GLUA_DEVICE *(volatile uint32_t*)0x12000000
|
||||
#define GLUA_DEVICE_BASE 0x11300000 // base address of the lua test device
|
||||
#define GLUA_DEVICE_WORLDTIME *(volatile uint32_t*)GLUA_DEVICE_BASE // world time register (read only)
|
||||
#define GLUA_DEVICE_LUAREG *(volatile uint32_t*)(GLUA_DEVICE_BASE + 4) // lua register (read/write)
|
||||
|
||||
#define SYSCON *(volatile uint32_t*)0x11100000
|
||||
|
||||
|
@ -70,9 +72,9 @@ void vprintf(const char* format, va_list val) {
|
|||
for(int i = 0; i < fl; ++i) {
|
||||
switch(format[i]) {
|
||||
case '%':
|
||||
if(format[i+1] == '%')
|
||||
if(format[i + 1] == '%')
|
||||
putc('%');
|
||||
switch(format[i+1]) {
|
||||
switch(format[i + 1]) {
|
||||
case 'i':
|
||||
case 'd': {
|
||||
char a[32];
|
||||
|
@ -81,6 +83,7 @@ void vprintf(const char* format, va_list val) {
|
|||
const int al = strlen(a);
|
||||
for(int j = 0; j < al; ++j)
|
||||
putc(a[j]);
|
||||
i++;
|
||||
} break;
|
||||
|
||||
case 's': {
|
||||
|
@ -89,16 +92,13 @@ void vprintf(const char* format, va_list val) {
|
|||
puts("(null)");
|
||||
else
|
||||
puts(p);
|
||||
i++;
|
||||
};
|
||||
|
||||
default:
|
||||
putc(' ');
|
||||
break;
|
||||
default: putc(' '); break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
putc(format[i]);
|
||||
break;
|
||||
default: putc(format[i]); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,13 +110,17 @@ void printf(const char* format, ...) {
|
|||
va_end(val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main() {
|
||||
puts("fuck you garry I win");
|
||||
|
||||
for(int i = 0; i < 256; ++i)
|
||||
printf("uhh %d\n", GLUA_DEVICE);
|
||||
for(int i = 0; i < 8; ++i)
|
||||
printf("GLUA_DEVICE_WORLDTIME reading says -> %d\n", GLUA_DEVICE_WORLDTIME);
|
||||
|
||||
// try writing to it
|
||||
GLUA_DEVICE_LUAREG = 0x1234;
|
||||
|
||||
for(int i = 0; i < 8; ++i)
|
||||
printf("GLUA_DEVICE_LUAREG reading says -> %d\n", GLUA_DEVICE_LUAREG);
|
||||
|
||||
SYSCON = 0x5555;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue