#include #include #include #include #include "device.h" #include "libhmmmm/mem.h" #include "mem.h" #include "mem_seg.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 spec->memSpecs[seg]->start + localaddr; } void freeDevMem(device_mem_t* devMem) { free(devMem->memsegShifts); free(devMem->memsegSizes); free(devMem->rawCells); free(devMem->memreadCellAddrs); free(devMem->memwriteCellAddrs); free(devMem->memwriteCellSegments); free(devMem->memwriteValues[0]); free(devMem->memwriteValues); free(devMem->memwriteWordLengths); 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) { device_mem_t* devMem = (device_mem_t*)calloc(1, 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*)calloc(memTotalSize, sizeof(void*)); if (rawCells == NULL) { sprintf(errbuf, "unable to allocate raw memory buf %lu bytes", memTotalSize); free(devMem); return NULL; } for (size_t i = 0; i < memTotalSize; i++) { ((uint8_t*)rawCells)[i] = 0; } devMem->memsegShifts = calloc(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 = calloc(devSpec->memSpecsCount, sizeof(void*)); if (cells == NULL) { sprintf(errbuf, "unable to allocate segment pointers"); free(rawCells); free(devMem->memsegShifts); free(devMem); return NULL; } char** cellNames = calloc(devSpec->memSpecsCount, sizeof(char*)); 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; } for (uint8_t i = 0; i < devSpec->memSpecsCount; i++) { printf("init seg \"%s\": %lu:%lu\n", devSpec->memSpecs[i]->name, devSpec->memSpecs[i]->start, devSpec->memSpecs[i]->len); cells[i] = &(((uint8_t*)rawCells)[devSpec->memSpecs[i]->start]); cellNames[i] = devSpec->memSpecs[i]->name; // cells[i] = (void*)((size_t)rawCells + (size_t)devSpec->memSpecs[i]->start); } uint64_t* memreadCellAddrs = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, 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 = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, 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; } uint8_t* memwriteCellSegments = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, sizeof(uint8_t)); if(memwriteCellSegments == NULL) { sprintf(errbuf, "unable to allocate write interception addrs"); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(cells); free(cellNames); free(memwriteCellAddrs); return NULL; } void** memwriteValues = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, sizeof(void*)); if(memwriteValues == NULL) { sprintf(errbuf, "unable to allocate write interception addrs"); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(cells); free(cellNames); free(memwriteCellAddrs); free(memwriteCellSegments); return NULL; } uint64_t* memwriteValuesContainers = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, sizeof(uint64_t)); if(memwriteValuesContainers == NULL) { sprintf(errbuf, "unable to allocate write interception addrs"); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(cells); free(cellNames); free(memwriteCellAddrs); free(memwriteCellSegments); free(memwriteValues); return NULL; } for(size_t i = 0; i < 64; i++) { memwriteValues[i] = &memwriteValuesContainers[i]; } uint8_t* memwriteWordLengths = calloc(MEM_ACCESS_INTERCEPT_BUF_SIZE, sizeof(uint8_t)); if(memwriteWordLengths == NULL) { sprintf(errbuf, "unable to allocate write interception addrs"); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(cells); free(cellNames); free(memwriteCellAddrs); free(memwriteCellSegments); free(memwriteValues); free(memwriteValuesContainers); return NULL; } uint64_t smartAddrReadMask = 0; uint64_t smartAddrWriteMask = 0; mem_h_read_handler* smartAddrReadHandlers = calloc(memTotalSize, sizeof(mem_h_read_handler)); if(memwriteCellSegments == NULL) { sprintf(errbuf, "unable to allocate read interception handlers"); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(cells); free(cellNames); free(memwriteCellAddrs); free(memwriteCellSegments); free(memwriteValues); free(memwriteValuesContainers); free(memwriteWordLengths); return NULL; } mem_h_write_handler* smartAddrWriteHandlers = calloc(memTotalSize, sizeof(mem_h_write_handler)); if (smartAddrWriteHandlers == NULL) { sprintf(errbuf, "unable to allocate write interception handlers"); free(smartAddrReadHandlers); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(memwriteCellAddrs); free(memwriteCellSegments); free(memwriteValues); free(memwriteValuesContainers); free(memwriteWordLengths); free(cells); free(cellNames); return NULL; } uint64_t* memsegSizes = calloc(devSpec->memSpecsCount, sizeof(uint64_t)); if(memsegSizes == NULL) { sprintf(errbuf, "unable to allocate write interception handlers"); free(smartAddrWriteHandlers); free(smartAddrReadHandlers); free(devMem->memsegShifts); free(devMem); free(rawCells); free(memreadCellAddrs); free(memwriteCellAddrs); free(memwriteCellSegments); free(memwriteValues); free(memwriteValuesContainers); free(memwriteWordLengths); 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->memwriteCellSegments = memwriteCellSegments; devMem->memwriteWordLengths = memwriteWordLengths; devMem->memwriteValues = memwriteValues; devMem->memreadLen = 0; devMem->memwriteLen = 0; devMem->smartAddrReadMask = smartAddrReadMask; devMem->smartAddrReadHandlers = smartAddrReadHandlers; devMem->smartAddrWriteMask = smartAddrWriteMask; devMem->smartAddrWriteHandlers = smartAddrWriteHandlers; devMem->memsegNames = cellNames; devMem->memsegSizes = memsegSizes; memseg_metadata_t requiredSegments[] = MEMSEG_DEFINES; for (uint8_t i = 0; i < devSpec->memSpecsCount; i++) { for(uint8_t j = 0; j < sizeof(requiredSegments) / sizeof(memseg_metadata_t); j++) { const memseg_metadata_t seg_def = requiredSegments[j]; if(strcmp(seg_def.name, devSpec->memSpecs[i]->name) == 0) { const uint8_t seg_id = seg_def.seg_id; devMem->memsegShifts[seg_id] = memSegToGlobal(devSpec, i, 0); devMem->memsegSizes[seg_id] = devSpec->memSpecs[i]->len; printf("set mem segment %d meta: +%lu/%lu \n", seg_id, devMem->memsegShifts[j], devMem->memsegSizes[j]); } } } // for(uint8_t i = 0; i < devSpec->memSpecsCount; i++) // { // devMem->memsegShifts[i] = memSegToGlobal(devSpec, i, 0); // devMem->memsegSizes[i] = devSpec->memSpecs[i]->len; // } 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; prog_counter_t _pc; READ_MEM(_pc, devInfo->deviceMem, MEMSEG_PC_SEG_NUM, MEMSEG_PC_ADDR, prog_counter_t) // printf("old PC is %d\n", _pc); uint8_t ticks = makeTick(&_pc, devInfo->instr, devInfo->deviceMem); WRITE_MEM(devInfo->deviceMem, MEMSEG_PC_SEG_NUM, MEMSEG_PC_ADDR, prog_counter_t, _pc); // printf("new PC is %d\n", _pc); return ticks; } device_info_t* initSpecs(device_specs_t* specs, char* errbuf) { device_info_t* devInfo = calloc(1, 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->cells[MEMSEG_PC_SEG_NUM]))[MEMSEG_PC_ADDR]; *(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 = calloc(1, sizeof(device_specs_t)); if (specs == NULL) { error("unable to allocate mem specs struct", errbuf); return NULL; } memseg_metadata_t requiredSegments[] = MEMSEG_DEFINES; uint8_t* requiredSegmentsFoundMap = (uint8_t*)calloc(sizeof(requiredSegments) / sizeof(memseg_metadata_t), sizeof(uint8_t)); if(requiredSegmentsFoundMap == NULL) { error("unable to allocate found map", errbuf); free(specs); return NULL; } uint8_t specCount = 0; specs->executableSegmentsCount = 0; while (segments[specCount] != NULL) { if(segments[specCount]->isExecutable) { specs->executableSegmentsCount++; } specCount++; } const uint8_t providedSpecCount = specCount; if(specCount < sizeof(requiredSegments)/sizeof(memseg_metadata_t)) { specCount = sizeof(requiredSegments)/sizeof(memseg_metadata_t); } specs->memSpecsCount = specCount; specs->memSpecs = calloc(specCount, sizeof(memseg_spec_t*)); if (specs->memSpecs == NULL) { free(specs); free(requiredSegmentsFoundMap); error("unable to allocate mem segment specs", errbuf); return NULL; } specs->executableSegments = calloc(specs->executableSegmentsCount, sizeof(uint8_t)); if (specs->executableSegments == NULL) { error("unable to allocate mem executable specs", errbuf); free(specs->memSpecs); free(specs); free(requiredSegmentsFoundMap); return NULL; } for (uint8_t i = 0; i < specCount; i++) { memseg_spec_t* spec = (memseg_spec_t*)calloc(1, 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); free(requiredSegmentsFoundMap); return NULL; } spec->name = NULL; specs->memSpecs[i] = spec; } uint8_t executableSegmentsFound = 0; for (uint8_t i = 0; i < providedSpecCount; i++) { uint8_t specNum = 0xFF; uint8_t is_error = 0; uint8_t seek_found = 0; for(uint8_t j = 0; j < sizeof(requiredSegments) / sizeof(memseg_metadata_t); j++) { const memseg_metadata_t seg_def = requiredSegments[j]; if(strcmp(seg_def.name, segments[i]->name) == 0) { printf("found seg \"%s\"\n", seg_def.name); const uint8_t is_found = requiredSegmentsFoundMap[j]; if(is_found) { is_error = 1; sprintf(errbuf, "duplicate segment %s", seg_def.name); } else { if(seg_def.is_executable == segments[i]->isExecutable || segments[i]->isExecutable) { printf("seg executable req satisfyed (%d)\n", seg_def.is_executable); requiredSegmentsFoundMap[j] = 1; specNum = seg_def.seg_id; seek_found = 1; } else { is_error = 1; sprintf(errbuf, "segment %s must be executable", seg_def.name); } } break; } } if(seek_found == 0) { is_error = 1; sprintf(errbuf, "unsupported memory segment: %s", segments[i]->name); } if(is_error) { freeDevSpec(specs); free(requiredSegmentsFoundMap); return NULL; } specs->memSpecs[specNum]->name = calloc(strlen(segments[i]->name) + 1, sizeof(char)); if(specs->memSpecs[specNum]->name == NULL) { sprintf(errbuf, "unable to allocate spec %d name", i); freeDevSpec(specs); free(requiredSegmentsFoundMap); 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; printf("set segment %s :%lu->%lu/%d\n", segments[i]->name, segments[i]->start, segments[i]->len, segments[i]->wordLen); if(segments[i]->isExecutable) { specs->executableSegments[executableSegmentsFound] = specNum; executableSegmentsFound++; } } for(uint8_t i = 0; i < sizeof(requiredSegments)/sizeof(memseg_metadata_t); i++) { if(requiredSegmentsFoundMap[i] == 0) { const memseg_metadata_t seg_def = requiredSegments[i]; printf("found segment that not specified: \"%s\"\n", seg_def.name); specs->memSpecs[seg_def.seg_id]->start = seg_def.default_addr; specs->memSpecs[seg_def.seg_id]->len = seg_def.default_size; specs->memSpecs[seg_def.seg_id]->wordLen = seg_def.word_len; specs->memSpecs[seg_def.seg_id]->name = calloc(strlen(seg_def.name) + 1, sizeof(char)); if(specs->memSpecs[seg_def.seg_id]->name == NULL) { sprintf(errbuf, "unable to allocate spec %d name", i); freeDevSpec(specs); free(requiredSegmentsFoundMap); return NULL; } strcpy(specs->memSpecs[seg_def.seg_id]->name, seg_def.name); if(seg_def.is_executable) { specs->executableSegments[executableSegmentsFound] = seg_def.seg_id; executableSegmentsFound++; } } } if(executableSegmentsFound < specs->executableSegmentsCount) { sprintf(errbuf, "Not all executable segments found"); freeDevSpec(specs); free(requiredSegmentsFoundMap); return NULL; } printf("set all segments\n"); #ifdef MEMSEG_PC_SEG_NUM #ifndef MEMSEG_PC_ADDR specs->pcAddr = memSegToGlobal(specs, MEMSEG_PC_SEG_NUM, 0); #else specs->pcAddr = memSegToGlobal(specs, MEMSEG_PC_SEG_NUM, MEMSEG_PC_ADDR); #endif #endif free(requiredSegmentsFoundMap); printf("parse specs done\n"); 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) { return NULL; //TODO device_specs_t* specs = calloc(1, sizeof(device_specs_t)); if (specs == NULL) { return NULL; } specs->memSpecsCount = 4; specs->memSpecs = calloc(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 = calloc(1, sizeof(uint8_t)); 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] = calloc(1, 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) { device_public_context_t* pubDevContext = calloc(1, sizeof(device_public_context_t)); if (pubDevContext == NULL) { sprintf(errbuf, "unable to allocate public context"); return NULL; } char initErrbuf[200]; device_info_t* devInfo = initSpecs(specs, initErrbuf); if (devInfo == NULL) { sprintf(errbuf, "unable to init specs: %s", initErrbuf); free(pubDevContext); return NULL; } pubDevContext->deviceInfo = (void*)devInfo; pubDevContext->deviceMem = devInfo->deviceMem; return pubDevContext; } uint8_t pubDeviceType() { return DEVICE_TYPE; } 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); } void reset (device_specs_t* specs, device_public_context_t* devInfo) { // printf("reset device\n"); // uint8_t fuck = 0; for(size_t i = 0; i < specs->memSpecsCount; i++) { if(i != MEMDATA_OPSIZE) { const memseg_spec_t* spec = specs->memSpecs[i]; for(size_t j = 0; j < spec->len; j++) { ((uint8_t*)devInfo->deviceMem->cells[i])[j] = 0; // fuck++; } } } devInfo->deviceMem->memwriteLen = 0; devInfo->deviceMem->memreadLen = 0; }