improved EEPROM system

This commit is contained in:
IonutParau 2025-07-12 13:13:46 +02:00
parent 1bf8604433
commit d9670610f8
4 changed files with 146 additions and 89 deletions

View File

@ -13,11 +13,6 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module {
.root_source_file = b.path("src/data.zig"), .root_source_file = b.path("src/data.zig"),
.target = opts.target, .target = opts.target,
.optimize = opts.optimize, .optimize = opts.optimize,
.single_threaded = true,
.sanitize_c = true,
.valgrind = true,
.stack_check = true,
.stack_protector = true,
}); });
dataMod.addCSourceFiles(.{ dataMod.addCSourceFiles(.{

View File

@ -1,11 +1,53 @@
#include "../neonucleus.h" #include "../neonucleus.h"
nn_eepromControl nn_eeprom_getControl(nn_component *component, nn_eeprom *eeprom) { typedef struct nn_eeprom {
return eeprom->control(component, eeprom->userdata); nn_Context ctx;
nn_refc refc;
nn_guard *lock;
nn_eepromTable table;
nn_eepromControl control;
} nn_eeprom;
nn_eeprom *nn_newEEPROM(nn_Context *context, nn_eepromTable table, nn_eepromControl control) {
nn_eeprom *e = nn_alloc(&context->allocator, sizeof(nn_eeprom));
if(e == NULL) return NULL;
e->lock = nn_newGuard(context);
if(e->lock == NULL) {
nn_dealloc(&context->allocator, e, sizeof(nn_eeprom));
return NULL;
}
e->ctx = *context;
e->refc = 1;
e->control = control;
e->table = table;
return e;
}
nn_guard *nn_getEEPROMLock(nn_eeprom *eeprom) {
return eeprom->lock;
}
void nn_retainEEPROM(nn_eeprom *eeprom) {
nn_incRef(&eeprom->refc);
}
nn_bool_t nn_destroyEEPROM(nn_eeprom *eeprom) {
if(!nn_decRef(&eeprom->refc)) return false;
// no need to lock, we are the only one with a reference
if(eeprom->table.deinit != NULL) {
eeprom->table.deinit(eeprom->table.userdata);
}
nn_Context ctx = eeprom->ctx;
nn_deleteGuard(&ctx, eeprom->lock);
nn_dealloc(&ctx.allocator, eeprom, sizeof(nn_eeprom));
return true;
} }
static void nn_eeprom_readCost(nn_component *component, nn_size_t bytesRead) { static void nn_eeprom_readCost(nn_component *component, nn_size_t bytesRead) {
nn_eepromControl control = nn_eeprom_getControl(component, nn_getComponentUserdata(component)); nn_eepromControl control = ((nn_eeprom *)nn_getComponentUserdata(component))->control;
nn_computer *computer = nn_getComputerOfComponent(component); nn_computer *computer = nn_getComputerOfComponent(component);
nn_removeEnergy(computer, control.readEnergyCostPerByte * bytesRead); nn_removeEnergy(computer, control.readEnergyCostPerByte * bytesRead);
@ -14,7 +56,7 @@ static void nn_eeprom_readCost(nn_component *component, nn_size_t bytesRead) {
} }
static void nn_eeprom_writeCost(nn_component *component, nn_size_t bytesWritten) { static void nn_eeprom_writeCost(nn_component *component, nn_size_t bytesWritten) {
nn_eepromControl control = nn_eeprom_getControl(component, nn_getComponentUserdata(component)); nn_eepromControl control = ((nn_eeprom *)nn_getComponentUserdata(component))->control;
nn_computer *computer = nn_getComputerOfComponent(component); nn_computer *computer = nn_getComputerOfComponent(component);
nn_removeEnergy(computer, control.writeEnergyCostPerByte * bytesWritten); nn_removeEnergy(computer, control.writeEnergyCostPerByte * bytesWritten);
@ -23,25 +65,21 @@ static void nn_eeprom_writeCost(nn_component *component, nn_size_t bytesWritten)
} }
void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) { void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) {
if(!nn_decRef(&eeprom->refc)) return; nn_destroyEEPROM(eeprom);
if(eeprom->deinit != NULL) {
eeprom->deinit(component, eeprom->userdata);
}
} }
void nn_eeprom_getSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_return(computer, nn_values_integer(eeprom->getSize(component, eeprom->userdata))); nn_return(computer, nn_values_integer(eeprom->table.size));
} }
void nn_eeprom_getDataSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getDataSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_return(computer, nn_values_integer(eeprom->getDataSize(component, eeprom->userdata))); nn_return(computer, nn_values_integer(eeprom->table.dataSize));
} }
void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
char buf[NN_LABEL_SIZE]; char buf[NN_LABEL_SIZE];
nn_size_t l = NN_LABEL_SIZE; nn_size_t l = NN_LABEL_SIZE;
eeprom->getLabel(component, eeprom->userdata, buf, &l); eeprom->table.getLabel(eeprom->table.userdata, buf, &l);
if(l == 0) { if(l == 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
@ -60,7 +98,9 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
nn_setCError(computer, "bad label (string expected)"); nn_setCError(computer, "bad label (string expected)");
return; return;
} }
l = eeprom->setLabel(component, eeprom->userdata, buf, l); nn_lock(&eeprom->ctx, eeprom->lock);
l = eeprom->table.setLabel(eeprom->table.userdata, buf, l);
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_return_string(computer, buf, l); nn_return_string(computer, buf, l);
// Latency, energy costs and stuff // Latency, energy costs and stuff
@ -68,14 +108,16 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
} }
void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_size_t cap = eeprom->getSize(component, eeprom->userdata); nn_size_t cap = eeprom->table.size;
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap); char *buf = nn_alloc(alloc, cap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
} }
nn_size_t len = eeprom->get(component, eeprom->userdata, buf); nn_lock(&eeprom->ctx, eeprom->lock);
nn_size_t len = eeprom->table.get(eeprom->table.userdata, buf);
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_return_string(computer, buf, len); nn_return_string(computer, buf, len);
nn_dealloc(alloc, buf, cap); nn_dealloc(alloc, buf, cap);
@ -86,7 +128,7 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
nn_value data = nn_getArgument(computer, 0); nn_value data = nn_getArgument(computer, 0);
nn_size_t len; nn_size_t len;
const char *buf = nn_toString(data, &len); const char *buf = nn_toString(data, &len);
if(len > eeprom->getSize(component, eeprom->userdata)) { if(len > eeprom->table.size) {
nn_setCError(computer, "out of space"); nn_setCError(computer, "out of space");
return; return;
} }
@ -99,20 +141,24 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
return; return;
} }
} }
eeprom->set(component, eeprom->userdata, buf, len); nn_lock(&eeprom->ctx, eeprom->lock);
eeprom->table.set(eeprom->table.userdata, buf, len);
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_eeprom_writeCost(component, len); nn_eeprom_writeCost(component, len);
} }
void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_size_t cap = eeprom->getDataSize(component, eeprom->userdata); nn_size_t cap = eeprom->table.dataSize;
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap); char *buf = nn_alloc(alloc, cap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
} }
int len = eeprom->getData(component, eeprom->userdata, buf); nn_lock(&eeprom->ctx, eeprom->lock);
int len = eeprom->table.getData(eeprom->table.userdata, buf);
nn_unlock(&eeprom->ctx, eeprom->lock);
if(len < 0) { if(len < 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
@ -136,42 +182,52 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c
return; return;
} }
} }
if(len > eeprom->getDataSize(component, eeprom->userdata)) { if(len > eeprom->table.dataSize) {
nn_setCError(computer, "out of space"); nn_setCError(computer, "out of space");
return; return;
} }
eeprom->setData(component, eeprom->userdata, buf, len); nn_lock(&eeprom->ctx, eeprom->lock);
eeprom->table.setData(eeprom->table.userdata, buf, len);
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_eeprom_writeCost(component, len); nn_eeprom_writeCost(component, len);
} }
void nn_eeprom_isReadOnly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_isReadOnly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_return(computer, nn_values_boolean(eeprom->isReadonly(component, eeprom->userdata))); nn_lock(&eeprom->ctx, eeprom->lock);
nn_return(computer, nn_values_boolean(eeprom->table.isReadonly(eeprom->table.userdata)));
nn_unlock(&eeprom->ctx, eeprom->lock);
} }
void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
eeprom->makeReadonly(component, eeprom->userdata); nn_lock(&eeprom->ctx, eeprom->lock);
eeprom->table.makeReadonly(eeprom->table.userdata);
nn_unlock(&eeprom->ctx, eeprom->lock);
} }
void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
nn_size_t dataCap = eeprom->getDataSize(component, eeprom->userdata); nn_size_t dataCap = eeprom->table.dataSize;
nn_size_t codeCap = eeprom->getSize(component, eeprom->userdata); nn_size_t codeCap = eeprom->table.size;
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, dataCap + codeCap); char *buf = nn_alloc(alloc, dataCap + codeCap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
} }
int dataLen = eeprom->getData(component, eeprom->userdata, buf); nn_lock(&eeprom->ctx, eeprom->lock);
int dataLen = eeprom->table.getData(eeprom->table.userdata, buf);
if(dataLen < 0) { if(dataLen < 0) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_dealloc(alloc, buf, dataCap + codeCap); nn_dealloc(alloc, buf, dataCap + codeCap);
return; return;
} }
int codeLen = eeprom->get(component, eeprom->userdata, buf + dataLen); int codeLen = eeprom->table.get(eeprom->table.userdata, buf + dataLen);
if(codeLen < 0) { if(codeLen < 0) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_dealloc(alloc, buf, dataCap + codeCap); nn_dealloc(alloc, buf, dataCap + codeCap);
return; return;
} }
nn_unlock(&eeprom->ctx, eeprom->lock);
char hash[4]; char hash[4];
nn_data_crc32(buf, dataLen + codeLen, hash); nn_data_crc32(buf, dataLen + codeLen, hash);
nn_dealloc(alloc, buf, dataCap + codeCap); nn_dealloc(alloc, buf, dataCap + codeCap);

View File

@ -96,8 +96,7 @@ Color ne_processColor(unsigned int color) {
return GetColor(color); return GetColor(color);
} }
nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) { nn_eepromControl ne_eeprom_ctrl = {
return (nn_eepromControl) {
.readHeatPerByte = 0.0015, .readHeatPerByte = 0.0015,
.writeHeatPerByte = 0.03, .writeHeatPerByte = 0.03,
.readEnergyCostPerByte = 0.001, .readEnergyCostPerByte = 0.001,
@ -105,21 +104,12 @@ nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) {
.bytesReadPerTick = 32768, .bytesReadPerTick = 32768,
.bytesWrittenPerTick = 4096, .bytesWrittenPerTick = 4096,
}; };
}
size_t ne_eeprom_getSize(nn_component *component, void *_) { void ne_eeprom_getLabel(void *_, char *buf, size_t *buflen) {
return 4096;
}
size_t ne_eeprom_getDataSize(nn_component *component, void *_) {
return 1024;
}
void ne_eeprom_getLabel(nn_component *component, void *_, char *buf, size_t *buflen) {
*buflen = 0; *buflen = 0;
} }
size_t ne_eeprom_setLabel(nn_component *component, void *_, const char *buf, size_t buflen) { size_t ne_eeprom_setLabel(void *_, const char *buf, size_t buflen) {
return 0; return 0;
} }
@ -129,8 +119,8 @@ const char *ne_location(nn_address address) {
return buffer; return buffer;
} }
size_t ne_eeprom_get(nn_component *component, void *_, char *buf) { size_t ne_eeprom_get(void *addr, char *buf) {
FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "rb"); FILE *f = fopen(ne_location(addr), "rb");
if (f == NULL) { if (f == NULL) {
printf("couldn't read eeprom"); printf("couldn't read eeprom");
exit(1); exit(1);
@ -143,8 +133,8 @@ size_t ne_eeprom_get(nn_component *component, void *_, char *buf) {
return len; return len;
} }
void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len) { void ne_eeprom_set(void *addr, const char *buf, size_t len) {
FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "wb"); FILE *f = fopen(ne_location(addr), "wb");
if (f == NULL) { if (f == NULL) {
printf("couldn't write eeprom"); printf("couldn't write eeprom");
exit(1); exit(1);
@ -153,17 +143,17 @@ void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len
fclose(f); fclose(f);
} }
int ne_eeprom_getData(nn_component *component, void *_, char *buf) { int ne_eeprom_getData(void *_, char *buf) {
return 0; return 0;
} }
void ne_eeprom_setData(nn_component *component, void *_, const char *buf, size_t len) {} void ne_eeprom_setData(void *_, const char *buf, size_t len) {}
nn_bool_t ne_eeprom_isReadonly(nn_component *component, void *userdata) { nn_bool_t ne_eeprom_isReadonly(void *userdata) {
return false; return false;
} }
void ne_eeprom_makeReadonly(nn_component *component, void *userdata) {} void ne_eeprom_makeReadonly(void *userdata) {}
#define NE_FS_MAX 128 #define NE_FS_MAX 128
@ -191,6 +181,18 @@ nn_filesystemControl ne_fs_getControl(nn_component *component, ne_fs *_) {
}; };
} }
void ne_fs_getLabel(nn_component *component, void *_, char *buf, size_t *buflen) {
*buflen = 0;
}
nn_size_t ne_fs_setLabel(nn_component *component, void *_, const char *buf, size_t buflen) {
return 0;
}
nn_bool_t ne_fs_isReadonly(nn_component *component, void *userdata) {
return false;
}
size_t ne_fs_spaceUsed(nn_component *component, void *_) { size_t ne_fs_spaceUsed(nn_component *component, void *_) {
return 0; // ultra accurate return 0; // ultra accurate
} }
@ -677,16 +679,14 @@ int main() {
// 1MB of RAM, 16 components max // 1MB of RAM, 16 components max
nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16); nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16);
nn_setEnergyInfo(computer, 5000, 5000); nn_setEnergyInfo(computer, 5000, 5000);
nn_setCallBudget(computer, 18000); //nn_setCallBudget(computer, 18000);
nn_addSupportedArchitecture(computer, arch); nn_addSupportedArchitecture(computer, arch);
nn_eeprom genericEEPROM = { nn_eepromTable genericEEPROMTable = {
.userdata = NULL, .userdata = "luaBios.lua",
.refc = 1,
.deinit = NULL, .deinit = NULL,
.control = ne_eeprom_getControl, .size = 4096,
.getSize = ne_eeprom_getSize, .dataSize = 1024,
.getDataSize = ne_eeprom_getDataSize,
.getLabel = ne_eeprom_getLabel, .getLabel = ne_eeprom_getLabel,
.setLabel = ne_eeprom_setLabel, .setLabel = ne_eeprom_setLabel,
.get = ne_eeprom_get, .get = ne_eeprom_get,
@ -697,7 +697,9 @@ int main() {
.makeReadonly = ne_eeprom_makeReadonly, .makeReadonly = ne_eeprom_makeReadonly,
}; };
nn_addEeprom(computer, "luaBios.lua", 0, &genericEEPROM); nn_eeprom *genericEEPROM = nn_newEEPROM(&ctx, genericEEPROMTable, ne_eeprom_ctrl);
nn_addEeprom(computer, "luaBios.lua", 0, genericEEPROM);
ne_fs fs = { ne_fs fs = {
.files = {NULL}, .files = {NULL},
@ -709,11 +711,11 @@ int main() {
.userdata = &fs, .userdata = &fs,
.deinit = NULL, .deinit = NULL,
.control = (void *)ne_fs_getControl, .control = (void *)ne_fs_getControl,
.getLabel = ne_eeprom_getLabel, .getLabel = ne_fs_getLabel,
.setLabel = ne_eeprom_setLabel, .setLabel = ne_fs_setLabel,
.spaceUsed = ne_fs_spaceUsed, .spaceUsed = ne_fs_spaceUsed,
.spaceTotal = ne_fs_spaceTotal, .spaceTotal = ne_fs_spaceTotal,
.isReadOnly = ne_eeprom_isReadonly, .isReadOnly = ne_fs_isReadonly,
.size = (void *)ne_fs_size, .size = (void *)ne_fs_size,
.remove = NULL, .remove = NULL,
.lastModified = (void *)ne_fs_lastModified, .lastModified = (void *)ne_fs_lastModified,
@ -740,8 +742,8 @@ int main() {
.userdata = &drive, .userdata = &drive,
.deinit = (void *)ne_drive_close, .deinit = (void *)ne_drive_close,
.control = (void *)ne_drive_getControl, .control = (void *)ne_drive_getControl,
.getLabel = ne_eeprom_getLabel, .getLabel = ne_fs_getLabel,
.setLabel = ne_eeprom_setLabel, .setLabel = ne_fs_setLabel,
.getPlatterCount = (void *)ne_drive_getPlatterCount, .getPlatterCount = (void *)ne_drive_getPlatterCount,
.getSectorSize = (void *)ne_drive_getSectorSize, .getSectorSize = (void *)ne_drive_getSectorSize,
.getCapacity = (void *)ne_drive_getCapacity, .getCapacity = (void *)ne_drive_getCapacity,

View File

@ -582,25 +582,29 @@ typedef struct nn_eepromControl {
double bytesWrittenPerTick; double bytesWrittenPerTick;
} nn_eepromControl; } nn_eepromControl;
typedef struct nn_eeprom { typedef struct nn_eepromTable {
nn_refc refc;
void *userdata; void *userdata;
void (*deinit)(nn_component *component, void *userdata); void (*deinit)(void *userdata);
nn_eepromControl (*control)(nn_component *component, void *userdata);
// methods // methods
nn_size_t (*getSize)(nn_component *component, void *userdata); nn_size_t size;
nn_size_t (*getDataSize)(nn_component *component, void *userdata); nn_size_t dataSize;
void (*getLabel)(nn_component *component, void *userdata, char *buf, nn_size_t *buflen); void (*getLabel)(void *userdata, char *buf, nn_size_t *buflen);
nn_size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, nn_size_t buflen); nn_size_t (*setLabel)(void *userdata, const char *buf, nn_size_t buflen);
nn_size_t (*get)(nn_component *component, void *userdata, char *buf); nn_size_t (*get)(void *userdata, char *buf);
void (*set)(nn_component *component, void *userdata, const char *buf, nn_size_t len); void (*set)(void *userdata, const char *buf, nn_size_t len);
int (*getData)(nn_component *component, void *userdata, char *buf); int (*getData)(void *userdata, char *buf);
void (*setData)(nn_component *component, void *userdata, const char *buf, nn_size_t len); void (*setData)(void *userdata, const char *buf, nn_size_t len);
nn_bool_t (*isReadonly)(nn_component *component, void *userdata); nn_bool_t (*isReadonly)(void *userdata);
void (*makeReadonly)(nn_component *component, void *userdata); void (*makeReadonly)(void *userdata);
} nn_eeprom; } nn_eepromTable;
typedef struct nn_eeprom nn_eeprom;
nn_eeprom *nn_newEEPROM(nn_Context *context, nn_eepromTable table, nn_eepromControl control);
nn_guard *nn_getEEPROMLock(nn_eeprom *eeprom);
void nn_retainEEPROM(nn_eeprom *eeprom);
nn_bool_t nn_destroyEEPROM(nn_eeprom *eeprom);
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom); nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom);
// FileSystem // FileSystem