From b35dd7d9b50e4448bf57efe483e6092362241cac Mon Sep 17 00:00:00 2001 From: IonutParau Date: Fri, 23 May 2025 19:59:40 +0200 Subject: [PATCH] basic computer running --- build.zig | 2 + src/computer.c | 12 ++-- src/emulator.c | 25 ++++++- src/neonucleus.h | 9 +-- src/sandbox.lua | 2 + src/testLuaArch.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++ src/testLuaArch.h | 7 ++ 7 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 src/sandbox.lua create mode 100644 src/testLuaArch.c create mode 100644 src/testLuaArch.h diff --git a/build.zig b/build.zig index 660ceae..cd7809d 100644 --- a/build.zig +++ b/build.zig @@ -58,8 +58,10 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); emulator.linkLibC(); + emulator.linkSystemLibrary("lua"); emulator.addCSourceFiles(.{ .files = &.{ + "src/testLuaArch.c", "src/emulator.c", }, }); diff --git a/src/computer.c b/src/computer.c index fade607..078a5eb 100644 --- a/src/computer.c +++ b/src/computer.c @@ -61,6 +61,10 @@ void nn_setTmpAddress(nn_computer *computer, nn_address tmp) { } nn_address nn_getComputerAddress(nn_computer *computer) { + return computer->address; +} + +nn_address nn_getTmpAddress(nn_computer *computer) { return computer->tmpAddress; } @@ -329,12 +333,12 @@ size_t nn_getReturnCount(nn_computer *computer) { return computer->retc; } -char *nn_serializeProgram(nn_computer *computer) { - return computer->arch->serialize(computer, computer->archState, computer->arch->userdata); +char *nn_serializeProgram(nn_computer *computer, size_t *len) { + return computer->arch->serialize(computer, computer->archState, computer->arch->userdata, len); } -void nn_deserializeProgram(nn_computer *computer, char *memory) { - computer->arch->deserialize(computer, memory, computer->archState, computer->arch->userdata); +void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len) { + computer->arch->deserialize(computer, memory, len, computer->archState, computer->arch->userdata); } void nn_lockComputer(nn_computer *computer) { diff --git a/src/emulator.c b/src/emulator.c index 77aad55..7d64e83 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -1,13 +1,36 @@ +#include #include #include "neonucleus.h" +#include "testLuaArch.h" int main() { printf("Setting up universe\n"); nn_universe *universe = nn_newUniverse(); - // we need an arch + nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua"); + assert(arch != NULL && "Loading architecture failed"); + + // 1MB of RAM, 16 components max + nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16); + while(true) { + nn_tickComputer(computer); + const char *e = nn_getError(computer); + if(e != NULL) { + printf("Error: %s\n", e); + break; + } + int state = nn_getState(computer); + if(state == NN_STATE_CLOSING || state == NN_STATE_REPEAT || state == NN_STATE_SWITCH) { + if(state == NN_STATE_SWITCH) { + nn_architecture *nextArch = nn_getNextArchitecture(computer); + printf("Next architecture: %s\n", nextArch->archName); + } + break; + } + } // destroy + nn_deleteComputer(computer); nn_unsafeDeleteUniverse(universe); printf("Emulator is nowhere close to complete\n"); return 0; diff --git a/src/neonucleus.h b/src/neonucleus.h index 6d1a94e..78f0abe 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -71,8 +71,8 @@ typedef struct nn_architecture { size_t (*getMemoryUsage)(nn_computer *computer, void *state, void *userdata); void (*tick)(nn_computer *computer, void *state, void *userdata); /* Pointer returned should be allocated with nn_malloc or nn_realloc, so it can be freed with nn_free */ - char *(*serialize)(nn_computer *computer, void *state, void *userdata); - void (*deserialize)(nn_computer *computer, const char *data, void *state, void *userdata); + char *(*serialize)(nn_computer *computer, void *state, void *userdata, size_t *len); + void (*deserialize)(nn_computer *computer, const char *data, size_t len, void *state, void *userdata); } nn_architecture; typedef char *nn_address; @@ -170,8 +170,8 @@ const char *nn_indexUser(nn_computer *computer, size_t idx); bool nn_isUser(nn_computer *computer, const char *name); /* The memory returned can be freed with nn_free() */ -char *nn_serializeProgram(nn_computer *computer); -void nn_deserializeProgram(nn_computer *computer, char *memory); +char *nn_serializeProgram(nn_computer *computer, size_t *len); +void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len); void nn_lockComputer(nn_computer *computer); void nn_unlockComputer(nn_computer *computer); @@ -234,6 +234,7 @@ void nn_setCError(nn_computer *computer, const char *err); nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slot, nn_componentTable *table, void *userdata); void nn_setTmpAddress(nn_computer *computer, nn_address tmp); nn_address nn_getComputerAddress(nn_computer *computer); +nn_address nn_getTmpAddress(nn_computer *computer); void nn_removeComponent(nn_computer *computer, nn_address address); void nn_destroyComponent(nn_component *component); nn_computer *nn_getComputerOfComponent(nn_component *component); diff --git a/src/sandbox.lua b/src/sandbox.lua new file mode 100644 index 0000000..1809960 --- /dev/null +++ b/src/sandbox.lua @@ -0,0 +1,2 @@ +print(string.format("%d / %d", computer.usedMemory(), computer.totalMemory())) +print(string.format("Computer Address: %q, Tmp Address: %q", computer.address(), computer.tmpAddress())) diff --git a/src/testLuaArch.c b/src/testLuaArch.c new file mode 100644 index 0000000..bc4bba3 --- /dev/null +++ b/src/testLuaArch.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include "neonucleus.h" + +char *testLuaSandbox = NULL; + +typedef struct testLuaArch { + lua_State *L; + nn_computer *computer; + size_t memoryUsed; +} testLuaArch; + +void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize) { + if(nsize == 0) { + arch->memoryUsed -= osize; + nn_free(ptr); + return NULL; + } else { + if(arch->memoryUsed - osize + nsize > nn_getComputerMemoryTotal(arch->computer)) { + return NULL; // OOM condition + } + if(ptr != NULL) { + // if ptr is NULL, osize will actually encode the type. + // We do not want that to mess us up. + arch->memoryUsed -= osize; + } + arch->memoryUsed += nsize; + return nn_realloc(ptr, nsize); + } +} + +testLuaArch *testLuaArch_get(lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "archPtr"); + testLuaArch *arch = lua_touserdata(L, -1); + lua_pop(L, 1); + return arch; +} + +nn_computer *testLuaArch_getComputer(lua_State *L) { + return testLuaArch_get(L)->computer; +} + +static int testLuaArch_computer_usedMemory(lua_State *L) { + testLuaArch *s = testLuaArch_get(L); + lua_pushinteger(L, s->memoryUsed); + return 1; +} + +static int testLuaArch_computer_freeMemory(lua_State *L) { + testLuaArch *s = testLuaArch_get(L); + lua_pushinteger(L, nn_getComputerMemoryTotal(s->computer) - s->memoryUsed); + return 1; +} + +static int testLuaArch_computer_totalMemory(lua_State *L) { + testLuaArch *s = testLuaArch_get(L); + lua_pushinteger(L, nn_getComputerMemoryTotal(s->computer)); + return 1; +} + +static int testLuaArch_computer_address(lua_State *L) { + nn_computer *c = testLuaArch_getComputer(L); + lua_pushstring(L, nn_getComputerAddress(c)); + return 1; +} + +static int testLuaArch_computer_tmpAddress(lua_State *L) { + nn_computer *c = testLuaArch_getComputer(L); + lua_pushstring(L, nn_getTmpAddress(c)); + return 1; +} + +void testLuaArch_loadEnv(lua_State *L) { + lua_createtable(L, 0, 10); + int computer = lua_gettop(L); + lua_pushcfunction(L, testLuaArch_computer_usedMemory); + lua_setfield(L, computer, "usedMemory"); + lua_pushcfunction(L, testLuaArch_computer_freeMemory); + lua_setfield(L, computer, "freeMemory"); + lua_pushcfunction(L, testLuaArch_computer_totalMemory); + lua_setfield(L, computer, "totalMemory"); + lua_pushcfunction(L, testLuaArch_computer_address); + lua_setfield(L, computer, "address"); + lua_pushcfunction(L, testLuaArch_computer_tmpAddress); + lua_setfield(L, computer, "tmpAddress"); + lua_setglobal(L, "computer"); +} + +testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) { + testLuaArch *s = nn_malloc(sizeof(testLuaArch)); + if(s == NULL) return NULL; + s->memoryUsed = 0; + s->computer = computer; + lua_State *L = lua_newstate((void *)testLuaArch_alloc, s); + assert(L != NULL); + luaL_openlibs(L); + lua_pushlightuserdata(L, s); + lua_setfield(L, LUA_REGISTRYINDEX, "archPtr"); + s->L = L; + testLuaArch_loadEnv(L); + assert(luaL_loadbufferx(L, testLuaSandbox, strlen(testLuaSandbox), "=machine.lua", "t") == LUA_OK); + return s; +} + +void testLuaArch_teardown(nn_computer *computer, testLuaArch *arch, void *_) { + lua_close(arch->L); + nn_free(arch); +} + +void testLuaArch_tick(nn_computer *computer, testLuaArch *arch, void *_) { + int ret = 0; + int res = lua_resume(arch->L, NULL, 0, &ret); + if(res == LUA_OK) { + // machine halted, this is no good + lua_pop(arch->L, ret); + nn_setCError(computer, "machine halted"); + } else if(res == LUA_YIELD) { + lua_pop(arch->L, ret); + } else { + const char *s = lua_tostring(arch->L, -1); + nn_setError(computer, s); + lua_pop(arch->L, 1); + } +} + +size_t testLuaArch_getMemoryUsage(nn_computer *computer, testLuaArch *arch, void *_) { + return arch->memoryUsed; +} + +char *testLuaArch_serialize(nn_computer *computer, testLuaArch *arch, void *_, size_t *len) { + *len = 0; + return NULL; +} + +void testLuaArch_deserialize(nn_computer *computer, const char *data, size_t len, testLuaArch *arch, void *_) {} + +nn_architecture testLuaArchTable = { + .archName = "Lua Test", + .userdata = NULL, + .setup = (void *)testLuaArch_setup, + .teardown = (void *)testLuaArch_teardown, + .tick = (void *)testLuaArch_tick, + .getMemoryUsage = (void*)testLuaArch_getMemoryUsage, +}; + +nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath) { + if(testLuaSandbox == NULL) { + FILE *f = fopen(sandboxPath, "r"); + if(f == NULL) return NULL; + fseek(f, 0, SEEK_END); + size_t l = ftell(f); + testLuaSandbox = nn_malloc(l+1); + if(testLuaSandbox == NULL) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_SET); + fread(testLuaSandbox, sizeof(char), l, f); + testLuaSandbox[l] = '\0'; + fclose(f); + } + return &testLuaArchTable; +} diff --git a/src/testLuaArch.h b/src/testLuaArch.h new file mode 100644 index 0000000..6dd6e75 --- /dev/null +++ b/src/testLuaArch.h @@ -0,0 +1,7 @@ +#ifndef TEST_LUA_ARCH +#define TEST_LUA_ARCH + +#include "neonucleus.h" +nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath); + +#endif