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"),
.target = opts.target,
.optimize = opts.optimize,
.single_threaded = true,
.sanitize_c = true,
.valgrind = true,
.stack_check = true,
.stack_protector = true,
});
dataMod.addCSourceFiles(.{

View File

@ -1,11 +1,53 @@
#include "../neonucleus.h"
nn_eepromControl nn_eeprom_getControl(nn_component *component, nn_eeprom *eeprom) {
return eeprom->control(component, eeprom->userdata);
typedef struct nn_eeprom {
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) {
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_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) {
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_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) {
if(!nn_decRef(&eeprom->refc)) return;
if(eeprom->deinit != NULL) {
eeprom->deinit(component, eeprom->userdata);
}
nn_destroyEEPROM(eeprom);
}
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) {
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) {
char buf[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) {
nn_return(computer, nn_values_nil());
} else {
@ -60,7 +98,9 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
nn_setCError(computer, "bad label (string expected)");
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);
// 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) {
nn_size_t cap = eeprom->getSize(component, eeprom->userdata);
nn_size_t cap = eeprom->table.size;
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap);
if(buf == NULL) {
nn_setCError(computer, "out of memory");
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_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_size_t 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");
return;
}
@ -99,20 +141,24 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
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);
}
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));
char *buf = nn_alloc(alloc, cap);
if(buf == NULL) {
nn_setCError(computer, "out of memory");
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) {
nn_return(computer, nn_values_nil());
} else {
@ -136,42 +182,52 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c
return;
}
}
if(len > eeprom->getDataSize(component, eeprom->userdata)) {
if(len > eeprom->table.dataSize) {
nn_setCError(computer, "out of space");
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);
}
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) {
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) {
nn_size_t dataCap = eeprom->getDataSize(component, eeprom->userdata);
nn_size_t codeCap = eeprom->getSize(component, eeprom->userdata);
nn_size_t dataCap = eeprom->table.dataSize;
nn_size_t codeCap = eeprom->table.size;
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, dataCap + codeCap);
if(buf == NULL) {
nn_setCError(computer, "out of memory");
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) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_dealloc(alloc, buf, dataCap + codeCap);
return;
}
int codeLen = eeprom->get(component, eeprom->userdata, buf + dataLen);
int codeLen = eeprom->table.get(eeprom->table.userdata, buf + dataLen);
if(codeLen < 0) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_dealloc(alloc, buf, dataCap + codeCap);
return;
}
nn_unlock(&eeprom->ctx, eeprom->lock);
char hash[4];
nn_data_crc32(buf, dataLen + codeLen, hash);
nn_dealloc(alloc, buf, dataCap + codeCap);

View File

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

View File

@ -582,25 +582,29 @@ typedef struct nn_eepromControl {
double bytesWrittenPerTick;
} nn_eepromControl;
typedef struct nn_eeprom {
nn_refc refc;
typedef struct nn_eepromTable {
void *userdata;
void (*deinit)(nn_component *component, void *userdata);
nn_eepromControl (*control)(nn_component *component, void *userdata);
void (*deinit)(void *userdata);
// methods
nn_size_t (*getSize)(nn_component *component, void *userdata);
nn_size_t (*getDataSize)(nn_component *component, void *userdata);
void (*getLabel)(nn_component *component, 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 (*get)(nn_component *component, void *userdata, char *buf);
void (*set)(nn_component *component, void *userdata, const char *buf, nn_size_t len);
int (*getData)(nn_component *component, void *userdata, char *buf);
void (*setData)(nn_component *component, void *userdata, const char *buf, nn_size_t len);
nn_bool_t (*isReadonly)(nn_component *component, void *userdata);
void (*makeReadonly)(nn_component *component, void *userdata);
} nn_eeprom;
nn_size_t size;
nn_size_t dataSize;
void (*getLabel)(void *userdata, char *buf, nn_size_t *buflen);
nn_size_t (*setLabel)(void *userdata, const char *buf, nn_size_t buflen);
nn_size_t (*get)(void *userdata, char *buf);
void (*set)(void *userdata, const char *buf, nn_size_t len);
int (*getData)(void *userdata, char *buf);
void (*setData)(void *userdata, const char *buf, nn_size_t len);
nn_bool_t (*isReadonly)(void *userdata);
void (*makeReadonly)(void *userdata);
} 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);
// FileSystem