feat: migrate config management from TOML to FlatBuffers
Config is now loaded at runtime via WebSocket (ConfigCtrlMessage) instead of from hardcoded TOML files. The emulator starts with no devices and waits for clients to send configuration. - Define FlatBuffers schemas: EmulationConfig, ComposeDeviceConfig, BaseDeviceConfig with recursive DeviceConfig union - Rename MemSegment.start → addr (flatcc builder/reader name collision) - Add ConfigCtrlMessage handler: validates STILL state, walks the device tree depth-first, assigns numeric IDs, responds with DeviceIdMappingNotif or ConfigLoadError - Add fb_build_config_device_id_mapping() and fb_build_config_error() FlatBuffer builders - Remove hardcoded device loading from main.c; iterate dynamically loaded devices in the exec loop - Fix double-free: freeConf() already frees the struct itself, remove redundant free() calls in config.c and base_device.c - Fix heap-buffer-overflow in device parseSpecsFromConfig: malloc for segment name was missing +1 for the null terminator Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
764
devices/avr_generic/src/device.c
Normal file
764
devices/avr_generic/src/device.c
Normal file
@@ -0,0 +1,764 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "mem.h"
|
||||
#include "runner.h"
|
||||
#include "instr.h"
|
||||
#include "addrs.h"
|
||||
|
||||
|
||||
uint64_t memSegToGlobal(device_specs_t* spec, uint8_t seg, uint64_t localaddr)
|
||||
{
|
||||
uint64_t offset = 0;
|
||||
for (uint8_t i = 0; i < seg; i++)
|
||||
{
|
||||
offset += spec->memSpecs[i]->len * spec->memSpecs[i]->wordLen;
|
||||
}
|
||||
return offset + localaddr;
|
||||
}
|
||||
|
||||
|
||||
void freeDevMem(device_mem_t* devMem)
|
||||
{
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem->rawCells);
|
||||
free(devMem->memreadCellAddrs);
|
||||
free(devMem->memwriteCellAddrs);
|
||||
free(devMem->cells);
|
||||
free(devMem->smartAddrReadHandlers);
|
||||
free(devMem->smartAddrWriteHandlers);
|
||||
free(devMem);
|
||||
}
|
||||
|
||||
void freeDevSpec(void* _specs)
|
||||
{
|
||||
device_specs_t* specs = _specs;
|
||||
for (uint8_t i = 0; i < specs->memSpecsCount; i++)
|
||||
{
|
||||
free(specs->memSpecs[i]);
|
||||
}
|
||||
free(specs->memSpecs);
|
||||
free(specs->executableSegments);
|
||||
free(specs);
|
||||
}
|
||||
|
||||
|
||||
device_mem_t* genDevMem(device_specs_t* devSpec, char* errbuf)
|
||||
{
|
||||
if (devSpec->memSpecsCount < MEMDATA_OPSIZE)
|
||||
{
|
||||
sprintf(errbuf, "invalid amount of mem specs: %u", devSpec->memSpecsCount);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device_mem_t* devMem = (device_mem_t*)malloc(sizeof(device_mem_t));
|
||||
if (devMem == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate dev memory struct");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t memTotalSize = 0;
|
||||
for (uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||
{
|
||||
size_t tmp = devSpec->memSpecs[i]->start + devSpec->memSpecs[i]->len * devSpec->memSpecs[i]->wordLen;
|
||||
if (memTotalSize < tmp)
|
||||
{
|
||||
memTotalSize = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void* rawCells = (void*)malloc(memTotalSize);
|
||||
if (rawCells == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate raw memory buf");
|
||||
free(devMem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < memTotalSize; i++)
|
||||
{
|
||||
((uint8_t*)rawCells)[i] = 0;
|
||||
}
|
||||
|
||||
devMem->memsegShifts = malloc(devSpec->memSpecsCount * sizeof(uint64_t));
|
||||
|
||||
if(devMem->memsegShifts == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate segment shift buffers");
|
||||
free(rawCells);
|
||||
free(devMem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void** cells = malloc(devSpec->memSpecsCount * sizeof(void*));
|
||||
|
||||
if (cells == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate segment pointers");
|
||||
free(rawCells);
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||
{
|
||||
cells[i] = rawCells + devSpec->memSpecs[i]->start;
|
||||
}
|
||||
|
||||
char** cellNames = malloc(sizeof(char*) * devSpec->memSpecsCount);
|
||||
|
||||
if(cellNames == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate segment names map");
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
free(rawCells);
|
||||
free(cells);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||
{
|
||||
cellNames[i] = devSpec->memSpecs[i]->name;
|
||||
}
|
||||
|
||||
uint64_t* memreadCellAddrs = malloc(64 * sizeof(uint64_t));
|
||||
if (memreadCellAddrs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate read interception addrs");
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
free(rawCells);
|
||||
free(cells);
|
||||
free(cellNames);
|
||||
return NULL;
|
||||
}
|
||||
uint64_t* memwriteCellAddrs = malloc(64 * sizeof(uint64_t));
|
||||
|
||||
if (memwriteCellAddrs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate write interception addrs");
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
free(rawCells);
|
||||
free(memreadCellAddrs);
|
||||
free(cells);
|
||||
free(cellNames);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t smartAddrReadMask = 0;
|
||||
// memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x16)
|
||||
// | memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x17)
|
||||
// | memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x18);
|
||||
|
||||
uint64_t smartAddrWriteMask = 0;
|
||||
// memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x16)
|
||||
// | memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x17)
|
||||
// | memSegToGlobal(devSpec, MEMDATA_IO_REGS, 0x18);
|
||||
|
||||
mem_h_read_handler* smartAddrReadHandlers = malloc(sizeof(mem_h_read_handler) * memTotalSize);
|
||||
|
||||
|
||||
if (smartAddrReadHandlers == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate read interception handlers");
|
||||
free(memwriteCellAddrs);
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
free(rawCells);
|
||||
free(memreadCellAddrs);
|
||||
free(cells);
|
||||
free(cellNames);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem_h_write_handler* smartAddrWriteHandlers = malloc(sizeof(mem_h_write_handler) * memTotalSize);
|
||||
|
||||
|
||||
if (smartAddrWriteHandlers == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate write interception handlers");
|
||||
free(smartAddrReadHandlers);
|
||||
free(memwriteCellAddrs);
|
||||
free(devMem->memsegShifts);
|
||||
free(devMem);
|
||||
free(rawCells);
|
||||
free(memreadCellAddrs);
|
||||
free(cells);
|
||||
free(cellNames);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for(uint64_t i = 0; i < memTotalSize; i++)
|
||||
{
|
||||
smartAddrReadHandlers[i].func = NULL;
|
||||
smartAddrReadHandlers[i].ident = 0;
|
||||
|
||||
smartAddrWriteHandlers[i].func = NULL;
|
||||
smartAddrWriteHandlers[i].ident = 0;
|
||||
}
|
||||
|
||||
|
||||
for(uint64_t i = 0; i < memTotalSize; i++)
|
||||
{
|
||||
if((i & smartAddrReadMask) == smartAddrReadMask)
|
||||
{
|
||||
smartAddrReadHandlers[i].func = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (devSpec->smartReadSpecsCount > 0)
|
||||
{
|
||||
for(uint64_t i = 0; i < devSpec->smartReadSpecsCount; i++)
|
||||
{
|
||||
smart_read_spec_t t = devSpec->smartReadSpecs[i];
|
||||
uint64_t addr;
|
||||
if (t.addrType == SMART_ADDR_TYPE_GLOBAL)
|
||||
{
|
||||
addr = t.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = memSegToGlobal(devSpec, t.segno, t.localAddr);
|
||||
}
|
||||
smartAddrReadHandlers[addr].func = *t.handler;
|
||||
smartAddrReadHandlers[addr].ident = t.ident;
|
||||
smartAddrReadMask |= addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (devSpec->smartWriteSpecsCount > 0)
|
||||
{
|
||||
for(uint64_t i = 0; i < devSpec->smartWriteSpecsCount; i++)
|
||||
{
|
||||
smart_write_spec_t t = devSpec->smartWriteSpecs[i];
|
||||
|
||||
uint64_t addr;
|
||||
if (t.addrType == SMART_ADDR_TYPE_GLOBAL)
|
||||
{
|
||||
addr = t.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = memSegToGlobal(devSpec, t.segno, t.localAddr);
|
||||
}
|
||||
smartAddrWriteHandlers[addr].func = *t.handler;
|
||||
smartAddrWriteHandlers[addr].ident = t.ident;
|
||||
smartAddrWriteMask |= t.addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
devMem->cells = cells;
|
||||
devMem->rawCells = rawCells;
|
||||
devMem->memreadCellAddrs = memreadCellAddrs;
|
||||
devMem->memwriteCellAddrs = memwriteCellAddrs;
|
||||
devMem->memreadLen = 0;
|
||||
devMem->memwriteLen = 0;
|
||||
devMem->smartAddrReadMask = smartAddrReadMask;
|
||||
devMem->smartAddrReadHandlers = smartAddrReadHandlers;
|
||||
devMem->smartAddrWriteMask = smartAddrWriteMask;
|
||||
devMem->smartAddrWriteHandlers = smartAddrWriteHandlers;
|
||||
devMem->memsegNames = cellNames;
|
||||
|
||||
for(uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||
{
|
||||
devMem->memsegShifts[i] = memSegToGlobal(devSpec, i, 0);
|
||||
}
|
||||
|
||||
setOpcodeSizes((uint8_t*)(devMem->cells[MEMDATA_OPSIZE]));
|
||||
|
||||
return devMem;
|
||||
}
|
||||
|
||||
|
||||
uint8_t makeDeviceTick(device_public_context_t* devContext)
|
||||
{
|
||||
device_info_t* devInfo = (device_info_t*)devContext->deviceInfo;
|
||||
return makeTick(devInfo->pc, devInfo->instr, devInfo->deviceMem);
|
||||
}
|
||||
|
||||
device_info_t* initSpecs(device_specs_t* specs, char* errbuf)
|
||||
{
|
||||
device_info_t* devInfo = malloc(sizeof(device_info_t));
|
||||
if (devInfo == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate dev info");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char genErrBuf[200];
|
||||
device_mem_t* devMem = genDevMem(specs, genErrBuf);
|
||||
|
||||
if (devMem == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to generate device memory: %s", genErrBuf);
|
||||
free(devInfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
devInfo->pc = (prog_counter_t*)(devMem->rawCells + specs->pcAddr);
|
||||
*(devInfo->pc) = 0;
|
||||
devInfo->specs = specs;
|
||||
|
||||
devInfo->deviceMem = devMem;
|
||||
|
||||
|
||||
instr_h_func* instrs = genInstrArray(genErrBuf);
|
||||
|
||||
if (instrs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to initialize instructions: %s", genErrBuf);
|
||||
freeDevMem(devInfo->deviceMem);
|
||||
free(devInfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
devInfo->instr = instrs;
|
||||
|
||||
return devInfo;
|
||||
}
|
||||
|
||||
void error(const char* err, char* errbuf)
|
||||
{
|
||||
strcpy(errbuf, err);
|
||||
}
|
||||
|
||||
device_specs_t* parseSpecsFromConfig(const conf_dev_t* devConf, char* errbuf)
|
||||
{
|
||||
conf_mem_seg_t** segments = devConf->memConf->memSegConfs;
|
||||
device_specs_t* specs = malloc(sizeof(device_specs_t));
|
||||
if (specs == NULL)
|
||||
{
|
||||
error("unable to allocate mem specs struct", errbuf);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t specCount = 0;
|
||||
specs->executableSegmentsCount = 0;
|
||||
|
||||
while (segments[specCount] != NULL)
|
||||
{
|
||||
if(segments[specCount]->isExecutable)
|
||||
{
|
||||
specs->executableSegmentsCount++;
|
||||
}
|
||||
specCount++;
|
||||
}
|
||||
specs->memSpecsCount = specCount;
|
||||
|
||||
specs->memSpecs = malloc(specCount * sizeof(memseg_spec_t*));
|
||||
if (specs->memSpecs == NULL)
|
||||
{
|
||||
free(specs);
|
||||
error("unable to allocate mem segment specs", errbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
specs->executableSegments = malloc(sizeof(uint8_t) * specs->executableSegmentsCount);
|
||||
if (specs->executableSegments == NULL)
|
||||
{
|
||||
error("unable to allocate mem executable specs", errbuf);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < specCount; i++)
|
||||
{
|
||||
memseg_spec_t* spec = (memseg_spec_t*)malloc(sizeof(memseg_spec_t));
|
||||
if (spec == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate spec %d", i);
|
||||
|
||||
for (uint8_t j = 0; j < i; j++)
|
||||
{
|
||||
free(specs->memSpecs[j]);
|
||||
}
|
||||
free(specs->memSpecs);
|
||||
free(specs->executableSegments);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
spec->name = NULL;
|
||||
|
||||
specs->memSpecs[i] = spec;
|
||||
}
|
||||
|
||||
uint8_t foundSegments = 0;
|
||||
uint8_t executableSegmentsFound = 0;
|
||||
|
||||
for (uint8_t i = 0; i < specCount; i++)
|
||||
{
|
||||
uint8_t specNum = 0xFF;
|
||||
if (strcmp(segments[i]->name, "reg_gp") == 0)
|
||||
{
|
||||
specNum = MEMDATA_GP_REGS;
|
||||
}
|
||||
else if (strcmp(segments[i]->name, "reg_io") == 0)
|
||||
{
|
||||
specNum = MEMDATA_IO_REGS;
|
||||
}
|
||||
else if (strcmp(segments[i]->name, "ds") == 0)
|
||||
{
|
||||
specNum = MEMDATA_DS;
|
||||
}
|
||||
else if (strcmp(segments[i]->name, "ps") == 0)
|
||||
{
|
||||
specNum = MEMDATA_PS;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errbuf, "invalid segment: %s", segments[i]->name);
|
||||
for(size_t j = 0; j < specCount; j++)
|
||||
{
|
||||
if(specs->memSpecs[j]->name != NULL)
|
||||
{
|
||||
free(specs->memSpecs[j]->name);
|
||||
}
|
||||
free(specs->memSpecs[j]);
|
||||
}
|
||||
free(specs->executableSegments);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
specs->memSpecs[specNum]->name = malloc(sizeof(char) * (strlen(segments[i]->name) + 1));
|
||||
if(specs->memSpecs[specNum]->name == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate spec %d name", i);
|
||||
for(size_t j = 0; j < specCount; j++)
|
||||
{
|
||||
if(specs->memSpecs[j]->name != NULL)
|
||||
{
|
||||
free(specs->memSpecs[j]->name);
|
||||
}
|
||||
free(specs->memSpecs[j]);
|
||||
}
|
||||
free(specs->executableSegments);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(specs->memSpecs[specNum]->name, segments[i]->name);
|
||||
specs->memSpecs[specNum]->start = segments[i]->start;
|
||||
specs->memSpecs[specNum]->len = segments[i]->len;
|
||||
specs->memSpecs[specNum]->wordLen = segments[i]->wordLen;
|
||||
if(segments[i]->isExecutable)
|
||||
{
|
||||
specs->executableSegments[executableSegmentsFound] = specNum;
|
||||
executableSegmentsFound++;
|
||||
}
|
||||
foundSegments += 1;
|
||||
}
|
||||
|
||||
if(executableSegmentsFound < specs->executableSegmentsCount)
|
||||
{
|
||||
sprintf(errbuf, "Not all executable segments found");
|
||||
for(size_t j = 0; j < specCount; j++)
|
||||
{
|
||||
if(specs->memSpecs[j]->name != NULL)
|
||||
{
|
||||
free(specs->memSpecs[j]->name);
|
||||
}
|
||||
free(specs->memSpecs[j]);
|
||||
}
|
||||
free(specs->executableSegments);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (foundSegments < 4)
|
||||
{
|
||||
sprintf(errbuf, "invalid amount of segments: must be 4");
|
||||
for(size_t k = 0; k < specs->memSpecsCount; k++)
|
||||
{
|
||||
if(specs->memSpecs[k]->name != NULL)
|
||||
{
|
||||
free(specs->memSpecs[k]->name);
|
||||
}
|
||||
free(specs->memSpecs[k]);
|
||||
}
|
||||
free(specs->executableSegments);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return specs;
|
||||
}
|
||||
|
||||
void freeDevSpecs(device_specs_t* specs)
|
||||
{
|
||||
for(size_t k = 0; k < specs->memSpecsCount; k++)
|
||||
{
|
||||
if(specs->memSpecs[k]->name != NULL)
|
||||
{
|
||||
free(specs->memSpecs[k]->name);
|
||||
}
|
||||
free(specs->memSpecs[k]);
|
||||
}
|
||||
free(specs->executableSegments);
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
}
|
||||
|
||||
void fillSmartReadSpecs(device_specs_t* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount)
|
||||
{
|
||||
specs->smartReadSpecs = smartReadSpecs;
|
||||
specs->smartReadSpecsCount = smartReadSpecsCount;
|
||||
}
|
||||
|
||||
void fillSmartWriteSpecs(device_specs_t* specs, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount)
|
||||
{
|
||||
specs->smartWriteSpecs = smartWriteSpecs;
|
||||
specs->smartWriteSpecsCount = smartWriteSpecsCount;
|
||||
}
|
||||
|
||||
device_public_context_t* initDefault(smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount, char* errbuf)
|
||||
{
|
||||
|
||||
device_specs_t* specs = malloc(sizeof(device_specs_t));
|
||||
if (specs == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
specs->memSpecsCount = 4;
|
||||
specs->memSpecs = malloc(specs->memSpecsCount * sizeof(memseg_spec_t*));
|
||||
if (specs->memSpecs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate default mem segment specs");
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
specs->executableSegmentsCount = 1;
|
||||
specs->executableSegments = malloc(sizeof(uint8_t) * 1);
|
||||
if (specs->executableSegments == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate default executable segments");
|
||||
free(specs->memSpecs);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
specs->executableSegments[0] = 0;
|
||||
|
||||
for (uint8_t i = 0; i < specs->memSpecsCount; i++)
|
||||
{
|
||||
specs->memSpecs[i] = malloc(sizeof(memseg_spec_t));
|
||||
if (specs->memSpecs[i] == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate default mem seg spec %u", i);
|
||||
for (uint8_t j = 0; j < i; j++)
|
||||
{
|
||||
free(specs->memSpecs[j]);
|
||||
}
|
||||
free(specs->memSpecs);
|
||||
free(specs->executableSegments);
|
||||
free(specs);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
specs->smartReadSpecs = smartReadSpecs;
|
||||
specs->smartReadSpecsCount = smartReadSpecsCount;
|
||||
|
||||
specs->smartWriteSpecs = smartWriteSpecs;
|
||||
specs->smartWriteSpecsCount = smartWriteSpecsCount;
|
||||
|
||||
specs->memSpecs[0]->len = 1024;
|
||||
specs->memSpecs[0]->start = 0;
|
||||
specs->memSpecs[0]->wordLen = OPCODE_WORDSIZE;
|
||||
|
||||
specs->memSpecs[1]->len = 32;
|
||||
specs->memSpecs[1]->start = (1024 * OPCODE_WORDSIZE);
|
||||
specs->memSpecs[1]->wordLen = GP_REG_CELL_WORDS;
|
||||
|
||||
specs->memSpecs[2]->len = 0xFF;
|
||||
specs->memSpecs[2]->start = (1024 * OPCODE_WORDSIZE) + (32 * GP_REG_CELL_WORDS);
|
||||
specs->memSpecs[2]->wordLen = IO_REG_CELL_WORDS;
|
||||
|
||||
specs->memSpecs[3]->len = 0xFFFF;
|
||||
specs->memSpecs[3]->start = (1024 * OPCODE_WORDSIZE) + (32 * GP_REG_CELL_WORDS) + (0xFF * IO_REG_CELL_WORDS);
|
||||
specs->memSpecs[3]->wordLen = RAM_CELL_WORDS;
|
||||
|
||||
char initErrbuf[200];
|
||||
device_public_context_t* ret = init(specs, initErrbuf);
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to init default: %s", initErrbuf);
|
||||
freeDevSpec(specs);
|
||||
return NULL;
|
||||
}
|
||||
free(specs->memSpecs);
|
||||
free(specs->executableSegments);
|
||||
free(specs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
device_public_context_t* init(device_specs_t* specs, char* errbuf)
|
||||
{
|
||||
if (specs->memSpecsCount >= 0xFF - 2)
|
||||
{
|
||||
sprintf(errbuf, "Too many mem specifications");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device_specs_t* realSpecs = malloc(sizeof(device_specs_t));
|
||||
if (realSpecs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate spec struct");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t specCount = specs->memSpecsCount + 2;
|
||||
realSpecs->memSpecsCount = specCount;
|
||||
realSpecs->memSpecs = (memseg_spec_t**)malloc(realSpecs->memSpecsCount * sizeof(memseg_spec_t*));
|
||||
if (realSpecs->memSpecs == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate mem specs");
|
||||
free(realSpecs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
realSpecs->executableSegments = malloc(sizeof(uint8_t) * specs->executableSegmentsCount);
|
||||
if (realSpecs->executableSegments == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate executable segments");
|
||||
free(realSpecs->memSpecs);
|
||||
free(realSpecs);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i = 0; i < specs->executableSegmentsCount; i++)
|
||||
{
|
||||
realSpecs->executableSegments[i] = specs->executableSegments[i];
|
||||
}
|
||||
realSpecs->executableSegmentsCount = specs->executableSegmentsCount;
|
||||
|
||||
|
||||
realSpecs->smartReadSpecs = specs->smartReadSpecs;
|
||||
realSpecs->smartReadSpecsCount = specs->smartReadSpecsCount;
|
||||
|
||||
realSpecs->smartWriteSpecs = specs->smartWriteSpecs;
|
||||
realSpecs->smartWriteSpecsCount = specs->smartWriteSpecsCount;
|
||||
|
||||
uint64_t maxAddr = 0;
|
||||
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < specCount; i++)
|
||||
{
|
||||
memseg_spec_t *segSpec = (memseg_spec_t*)malloc(sizeof(memseg_spec_t));
|
||||
realSpecs->memSpecs[i] = segSpec;
|
||||
if (segSpec == NULL)
|
||||
{
|
||||
|
||||
sprintf(errbuf, "unable to allocate mem spec segment %u", i);
|
||||
for (uint8_t j = 0; j < i; j++)
|
||||
{
|
||||
free(realSpecs->memSpecs[j]);
|
||||
}
|
||||
free(realSpecs->memSpecs);
|
||||
free(realSpecs->executableSegments);
|
||||
free(realSpecs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i < specCount - 2)
|
||||
{
|
||||
realSpecs->memSpecs[i]->name = specs->memSpecs[i]->name;
|
||||
realSpecs->memSpecs[i]->len = specs->memSpecs[i]->len;
|
||||
realSpecs->memSpecs[i]->start = specs->memSpecs[i]->start;
|
||||
realSpecs->memSpecs[i]->wordLen = specs->memSpecs[i]->wordLen;
|
||||
uint64_t testMaxAddr = realSpecs->memSpecs[i]->start + (realSpecs->memSpecs[i]->len * realSpecs->memSpecs[i]->wordLen);
|
||||
if (testMaxAddr > maxAddr)
|
||||
{
|
||||
maxAddr = testMaxAddr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t pcSpecSegNum = specs->memSpecsCount;
|
||||
|
||||
realSpecs->memSpecs[MEMDATA_OPSIZE]->len = ((opcode_t)~0);
|
||||
realSpecs->memSpecs[MEMDATA_OPSIZE]->start = maxAddr + PC_WORDSIZE;
|
||||
realSpecs->memSpecs[MEMDATA_OPSIZE]->wordLen = 1;
|
||||
realSpecs->memSpecs[MEMDATA_OPSIZE]->name = NULL;
|
||||
|
||||
realSpecs->memSpecs[specCount - 2]->len = 1;
|
||||
realSpecs->memSpecs[specCount - 2]->start = maxAddr;
|
||||
realSpecs->memSpecs[specCount - 2]->wordLen = PC_WORDSIZE;
|
||||
realSpecs->memSpecs[specCount - 2]->name = NULL;
|
||||
|
||||
|
||||
realSpecs->pcAddr = memSegToGlobal(realSpecs, pcSpecSegNum, 0);
|
||||
|
||||
device_public_context_t* pubDevContext = malloc(sizeof(device_public_context_t));
|
||||
if (pubDevContext == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to allocate public context");
|
||||
freeDevSpec(realSpecs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char initErrbuf[200];
|
||||
device_info_t* devInfo = initSpecs(realSpecs, initErrbuf);
|
||||
if (devInfo == NULL)
|
||||
{
|
||||
sprintf(errbuf, "unable to init specs: %s", initErrbuf);
|
||||
freeDevSpec(realSpecs);
|
||||
free(pubDevContext);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pubDevContext->deviceInfo = (void*)devInfo;
|
||||
pubDevContext->deviceMem = devInfo->deviceMem;
|
||||
|
||||
return pubDevContext;
|
||||
}
|
||||
|
||||
|
||||
size_t pubExtractPcounter(device_public_context_t* devContext)
|
||||
{
|
||||
device_info_t* devInfo = (device_info_t*)devContext->deviceInfo;
|
||||
return (size_t)(*devInfo->pc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void* pubExtractPcounterPtr(device_public_context_t* devContext)
|
||||
{
|
||||
device_info_t* devInfo = (device_info_t*)devContext->deviceInfo;
|
||||
return (void*)(devInfo->pc);
|
||||
|
||||
}
|
||||
uint8_t pubExtractPcounterSizeWords()
|
||||
{
|
||||
return sizeof(prog_counter_t);
|
||||
}
|
||||
|
||||
uint8_t pubDeviceType()
|
||||
{
|
||||
return EXTENDED_DEVICE_TYPE_INSTR_SIMUL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user