From 2ff6b1a4542b498ef111bbfec751ac2aa4b911c6 Mon Sep 17 00:00:00 2001 From: nikto_b Date: Tue, 21 Jan 2025 22:03:23 +0300 Subject: [PATCH] Initial commit --- .gitignore | 9 + .gitmodules | 3 + Makefile | 89 ++++ clean_build.sh | 3 + deps/.gitignore | 4 + deps/Makefile | 27 ++ glob.toml | 60 +++ hmmmm_scripts | 1 + inc/base_device.h | 21 + inc/compose_device.h | 41 ++ inc/config.h | 36 ++ inc/hmmmm.h | 33 ++ inc/libdevice.h | 37 ++ inc/libhmmmm.h | 14 + inc/libmem.h | 52 +++ inc/my_mutex.h | 22 + src/base_device.c | 276 +++++++++++++ src/compose_device.c | 529 ++++++++++++++++++++++++ src/config.c | 86 ++++ src/hmmmm.c | 238 +++++++++++ src/main.c | 960 +++++++++++++++++++++++++++++++++++++++++++ 21 files changed, 2541 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 100755 clean_build.sh create mode 100644 deps/.gitignore create mode 100644 deps/Makefile create mode 100644 glob.toml create mode 160000 hmmmm_scripts create mode 100644 inc/base_device.h create mode 100644 inc/compose_device.h create mode 100644 inc/config.h create mode 100644 inc/hmmmm.h create mode 100644 inc/libdevice.h create mode 100644 inc/libhmmmm.h create mode 100644 inc/libmem.h create mode 100644 inc/my_mutex.h create mode 100644 src/base_device.c create mode 100644 src/compose_device.c create mode 100644 src/config.c create mode 100644 src/hmmmm.c create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89ef8d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.vscode +compile_commands.json +out +.ccls-cache +.*.sh +build +devices +.cache +*.bin diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..eac5f94 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "hmmmm_scripts"] + path = hmmmm_scripts + url = git@192.168.8.167:nikto_b/hmmmm_scripts.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f568845 --- /dev/null +++ b/Makefile @@ -0,0 +1,89 @@ +BUILD_DIR=out +SRC_DIR=src +INC_DIR=inc +CC=gcc +OBJDUMP=objdump +LIBS=deps/tomlc99/libtoml.a deps/ptQueue/out/ptQueue.a deps/wsServer/libws.a +LIBS_HEADERS=deps/ +STANDART=c23 +OPTIMIZE=-Og +TARGET=main + + +DEFINES=#-DOPCODE_WORDSIZE=2 -DMEM_CELL_WORDS=1 -DPC_WORDSIZE=2 -DGP_REG_CELL_WORDS=1 -DIO_REG_CELL_WORDS=1 + +C_SOURCES=$(wildcard $(SRC_DIR)/*.c) +# C_SOURCES=$(wildcard $(SRC_DIR)/*.c) +C_HEADERS=$(wildcard $(INC_DIR)/*.h) + +C_INCLUDES=-I$(INC_DIR)/ $(addprefix -I,$(LIBS_HEADERS)) + +C_DEFS=-D_POSIX_C_SOURCE=199309L + +DISABLE_FLAGS=-Wno-unused-variable -Wno-unused-parameter -Wno-write-strings -Wno-pointer-arith +PEDANTIC_FLAGS=-pedantic -pedantic-errors $(DISABLE_FLAGS) -Wall -Wcast-align -Wcast-qual -Wconversion -Wduplicated-branches -Wduplicated-cond -Werror -Wextra -Wfloat-equal -Wlogical-op -Wpedantic -Wredundant-decls -Wsign-conversion +ANALYZER_FLAGS=-fanalyzer -fdiagnostics-show-option -fdiagnostics-color=always +LSECTIONS=-ffunction-sections -fdata-sections -Wl,--gc-sections +CFLAGS=$(C_DEFS) -g $(C_INCLUDES) $(DEFINES) $(OPTIMIZE) --std=$(STANDART) $(PEDANTIC_FLAGS) $(ANALYZER_FLAGS) +LFLAGS=$(OPTIMIZE) -g $(PEDANTIC_FLAGS) $(DEFINES) -flto -fuse-linker-plugin $(LSECTIONS) -lm + + + +OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) $(LIBS) +vpath %.c $(sort $(dir $(C_SOURCES))) +vpath %.h $(sort $(dir $(C_HEADERS))) + +# $(info SOURCES=$(C_SOURCES)) +# $(info HEADERS=$(C_HEADERS)) +# $(info OBJECTS=$(OBJECTS)) + + +all: build + +build: date deps Dir $(C_HEADERS) target compile_commands + +rebuild: clean | build + +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + @echo -e '\033[1;32mCC\t'$<'\t->\t'$@'\033[0m' + @$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ + @$(OBJDUMP) -d -S $@ > $(BUILD_DIR)/$(notdir $(<:.c=.casm)) + +target: date $(BUILD_DIR)/$(TARGET).elf + +$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) + @echo -e '\033[1;32mELF\t'$(OBJECTS)'\n\t\t\t->\t'$@'\033[0m' + @$(CC) $(LFLAGS) $(OBJECTS) -o $(BUILD_DIR)/$(TARGET).elf + +deps: + @make -C deps all + + + +BuildDir: + @mkdir -p $(BUILD_DIR) + +SrcDir: + @mkdir -p $(SRC_DIR) + +IncDir: + @mkdir -p $(INC_DIR) + +Dir: BuildDir SrcDir IncDir + + +.PHONY: clean deps +clean: + @rm -rf $(BUILD_DIR)/* +# @rm -f compile_commands.json + @echo -e '\033[0;31mCleaned\033[0m' + +.NOTPARALLEL: date target rebuild deps +date: + @echo -e '\033[1;32m'"Starting build at " | tr -d '\n' + @date + @echo -e '\033[0m' + + +compile_commands: +# @bear -- ./.gen_compile_commands.sh $(TARGET) $(CC) "$(CFLAGS)" "$(LFLAGS)" "$(OBJECTS)" diff --git a/clean_build.sh b/clean_build.sh new file mode 100755 index 0000000..0482857 --- /dev/null +++ b/clean_build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make clean +make build \ No newline at end of file diff --git a/deps/.gitignore b/deps/.gitignore new file mode 100644 index 0000000..12c2d55 --- /dev/null +++ b/deps/.gitignore @@ -0,0 +1,4 @@ +tomlc99 +ptQueue +tomlc99 +wsServer diff --git a/deps/Makefile b/deps/Makefile new file mode 100644 index 0000000..c036422 --- /dev/null +++ b/deps/Makefile @@ -0,0 +1,27 @@ +all: tomlc99.a ptQueue.a libws.a + +tomlc99: + @git clone https://github.com/cktan/tomlc99 + +tomlc99.a: tomlc99 + @make -C tomlc99 libtoml.a + + +ptQueue: + @git clone git@192.168.8.167:nikto_b/ptQueue.git + +ptQueue.a: ptQueue + @make -C ptQueue + +wsServer: + @git clone https://github.com/Theldus/wsServer + +libws.a: wsServer + @make -C wsServer + +clean: + @rm -rf wsServer ptQueue tomlc99 + + +.PHONY: all clean + diff --git a/glob.toml b/glob.toml new file mode 100644 index 0000000..2193245 --- /dev/null +++ b/glob.toml @@ -0,0 +1,60 @@ +[dev] +core = "/home/nikto_b/Documents/baum/hmmmm/devices/avr_generic/AVRrc.toml" +# gpio_a = "/home/nikto_b/Documents/baum/hmmmm/devices/avr_gpio/gpio.toml" + +[config.core.mem.ps] +len = 128 + + +[clock] +limiter = 16000000 + +[clock.core] +src = "" +divider = 1 + +[clock.gpio_a] +src = "core" +divider = 2 + + +# [mem.projection.gpio_a.ext_reg_io] +# base_at = "core" +# base_seg = "reg_io" +# projection_shift = 0 + + +[mem.intercept.PORTA] +base_at = "core" +point_at = "gpio_a" +addr = 0 +seg = "reg_io" + + +[mem.intercept.PINA] +base_at = "core" +point_at = "gpio_a" +base_addr = 1 +point_addr = 1 +base_seg = "reg_io" +point_seg = "ext_reg_io" + +[mem.setup.core.ps] +filepath = "/home/nikto_b/Documents/avr_selftests/test.bin" + + +[mem.setup.core.ds] +filepath = "/dev/urandom" +overflow_behaviour = "ignore" + +# - почему си (адресная арифметика, отсутствие мешающих фичей языка, широкое распространение среди разработчеков-железячников) +# - подход к модульности (всё базовое устройство, запускаем комбинированные устройства из базовых и комбинированных) +# - структура базового модуля эмулятора (какие есть варианты полей конфига) +# - структура комбинированного модуля эмулятора (какие есть варианты полей конфига) +# - структура комбинированного модуля эмулятора (какие конфиг вырождается в эмулятор) +# - процесс инициализации модуля (6 этапов инициализации) +# - процесс исполнения модуля (чисто дергаем "makeTick" у каждой dlib'ы) +# - реализация перехватчиков доступа (пример с sbi, диаграмма с тестовым перехватчиком) +# - реализация проецирования памяти (диаграммы с колбасами) +# - тестовая прошивка (селфтест сложения-вычитания) +# - пример исполнения (?) diff --git a/hmmmm_scripts b/hmmmm_scripts new file mode 160000 index 0000000..9cc7b36 --- /dev/null +++ b/hmmmm_scripts @@ -0,0 +1 @@ +Subproject commit 9cc7b36cbbfbd6324874069add330fcd60839f54 diff --git a/inc/base_device.h b/inc/base_device.h new file mode 100644 index 0000000..f861185 --- /dev/null +++ b/inc/base_device.h @@ -0,0 +1,21 @@ +#ifndef __BASE_DEVICE_H__ +#define __BASE_DEVICE_H__ + +#include "hmmmm.h" + +typedef struct { + void* specs; + device_lib_t* lib; + device_public_context_t* ctx; + uint64_t clockCycleLimit; + uint64_t clockCycleCounter; +} device_handle_t; + + +device_handle_t* openBaseDeviceFromConfig(const char* configPath, char* errbuf); +device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf); +conf_dev_t* openBaseDeviceConfig(const char* configPath, char* errbuf); +void closeBaseDevice(device_handle_t* devHandle); + + +#endif // ifndef __BASE_DEVICE_H__ diff --git a/inc/compose_device.h b/inc/compose_device.h new file mode 100644 index 0000000..3223d6d --- /dev/null +++ b/inc/compose_device.h @@ -0,0 +1,41 @@ +#ifndef __COMPOSE_DEVICE_H__ +#define __COMPOSE_DEVICE_H__ +#include "base_device.h" + +typedef struct { + uint64_t limiter; +} clock_conf_t; + +typedef struct { + char** baseAt; + char* baseSeg; + char** target; + uint64_t projectionShift; + +} projection_conf_t; + +typedef struct { + + char** baseAt; + char** pointAt; + uint64_t addr; + char* seg; + +} intercept_conf_t; + + +typedef struct { + clock_conf_t clockConf; + conf_dev_t** baseConfigs; + projection_conf_t** projections; + intercept_conf_t** intercepts; +} compose_dev_conf_t; + +typedef struct { + device_handle_t** devHandlers; +} compose_dev_handle_t; + +compose_dev_conf_t* openComposeDeviceConfig(const char* configPath, char* errbuf); +device_handle_t** openComposeDevice(compose_dev_conf_t* conf, char* errbuf); + +#endif // ifndef __COMPOSE_DEVICE_H__ \ No newline at end of file diff --git a/inc/config.h b/inc/config.h new file mode 100644 index 0000000..e08df2f --- /dev/null +++ b/inc/config.h @@ -0,0 +1,36 @@ +#ifndef __HMMMM_CONFIG_H__ +#define __HMMMM_CONFIG_H__ +#include +#include + + +typedef struct { + char* name; + size_t start; + size_t len; + uint8_t wordLen; + uint8_t isExecutable; +} conf_mem_seg_t; + +typedef struct { + conf_mem_seg_t** memSegConfs; +} conf_mem_t; + +typedef struct { + char** id; + char** clockId; + uint64_t clockDivider; + uint64_t clockMultipler; + conf_mem_t* memConf; + char* libPath; +} conf_dev_t; + + + +void freeMemSegConf(conf_mem_seg_t* memSegConf); +void freeMemConf(conf_mem_t* memConf); +void freeConf(conf_dev_t* conf); +void freeComposeId(char** id); +uint8_t compareComposeId(char** idA, char** idB); + +#endif // ifndef __HMMMM_CONFIG_H__ diff --git a/inc/hmmmm.h b/inc/hmmmm.h new file mode 100644 index 0000000..03a2864 --- /dev/null +++ b/inc/hmmmm.h @@ -0,0 +1,33 @@ +#ifndef __HMMMMM__ +#define __HMMMMM__ +#include "libhmmmm.h" +#include "config.h" + +typedef struct { + void* (*extractPcounterPtr)(device_public_context_t* devContext); + + size_t (*extractPcounter)(device_public_context_t* devContext); + size_t (*extractOpcode)(device_mem_t* devMem, size_t _programCounter); + uint8_t (*extractPcounterSizeWords)(); + + +} instruction_simul_handlers_t; + +typedef struct { + uint8_t devType; + device_public_context_t* (*init)(void*, char* errbuf); + uint8_t (*makeDeviceTick)(device_public_context_t* devInfo); + void* extendedHandlers; + device_public_context_t* devContext; + void* _dlhandl; + void* (*parseSpecsFromConfig)(const conf_dev_t* devConf, char* errbuf); + void (*freeSpecs)(void* specs); + void (*freeDevMem)(device_mem_t* mem); + void (*fillSmartReadSpecs)(void* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount); + void (*fillSmartWriteSpecs)(void* specs, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount); +} device_lib_t; + +device_lib_t* loadDeviceLib(const char *libpath, char* errbuf); + + +#endif // ifndef __HMMMMM__ \ No newline at end of file diff --git a/inc/libdevice.h b/inc/libdevice.h new file mode 100644 index 0000000..93c5ca9 --- /dev/null +++ b/inc/libdevice.h @@ -0,0 +1,37 @@ +#ifndef __LIBDEVICE_H__ +#define __LIBDEVICE_H__ + +#include +#include "libmem.h" + +#define SMART_ADDR_TYPE_GLOBAL 1 +#define SMART_ADDR_TYPE_SEGMENTED 2 +typedef struct +{ + uint64_t addr; + uint8_t segno; + uint64_t localAddr; + uint8_t addrType; + mem_h_read_func* handler; + uint64_t ident; +} smart_read_spec_t; + +typedef struct +{ + uint64_t addr; + uint8_t segno; + uint64_t localAddr; + uint8_t addrType; + mem_h_write_func handler; + uint64_t ident; +} smart_write_spec_t; + +typedef struct { + device_mem_t* deviceMem; + void* deviceInfo; +} device_public_context_t; + + + +#endif // ifndef __LIBDEVICE_H__ + diff --git a/inc/libhmmmm.h b/inc/libhmmmm.h new file mode 100644 index 0000000..4fc30a7 --- /dev/null +++ b/inc/libhmmmm.h @@ -0,0 +1,14 @@ +#ifndef __LIB_HMMMMM__ +#define __LIB_HMMMMM__ + +#include "libmem.h" +#include "libdevice.h" + +#define EXTENDED_DEVICE_TYPE_DUMMY 0 +#define EXTENDED_DEVICE_TYPE_INSTR_SIMUL 1 + + + + + +#endif // ifndef __LIB_HMMMMM__ \ No newline at end of file diff --git a/inc/libmem.h b/inc/libmem.h new file mode 100644 index 0000000..72f7965 --- /dev/null +++ b/inc/libmem.h @@ -0,0 +1,52 @@ +#ifndef __LIBMEM_H__ +#define __LIBMEM_H__ + +#include +#include + +#define GET_BIT(n, b) ((n >> b) & 1) + +// Internal mem handlers +typedef void* (*mem_h_read_func)(uint64_t ident, uint64_t addr, void* rawCells); +typedef void (*mem_h_write_func)(uint64_t ident, uint64_t addr, void* rawCells, void* data); + +typedef struct { + mem_h_read_func func; + uint64_t ident; +} mem_h_read_handler; +typedef struct { + mem_h_write_func func; + uint64_t ident; +} mem_h_write_handler; + +typedef struct +{ + void* rawCells; + void** cells; + uint64_t smartAddrReadMask; + uint64_t smartAddrWriteMask; + mem_h_read_handler* smartAddrReadHandlers; + mem_h_write_handler* smartAddrWriteHandlers; + char** memsegNames; + uint64_t* memsegShifts; + uint64_t* memreadCellAddrs; + uint64_t* memwriteCellAddrs; + uint8_t memreadLen; + uint8_t memwriteLen; +} device_mem_t; + + +typedef struct +{ + uint64_t start; + uint64_t len; + uint8_t wordLen; + char* name; +} memseg_spec_t; + + +// External handlers +typedef void* (*ext_h_read_func)(uint64_t addr, void* rawCells, void* devContext); +typedef void (*ext_h_write_func)(uint64_t addr, void* rawCells, void* data, void* devContext); + +#endif // ifndef __LIBMEM_H__ diff --git a/inc/my_mutex.h b/inc/my_mutex.h new file mode 100644 index 0000000..2ed119e --- /dev/null +++ b/inc/my_mutex.h @@ -0,0 +1,22 @@ +#ifndef __MY_MUTEX_H__ +#define __MY_MUTEX_H__ +#include + +/** + * Макрос для pthread_mutex_t + * Использовать так: + * with_lock(&mtx) + * { + * secured_code(); + * } + */ + +#define __MY_MUTEX__CONCAT(x, y) x##y +#define __MY_MUTEX__UNIQUE_NAME(base) __MY_MUTEX__CONCAT(base, __LINE__) + +#define with_lock(mutex) \ + for (int __MY_MUTEX__UNIQUE_NAME(_once) = (pthread_mutex_lock(mutex), 1); \ + __MY_MUTEX__UNIQUE_NAME(_once); \ + pthread_mutex_unlock(mutex), __MY_MUTEX__UNIQUE_NAME(_once) = 0) + +#endif //ifndef __MY_MUTEX_H__ \ No newline at end of file diff --git a/src/base_device.c b/src/base_device.c new file mode 100644 index 0000000..98eb981 --- /dev/null +++ b/src/base_device.c @@ -0,0 +1,276 @@ +#include +#include +#include + +#include "tomlc99/toml.h" + +#include "base_device.h" + + + + +device_handle_t* openBaseDeviceFromConfig(const char* configPath, char* errbuf) +{ + char intErrbuf[1024]; + + conf_dev_t *devConf = openBaseDeviceConfig(configPath, intErrbuf); + if (devConf == NULL) + { + sprintf(errbuf, "unable to read device config: %s", intErrbuf); + return NULL; + } + + device_handle_t* ret = openBaseDevice(devConf, intErrbuf); + + if(ret == NULL) + { + freeConf(devConf); + free(devConf); + } + + return ret; +} + +void closeBaseDevice(device_handle_t* devHandle) +{ + if(devHandle->ctx != NULL) + { + if(devHandle->specs != NULL) + { + devHandle->lib->freeSpecs(devHandle->specs); + } + if(devHandle->ctx->deviceMem != NULL) + { + devHandle->lib->freeDevMem(devHandle->ctx->deviceMem); + } + free(devHandle->ctx); + } + if(devHandle->lib->extendedHandlers != NULL) + { + free(devHandle->lib->extendedHandlers); + } + dlclose(devHandle->lib->_dlhandl); + free(devHandle->lib); +} + +device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf) +{ + device_handle_t* ret = malloc(sizeof(device_handle_t)); + if (ret == NULL) + { + sprintf(errbuf, "unable to allocate device handle struct"); + return NULL; + } + + char intErrbuf[1024]; + + device_lib_t* devLib = loadDeviceLib(devConf->libPath, intErrbuf); + if (devLib == NULL) + { + sprintf(errbuf, "unable to load device library %s: %s", devConf->libPath, intErrbuf); + free(ret); + return NULL; + } + + void* devSpecs = devLib->parseSpecsFromConfig(devConf, intErrbuf); + + if (devSpecs == NULL) + { + sprintf(errbuf, "device config parse error: %s", intErrbuf); + dlclose(devLib->_dlhandl); + free(ret); + free(devLib); + return NULL; + } + + + ret->lib = devLib; + ret->specs = devSpecs; + ret->clockCycleCounter = 0; + ret->clockCycleLimit = 0; + + return ret; +} + + + +conf_mem_seg_t** parseMemToml(const toml_table_t* memTable) +{ + uint16_t memSegIdx = 0; + const char* memSegKey = toml_key_in(memTable, 0); + while (memSegKey && memSegIdx < 0xFFFF) + { + memSegIdx++; + memSegKey = toml_key_in(memTable, memSegIdx); + } + + conf_mem_seg_t** segConfigs = malloc(sizeof(conf_mem_seg_t*) * ((size_t)memSegIdx + 1)); + if (segConfigs == NULL) + { + return NULL; + } + segConfigs[memSegIdx] = NULL; + + for (size_t i = 0; i < memSegIdx; i++) + { + segConfigs[i] = (conf_mem_seg_t*)malloc(sizeof(conf_mem_seg_t)); + memSegKey = toml_key_in(memTable, (int)i); + + if (segConfigs[i] == NULL || memSegKey == NULL) + { + if (segConfigs[i] != NULL) + { + free(segConfigs[i]); + } + else + { + } + for(size_t j = 0; j < i; j++) + { + free(segConfigs[j]->name); + free(segConfigs[j]); + } + free(segConfigs); + return NULL; + } + segConfigs[i]->name = (char*)malloc(strlen(memSegKey) + 1); + if (segConfigs[i]->name == NULL) + { + for(size_t j = 0; j <= i; j++) + { + if (j < i) + free(segConfigs[j]->name); + free(segConfigs[j]); + } + free(segConfigs); + return NULL; + } + strcpy(segConfigs[i]->name, memSegKey); + + toml_table_t* segTable = toml_table_in(memTable, memSegKey); + if (segTable == NULL) + { + + for(size_t j = 0; j <= i; j++) + { + free(segConfigs[j]->name); + free(segConfigs[j]); + } + free(segConfigs); + return NULL; + } + + toml_datum_t startDatum = toml_int_in(segTable, "start"); + toml_datum_t lenDatum = toml_int_in(segTable, "len"); + toml_datum_t wordLenDatum = toml_int_in(segTable, "wordLen"); + toml_datum_t executableDatum = toml_bool_in(segTable, "executable"); + + if (!startDatum.ok || !lenDatum.ok || !wordLenDatum.ok) + { + for(size_t j = 0; j <= i; j++) + { + free(segConfigs[j]->name); + free(segConfigs[j]); + } + free(segConfigs); + return NULL; + } + + segConfigs[i]->start = (size_t)startDatum.u.i; + segConfigs[i]->len = (size_t)lenDatum.u.i; + segConfigs[i]->wordLen = (uint8_t)wordLenDatum.u.i; + segConfigs[i]->isExecutable = 0; + if (executableDatum.ok) + { + segConfigs[i]->isExecutable = executableDatum.u.b != 0; + } + } + + + + return segConfigs; +} + + +conf_dev_t* openBaseDeviceConfig(const char* configPath, char* errbuf) +{ + conf_dev_t* ret = malloc(sizeof(conf_dev_t)); + if (ret == NULL) + { + sprintf(errbuf, "unable to allocate device conf struct"); + return NULL; + } + + ret->id = NULL; + ret->clockDivider = 1; + ret->clockMultipler = 1; + ret->clockId = NULL; + + + ret->memConf = malloc(sizeof(conf_mem_t)); + if (ret->memConf == NULL) + { + sprintf(errbuf, "unable to allocate device memory conf struct"); + free(ret); + return NULL; + } + + char intErrbuf[1024]; + + + + FILE *fp = fopen (configPath, "rb"); + if (!fp) { + sprintf(errbuf, "unable to open config file %s", configPath); + free(ret->memConf); + free(ret); + return NULL; + } + toml_table_t* conf = toml_parse_file(fp, intErrbuf, sizeof(intErrbuf)); + fclose(fp); + + if (!conf) { + sprintf(errbuf, "cannot parse - %s", intErrbuf); + free(ret->memConf); + free(ret); + return NULL; + } + + toml_table_t* devBlock = toml_table_in(conf, "dev"); + if (!devBlock) { + sprintf(errbuf, "missing [dev]"); + free(ret->memConf); + free(ret); + return NULL; + } + + toml_table_t* memTable = toml_table_in(conf, "mem"); + if (!memTable) { + sprintf(errbuf, "missing [mem]"); + free(ret->memConf); + free(ret); + return NULL; + } + + toml_datum_t libpathBlock = toml_string_in(devBlock, "libpath"); + if (!libpathBlock.ok) { + sprintf(errbuf, "unable to read dev.libpath"); + free(ret->memConf); + free(ret); + return NULL; + } + + conf_mem_seg_t** memSegConfs = parseMemToml(memTable); + if (memSegConfs == NULL) + { + sprintf(errbuf, "unable to parse mem segments"); + free(ret->memConf); + free(ret); + return NULL; + } + + ret->memConf->memSegConfs = memSegConfs; + ret->libPath = libpathBlock.u.s; + + return ret; +} diff --git a/src/compose_device.c b/src/compose_device.c new file mode 100644 index 0000000..d0fc3b4 --- /dev/null +++ b/src/compose_device.c @@ -0,0 +1,529 @@ +#include +#include +#include + +#include "tomlc99/toml.h" + +#include "base_device.h" +#include "compose_device.h" + + +// void fillDevClockConfig(const toml_table_t* clockTable, conf_dev_t** devConfs) +// { +// uint16_t clockSegIdx = 0; +// uint16_t clockSegSkips = 0; +// const char* clockSegKey = toml_key_in(clockTable, 0); +// while (clockSegKey && (clockSegIdx + clockSegSkips) < 0xFFFF) +// { +// clockSegKey = toml_key_in(clockTable, clockSegIdx + clockSegSkips + 1); +// if(strcmp(clockSegKey, "limiter") != 0) +// { +// clockSegIdx++; +// } +// else +// { +// clockSegSkips++; +// } +// } +// } + +char** appendId(char** prev, const char* cur, char* errbuf) +{ + if(prev == NULL) + { + prev = malloc(sizeof(char*) * 2); + if(prev == NULL) + { + sprintf(errbuf, "unable to allocate id"); + return NULL; + } + prev[0] = NULL; + prev[1] = NULL; + } + + size_t clockIdLen = 0; + while (prev[clockIdLen] != NULL){clockIdLen++;} + + clockIdLen++; + + char** new = realloc(prev, sizeof(char*) * (clockIdLen + 1)); + + if(new == NULL) + { + sprintf(errbuf, "unable to reallocate id"); + freeComposeId(prev); + return NULL; + } + prev = new; + + prev[clockIdLen] = NULL; + size_t idLen = strlen(cur); + prev[clockIdLen - 1] = malloc(sizeof(char) * (idLen + 1)); + if(prev[clockIdLen - 1] == NULL) + { + sprintf(errbuf, "unable to allocate new id entry"); + freeComposeId(prev); + return NULL; + } + strcpy(prev[clockIdLen - 1], cur); + prev[clockIdLen - 1][idLen] = '\0'; + return prev; +} + +conf_dev_t** parseDevToml(const toml_table_t* devTable, const toml_table_t* clockTable, char* errbuf) +{ + uint16_t devSegIdx = 0; + const char* devSegKey = toml_key_in(devTable, 0); + while (devSegKey && devSegIdx < 0xFFFF) + { + devSegIdx++; + devSegKey = toml_key_in(devTable, devSegIdx); + } + + conf_dev_t** deviceConfigs = malloc(sizeof(conf_dev_t*) * (devSegIdx + 1)); + if(deviceConfigs == NULL) + { + return NULL; + } + + deviceConfigs[devSegIdx] = NULL; + + for(size_t i = 0; i < devSegIdx; i++) + { + devSegKey = toml_key_in(devTable, (int)i); + if(devSegKey == NULL) + { + sprintf(errbuf, "unable to load device key %lu", i); + for(size_t j = 0; j < i; j++) + { + freeConf(deviceConfigs[j]); + free(deviceConfigs[j]); + } + free(deviceConfigs); + return NULL; + } + toml_datum_t devpathDatum = toml_string_in(devTable, devSegKey); + if(!devpathDatum.ok || !devpathDatum.u.s) + { + sprintf(errbuf, "unable to get device path for %s", devSegKey); + + for(size_t j = 0; j < i; j++) + { + freeConf(deviceConfigs[j]); + free(deviceConfigs[j]); + } + free(deviceConfigs); + return NULL; + } + char intErrbuf[1024]; + + conf_dev_t* conf = openBaseDeviceConfig(devpathDatum.u.s, intErrbuf); + if(conf == NULL) + { + sprintf(errbuf, "unable to load config for %s: %s", devSegKey, intErrbuf); + + for(size_t j = 0; j < i; j++) + { + freeConf(deviceConfigs[j]); + free(deviceConfigs[j]); + } + free(deviceConfigs); + return NULL; + } + + conf->id = NULL; + conf->id = appendId(conf->id, devSegKey, intErrbuf); + + + if(conf->id == NULL) + { + sprintf(errbuf, "unable to allocate device %s name field", devSegKey); + for(size_t j = 0; j <= i; j++) + { + freeConf(deviceConfigs[j]); + free(deviceConfigs[j]); + } + free(deviceConfigs); + return NULL; + } + + deviceConfigs[i] = conf; + } + + if(clockTable != NULL) + { + for(size_t i = 0; i < devSegIdx; i++) + { + conf_dev_t* conf = deviceConfigs[i]; + toml_table_t* devClockTable = toml_table_in(clockTable, conf->id[0]); + if(devClockTable == NULL) + { + continue; + } + + toml_datum_t dividerDatum = toml_int_in(devClockTable, "divider"); + if(dividerDatum.ok) + { + conf->clockDivider = (uint64_t)dividerDatum.u.i; + } + toml_datum_t multiplerDatum = toml_int_in(devClockTable, "multipler"); + if(multiplerDatum.ok) + { + conf->clockMultipler = (uint64_t)multiplerDatum.u.i; + } + + toml_datum_t srcDatum = toml_string_in(devClockTable, "src"); + if(srcDatum.ok && srcDatum.u.s != NULL) + { + char intErrbuf[1024] = {0}; + conf->clockId = appendId(conf->clockId, srcDatum.u.s, intErrbuf); + if(conf->clockId == NULL) + { + sprintf(errbuf, "unable to append clock id for %s: %s", conf->id[0], intErrbuf); + for(size_t j = 0; j <= i; j++) + { + freeConf(deviceConfigs[j]); + free(deviceConfigs[j]); + } + free(deviceConfigs); + return NULL; + } + } + + } + } + + return deviceConfigs; +} +void freeProjectionConfig(projection_conf_t* conf) +{ + if(conf == NULL) + { + return; + } + freeComposeId(conf->target); + freeComposeId(conf->baseAt); + if(conf->baseSeg != NULL) + { + free(conf->baseSeg); + } + conf->target = NULL; + conf->baseAt = NULL; + conf->baseSeg = NULL; + free(conf); +} +void freeProjectionConfigs(projection_conf_t** confs) +{ + if(confs == NULL) + { + return; + } + size_t i = 0; + while(confs[i] != NULL) + { + freeProjectionConfig(confs[i]); + confs[i] = NULL; + } + free(confs); +} + + +projection_conf_t* parseDeviceProjectionConf(const toml_table_t* deviceProjectionTable, char* errbuf) +{ + toml_datum_t baseAtDatum = toml_string_in(deviceProjectionTable, "base_at"); + if(!baseAtDatum.ok || baseAtDatum.u.s == NULL) + { + sprintf(errbuf, "missing 'base_at'"); + return NULL; + } + + toml_datum_t baseSegDatum = toml_string_in(deviceProjectionTable, "base_seg"); + if(!baseSegDatum.ok || baseSegDatum.u.s == NULL) + { + sprintf(errbuf, "missing 'base_seg'"); + return NULL; + } + + toml_datum_t projectionShiftDatum = toml_int_in(deviceProjectionTable, "projection_shift"); + + char intErrbuf[1024] = {0}; + + projection_conf_t* ret = malloc(sizeof(projection_conf_t)); + if(ret == NULL) + { + sprintf(errbuf, "unable to allocate projection conf"); + return NULL; + } + ret->baseAt = NULL; + ret->baseSeg = NULL; + ret->target = NULL; + ret->projectionShift = 0; + + if(projectionShiftDatum.ok) + { + ret->projectionShift = (uint64_t)projectionShiftDatum.u.i; + } + + ret->baseAt = appendId(ret->baseAt, baseAtDatum.u.s, intErrbuf); + if(ret->baseAt == NULL) + { + sprintf(errbuf, "unable to append base_at id"); + freeProjectionConfig(ret); + return NULL; + } + ret->baseSeg = malloc(strlen(baseSegDatum.u.s)); + if(ret->baseSeg == NULL) + { + sprintf(errbuf, "unable to fill base_seg"); + freeProjectionConfig(ret); + return NULL; + } + strcpy(ret->baseSeg, baseSegDatum.u.s); + + return ret; +} + +projection_conf_t** parseDeviceProjectionConfs(const toml_table_t* deviceProjectionsTable, char* errbuf) +{ + uint16_t projSegIdx = 0; + const char* projSegKey = toml_key_in(deviceProjectionsTable, 0); + while (projSegKey && projSegIdx < 0xFFFF) + { + projSegIdx++; + projSegKey = toml_key_in(deviceProjectionsTable, projSegIdx); + } + char intErrbuf[1024] = {0}; + + projection_conf_t** ret = malloc(sizeof(projection_conf_t*) * (projSegIdx + 1)); + if(ret == NULL) + { + sprintf(errbuf, "unable to allocate device projections confs"); + return NULL; + } + + for(size_t i = 0; i <= projSegIdx; i++){ret[i] = NULL;} + + for(size_t i = 0; i < projSegIdx; i++) + { + projSegKey = toml_key_in(deviceProjectionsTable, (int)i); + if(projSegKey == NULL) + { + sprintf(errbuf, "unable to load device projection key %lu", i); + freeProjectionConfigs(ret); + return NULL; + } + + toml_table_t* projTable = toml_table_in(deviceProjectionsTable, projSegKey); + if(projTable == NULL) + { + sprintf(errbuf, "unable to open device %s projection table", projSegKey); + freeProjectionConfigs(ret); + return NULL; + } + + ret[i] = parseDeviceProjectionConf(projTable, intErrbuf); + if(ret[i] == NULL) + { + sprintf(errbuf, "unable to load device %s projection configs: %s", projSegKey, intErrbuf); + freeProjectionConfigs(ret); + return NULL; + } + + ret[i]->target = appendId(ret[i]->target, projSegKey, intErrbuf); + if(ret[i]->target == NULL) + { + sprintf(errbuf, "unable to append projection target id: %s", intErrbuf); + freeProjectionConfigs(ret); + return NULL; + } + } + + return ret; +} + +projection_conf_t** parseProjectionConfs(const toml_table_t* projectionTable, char* errbuf) +{ + uint16_t devicesProjSegIdx = 0; + const char* devicesProjSegKey = toml_key_in(projectionTable, 0); + while (devicesProjSegKey && devicesProjSegIdx < 0xFFFF) + { + devicesProjSegIdx++; + devicesProjSegKey = toml_key_in(projectionTable, devicesProjSegIdx); + } + + + char intErrbuf[1024] = {0}; + + size_t totalRetSize = 0; + projection_conf_t** ret = malloc(sizeof(projection_conf_t*)); + if(ret == NULL) + { + sprintf(errbuf, "unable to allocate base projection conf array"); + return NULL; + } + ret[0] = NULL; + + for(size_t i = 0; i < devicesProjSegIdx; i++) + { + devicesProjSegKey = toml_key_in(projectionTable, (int)i); + if(devicesProjSegKey == NULL) + { + sprintf(errbuf, "unable to load proj key %lu", i); + freeProjectionConfigs(ret); + return NULL; + } + + toml_table_t* deviceProjTable = toml_table_in(projectionTable, devicesProjSegKey); + if(deviceProjTable == NULL) + { + sprintf(errbuf, "unable to open device projection table"); + freeProjectionConfigs(ret); + return NULL; + } + + projection_conf_t** devProjections = parseDeviceProjectionConfs(deviceProjTable, intErrbuf); + + if(devProjections == NULL) + { + sprintf(errbuf, "unable to parse device %s projection rules: %s", devicesProjSegKey, intErrbuf); + freeProjectionConfigs(ret); + return NULL; + } + size_t dlen = 0; + while(devProjections[dlen] != NULL) + { + devProjections[dlen]->target = appendId(devProjections[dlen]->target, devicesProjSegKey, intErrbuf); + if(devProjections[dlen]->target == NULL) + { + freeProjectionConfigs(ret); + freeProjectionConfigs(devProjections); + return NULL; + } + dlen++; + } + ret = realloc(ret, sizeof(projection_conf_t*) * (dlen + totalRetSize + 1)); + if(ret == NULL) + { + sprintf(errbuf, "unable to reallocate full projection array"); + freeProjectionConfigs(devProjections); + return NULL; + } + for(size_t i = 0; i <= dlen; i++) + { + ret[totalRetSize + i] = devProjections[i]; + } + totalRetSize += dlen; + ret[totalRetSize] = NULL; + free(devProjections); + } + + return ret; +} + +compose_dev_conf_t* openComposeDeviceConfig(const char* configPath, char* errbuf) +{ + compose_dev_conf_t* ret = malloc(sizeof(compose_dev_conf_t)); + + if(ret == NULL) + { + sprintf(errbuf, "unable to allocate device struct"); + return NULL; + } + + char intErrbuf[1024] = {0}; + FILE *fp = fopen (configPath, "rb"); + if (!fp) { + sprintf(errbuf, "unable to open config file %s", configPath); + free(ret); + return NULL; + } + toml_table_t* conf = toml_parse_file(fp, intErrbuf, sizeof(intErrbuf)); + fclose(fp); + + + toml_table_t* devTable = toml_table_in(conf, "dev"); + if (!devTable) { + sprintf(errbuf, "missing [dev]"); + free(ret); + return NULL; + } + ret->projections = NULL; + + toml_table_t* memTable = toml_table_in(conf, "mem"); + if(memTable) + { + toml_table_t* projectionTable = toml_table_in(memTable, "projection"); + if(projectionTable) + { + ret->projections = parseProjectionConfs(projectionTable, intErrbuf); + if(ret->projections == NULL) + { + sprintf(errbuf, "unable to load projections: %s", intErrbuf); + free(ret); + return NULL; + } + } + } + + + toml_table_t* clockTable = toml_table_in(conf, "clock"); + + + conf_dev_t** devHandlers = parseDevToml(devTable, clockTable, intErrbuf); + + if(devHandlers == NULL) + { + sprintf(errbuf, "unable to load devices configs: %s", intErrbuf); + freeProjectionConfigs(ret->projections); + free(ret); + return NULL; + } + + ret->baseConfigs = devHandlers; + + + return ret; +} + + +device_handle_t** openComposeDevice(compose_dev_conf_t* conf, char* errbuf) +{ + size_t devIdx = 0; + while(conf->baseConfigs[devIdx] != NULL){devIdx++;} + + device_handle_t** devHandlers = malloc(sizeof(device_handle_t*) * (devIdx + 1)); + + if(devHandlers == NULL) + { + sprintf(errbuf, "unable to allocate dev handlers"); + return NULL; + } + devHandlers[devIdx] = NULL; + + + for(size_t i = 0; i < devIdx; i++) + { + conf_dev_t* devConf = conf->baseConfigs[i]; + char intErrbuf[1024] = {0}; + device_handle_t* devHandle = openBaseDevice(devConf, intErrbuf); + if(devHandle == NULL) + { + sprintf(errbuf, "unable to open base device %s: %s", devConf->id[0], intErrbuf); + for(size_t j = 0; j < i; j++) + { + closeBaseDevice(devHandlers[j]); + free(devHandlers[j]); + } + free(devHandlers); + return NULL; + } + + devHandlers[i] = devHandle; + } + + return devHandlers; +} + + + + diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..8794c55 --- /dev/null +++ b/src/config.c @@ -0,0 +1,86 @@ +#include +#include + +#include "config.h" + + +void xfree(void* p) +{ + if(p != NULL) + { + free(p); + } +} + +void freeComposeId(char** id) +{ + if(id == NULL) + { + return; + } + size_t i = 0; + while(id[i] != NULL) + { + free(id[i]); + i++; + } + free(id); +} + + +uint8_t compareComposeId(char** idA, char** idB) +{ + size_t i = 0; + while(idA[i] != NULL && idB[i] != NULL) + { + if(strcmp(idA[i], idB[i]) != 0) + { + return 0; + } + i++; + } + return idA[i] == NULL && idB[i] == NULL; +} + +void freeMemSegConf(conf_mem_seg_t* memSegConf) +{ + if(memSegConf == NULL) + { + return; + } + xfree(memSegConf->name); +} +void freeMemConf(conf_mem_t* memConf) +{ + if(memConf == NULL) + { + return; + } + for(size_t i = 0; i < 0xFF && memConf->memSegConfs[i] != NULL; i++) + { + freeMemSegConf(memConf->memSegConfs[i]); + } + xfree(memConf->memSegConfs); + free(memConf); +} +void freeConf(conf_dev_t* conf) +{ + if(conf == NULL) + { + return; + } + if(conf->clockId != NULL) + { + size_t i = 0; + while(conf->clockId[i] != NULL) + { + free(conf->clockId[i]); + i++; + } + free(conf->clockId); + } + freeComposeId(conf->id); + xfree(conf->libPath); + freeMemConf(conf->memConf); + free(conf); +} diff --git a/src/hmmmm.c b/src/hmmmm.c new file mode 100644 index 0000000..00f6d2a --- /dev/null +++ b/src/hmmmm.c @@ -0,0 +1,238 @@ +#include "hmmmm.h" + + +#include +#include + +typedef size_t (*_dlib_pubExtractPcounter_t)(device_public_context_t* devContext); +typedef size_t (*_dlib_pubExtractOpcode_t)(device_mem_t* devMem, size_t _programCounter); + +typedef uint8_t(*_dlib_pubExtractPcounterSizeWords_t)(); + +typedef device_public_context_t* (*_dlib_dev_init_t)(void* specs, char* errbuf); + +typedef uint8_t (*_dlib_makeDeviceTick_t)(device_public_context_t* devInfo); + +typedef uint8_t (*_dlib_deviceType_t)(); + +typedef void* (*_dlib_pubExtractPcounterPtr_t)(device_public_context_t* devContext); + +typedef void* (*_dlib_parseSpecsFromConfig_t)(const conf_dev_t* devConf, char* errbuf); + +typedef void (*_dlib_freeSpecs_t)(void* specs); +typedef void (*_dlib_freeDevMem_t)(device_mem_t* mem); + +typedef void (*_dlib_fillSmartReadSpecs_t)(void* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount); +typedef void (*_dlib_fillSmartWriteSpecs_t)(void* specs, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount); + +instruction_simul_handlers_t* _fillInstructionSimul(void* handle) +{ + instruction_simul_handlers_t* ret = malloc(sizeof(instruction_simul_handlers_t)); + + if (ret == NULL) + { + return NULL; + } + + _dlib_pubExtractPcounterPtr_t _dlib_pubExtractPcounterPtr = (_dlib_pubExtractPcounterPtr_t)(uintptr_t)dlsym(handle, "pubExtractPcounterPtr"); + + const char *dlib_pubExtractPcounterPtr_error = dlerror(); + if (dlib_pubExtractPcounterPtr_error) { + dlclose(handle); + free(ret); + return NULL; + } + + ret->extractPcounterPtr = _dlib_pubExtractPcounterPtr; + + + _dlib_pubExtractPcounter_t _dlib_pubExtractPcounter = (_dlib_pubExtractPcounter_t)(uintptr_t)dlsym(handle, "pubExtractPcounter"); + + const char *dlib_pubExtractPcounter_error = dlerror(); + if (dlib_pubExtractPcounter_error) { + dlclose(handle); + free(ret); + return NULL; + } + + ret->extractPcounter = _dlib_pubExtractPcounter; + + + _dlib_pubExtractOpcode_t _dlib_pubExtractOpcode = (_dlib_pubExtractOpcode_t)(uintptr_t)dlsym(handle, "pubExtractOpcode"); + + const char *dlib_pubExtractOpcode_error = dlerror(); + if (dlib_pubExtractOpcode_error) { + dlclose(handle); + free(ret); + return NULL; + } + + ret->extractOpcode = _dlib_pubExtractOpcode; + + _dlib_pubExtractPcounterSizeWords_t _dlib_pubExtractPcounterSizeWords = (_dlib_pubExtractPcounterSizeWords_t)(uintptr_t)dlsym(handle, "pubExtractPcounterSizeWords"); + + const char *dlib_pubExtractPcounterSizeWords_error = dlerror(); + if (dlib_pubExtractPcounterSizeWords_error) { + dlclose(handle); + free(ret); + return NULL; + } + + ret->extractPcounterSizeWords = _dlib_pubExtractPcounterSizeWords; + + + + return ret; +} + + +device_lib_t* loadDeviceLib(const char *libpath, char* errbuf) +{ + device_lib_t* dev = malloc(sizeof(device_lib_t)); + + if (dev == NULL) + { + sprintf(errbuf, "unable to allocate device lib struct"); + return NULL; + } + + void *handle = dlopen(libpath, RTLD_NOW); + + if (!handle) { + sprintf(errbuf, "unable to open dl handle"); + free(dev); + return NULL; + } + + dlerror(); + + _dlib_dev_init_t _dlib_dev_init = (_dlib_dev_init_t)(uintptr_t)dlsym(handle, "init"); + + const char *dlsym_init_error = dlerror(); + if (dlsym_init_error) { + sprintf(errbuf, "unable to find init symbol: %s", dlsym_init_error); + dlclose(handle); + free(dev); + return NULL; + } + + _dlib_makeDeviceTick_t _dlib_makeDeviceTick = (_dlib_makeDeviceTick_t)(uintptr_t)dlsym(handle, "makeDeviceTick"); + + + const char *dlsym_maketick_error = dlerror(); + if (dlsym_maketick_error) { + sprintf(errbuf, "unable to find makeDeviceTick symbol: %s", dlsym_maketick_error); + dlclose(handle); + free(dev); + return NULL; + } + + + + _dlib_parseSpecsFromConfig_t _dlib_parseSpecsFromConfig = (_dlib_parseSpecsFromConfig_t)(uintptr_t)dlsym(handle, "parseSpecsFromConfig"); + + const char *_dlib_parseSpecsFromConfig_error = dlerror(); + if (_dlib_parseSpecsFromConfig_error) { + sprintf(errbuf, "unable to find parseSpecsFromConfig symbol: %s", _dlib_parseSpecsFromConfig_error); + dlclose(handle); + free(dev); + return NULL; + } + + + + _dlib_fillSmartReadSpecs_t _dlib_fillSmartReadSpecs = (_dlib_fillSmartReadSpecs_t)(uintptr_t)dlsym(handle, "fillSmartReadSpecs"); + + const char *_dlib_fillSmartReadSpecs_error = dlerror(); + if (_dlib_fillSmartReadSpecs_error) { + sprintf(errbuf, "unable to find fillSmartReadSpecs symbol: %s", _dlib_fillSmartReadSpecs_error); + dlclose(handle); + free(dev); + return NULL; + } + + + + _dlib_fillSmartWriteSpecs_t _dlib_fillSmartWriteSpecs = (_dlib_fillSmartWriteSpecs_t)(uintptr_t)dlsym(handle, "fillSmartWriteSpecs"); + + const char *_dlib_fillSmartWriteSpecs_error = dlerror(); + if (_dlib_fillSmartWriteSpecs_error) { + sprintf(errbuf, "unable to find fillSmartWriteSpecs symbol: %s", _dlib_fillSmartWriteSpecs_error); + dlclose(handle); + free(dev); + return NULL; + } + + + _dlib_deviceType_t _dlib_deviceType = (_dlib_deviceType_t)(uintptr_t)dlsym(handle, "pubDeviceType"); + + const char *dlib_deviceType_error = dlerror(); + if (dlib_deviceType_error) { + sprintf(errbuf, "unable to find pubDeviceType symbol: %s", dlib_deviceType_error); + dlclose(handle); + free(dev); + return NULL; + } + + + + + _dlib_freeSpecs_t _dlib_freeSpecs = (_dlib_freeSpecs_t)(uintptr_t)dlsym(handle, "freeDevSpecs"); + + const char *dlib_freeSpecs_error = dlerror(); + if (dlib_freeSpecs_error) { + sprintf(errbuf, "unable to find freeSpecs symbol: %s", dlib_freeSpecs_error); + dlclose(handle); + free(dev); + return NULL; + } + + + _dlib_freeDevMem_t _dlib_freeDevMem = (_dlib_freeDevMem_t)(uintptr_t)dlsym(handle, "freeDevSpecs"); + + const char *dlib_freeDevMem_error = dlerror(); + if (dlib_freeDevMem_error) { + sprintf(errbuf, "unable to find freeDevMem symbol: %s", dlib_freeDevMem_error); + dlclose(handle); + free(dev); + return NULL; + } + + dev->devContext = NULL; + dev->init = _dlib_dev_init; + dev->makeDeviceTick = _dlib_makeDeviceTick; + dev->parseSpecsFromConfig = _dlib_parseSpecsFromConfig; + dev->fillSmartReadSpecs = _dlib_fillSmartReadSpecs; + dev->fillSmartWriteSpecs = _dlib_fillSmartWriteSpecs; + dev->freeSpecs = _dlib_freeSpecs; + dev->freeDevMem = _dlib_freeDevMem; + + uint8_t devType = _dlib_deviceType(); + + dev->devType = devType; + + if (devType == EXTENDED_DEVICE_TYPE_DUMMY) + { + dev->extendedHandlers = NULL; + } + else if (devType == EXTENDED_DEVICE_TYPE_INSTR_SIMUL) + { + dev->extendedHandlers = _fillInstructionSimul(handle); + if (dev->extendedHandlers == NULL) + { + free(dev); + dlclose(handle); + return NULL; + } + } + else + { + free(dev); + dlclose(handle); + return NULL; + } + + dev->_dlhandl = handle; + + return dev; +} \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ecfd534 --- /dev/null +++ b/src/main.c @@ -0,0 +1,960 @@ +#include +#include +#include +#include +#include + +#include +#include + +// #define OPCODE_WORDSIZE 2 +// #define MEM_CELL_WORDS 1 + +// #include "abc.h" +// #include "instr.h" +// #include "mem.h" +// #include "runner.h" + +#include +// #include "runner.h" +#include "hmmmm.h" + +#include "my_mutex.h" + +#include "tomlc99/toml.h" + +#include + + +#include "compose_device.h" + + +#include "ptQueue/inc/ptQueue.h" +#include "wsServer/include/ws.h" + + +void printMemory(void* cells, uint64_t cellsCount) +{ + + for(uint64_t i = 0; i < cellsCount; i++) + { + printf("%lu: 0x%04X", i, ((uint8_t*)cells)[i]); + + // uint8_t wasRead = 0; + // for (uint8_t j = 0; j < mem->memreadLen; j++) + // { + // if(mem->memreadCellAddrs[j] == i) + // { + // wasRead = 1; + // break; + // } + // } + // uint8_t wasWrite = 0; + // for (uint8_t j = 0; j < mem->memwriteLen; j++) + // { + // if(mem->memwriteCellAddrs[j] == i) + // { + // wasWrite = 1; + // break; + // } + // } + + // if (wasRead == 1) + // { + // printf("\t[was read]"); + // } + // else + // { + // printf("\t[was not read]"); + // } + + // if (wasWrite == 1) + // { + // printf("\t[was written]"); + // } + // else + // { + // printf("\t[was not written]"); + // } + printf("\n"); + } +} + + + + +void dummyWriteHandler(uint64_t ident, uint64_t addr, void* rawCells, void* data) +{ + // printf("Intercepted write on 0x%lx: 0x%02x\n", addr, *((uint8_t*)data)); + printf("Intercepted write on 0x%lx: ", addr); + printf("0b"); + for(uint8_t i = 0; i < 8; i++) + { + printf("%d", (*((uint8_t*)data) >> (7 - i)) & 1); + } + printf("\n"); + ((uint8_t*)rawCells)[addr] = *((uint8_t*)data); + return; +} + + + + +ext_h_read_func* interceptReadRouter; +ext_h_write_func* interceptWriteRouter; +void** iterceptDevContextRouter; + +void* readExt(uint64_t ident, uint64_t addr, void* rawCells) +{ + void* devContext = iterceptDevContextRouter[ident]; + ext_h_read_func tgt = interceptReadRouter[ident]; + return tgt(addr, rawCells, devContext); +} +void writeExt(uint64_t ident, uint64_t addr, void* rawCells, void* data) +{ + void* devContext = iterceptDevContextRouter[ident]; + ext_h_write_func tgt = interceptWriteRouter[ident]; + tgt(addr, rawCells, data, devContext); +} + + + +// void *threadMain(void *param); +#define _GNU_SOURCE +#include +#include + + +void my_sleep(int microseconds) { + struct timespec ts; + ts.tv_sec = microseconds / 1000000; // секунды + ts.tv_nsec = (microseconds % 1000000) * 1000; // наносекунды + nanosleep(&ts, NULL); +} + +#define REG_EVTYPE_CONNECT 1 +#define REG_EVTYPE_CLOSE 2 + + +#define CLIENT_STATE_UNAUTHED 0 + +typedef struct { + pthread_mutex_t registerMutex; + ptQueue* regQueue; +} ServerContext; + +typedef struct { + ws_cli_conn_t clientId; + uint8_t isAuthed; + ptQueue* incomeQ; + ptQueue* outcomeQ; +} ClientContext; + +typedef struct { + uint8_t regType; + ClientContext* ctx; +} ClientRegistrationEvent; + +/** + * @brief This function is called whenever a new connection is opened. + * @param client Client connection. + */ +void onopen(ws_cli_conn_t client) +{ + char errbuf[1024]; + + ptQueue* incomeQueue = ptQueueCreate(errbuf); + if(incomeQueue == NULL) + { + printf("Unable to create income queue: %s\n", errbuf); + abort(); + } + + ptQueue* outcomeQueue = ptQueueCreate(errbuf); + if(outcomeQueue == NULL) + { + printf("Unable to create outcome queue: %s\n", errbuf); + ptQueueFree(incomeQueue); + abort(); + } + + ClientContext* cctx = malloc(sizeof(ClientContext)); + if(cctx == NULL) + { + printf("Unable to allocate client context\n"); + ptQueueFree(incomeQueue); + ptQueueFree(outcomeQueue); + abort(); + } + cctx->clientId = client; + cctx->isAuthed = 0; + cctx->incomeQ = incomeQueue; + cctx->outcomeQ = outcomeQueue; + + ClientRegistrationEvent* ev = malloc(sizeof(ClientContext)); + if(ev == NULL) + { + printf("Unable to allocate register event"); + ptQueueFree(incomeQueue); + ptQueueFree(outcomeQueue); + free(cctx); + abort(); + } + ev->regType = REG_EVTYPE_CONNECT; + ev->ctx = cctx; + + ws_set_connection_context(client, cctx); + + ServerContext* ctx = ws_get_server_context(client); + + with_lock(&ctx->registerMutex) + { + int exitCode = ptQueuePush(ctx->regQueue, ev, errbuf); + if(exitCode) + { + printf("Unable to push to reg queue: %s\n", errbuf); + ptQueueFree(incomeQueue); + ptQueueFree(outcomeQueue); + free(cctx); + abort(); + } + } + + char *cli; + cli = ws_getaddress(client); + printf("Connection opened, addr: %s\n", cli); +} + +/** + * @brief This function is called whenever a connection is closed. + * @param client Client connection. + */ +void onclose(ws_cli_conn_t client) +{ + char errbuf[1024]; + + ClientContext* cctx = ws_get_connection_context(client); + if(cctx == NULL) + { + printf("Unable to get client context\n"); + abort(); + } + + + ClientRegistrationEvent* ev = malloc(sizeof(ClientContext)); + if(ev == NULL) + { + printf("Unable to allocate register event"); + abort(); + } + ev->regType = REG_EVTYPE_CONNECT; + ev->ctx = cctx; + + ws_set_connection_context(client, cctx); + + ServerContext* ctx = ws_get_server_context(client); + + with_lock(&ctx->registerMutex) + { + int exitCode = ptQueuePush(ctx->regQueue, ev, errbuf); + if(exitCode) + { + printf("Unable to push to reg queue: %s\n", errbuf); + abort(); + } + } + + + pthread_t tid = pthread_self(); + char *cli; + cli = ws_getaddress(client); + printf("Connection closed, addr: %s, thread id: %lu\n", cli, tid); +} + +/** + * @brief Message events goes here. + * @param client Client connection. + * @param msg Message content. + * @param size Message size. + * @param type Message type. + */ +void onmessage(ws_cli_conn_t client, + const unsigned char *msg, uint64_t size, int type) +{ + ClientContext* cctx = ws_get_connection_context(client); + if(cctx == NULL) + { + printf("Unable to get client context\n"); + abort(); + } + + pthread_t tid = pthread_self(); + char *cli; + cli = ws_getaddress(client); + printf("I receive a message: %s (%zu), from: %s, thread id: %lu\n", msg, + size, cli, tid); + + ws_sendframe_txt(client, "hello"); + ws_sendframe_txt(client, "world"); +} + + +int main(int argc, char** argv) +{ + char errbuf[1024]; + pthread_mutex_t mtx; + pthread_mutex_init(&mtx, NULL); + + ptQueue* regQ = ptQueueCreate(errbuf); + if(regQ == NULL) + { + printf("Unable to create reg q: %s\n", errbuf); + abort(); + } + + ServerContext ctx = { + mtx, + regQ + }; + + + ws_socket(&(struct ws_server){ + /* + * Bind host, such as: + * localhost -> localhost/127.0.0.1 + * 0.0.0.0 -> global IPv4 + * :: -> global IPv4+IPv6 (Dual stack) + */ + .host = "localhost", + .port = 8080, + .thread_loop = 1, + .timeout_ms = 1000, + .context = &ctx, + .evs.onopen = &onopen, + .evs.onclose = &onclose, + .evs.onmessage = &onmessage + }); + + while(1) + { + sleep(1); + } + return 0; +} + + +// int main(int argc, char** argv) +// { +// char errbuf[1024]; + +// pthread_t tid; /* идентификатор потока */ +// pthread_attr_t attr; /* отрибуты потока */ + + +// ptQueue* qOut = ptQueueCreate(errbuf); +// ptQueue* qIn = ptQueueCreate(errbuf); + +// ptQueue** ptArgs = malloc(sizeof(ptQueue*) * 2); +// if(ptArgs == NULL) +// { +// abort(); +// } +// ptArgs[0] = qOut; +// ptArgs[1] = qIn; + +// pthread_attr_init(&attr); +// pthread_create(&tid, &attr, threadMain, ptArgs); + + +// for(int i = 1; i < 4096; i++) +// { +// int* pass = malloc(sizeof(int)); +// if(pass == NULL) +// { +// abort(); +// } +// *pass = i; + +// ptQueuePush(qOut, pass, errbuf); +// } + +// int* ii = malloc(sizeof(int)); +// if(ii == NULL) +// { +// abort(); +// } +// *ii = 0; + +// ptQueuePush(qOut, ii, errbuf); + +// ptQueueElem* tailIn = qIn->tail; + +// while (1) +// { +// void* payload = atomic_load(&(tailIn->payload)); +// if(payload == NULL) +// { +// my_sleep(100); +// continue; +// } +// int* code = payload; + +// printf("nextEl)); +// if (newTail == NULL) +// { +// abort(); +// } +// free(tailIn); +// tailIn = newTail; +// } + +// pthread_join(tid, NULL); +// return 0; +// } + + + +// void *threadMain(void *param) +// { +// char errubf[1024]; +// ptQueue** params = param; +// ptQueue* qIn = params[0]; +// ptQueue* qOut = params[1]; +// ptQueueElem* tailIn = atomic_load(&(qIn->head)); + +// while (1) +// { +// void* payload = atomic_load(&(tailIn->payload)); +// if(payload == NULL) +// { +// my_sleep(100); +// continue; +// } +// int* code = payload; + +// printf(">Done reading %d\n", *code); + + +// int* pass = malloc(sizeof(int)); +// if(pass != NULL) +// { +// *pass = *code; +// ptQueuePush(qOut, pass, errubf); +// } + +// if(*code == 0) +// { +// free(payload); +// break; +// } +// free(payload); +// ptQueueElem* newTail = atomic_load(&(tailIn->nextEl)); +// if (newTail == NULL) +// { +// abort(); +// } +// free(tailIn); +// tailIn = newTail; + +// } + +// for(int i = 4096; i >= 0; i--) +// { +// int* pass = malloc(sizeof(int)); +// if(pass == NULL) +// { +// continue; +// } +// *pass = i; +// ptQueuePush(qOut, pass, errubf); +// } + +// pthread_exit(0); +// } + +// int _main(int argc, char** argv) +// { +// char errbuf[4096] = {0}; +// compose_dev_conf_t* devConf = openComposeDeviceConfig("/home/nikto_b/Documents/baum/hmmmm/glob.toml", errbuf); +// if(devConf == NULL) +// { +// printf("Err: %s\n", errbuf); +// return 1; +// } + +// device_handle_t** devices = openComposeDevice(devConf, errbuf); +// if(devices == NULL) +// { +// printf("Err: %s\n", errbuf); +// return 1; +// } + +// uint8_t failed = 0; + + +// if(devices[0] != NULL) +// { +// uint64_t readSpecsCount = 0; +// uint64_t writeSpecsCount = 0x20; + +// smart_read_spec_t* readSpecs = malloc(sizeof(smart_read_spec_t) * readSpecsCount); +// smart_write_spec_t* writeSpecs = malloc(sizeof(smart_write_spec_t) * writeSpecsCount); + +// if (writeSpecs == NULL && writeSpecsCount != 0) +// { +// return 1; +// } +// if (readSpecs == NULL && readSpecsCount != 0) +// { +// return 1; +// } + +// for (size_t i = 0; i < writeSpecsCount; i++) +// { +// writeSpecs[i].addr = 0; +// writeSpecs[i].segno = 2; +// writeSpecs[i].ident = 0; +// writeSpecs[i].localAddr = i; +// writeSpecs[i].addrType = SMART_ADDR_TYPE_SEGMENTED; +// writeSpecs[i].handler = dummyWriteHandler; +// } + +// devices[0]->lib->fillSmartReadSpecs(devices[0]->specs, readSpecs, readSpecsCount); +// devices[0]->lib->fillSmartWriteSpecs(devices[0]->specs, writeSpecs, writeSpecsCount); +// } + + +// size_t devIdx = 0; +// while(devices[devIdx] != NULL) +// { +// device_handle_t* dev = devices[devIdx]; +// dev->ctx = dev->lib->init(dev->specs, errbuf); + +// if(dev->ctx == NULL) +// { +// printf("Unable to init device %lu: %s\n", devIdx, errbuf); +// memset(errbuf, 0, strlen(errbuf)); +// failed = 1; +// } +// devIdx++; +// } + +// if(failed) +// { +// for(size_t i = 0; i < devIdx; i++) +// { +// closeBaseDevice(devices[i]); +// } +// free(devices); +// return 1; +// } + +// size_t projectIdx = 0; +// // while(devConf->projections[projectIdx] != NULL) +// // { +// // projection_conf_t* projection = devConf->projections[projectIdx]; + +// // size_t foundBaseDevId = (size_t)~0; + +// // for(size_t i = 0; i < devIdx; i++) +// // { +// // conf_dev_t* cnf = devConf->baseConfigs[i]; +// // if(compareComposeId(cnf->id, projection->baseAt)) +// // { +// // foundBaseDevId = i; +// // break; +// // } +// // } + +// // if(foundBaseDevId == (size_t)~0) +// // { +// // printf("Unable to find projection base: "); +// // for(size_t i = 0; projection->baseAt[i] != NULL; i++) +// // { +// // printf("->%s", projection->baseAt[i]); +// // } +// // printf("\n"); +// // return 1; +// // } + +// // size_t foundTargetDevId = (size_t)~0; + +// // for(size_t i = 0; i < devIdx; i++) +// // { +// // conf_dev_t* cnf = devConf->baseConfigs[i]; +// // if(compareComposeId(cnf->id, projection->target + 1)) +// // { +// // foundTargetDevId = i; +// // break; +// // } +// // } + +// // if(foundTargetDevId == (size_t)~0) +// // { +// // printf("Unable to find projection target: "); +// // for(size_t i = 0; projection->target[i] != NULL; i++) +// // { +// // printf("->%s", projection->target[i]); +// // } +// // printf("\n"); +// // return 1; +// // } + +// // uint16_t baseDevMemSpecCount = 0; +// // while(devConf->baseConfigs[foundBaseDevId]->memConf->memSegConfs[baseDevMemSpecCount] != NULL){baseDevMemSpecCount++;} + +// // uint16_t foundBaseSegno = (uint16_t)~0; + +// // for(uint16_t i = 0; i < baseDevMemSpecCount; i++) +// // { +// // if(strcmp(devices[foundBaseDevId]->ctx->deviceMem->memsegNames[i], projection->baseSeg) == 0) +// // { +// // foundBaseSegno = i; +// // break; +// // } +// // } + +// // if(foundBaseSegno == (uint16_t)~0) +// // { +// // printf("Unable to find projection segment %s for base: ", projection->baseSeg); +// // for(size_t i = 0; projection->baseAt[i] != NULL; i++) +// // { +// // printf("->%s", projection->baseAt[i]); +// // } +// // printf("\n"); +// // return 1; +// // } + +// // uint16_t targetDevMemSpecCount = 0; +// // while(devConf->baseConfigs[foundTargetDevId]->memConf->memSegConfs[targetDevMemSpecCount] != NULL){targetDevMemSpecCount++;} + +// // uint16_t foundTargetSegno = (uint16_t)~0; + +// // for(uint16_t i = 0; i < targetDevMemSpecCount; i++) +// // { +// // if(strcmp(devices[foundTargetDevId]->ctx->deviceMem->memsegNames[i], projection->target[0]) == 0) +// // { +// // foundTargetSegno = i; +// // break; +// // } +// // } + +// // if(foundTargetSegno == (uint16_t)~0) +// // { +// // printf("Unable to find projection segment for target: "); +// // for(size_t i = 0; projection->target[i] != NULL; i++) +// // { +// // printf("->%s", projection->target[i]); +// // } +// // printf("\n"); +// // return 1; +// // } + + +// // void* foundBaseAt = devices[foundBaseDevId]->ctx->deviceMem->cells[foundBaseSegno]; + +// // foundBaseAt += projection->projectionShift; + +// // devices[foundTargetDevId]->ctx->deviceMem->cells[foundTargetSegno] = foundBaseAt; + + +// // projectIdx++; +// // } + +// FILE *fp = fopen ("/home/nikto_b/Documents/baum/avr_selftests/test.bin", "rb"); +// if (!fp) { +// fprintf (stderr, "error: file open failed.\n"); +// return 1; +// } + +// #define BUFSZ 1 + +// uint8_t buf[BUFSZ] = {0}; +// size_t bytes = 0, i, readsz = sizeof(buf); + +// size_t addr = 0; +// while ((bytes = fread(buf, sizeof(*buf), readsz, fp)) == readsz) +// { +// for (i = 0; i < readsz; i++) +// { +// ((uint8_t*)(devices[0]->ctx->deviceMem->rawCells))[addr] = buf[i]; +// addr += 1; +// } +// } + +// fclose(fp); + + +// // uint64_t ticks_limiter = 16 * 1000 * 1000 * 100; +// // uint64_t ticks_limiter = 40; +// uint64_t cycles_limiter = 18; +// uint64_t ticks = 0; +// uint64_t cycles = 0; + +// // instruction_simul_handlers_t* instr_handl = (instruction_simul_handlers_t*)dev->lib->extendedHandlers; + +// // uint16_t* pcounter = (uint16_t*)instr_handl->extractPcounterPtr(dev->ctx); + + +// struct timeval start; +// gettimeofday(&start, NULL); + +// // uint16_t prevOp = 0; +// // uint16_t opStrikeCount = 0; + +// printf("Init sequence done\n"); + +// while (cycles < cycles_limiter) +// { +// for(size_t i = 0; i < 1; i++) +// { +// device_handle_t* dev = devices[i]; +// dev->ctx->deviceMem->memreadLen = 0; +// dev->ctx->deviceMem->memwriteLen = 0; + +// // uint16_t op = ((uint16_t*)(devInfo->deviceMem->cells[0]))[*(pcounter)]; +// // if (op != prevOp) +// // { +// // opStrikeCount = 0; +// // } +// // else +// // { +// // opStrikeCount++; +// // if(opStrikeCount > 0xFFF) +// // { +// // printf("Found endless loop\n"); +// // break; +// // } +// // } +// // prevOp = op; +// // printf("Executing at 0x%04X: 0x%04X\n", (*(pcounter)), op); + +// ticks += dev->lib->makeDeviceTick(dev->ctx); +// // ticks += makeDeviceTick(devInfo); + +// } + +// cycles += 1; + + +// // for (size_t i = 0; i < devInfo->deviceMem->memwriteLen; i++) +// // { +// // printf("Got write [0x%04zuX] at 0x%04lX\n", i, devInfo->deviceMem->memwriteCellAddrs[i]); +// // } +// } +// struct timeval end; + +// gettimeofday(&end, NULL); + +// long seconds = end.tv_sec - start.tv_sec; +// long microseconds = end.tv_usec - start.tv_usec; + +// long long total_microseconds = seconds * 1000000 + microseconds; +// // double rate = 0; +// // if (total_microseconds > 0) +// // { +// // rate = ((double)total_microseconds) / ((double)cycles); +// // } + + + + +// // fflush(stdout); +// // printf("Rate: %f us/cycle (%f clock/us)\n", rate, ((double)ticks) / ((double)total_microseconds)); + + + +// printf("Execution consumed %lu ticks, %lu iterations and %llu us\n", ticks, cycles, total_microseconds); + + + +// return 0; +// } + +// int main(int argc, char** argv) +// { + +// char errbuf[4096];+ + +// device_handle_t* dev = openBaseDevice("/home/nikto_b/Documents/baum/hmmmm/devices/avr_generic/AVRrc.toml", errbuf); +// if (dev == NULL) +// { +// printf("Unable to open device: %s\n", errbuf); +// return 1; +// } + +// uint64_t readSpecsCount = 0; +// uint64_t writeSpecsCount = 0x20; + +// smart_read_spec_t* readSpecs = malloc(sizeof(smart_read_spec_t) * readSpecsCount); +// smart_write_spec_t* writeSpecs = malloc(sizeof(smart_write_spec_t) * writeSpecsCount); + +// if (writeSpecs == NULL && writeSpecsCount != 0) +// { +// return 1; +// } +// if (readSpecs == NULL && readSpecsCount != 0) +// { +// return 1; +// } + +// for (size_t i = 0; i < writeSpecsCount; i++) +// { +// writeSpecs[i].addr = 0; +// writeSpecs[i].segno = 2; +// writeSpecs[i].localAddr = i; +// writeSpecs[i].addrType = SMART_ADDR_TYPE_SEGMENTED; +// writeSpecs[i].handler = dummyWriteHandler; +// } + +// dev->lib->fillSmartReadSpecs(dev->specs, readSpecs, readSpecsCount); +// dev->lib->fillSmartWriteSpecs(dev->specs, writeSpecs, writeSpecsCount); + + +// dev->ctx = dev->lib->init(dev->specs, errbuf); + +// if (dev->ctx == NULL) +// { +// printf("Unable to init device: %s\n", errbuf); +// return 1; +// } + + +// FILE *fp = fopen ("/home/nikto_b/Documents/baum/avr_selftests/test.bin", "rb"); +// if (!fp) { +// fprintf (stderr, "error: file open failed.\n"); +// return 1; +// } + +// #define BUFSZ 1 + +// uint8_t buf[BUFSZ] = {0}; +// size_t bytes = 0, i, readsz = sizeof(buf); + +// size_t addr = 0; +// while ((bytes = fread(buf, sizeof(*buf), readsz, fp)) == readsz) +// { +// for (i = 0; i < readsz; i++) +// { +// ((uint8_t*)(dev->ctx->deviceMem->rawCells))[addr] = buf[i]; +// addr += 1; +// } +// } + +// fclose(fp); + +// printf("Done writing %zu bytes from dump file\n", addr); + + + +// uint64_t ticks_limiter = 16 * 1000 * 1000 * 100; +// // uint64_t ticks_limiter = 64; +// uint64_t ticks = 0; +// uint64_t cycles = 0; + +// instruction_simul_handlers_t* instr_handl = (instruction_simul_handlers_t*)dev->lib->extendedHandlers; + +// uint16_t* pcounter = (uint16_t*)instr_handl->extractPcounterPtr(dev->ctx); + + +// struct timeval start; +// gettimeofday(&start, NULL); + +// // uint16_t prevOp = 0; +// // uint16_t opStrikeCount = 0; + +// while (ticks < ticks_limiter) +// { +// dev->ctx->deviceMem->memreadLen = 0; +// dev->ctx->deviceMem->memwriteLen = 0; + +// // uint16_t op = ((uint16_t*)(devInfo->deviceMem->cells[0]))[*(pcounter)]; +// // if (op != prevOp) +// // { +// // opStrikeCount = 0; +// // } +// // else +// // { +// // opStrikeCount++; +// // if(opStrikeCount > 0xFFF) +// // { +// // printf("Found endless loop\n"); +// // break; +// // } +// // } +// // prevOp = op; +// // printf("Executing at 0x%04X: 0x%04X\n", (*(pcounter)), op); + +// ticks += dev->lib->makeDeviceTick(dev->ctx); +// // ticks += makeDeviceTick(devInfo); + + +// cycles += 1; + + +// // for (size_t i = 0; i < devInfo->deviceMem->memwriteLen; i++) +// // { +// // printf("Got write [0x%04zuX] at 0x%04lX\n", i, devInfo->deviceMem->memwriteCellAddrs[i]); +// // } +// } +// struct timeval end; + +// gettimeofday(&end, NULL); + +// long seconds = end.tv_sec - start.tv_sec; +// long microseconds = end.tv_usec - start.tv_usec; + +// long long total_microseconds = seconds * 1000000 + microseconds; +// // double rate = 0; +// // if (total_microseconds > 0) +// // { +// // rate = ((double)total_microseconds) / ((double)cycles); +// // } + + + + +// // fflush(stdout); +// // printf("Rate: %f us/cycle (%f clock/us)\n", rate, ((double)ticks) / ((double)total_microseconds)); + + + +// printf("Execution consumed %lu ticks, %lu cycles and %llu us\n", ticks, cycles, total_microseconds); + +// printf("general purpose registers:\n"); +// // printMemory(devInfo->deviceMem->cells[1], 32); + + +// // printf("SREG: 0x%016X\n", ((io_reg_cell_t*)devInfo->deviceMem->cells[2])[0x3F]); + +// // char* buf = foo(); +// // if (buf == NULL) { +// // return 1; +// // } +// // for (uint8_t i = 0; i < 32; i++) { +// // printf("%c", buf[i]); +// // } + +// // printf("\n"); + + +// // dlclose(handle); + +// return 0; +// }