test lua binding things
This commit is contained in:
parent
90e684e1e3
commit
887b66bbb0
|
@ -1,5 +1,6 @@
|
||||||
build/
|
build/
|
||||||
lua/bin
|
# this one is created by the build script
|
||||||
|
module_build/
|
||||||
native/projects/riscv/ref
|
native/projects/riscv/ref
|
||||||
|
|
||||||
.cache/
|
.cache/
|
||||||
|
|
|
@ -2,15 +2,17 @@
|
||||||
|
|
||||||
# Build the LCPU addon for the reccomended environment
|
# Build the LCPU addon for the reccomended environment
|
||||||
# and install it into the proper directory gmod wants native modules to be.
|
# and install it into the proper directory gmod wants native modules to be.
|
||||||
# This expects to be ran in [gmod]/addons/[addon folder].
|
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
cmake -Wno-dev -GNinja -S native -B build -DCMAKE_BUILD_TYPE=Release
|
# where your game server is
|
||||||
ninja -C build
|
GS_PATH="/home/lily/gs/gmod"
|
||||||
|
|
||||||
[[ ! -d '../../lua/bin' ]] && {
|
cmake -Wno-dev -GNinja -S native -B module_build -DCMAKE_BUILD_TYPE=Release
|
||||||
mkdir -p ../../lua/bin
|
ninja -C module_build
|
||||||
|
|
||||||
|
[[ ! -d "$GS_PATH/garrysmod/lua/bin" ]] && {
|
||||||
|
mkdir -p $GS_PATH/garrysmod/lua/bin
|
||||||
}
|
}
|
||||||
|
|
||||||
cp -v build/projects/lcpu/*.dll ../../lua/bin
|
cp -v module_build/projects/lcpu/*.dll $GS_PATH/garrysmod/lua/bin
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
-- skeleton load file to get gmod to recognize this as an addon
|
|
||||||
-- this will contain files later on in life.
|
|
||||||
AddCSLuaFile()
|
AddCSLuaFile()
|
||||||
|
|
||||||
|
-- prime the native lua module if running on the server
|
||||||
|
if SERVER then
|
||||||
|
require("lcpu_native")
|
||||||
|
|
||||||
|
if LCPUNative.ModuleVersion != 1 then
|
||||||
|
print("Your LCPU native module is somehow lagging behind the Lua code. Please rebuild it.")
|
||||||
|
LCPUNative = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
AddCSLuaFile("entities/gmod_lcpu_cpu.lua")
|
||||||
|
AddCSLuaFile("lcpu/stool_helper.lua")
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
AddCSLuaFile()
|
||||||
|
DEFINE_BASECLASS("base_wire_entity") -- for now?
|
||||||
|
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(64 * 1024)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ENT:Think()
|
||||||
|
self.cpu:Cycle()
|
||||||
|
-- Even though this is gated by tickrate I'm just trying to be nice here
|
||||||
|
self:NextThink(CurTime() + 0.1)
|
||||||
|
end
|
|
@ -0,0 +1,98 @@
|
||||||
|
-- default vars
|
||||||
|
TOOL.Mode = "lcpu_lcpu"
|
||||||
|
TOOL.short_name = "lcpu"
|
||||||
|
TOOL.Category = "Lily <3"
|
||||||
|
TOOL.Name = "#tool.lcpu.name"
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
language.Add("tool.lcpu.name", "LCPU Tool")
|
||||||
|
language.Add("tool.lcpu.desc", "Spawns a LCPU")
|
||||||
|
language.Add("tool.lcpu.model", "LCPU Model:")
|
||||||
|
TOOL.Information = {
|
||||||
|
{
|
||||||
|
name = "left",
|
||||||
|
text = "Spawn or update a LCPU"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
-- { name = "right", text = "Open editor" },
|
||||||
|
-- { name = "reload", text = "Attach debugger" },
|
||||||
|
-- { name = "reload_shift", text = "Shift+Reload: Clear" },
|
||||||
|
end
|
||||||
|
|
||||||
|
TOOL.ClientConVar = {
|
||||||
|
model = "models/cheeze/wires/cpu.mdl",
|
||||||
|
}
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Make sure firing animation is displayed clientside
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
function TOOL:LeftClick()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function TOOL:Reload()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function TOOL:RightClick()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
--function TOOL:Reload(trace)
|
||||||
|
-- if trace.Entity:IsPlayer() then return false end
|
||||||
|
-- local player = self:GetOwner()
|
||||||
|
|
||||||
|
-- return true
|
||||||
|
--end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function TOOL:LeftClick()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Right click: open editor
|
||||||
|
--function TOOL:RightClick(trace)
|
||||||
|
-- return true
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Build tool control panel
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
function TOOL.BuildCPanel(panel)
|
||||||
|
print("bruh")
|
||||||
|
panel:AddControl( "Header", { Description = "#tool.lcpu.desc" } )
|
||||||
|
panel:AddControl(
|
||||||
|
"Label",
|
||||||
|
{
|
||||||
|
Text = "LCPU settings:"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
panel:AddControl(
|
||||||
|
"PropSelect",
|
||||||
|
{
|
||||||
|
Label = "#tool.lcpu.model",
|
||||||
|
ConVar = "model",
|
||||||
|
Height = 0,
|
||||||
|
Models = list.Get("Wire_gate_Models")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
panel:AddControl(
|
||||||
|
"Label",
|
||||||
|
{
|
||||||
|
Text = ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
-- function TOOL:DrawToolScreen(width, height)
|
||||||
|
-- local currentTime = os.date("*t")
|
||||||
|
-- CPULib.RenderCPUTool(currentTime.yday % 4,"CPU")
|
||||||
|
-- end
|
||||||
|
end
|
|
@ -2,8 +2,11 @@ include(./gmod_headers.cmake)
|
||||||
|
|
||||||
|
|
||||||
add_library(lcpu_native SHARED
|
add_library(lcpu_native SHARED
|
||||||
src/main.cpp
|
|
||||||
src/SourceSink.cpp
|
src/SourceSink.cpp
|
||||||
|
|
||||||
|
src/main.cpp
|
||||||
|
src/LuaCpu.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "LuaCpu.hpp"
|
||||||
|
|
||||||
|
#include <lucore/Logger.hpp>
|
||||||
|
|
||||||
|
#include "LuaMember.hpp"
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
fputc(c, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int LuaCpu::__lua_typeid;
|
||||||
|
|
||||||
|
void LuaCpu::Bind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||||
|
lucore::LogInfo("In LuaCpu::Bind()");
|
||||||
|
__lua_typeid = LUA->CreateMetaTable("LuaCpu");
|
||||||
|
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_REG);
|
||||||
|
LUA->PushNumber(__lua_typeid);
|
||||||
|
LUA->SetField(-2, "LuaCpu__typeid");
|
||||||
|
LUA->Pop(); // Pop the registry
|
||||||
|
|
||||||
|
LUA->Push(-1);
|
||||||
|
// This method is called when the GC is done with our stuff
|
||||||
|
LUA->PushCFunction(__gc);
|
||||||
|
LUA->SetField(-1, "__gc");
|
||||||
|
|
||||||
|
LUA->PushCFunction(Cycle);
|
||||||
|
LUA->SetField(-1, "Cycle");
|
||||||
|
LUA->Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaCpu::Create(GarrysMod::Lua::ILuaBase* LUA, u32 memorySize) {
|
||||||
|
LUA->PushUserType(new LuaCpu(memorySize), __lua_typeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaCpu::LuaCpu(u32 memorySize) {
|
||||||
|
system = riscv::System::Create(memorySize);
|
||||||
|
system->OnPowerOff = [&]() { this->OnSysconShutdown(); };
|
||||||
|
|
||||||
|
system->bus->AttachDevice(new SimpleUartDevice);
|
||||||
|
|
||||||
|
// lame test code. this WILL be removed, I just want this for a quick test
|
||||||
|
auto fp = std::fopen("/home/lily/gs/gmod/garrysmod/addons/lcpu/native/projects/riscv_test_harness/test/test.bin", "rb");
|
||||||
|
if(fp) {
|
||||||
|
std::fseek(fp, 0, SEEK_END);
|
||||||
|
auto len = std::ftell(fp);
|
||||||
|
std::fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
std::fread(system->ram->Raw(), 1, len, fp);
|
||||||
|
std::fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaCpu::~LuaCpu() {
|
||||||
|
delete system;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaCpu::CycleImpl() {
|
||||||
|
if(!poweredOn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
system->Step();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaCpu::OnSysconShutdown() {
|
||||||
|
poweredOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LUA_MEMBER_FUNCTION(LuaCpu, __gc) {
|
||||||
|
auto self = LUA->GetUserType<LuaCpu>(1, __lua_typeid);
|
||||||
|
if(self != nullptr) { // GetUserType returns nullptr on failure
|
||||||
|
delete self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LUA_MEMBER_FUNCTION(LuaCpu, Cycle) {
|
||||||
|
auto self = LUA->GetUserType<LuaCpu>(1, __lua_typeid);
|
||||||
|
if(!self) {
|
||||||
|
LUA->ThrowError("invalid self argument for LuaCpu:Cycle()");
|
||||||
|
}
|
||||||
|
|
||||||
|
self->CycleImpl();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <riscv/System.hpp>
|
||||||
|
|
||||||
|
#include "LuaMember.hpp"
|
||||||
|
|
||||||
|
// A work-in-progress
|
||||||
|
struct LuaCpu {
|
||||||
|
/// Lua binding stuff
|
||||||
|
static void Bind(GarrysMod::Lua::ILuaBase* LUA);
|
||||||
|
static void Create(GarrysMod::Lua::ILuaBase* LUA, u32 memorySize);
|
||||||
|
|
||||||
|
LuaCpu(u32 memorySize);
|
||||||
|
~LuaCpu();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CycleImpl();
|
||||||
|
|
||||||
|
void OnSysconShutdown();
|
||||||
|
|
||||||
|
// LUA user type id.
|
||||||
|
static int __lua_typeid;
|
||||||
|
|
||||||
|
// Metafunctions
|
||||||
|
LUA_MEMBER_FUNCTION_DECLARE(__gc)
|
||||||
|
LUA_MEMBER_FUNCTION_DECLARE(__tostring)
|
||||||
|
|
||||||
|
// Called by the LCPU entity for specific tasks:
|
||||||
|
LUA_MEMBER_FUNCTION_DECLARE(Cycle)
|
||||||
|
LUA_MEMBER_FUNCTION_DECLARE(SetMemorySize)
|
||||||
|
|
||||||
|
// member variables
|
||||||
|
riscv::System* system;
|
||||||
|
bool poweredOn = false;
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GarrysMod/Lua/Interface.h>
|
||||||
|
|
||||||
|
// These are like the official GMOD header LUA_FUNCTION but allow forward declaration
|
||||||
|
// and implementation inside of classes. Pretty nifty!
|
||||||
|
#define LUA_MEMBER_FUNCTION_DECLARE(FUNC) \
|
||||||
|
static int FUNC##__ImpStatic(GarrysMod::Lua::ILuaBase* LUA); \
|
||||||
|
static int FUNC(lua_State* L) { \
|
||||||
|
GarrysMod::Lua::ILuaBase* LUA = L->luabase; \
|
||||||
|
LUA->SetState(L); \
|
||||||
|
return FUNC##__ImpStatic(LUA); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LUA_MEMBER_FUNCTION(CLASS, FUNC) int CLASS::FUNC##__ImpStatic(GarrysMod::Lua::ILuaBase* LUA)
|
|
@ -1,16 +1,60 @@
|
||||||
#include <GarrysMod/Lua/Interface.h>
|
#include <GarrysMod/Lua/Interface.h>
|
||||||
|
|
||||||
#include <lucore/Assert.hpp>
|
#include <cmath>
|
||||||
|
#include <lucore/Logger.hpp>
|
||||||
|
#include <lucore/Types.hpp>
|
||||||
|
|
||||||
#include "SourceSink.hpp"
|
#include "SourceSink.hpp"
|
||||||
|
|
||||||
LUA_FUNCTION(lcpu_native_test) {
|
#include "LuaCpu.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
LUA_FUNCTION(LCPUNative_CreateCPU) {
|
||||||
|
LUA->CheckType(1, GarrysMod::Lua::Type::Number);
|
||||||
|
auto memorySize = (u32)std::round(LUA->GetNumber(1));
|
||||||
|
|
||||||
|
if (memorySize > (64 * 1024 * 1024)) {
|
||||||
|
LUA->ThrowError("Over current RAM size limit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//LuaCpu::Create(LUA, memorySize);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a device object. This is internally used by the CPU to create Wire and other interface things.
|
||||||
|
LUA_FUNCTION(LCPUNative_CreateDevice) {
|
||||||
|
return 0; // for now, while LuaDevice doesn't exist?
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCPUNative_Bind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||||
|
LUA->PushSpecial( GarrysMod::Lua::SPECIAL_GLOB );
|
||||||
|
LUA->CreateTable();
|
||||||
|
LUA->PushNumber(1);
|
||||||
|
LUA->SetField(-2, "ModuleVersion");
|
||||||
|
|
||||||
|
LUA->PushCFunction(LCPUNative_CreateCPU);
|
||||||
|
LUA->SetField(-2, "CreateCPU");
|
||||||
|
|
||||||
|
LUA->PushCFunction(LCPUNative_CreateDevice);
|
||||||
|
LUA->SetField(-2, "CreateDevice");
|
||||||
|
LUA->SetField(-2, "LCPUNative");
|
||||||
|
LUA->Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GMOD_MODULE_OPEN() {
|
GMOD_MODULE_OPEN() {
|
||||||
lucore::Logger::The().AttachSink(lcpu::SourceSink::The());
|
lucore::Logger::The().AttachSink(lcpu::SourceSink::The());
|
||||||
|
|
||||||
lucore::LogInfo("LCPU Native Module loading");
|
lucore::LogInfo("LCPU Native Module!");
|
||||||
|
|
||||||
|
|
||||||
|
// Let lua types bind
|
||||||
|
//LuaCpu::Bind(LUA);
|
||||||
|
|
||||||
|
// Bind the global namespace
|
||||||
|
LCPUNative_Bind(LUA);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@ namespace riscv::devices {
|
||||||
RamDevice(Address base, Address size);
|
RamDevice(Address base, Address size);
|
||||||
virtual ~RamDevice();
|
virtual ~RamDevice();
|
||||||
|
|
||||||
|
// Resize. DO NOT call this while actively using the memory,
|
||||||
|
// or you WILL crash.
|
||||||
|
void Resize(Address newSize);
|
||||||
|
|
||||||
// Implementation of Device interface
|
// Implementation of Device interface
|
||||||
|
|
||||||
Address Base() const override;
|
Address Base() const override;
|
||||||
|
|
|
@ -279,9 +279,7 @@ namespace riscv {
|
||||||
// case 0xf12: rval = 0x00000000; break; //marchid
|
// case 0xf12: rval = 0x00000000; break; //marchid
|
||||||
// case 0xf13: rval = 0x00000000; break; //mimpid
|
// case 0xf13: rval = 0x00000000; break; //mimpid
|
||||||
// case 0xf14: rval = 0x00000000; break; //mhartid
|
// case 0xf14: rval = 0x00000000; break; //mhartid
|
||||||
default:
|
default: break;
|
||||||
// MINIRV32_OTHERCSR_READ(csrno, rval);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(microop) {
|
switch(microop) {
|
||||||
|
@ -309,9 +307,7 @@ namespace riscv {
|
||||||
// case 0xf13: break; //mimpid
|
// case 0xf13: break; //mimpid
|
||||||
// case 0xf14: break; //mhartid
|
// case 0xf14: break; //mhartid
|
||||||
// case 0x301: break; //misa
|
// case 0x301: break; //misa
|
||||||
default:
|
default: break;
|
||||||
// MINIRV32_OTHERCSR_WRITE(csrno, writeval);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else if(microop == 0x0) { // "SYSTEM" 0b000
|
} else if(microop == 0x0) { // "SYSTEM" 0b000
|
||||||
rdid = 0;
|
rdid = 0;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include <riscv/Devices/RamDevice.hpp>
|
#include <riscv/Devices/RamDevice.hpp>
|
||||||
|
|
||||||
#include "riscv/Types.hpp"
|
|
||||||
|
|
||||||
namespace riscv::devices {
|
namespace riscv::devices {
|
||||||
|
|
||||||
RamDevice::RamDevice(Address base, Address size) : memoryBase(base), memorySize(size) {
|
RamDevice::RamDevice(Address base, Address size) : memoryBase(base), memorySize(size) {
|
||||||
|
@ -13,6 +11,15 @@ namespace riscv::devices {
|
||||||
delete[] memory;
|
delete[] memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RamDevice::Resize(Address newSize) {
|
||||||
|
if(memory) {
|
||||||
|
delete[] memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory = new u8[newSize];
|
||||||
|
memorySize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
Address RamDevice::Base() const {
|
Address RamDevice::Base() const {
|
||||||
return memoryBase;
|
return memoryBase;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ struct SimpleUartDevice : public riscv::Bus::MmioDevice {
|
||||||
|
|
||||||
u32 Peek(riscv::Address address) override {
|
u32 Peek(riscv::Address address) override {
|
||||||
switch(address) {
|
switch(address) {
|
||||||
case BASE_ADDRESS: return 0x60; // active, but no keyboard input
|
case BASE_ADDRESS: return '\0'; // just return 0 for the input register
|
||||||
case BASE_ADDRESS + 5: return '\0';
|
case BASE_ADDRESS + 5: return 0x60; // active, but no keyboard input
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -53,8 +53,8 @@ void main() {
|
||||||
|
|
||||||
// Shut down the test harness once we're done testing.
|
// Shut down the test harness once we're done testing.
|
||||||
puts("Tests done, shutting down test harness...\n");
|
puts("Tests done, shutting down test harness...\n");
|
||||||
SYSCON = 0x5555;
|
//SYSCON = 0x5555;
|
||||||
|
|
||||||
// loop forever
|
// loop forever
|
||||||
// for(;;);
|
for(;;);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue