Initial commit

This commit is contained in:
2025-01-21 22:03:23 +03:00
commit 2ff6b1a454
21 changed files with 2541 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.vscode
compile_commands.json
out
.ccls-cache
.*.sh
build
devices
.cache
*.bin

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "hmmmm_scripts"]
path = hmmmm_scripts
url = git@192.168.8.167:nikto_b/hmmmm_scripts.git

89
Makefile Normal file
View File

@@ -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)"

3
clean_build.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
make clean
make build

4
deps/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
tomlc99
ptQueue
tomlc99
wsServer

27
deps/Makefile vendored Normal file
View File

@@ -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

60
glob.toml Normal file
View File

@@ -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, диаграмма с тестовым перехватчиком)
# - реализация проецирования памяти (диаграммы с колбасами)
# - тестовая прошивка (селфтест сложения-вычитания)
# - пример исполнения (?)

1
hmmmm_scripts Submodule

Submodule hmmmm_scripts added at 9cc7b36cbb

21
inc/base_device.h Normal file
View File

@@ -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__

41
inc/compose_device.h Normal file
View File

@@ -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__

36
inc/config.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef __HMMMM_CONFIG_H__
#define __HMMMM_CONFIG_H__
#include <unistd.h>
#include <stdint.h>
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__

33
inc/hmmmm.h Normal file
View File

@@ -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__

37
inc/libdevice.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef __LIBDEVICE_H__
#define __LIBDEVICE_H__
#include <stdint.h>
#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__

14
inc/libhmmmm.h Normal file
View File

@@ -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__

52
inc/libmem.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef __LIBMEM_H__
#define __LIBMEM_H__
#include <stdint.h>
#include <stdlib.h>
#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__

22
inc/my_mutex.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef __MY_MUTEX_H__
#define __MY_MUTEX_H__
#include <pthread.h>
/**
* Макрос для 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__

276
src/base_device.c Normal file
View File

@@ -0,0 +1,276 @@
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#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;
}

529
src/compose_device.c Normal file
View File

@@ -0,0 +1,529 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

86
src/config.c Normal file
View File

@@ -0,0 +1,86 @@
#include <stdlib.h>
#include <string.h>
#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);
}

238
src/hmmmm.c Normal file
View File

@@ -0,0 +1,238 @@
#include "hmmmm.h"
#include <dlfcn.h>
#include <stdio.h>
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;
}

960
src/main.c Normal file
View File

@@ -0,0 +1,960 @@
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdatomic.h>
#include <pthread.h>
// #define OPCODE_WORDSIZE 2
// #define MEM_CELL_WORDS 1
// #include "abc.h"
// #include "instr.h"
// #include "mem.h"
// #include "runner.h"
#include <dlfcn.h>
// #include "runner.h"
#include "hmmmm.h"
#include "my_mutex.h"
#include "tomlc99/toml.h"
#include <string.h>
#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 <unistd.h>
#include <sys/types.h>
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("<Done reading %d\n", *code);
// int* pass = malloc(sizeof(int));
// if(pass != NULL)
// {
// *pass = *code;
// ptQueuePush(qOut, pass, errbuf);
// }
// if(*code == 0)
// {
// free(payload);
// break;
// }
// free(payload);
// ptQueueElem* newTail = atomic_load(&(tailIn->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;
// }