From 38425792b1c9a18c5df8b2ba5478044d2bafff75 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Wed, 28 May 2025 14:02:09 +0200 Subject: [PATCH] bunch of work on the interfaces --- src/components/eeprom.c | 66 +++++++++++++++++++++++++++++++++++ src/computer.c | 10 +++--- src/computer.h | 4 +-- src/emulator.c | 21 +++++++++-- src/neonucleus.h | 77 ++++++++++++++++++++++++++++++++++++----- src/utils.c | 6 ++++ 6 files changed, 165 insertions(+), 19 deletions(-) diff --git a/src/components/eeprom.c b/src/components/eeprom.c index 535c7ad..296ce35 100644 --- a/src/components/eeprom.c +++ b/src/components/eeprom.c @@ -1,5 +1,9 @@ #include "../neonucleus.h" +nn_eepromControl nn_eeprom_getControl(nn_component *component, nn_eeprom *eeprom) { + return eeprom->control(component, eeprom->userdata); +} + void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) { if(!nn_decRef(&eeprom->refc)) return; @@ -10,10 +14,24 @@ void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *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))); + + // Latency, energy costs and stuff + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } 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))); + + // Latency, energy costs and stuff + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -25,6 +43,13 @@ void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ } else { nn_return(computer, nn_values_string(buf, l)); } + + // Latency, energy costs and stuff + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -37,6 +62,14 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ } l = eeprom->setLabel(component, eeprom->userdata, buf, l); nn_return(computer, nn_values_string(buf, l)); + + // Latency, energy costs and stuff + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.writeLatency); + nn_removeEnergy(computer, control.writeEnergyCost); + nn_removeHeat(computer, control.writeHeatCost); + nn_callCost(computer, control.writeCost); } void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -49,6 +82,12 @@ void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu size_t len = eeprom->get(component, eeprom->userdata, buf); nn_return(computer, nn_values_string(buf, len)); nn_free(buf); + + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -60,6 +99,13 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu return; } eeprom->set(component, eeprom->userdata, buf, len); + + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.writeLatency); + nn_removeEnergy(computer, control.writeEnergyCost); + nn_removeHeat(computer, control.writeHeatCost); + nn_callCost(computer, control.writeCost); } void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -76,6 +122,12 @@ void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c nn_return(computer, nn_values_string(buf, len)); } nn_free(buf); + + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { @@ -91,10 +143,18 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c 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_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_removeEnergy(computer, control.readEnergyCost); } void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { eeprom->makeReadonly(component, eeprom->userdata); + + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_removeEnergy(computer, control.writeEnergyCost); } // TODO: make good @@ -113,6 +173,12 @@ void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_free(buf); nn_return(computer, nn_values_string((void *)&sum, sizeof(sum))); + + nn_eepromControl control = nn_eeprom_getControl(component, eeprom); + nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); + nn_busySleep(control.readLatency); + nn_removeEnergy(computer, control.readEnergyCost); + nn_callCost(computer, control.readCost); } void nn_loadEepromTable(nn_universe *universe) { diff --git a/src/computer.c b/src/computer.c index 7313faf..d387d88 100644 --- a/src/computer.c +++ b/src/computer.c @@ -241,20 +241,20 @@ void nn_setState(nn_computer *computer, int state) { computer->state = state; } -void nn_setEnergyInfo(nn_computer *computer, size_t energy, size_t capacity) { +void nn_setEnergyInfo(nn_computer *computer, double energy, double capacity) { computer->energy = energy; computer->maxEnergy = capacity; } -size_t nn_getEnergy(nn_computer *computer) { +double nn_getEnergy(nn_computer *computer) { return computer->energy; } -size_t nn_getMaxEnergy(nn_computer *computer) { +double nn_getMaxEnergy(nn_computer *computer) { return computer->maxEnergy; } -void nn_removeEnergy(nn_computer *computer, size_t energy) { +void nn_removeEnergy(nn_computer *computer, double energy) { if(computer->energy < energy) { // blackout computer->energy = 0; @@ -264,7 +264,7 @@ void nn_removeEnergy(nn_computer *computer, size_t energy) { computer->energy -= energy; } -void nn_addEnergy(nn_computer *computer, size_t amount) { +void nn_addEnergy(nn_computer *computer, double amount) { if(computer->maxEnergy - computer->energy < amount) { computer->energy = computer->maxEnergy; return; diff --git a/src/computer.h b/src/computer.h index 60fa5ba..db3307b 100644 --- a/src/computer.h +++ b/src/computer.h @@ -30,8 +30,8 @@ typedef struct nn_computer { nn_universe *universe; char *users[NN_MAX_USERS]; size_t userCount; - size_t energy; - size_t maxEnergy; + double energy; + double maxEnergy; nn_signal signals[NN_MAX_SIGNALS]; size_t signalCount; size_t memoryTotal; diff --git a/src/emulator.c b/src/emulator.c index 1ed238f..f8c68a0 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -4,6 +4,20 @@ #include #include "neonucleus.h" #include "testLuaArch.h" + +nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) { + return (nn_eepromControl) { + .randomLatencyMin = 0.001, + .randomLatencyMax = 0.012, + .readLatency = 0.03, + .writeLatency = 0.05, + .readCost = 3, + .writeCost = 5, + .readEnergyCost = 1, + .writeEnergyCost = 5, + .writeHeatCost = 0.2, + }; +} size_t ne_eeprom_getSize(nn_component *component, void *_) { return 4096; @@ -21,14 +35,14 @@ size_t ne_eeprom_setLabel(nn_component *component, void *_, const char *buf, siz return 0; } -const char *ne_eeprom_location(nn_address address) { +const char *ne_location(nn_address address) { static char buffer[256]; snprintf(buffer, 256, "data/%s", address); return buffer; } size_t ne_eeprom_get(nn_component *component, void *_, char *buf) { - FILE *f = fopen(ne_eeprom_location(nn_getComponentAddress(component)), "rb"); + FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "rb"); fseek(f, 0, SEEK_END); size_t len = ftell(f); fseek(f, 0, SEEK_SET); @@ -38,7 +52,7 @@ size_t ne_eeprom_get(nn_component *component, void *_, char *buf) { } void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len) { - FILE *f = fopen(ne_eeprom_location(nn_getComponentAddress(component)), "wb"); + FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "wb"); fwrite(buf, sizeof(char), len, f); fclose(f); } @@ -72,6 +86,7 @@ int main() { .userdata = NULL, .refc = 1, .deinit = NULL, + .control = ne_eeprom_getControl, .getSize = ne_eeprom_getSize, .getDataSize = ne_eeprom_getDataSize, .getLabel = ne_eeprom_getLabel, diff --git a/src/neonucleus.h b/src/neonucleus.h index 790f653..3b7dc5e 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -157,6 +157,8 @@ double nn_realTime(); double nn_realTimeClock(void *_); /* Will busy-loop until the time passes. This is meant for computed latencies in components. */ void nn_busySleep(double t); +// calls nn_busySleep with a random latency +void nn_randomLatency(double min, double max); typedef double nn_clock_t(void *_); @@ -233,11 +235,11 @@ void nn_unlockComputer(nn_computer *computer); int nn_getState(nn_computer *computer); void nn_setState(nn_computer *computer, int state); -void nn_setEnergyInfo(nn_computer *computer, size_t energy, size_t capacity); -size_t nn_getEnergy(nn_computer *computer); -size_t nn_getMaxEnergy(nn_computer *computer); -void nn_removeEnergy(nn_computer *computer, size_t energy); -void nn_addEnergy(nn_computer *computer, size_t amount); +void nn_setEnergyInfo(nn_computer *computer, double energy, double capacity); +double nn_getEnergy(nn_computer *computer); +double nn_getMaxEnergy(nn_computer *computer); +void nn_removeEnergy(nn_computer *computer, double energy); +void nn_addEnergy(nn_computer *computer, double amount); double nn_getTemperature(nn_computer *computer); double nn_getThermalCoefficient(nn_computer *computer); @@ -349,11 +351,30 @@ void nn_loadFilesystemTable(nn_universe *universe); // the helpers // EEPROM +typedef struct nn_eepromControl { + double readLatency; + double writeLatency; + + double readEnergyCost; + double writeEnergyCost; + + double writeHeatCost; + + double randomLatencyMin; + double randomLatencyMax; + + // Call costs + size_t readCost; + size_t writeCost; +} nn_eepromControl; + typedef struct nn_eeprom { nn_refc refc; void *userdata; void (*deinit)(nn_component *component, void *userdata); + nn_eepromControl (*control)(nn_component *component, void *userdata); + // methods size_t (*getSize)(nn_component *component, void *userdata); size_t (*getDataSize)(nn_component *component, void *userdata); @@ -389,19 +410,47 @@ typedef struct nn_filesystemControl { // thermals double motorHeat; // this times how many chunks have been seeked will be the heat addres, +/- the heat range. double heatRange; + + // call budget + size_t readCostPerChunk; + size_t writeCostPerChunk; + size_t seekCostPerChunk; } nn_filesystemControl; typedef struct nn_filesystem { nn_refc refc; - nn_filesystemControl *control; void *userdata; void (*deinit)(nn_component *component, void *userdata); + nn_filesystemControl (*control)(nn_component *component, void *userdata); void (*getLabel)(nn_component *component, void *userdata, char *buf, size_t *buflen); size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, size_t buflen); size_t (*spaceUsed)(nn_component *component, void *userdata); size_t (*spaceTotal)(nn_component *component, void *userdata); + bool (*isReadOnly)(nn_component *component, void *userdata); + + // general operations + size_t (*size)(nn_component *component, void *userdata, const char *path); + bool (*remove)(nn_component *component, void *userdata, const char *path); + size_t (*lastModified)(nn_component *component, void *userdata, const char *path); + bool (*rename)(nn_component *component, void *userdata, const char *from, const char *to); + bool (*exists)(nn_component *component, void *userdata, const char *path); + + // directory operations + bool (*isDirectory)(nn_component *component, void *userdata, const char *path); + bool (*makeDirectory)(nn_component *component, void *userdata, const char *path); + // the length and array must be nn_alloc'd. + // The strings must be NULL-terminated and also nn_alloc'd. + // See nn_strdup(). + char **(*list)(nn_component *component, void *userdata, const char *path, size_t *len); + + // file operations + size_t (*open)(nn_component *component, void *userdata, const char *path, const char *mode); + void (*close)(nn_component *component, void *userdata, int fd); + size_t (*seek)(nn_component *component, void *userdata, int fd, int whence, int off); + size_t (*read)(nn_component *component, void *userdata, int fd, char *buf, size_t required); + bool (*write)(nn_component *component, void *userdata, int fd, char *buf, size_t len); } nn_filesystem; nn_filesystem *nn_volatileFileSystem(size_t capacity, nn_filesystemControl *control); @@ -412,22 +461,32 @@ typedef struct nn_driveControl { // Set it to 0 to disable seek latency. int rpm; - double readLatencyPerByte; - double writeLatencyPerByte; + double readLatencyPerSector; + double writeLatencyPerSector; double randomLatencyMin; double randomLatencyMax; double motorHeat; double heatRange; + + // These are per sector + double motorEnergyCost; + double readEnergyCost; + double writeEnergyCost; + + // call budget + size_t readCostPerChunk; + size_t writeCostPerChunk; + size_t seekCostPerChunk; } nn_driveControl; typedef struct nn_drive { nn_refc refc; - nn_driveControl *control; void *userdata; void (*deinit)(nn_component *component, void *userdata); + nn_driveControl (*control)(nn_component *component, void *userdata); void (*getLabel)(nn_component *component, void *userdata, char *buf, size_t *buflen); size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, size_t buflen); diff --git a/src/utils.c b/src/utils.c index d59e065..b02b9db 100644 --- a/src/utils.c +++ b/src/utils.c @@ -64,3 +64,9 @@ void nn_busySleep(double t) { double deadline = nn_realTime() + t; while(nn_realTime() < deadline) {} } + +void nn_randomLatency(double min, double max) { + double t = (double)rand() / RAND_MAX; + double latency = min + t * (max - min); + nn_busySleep(latency); +}