Initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.vscode
|
||||||
|
.ccls-cache
|
||||||
|
out
|
||||||
|
compile_commands.json
|
||||||
79
Makefile
Normal file
79
Makefile
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
INCLUDES=-Iinc -I.
|
||||||
|
|
||||||
|
# BUILD_DIR=out
|
||||||
|
|
||||||
|
ifeq ($(BUILD_DIR),)
|
||||||
|
BUILD_DIR := out
|
||||||
|
endif
|
||||||
|
|
||||||
|
SRC_DIR=src
|
||||||
|
INC_DIR=inc
|
||||||
|
CC=gcc
|
||||||
|
OBJDUMP=objdump
|
||||||
|
LIBS=
|
||||||
|
STANDART=c23
|
||||||
|
OPTIMIZE=-Og
|
||||||
|
TARGET=device
|
||||||
|
|
||||||
|
|
||||||
|
DEFINES=-DOPCODE_WORDSIZE=2 -DMEM_CELL_WORDS=1 -DPC_WORDSIZE=3 -DGP_REG_CELL_WORDS=1 -DIO_REG_CELL_WORDS=1 -DARCH=$(ARCH)
|
||||||
|
|
||||||
|
C_SOURCES=$(wildcard $(SRC_DIR)/*.c)
|
||||||
|
C_HEADERS=$(wildcard $(INC_DIR)/*.h)
|
||||||
|
|
||||||
|
C_INCLUDES=-I$(INC_DIR)/
|
||||||
|
|
||||||
|
DISABLE_FLAGS=-Wno-unused-variable -Wno-unused-parameter -Wno-write-strings -Wno-pointer-arith -Wno-analyzer-use-of-uninitialized-value
|
||||||
|
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
|
||||||
|
LSECTIONS=-ffunction-sections -fdata-sections -Wl,--gc-sections
|
||||||
|
CFLAGS=$(C_DEFS) -g $(C_INCLUDES) $(DEFINES) $(OPTIMIZE) --std=$(STANDART) $(PEDANTIC_FLAGS) $(ANALYZER_FLAGS) -fPIC
|
||||||
|
LFLAGS=$(OPTIMIZE) -g $(PEDANTIC_FLAGS) $(DEFINES) -flto -fuse-linker-plugin $(LSECTIONS) -lm $(LIBS) -fPIC -shared
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
|
||||||
|
vpath %.c $(sort $(dir $(C_SOURCES)))
|
||||||
|
vpath %.h $(sort $(dir $(C_HEADERS)))
|
||||||
|
|
||||||
|
rebuild: clean | build
|
||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
build: date Dir $(C_HEADERS) target
|
||||||
|
|
||||||
|
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
|
||||||
|
@echo -e '\033[1;32mCC ('$(ARCH)')\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).so
|
||||||
|
|
||||||
|
$(BUILD_DIR)/$(TARGET).so: $(OBJECTS)
|
||||||
|
@echo -e '\033[1;32mELF ('$(ARCH)')\t'$(OBJECTS)'\n\t\t\t->\t'$@'\033[0m'
|
||||||
|
@$(CC) $(LFLAGS) $(OBJECTS) -o $(BUILD_DIR)/$(TARGET).so
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BuildDir:
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
SrcDir:
|
||||||
|
@mkdir -p $(SRC_DIR)
|
||||||
|
|
||||||
|
IncDir:
|
||||||
|
@mkdir -p $(INC_DIR)
|
||||||
|
|
||||||
|
Dir: BuildDir SrcDir IncDir
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
@rm -rf $(BUILD_DIR)/*
|
||||||
|
@echo -e '\033[0;31mCleaned\033[0m'
|
||||||
|
|
||||||
|
.NOTPARALLEL: date target rebuild
|
||||||
|
date:
|
||||||
|
@echo -e '\033[1;32m'"Starting build at " | tr -d '\n'
|
||||||
|
@date
|
||||||
|
@echo -e '\033[0m'
|
||||||
|
|
||||||
23
config.toml
Normal file
23
config.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[dev]
|
||||||
|
libpath = "out/device.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[mem.ext_reg_io]
|
||||||
|
start = 0
|
||||||
|
len = 255
|
||||||
|
wordLen = 1
|
||||||
|
|
||||||
|
[mem.extstate]
|
||||||
|
start = 256
|
||||||
|
len = 1
|
||||||
|
wordLen = 1
|
||||||
|
|
||||||
|
[mem.variables]
|
||||||
|
PIN = 0
|
||||||
|
PORT = 1
|
||||||
|
DDR = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
7
inc/addrs.h
Normal file
7
inc/addrs.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef __ADDRS_H__
|
||||||
|
#define __ADDRS_H__
|
||||||
|
|
||||||
|
#define MEMDATA_IO_REGS 0
|
||||||
|
#define MEMDATA_EXTSTATE 1
|
||||||
|
|
||||||
|
#endif // ifndef __ADDRS_H__
|
||||||
52
inc/device.h
Normal file
52
inc/device.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef __DEVICE_H__
|
||||||
|
#define __DEVICE_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "runner.h"
|
||||||
|
#include "addrs.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "../../../inc/config.h"
|
||||||
|
#include "../../../inc/libhmmmm.h"
|
||||||
|
#include "../../../inc/libdevice.h"
|
||||||
|
|
||||||
|
#define SMART_ADDR_TYPE_GLOBAL 1
|
||||||
|
#define SMART_ADDR_TYPE_SEGMENTED 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
memseg_spec_t** memSpecs;
|
||||||
|
uint8_t memSpecsCount;
|
||||||
|
uint64_t pcAddr;
|
||||||
|
uint8_t* executableSegments;
|
||||||
|
uint8_t executableSegmentsCount;
|
||||||
|
smart_read_spec_t* smartReadSpecs;
|
||||||
|
uint64_t smartReadSpecsCount;
|
||||||
|
smart_write_spec_t* smartWriteSpecs;
|
||||||
|
uint64_t smartWriteSpecsCount;
|
||||||
|
} device_specs_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
device_mem_t* deviceMem;
|
||||||
|
device_specs_t* specs;
|
||||||
|
} device_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// device_public_context_t* init(device_specs_t* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount);
|
||||||
|
device_public_context_t* init(device_specs_t* specs, char* errbuf);
|
||||||
|
device_public_context_t* initDefault(smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount, char* errbuf);
|
||||||
|
uint8_t makeDeviceTick(device_public_context_t* devContext);
|
||||||
|
|
||||||
|
device_mem_t* genDevMem(device_specs_t* devSpec, char* errbuf);
|
||||||
|
|
||||||
|
device_specs_t* parseSpecsFromConfig(const conf_dev_t* devConf, char* errbuf);
|
||||||
|
void fillSmartReadSpecs(device_specs_t* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount);
|
||||||
|
void fillSmartWriteSpecs(device_specs_t* specs, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount);
|
||||||
|
void freeDevSpec(void* specs);
|
||||||
|
void freeDevMem(device_mem_t* devMem);
|
||||||
|
|
||||||
|
#endif // ifndef __DEVICE_H__
|
||||||
|
|
||||||
61
inc/mem.h
Normal file
61
inc/mem.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef __MEM_H__
|
||||||
|
#define __MEM_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../../../inc/libhmmmm.h"
|
||||||
|
|
||||||
|
#ifndef RAM_CELL_WORDS
|
||||||
|
#define RAM_CELL_WORDS 1
|
||||||
|
#endif
|
||||||
|
#if RAM_CELL_WORDS == 1
|
||||||
|
typedef uint8_t ram_cell_t;
|
||||||
|
#endif
|
||||||
|
#if RAM_CELL_WORDS == 2
|
||||||
|
typedef uint16_t ram_cell_t;
|
||||||
|
#endif
|
||||||
|
#if RAM_CELL_WORDS == 3
|
||||||
|
typedef uint32_t ram_cell_t;
|
||||||
|
#endif
|
||||||
|
#if RAM_CELL_WORDS == 4
|
||||||
|
typedef uint32_t ram_cell_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GP_REG_CELL_WORDS
|
||||||
|
#define GP_REG_CELL_WORDS 1
|
||||||
|
#endif
|
||||||
|
#if GP_REG_CELL_WORDS == 1
|
||||||
|
typedef uint8_t gp_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if GP_REG_CELL_WORDS == 2
|
||||||
|
typedef uint16_t gp_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if GP_REG_CELL_WORDS == 3
|
||||||
|
typedef uint32_t gp_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if GP_REG_CELL_WORDS == 4
|
||||||
|
typedef uint32_t gp_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IO_REG_CELL_WORDS
|
||||||
|
#define IO_REG_CELL_WORDS 1
|
||||||
|
#endif
|
||||||
|
#if IO_REG_CELL_WORDS == 1
|
||||||
|
typedef uint8_t io_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if IO_REG_CELL_WORDS == 2
|
||||||
|
typedef uint16_t io_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if IO_REG_CELL_WORDS == 3
|
||||||
|
typedef uint32_t io_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
#if IO_REG_CELL_WORDS == 4
|
||||||
|
typedef uint32_t io_reg_cell_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void* default_addr_read_handler(uint64_t ident, uint64_t addr, void* rawCells);
|
||||||
|
void default_addr_write_handler(uint64_t ident, uint64_t addr, void* rawCells, void* data);
|
||||||
|
|
||||||
|
#endif // ifndef __MEM_H__
|
||||||
10
inc/runner.h
Normal file
10
inc/runner.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __RUNNER_H__
|
||||||
|
#define __RUNNER_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
uint8_t makeTick(device_mem_t* devMem);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ifndef __RUNNER_H__
|
||||||
693
src/device.c
Normal file
693
src/device.c
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "runner.h"
|
||||||
|
#include "addrs.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t memSegToGlobal(device_specs_t* spec, uint8_t seg, uint64_t localaddr)
|
||||||
|
{
|
||||||
|
uint64_t offset = 0;
|
||||||
|
for (uint8_t i = 0; i < seg; i++)
|
||||||
|
{
|
||||||
|
offset += spec->memSpecs[i]->len * spec->memSpecs[i]->wordLen;
|
||||||
|
}
|
||||||
|
return offset + localaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void freeDevMem(device_mem_t* devMem)
|
||||||
|
{
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem->rawCells);
|
||||||
|
free(devMem->memreadCellAddrs);
|
||||||
|
free(devMem->memwriteCellAddrs);
|
||||||
|
free(devMem->cells);
|
||||||
|
free(devMem->smartAddrReadHandlers);
|
||||||
|
free(devMem->smartAddrWriteHandlers);
|
||||||
|
free(devMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeDevSpec(void* _specs)
|
||||||
|
{
|
||||||
|
device_specs_t* specs = _specs;
|
||||||
|
for (uint8_t i = 0; i < specs->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[i]);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_mem_t* genDevMem(device_specs_t* devSpec, char* errbuf)
|
||||||
|
{
|
||||||
|
if (devSpec->memSpecsCount < 2)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "invalid amount of mem specs: %u", devSpec->memSpecsCount);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_mem_t* devMem = (device_mem_t*)malloc(sizeof(device_mem_t));
|
||||||
|
if (devMem == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate dev memory struct");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t memTotalSize = 0;
|
||||||
|
for (uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
size_t tmp = devSpec->memSpecs[i]->start + devSpec->memSpecs[i]->len * devSpec->memSpecs[i]->wordLen;
|
||||||
|
if (memTotalSize < tmp)
|
||||||
|
{
|
||||||
|
memTotalSize = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* rawCells = (void*)malloc(memTotalSize);
|
||||||
|
if (rawCells == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate raw memory buf");
|
||||||
|
free(devMem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < memTotalSize; i++)
|
||||||
|
{
|
||||||
|
((uint8_t*)rawCells)[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
devMem->memsegShifts = malloc(devSpec->memSpecsCount * sizeof(uint64_t));
|
||||||
|
|
||||||
|
if(devMem->memsegShifts == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate segment shift buffers");
|
||||||
|
free(rawCells);
|
||||||
|
free(devMem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void** cells = malloc(devSpec->memSpecsCount * sizeof(void*));
|
||||||
|
|
||||||
|
if (cells == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate segment pointers");
|
||||||
|
free(rawCells);
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
cells[i] = rawCells + devSpec->memSpecs[i]->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
char** cellNames = malloc(sizeof(char*) * devSpec->memSpecsCount);
|
||||||
|
|
||||||
|
if(cellNames == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate segment names map");
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
free(rawCells);
|
||||||
|
free(cells);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
cellNames[i] = devSpec->memSpecs[i]->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* memreadCellAddrs = malloc(64 * sizeof(uint64_t));
|
||||||
|
if (memreadCellAddrs == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate read interception addrs");
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
free(rawCells);
|
||||||
|
free(cells);
|
||||||
|
free(cellNames);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint64_t* memwriteCellAddrs = malloc(64 * sizeof(uint64_t));
|
||||||
|
|
||||||
|
if (memwriteCellAddrs == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate write interception addrs");
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
free(rawCells);
|
||||||
|
free(memreadCellAddrs);
|
||||||
|
free(cells);
|
||||||
|
free(cellNames);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t smartAddrReadMask = 0;
|
||||||
|
uint64_t smartAddrWriteMask = 0;
|
||||||
|
mem_h_read_handler* smartAddrReadHandlers = malloc(sizeof(mem_h_read_handler) * memTotalSize);
|
||||||
|
|
||||||
|
|
||||||
|
if (smartAddrReadHandlers == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate read interception handlers");
|
||||||
|
free(memwriteCellAddrs);
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
free(rawCells);
|
||||||
|
free(memreadCellAddrs);
|
||||||
|
free(cells);
|
||||||
|
free(cellNames);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_h_write_handler* smartAddrWriteHandlers = malloc(sizeof(mem_h_write_handler) * memTotalSize);
|
||||||
|
|
||||||
|
|
||||||
|
if (smartAddrWriteHandlers == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate write interception handlers");
|
||||||
|
free(smartAddrReadHandlers);
|
||||||
|
free(memwriteCellAddrs);
|
||||||
|
free(devMem->memsegShifts);
|
||||||
|
free(devMem);
|
||||||
|
free(rawCells);
|
||||||
|
free(memreadCellAddrs);
|
||||||
|
free(cells);
|
||||||
|
free(cellNames);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(uint64_t i = 0; i < memTotalSize; i++)
|
||||||
|
{
|
||||||
|
smartAddrReadHandlers[i].func = default_addr_read_handler;
|
||||||
|
smartAddrReadHandlers[i].ident = 0;
|
||||||
|
|
||||||
|
smartAddrWriteHandlers[i].func = default_addr_write_handler;
|
||||||
|
smartAddrWriteHandlers[i].ident = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(uint64_t i = 0; i < memTotalSize; i++)
|
||||||
|
{
|
||||||
|
if((i & smartAddrReadMask) == smartAddrReadMask)
|
||||||
|
{
|
||||||
|
smartAddrReadHandlers[i].func = default_addr_read_handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (devSpec->smartReadSpecsCount > 0)
|
||||||
|
{
|
||||||
|
for(uint64_t i = 0; i < devSpec->smartReadSpecsCount; i++)
|
||||||
|
{
|
||||||
|
smart_read_spec_t t = devSpec->smartReadSpecs[i];
|
||||||
|
uint64_t addr;
|
||||||
|
if (t.addrType == SMART_ADDR_TYPE_GLOBAL)
|
||||||
|
{
|
||||||
|
addr = t.addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = memSegToGlobal(devSpec, t.segno, t.localAddr);
|
||||||
|
}
|
||||||
|
smartAddrReadHandlers[addr].func = *t.handler;
|
||||||
|
smartAddrReadHandlers[addr].ident = t.ident;
|
||||||
|
smartAddrReadMask |= addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (devSpec->smartWriteSpecsCount > 0)
|
||||||
|
{
|
||||||
|
for(uint64_t i = 0; i < devSpec->smartWriteSpecsCount; i++)
|
||||||
|
{
|
||||||
|
smart_write_spec_t t = devSpec->smartWriteSpecs[i];
|
||||||
|
|
||||||
|
uint64_t addr;
|
||||||
|
if (t.addrType == SMART_ADDR_TYPE_GLOBAL)
|
||||||
|
{
|
||||||
|
addr = t.addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = memSegToGlobal(devSpec, t.segno, t.localAddr);
|
||||||
|
}
|
||||||
|
smartAddrWriteHandlers[addr].func = *t.handler;
|
||||||
|
smartAddrWriteHandlers[addr].ident = t.ident;
|
||||||
|
smartAddrWriteMask |= t.addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
devMem->cells = cells;
|
||||||
|
devMem->rawCells = rawCells;
|
||||||
|
devMem->memreadCellAddrs = memreadCellAddrs;
|
||||||
|
devMem->memwriteCellAddrs = memwriteCellAddrs;
|
||||||
|
devMem->memreadLen = 0;
|
||||||
|
devMem->memwriteLen = 0;
|
||||||
|
devMem->smartAddrReadMask = smartAddrReadMask;
|
||||||
|
devMem->smartAddrReadHandlers = smartAddrReadHandlers;
|
||||||
|
devMem->smartAddrWriteMask = smartAddrWriteMask;
|
||||||
|
devMem->smartAddrWriteHandlers = smartAddrWriteHandlers;
|
||||||
|
devMem->memsegNames = cellNames;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < devSpec->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
devMem->memsegShifts[i] = memSegToGlobal(devSpec, i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return devMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t makeDeviceTick(device_public_context_t* devContext)
|
||||||
|
{
|
||||||
|
device_info_t* devInfo = (device_info_t*)devContext->deviceInfo;
|
||||||
|
return makeTick(devInfo->deviceMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_info_t* initSpecs(device_specs_t* specs, char* errbuf)
|
||||||
|
{
|
||||||
|
device_info_t* devInfo = malloc(sizeof(device_info_t));
|
||||||
|
if (devInfo == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate dev info");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char genErrBuf[200];
|
||||||
|
device_mem_t* devMem = genDevMem(specs, genErrBuf);
|
||||||
|
|
||||||
|
if (devMem == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to generate device memory: %s", genErrBuf);
|
||||||
|
free(devInfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
devInfo->specs = specs;
|
||||||
|
devInfo->deviceMem = devMem;
|
||||||
|
|
||||||
|
return devInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void error(const char* err, char* errbuf)
|
||||||
|
{
|
||||||
|
strcpy(errbuf, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_specs_t* parseSpecsFromConfig(const conf_dev_t* devConf, char* errbuf)
|
||||||
|
{
|
||||||
|
conf_mem_seg_t** segments = devConf->memConf->memSegConfs;
|
||||||
|
device_specs_t* specs = malloc(sizeof(device_specs_t));
|
||||||
|
if (specs == NULL)
|
||||||
|
{
|
||||||
|
error("unable to allocate mem specs struct", errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint8_t specCount = 0;
|
||||||
|
specs->executableSegmentsCount = 0;
|
||||||
|
|
||||||
|
while (segments[specCount] != NULL)
|
||||||
|
{
|
||||||
|
if(segments[specCount]->isExecutable)
|
||||||
|
{
|
||||||
|
specs->executableSegmentsCount++;
|
||||||
|
}
|
||||||
|
specCount++;
|
||||||
|
}
|
||||||
|
specs->memSpecsCount = specCount;
|
||||||
|
|
||||||
|
specs->memSpecs = malloc(specCount * sizeof(memseg_spec_t*));
|
||||||
|
if (specs->memSpecs == NULL)
|
||||||
|
{
|
||||||
|
free(specs);
|
||||||
|
error("unable to allocate mem segment specs", errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
specs->executableSegments = malloc(sizeof(uint8_t) * specs->executableSegmentsCount);
|
||||||
|
if (specs->executableSegments == NULL)
|
||||||
|
{
|
||||||
|
error("unable to allocate mem executable specs", errbuf);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < specCount; i++)
|
||||||
|
{
|
||||||
|
memseg_spec_t* spec = (memseg_spec_t*)malloc(sizeof(memseg_spec_t));
|
||||||
|
if (spec == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate spec %d", i);
|
||||||
|
|
||||||
|
for (uint8_t j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
spec->name = NULL;
|
||||||
|
|
||||||
|
specs->memSpecs[i] = spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t foundSegments = 0;
|
||||||
|
uint8_t executableSegmentsFound = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < specCount; i++)
|
||||||
|
{
|
||||||
|
uint8_t specNum = 0xFF;
|
||||||
|
if (strcmp(segments[i]->name, "ext_reg_io") == 0)
|
||||||
|
{
|
||||||
|
specNum = MEMDATA_IO_REGS;
|
||||||
|
}
|
||||||
|
else if (strcmp(segments[i]->name, "extstate") == 0)
|
||||||
|
{
|
||||||
|
specNum = MEMDATA_EXTSTATE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "invalid segment: %s", segments[i]->name);
|
||||||
|
for(size_t j = 0; j < specCount; j++)
|
||||||
|
{
|
||||||
|
if(specs->memSpecs[j]->name != NULL)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[j]->name);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
specs->memSpecs[specNum]->name = malloc(sizeof(char) * strlen(segments[i]->name));
|
||||||
|
if(specs->memSpecs[specNum]->name == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate spec %d name", i);
|
||||||
|
for(size_t j = 0; j < specCount; j++)
|
||||||
|
{
|
||||||
|
if(specs->memSpecs[j]->name != NULL)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[j]->name);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(specs->memSpecs[specNum]->name, segments[i]->name);
|
||||||
|
specs->memSpecs[specNum]->start = segments[i]->start;
|
||||||
|
specs->memSpecs[specNum]->len = segments[i]->len;
|
||||||
|
specs->memSpecs[specNum]->wordLen = segments[i]->wordLen;
|
||||||
|
if(segments[i]->isExecutable)
|
||||||
|
{
|
||||||
|
specs->executableSegments[executableSegmentsFound] = specNum;
|
||||||
|
executableSegmentsFound++;
|
||||||
|
}
|
||||||
|
foundSegments += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(executableSegmentsFound < specs->executableSegmentsCount)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "Not all executable segments found");
|
||||||
|
for(size_t j = 0; j < specCount; j++)
|
||||||
|
{
|
||||||
|
if(specs->memSpecs[j]->name != NULL)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[j]->name);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundSegments < 2)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "invalid amount of segments: must be 2");
|
||||||
|
for(size_t k = 0; k < specs->memSpecsCount; k++)
|
||||||
|
{
|
||||||
|
if(specs->memSpecs[k]->name != NULL)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[k]->name);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs[k]);
|
||||||
|
}
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeDevSpecs(device_specs_t* specs)
|
||||||
|
{
|
||||||
|
for(size_t k = 0; k < specs->memSpecsCount; k++)
|
||||||
|
{
|
||||||
|
if(specs->memSpecs[k]->name != NULL)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[k]->name);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs[k]);
|
||||||
|
}
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillSmartReadSpecs(device_specs_t* specs, smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount)
|
||||||
|
{
|
||||||
|
specs->smartReadSpecs = smartReadSpecs;
|
||||||
|
specs->smartReadSpecsCount = smartReadSpecsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillSmartWriteSpecs(device_specs_t* specs, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount)
|
||||||
|
{
|
||||||
|
specs->smartWriteSpecs = smartWriteSpecs;
|
||||||
|
specs->smartWriteSpecsCount = smartWriteSpecsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_public_context_t* initDefault(smart_read_spec_t* smartReadSpecs, uint64_t smartReadSpecsCount, smart_write_spec_t* smartWriteSpecs, uint64_t smartWriteSpecsCount, char* errbuf)
|
||||||
|
{
|
||||||
|
|
||||||
|
device_specs_t* specs = malloc(sizeof(device_specs_t));
|
||||||
|
if (specs == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
specs->memSpecsCount = 4;
|
||||||
|
specs->memSpecs = malloc(specs->memSpecsCount * sizeof(memseg_spec_t*));
|
||||||
|
if (specs->memSpecs == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate default mem segment specs");
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
specs->executableSegmentsCount = 1;
|
||||||
|
specs->executableSegments = malloc(sizeof(uint8_t) * 1);
|
||||||
|
if (specs->executableSegments == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate default executable segments");
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
specs->executableSegments[0] = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < specs->memSpecsCount; i++)
|
||||||
|
{
|
||||||
|
specs->memSpecs[i] = malloc(sizeof(memseg_spec_t));
|
||||||
|
if (specs->memSpecs[i] == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate default mem seg spec %u", i);
|
||||||
|
for (uint8_t j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
free(specs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
specs->smartReadSpecs = smartReadSpecs;
|
||||||
|
specs->smartReadSpecsCount = smartReadSpecsCount;
|
||||||
|
|
||||||
|
specs->smartWriteSpecs = smartWriteSpecs;
|
||||||
|
specs->smartWriteSpecsCount = smartWriteSpecsCount;
|
||||||
|
|
||||||
|
specs->memSpecs[0]->len = 255;
|
||||||
|
specs->memSpecs[0]->start = 0;
|
||||||
|
specs->memSpecs[0]->wordLen = 1;
|
||||||
|
|
||||||
|
specs->memSpecs[1]->len = 1;
|
||||||
|
specs->memSpecs[1]->start = 256;
|
||||||
|
specs->memSpecs[1]->wordLen = 1;
|
||||||
|
|
||||||
|
|
||||||
|
char initErrbuf[200];
|
||||||
|
device_public_context_t* ret = init(specs, initErrbuf);
|
||||||
|
|
||||||
|
if (ret == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to init default: %s", initErrbuf);
|
||||||
|
freeDevSpec(specs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
free(specs->memSpecs);
|
||||||
|
free(specs->executableSegments);
|
||||||
|
free(specs);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_public_context_t* init(device_specs_t* specs, char* errbuf)
|
||||||
|
{
|
||||||
|
if (specs->memSpecsCount >= 0xFF - 2)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "Too many mem specifications");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_specs_t* realSpecs = malloc(sizeof(device_specs_t));
|
||||||
|
if (realSpecs == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate spec struct");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t specCount = specs->memSpecsCount + 2;
|
||||||
|
realSpecs->memSpecsCount = specCount;
|
||||||
|
realSpecs->memSpecs = (memseg_spec_t**)malloc(realSpecs->memSpecsCount * sizeof(memseg_spec_t*));
|
||||||
|
if (realSpecs->memSpecs == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate mem specs");
|
||||||
|
free(realSpecs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
realSpecs->executableSegments = malloc(sizeof(uint8_t) * specs->executableSegmentsCount);
|
||||||
|
if (realSpecs->executableSegments == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate executable segments");
|
||||||
|
free(realSpecs->memSpecs);
|
||||||
|
free(realSpecs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < specs->executableSegmentsCount; i++)
|
||||||
|
{
|
||||||
|
realSpecs->executableSegments[i] = specs->executableSegments[i];
|
||||||
|
}
|
||||||
|
realSpecs->executableSegmentsCount = specs->executableSegmentsCount;
|
||||||
|
|
||||||
|
|
||||||
|
realSpecs->smartReadSpecs = specs->smartReadSpecs;
|
||||||
|
realSpecs->smartReadSpecsCount = specs->smartReadSpecsCount;
|
||||||
|
|
||||||
|
realSpecs->smartWriteSpecs = specs->smartWriteSpecs;
|
||||||
|
realSpecs->smartWriteSpecsCount = specs->smartWriteSpecsCount;
|
||||||
|
|
||||||
|
uint64_t maxAddr = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < specCount; i++)
|
||||||
|
{
|
||||||
|
memseg_spec_t *segSpec = (memseg_spec_t*)malloc(sizeof(memseg_spec_t));
|
||||||
|
realSpecs->memSpecs[i] = segSpec;
|
||||||
|
if (segSpec == NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
sprintf(errbuf, "unable to allocate mem spec segment %u", i);
|
||||||
|
for (uint8_t j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
free(realSpecs->memSpecs[j]);
|
||||||
|
}
|
||||||
|
free(realSpecs->memSpecs);
|
||||||
|
free(realSpecs->executableSegments);
|
||||||
|
free(realSpecs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < specCount - 2)
|
||||||
|
{
|
||||||
|
realSpecs->memSpecs[i]->name = specs->memSpecs[i]->name;
|
||||||
|
realSpecs->memSpecs[i]->len = specs->memSpecs[i]->len;
|
||||||
|
realSpecs->memSpecs[i]->start = specs->memSpecs[i]->start;
|
||||||
|
realSpecs->memSpecs[i]->wordLen = specs->memSpecs[i]->wordLen;
|
||||||
|
uint64_t testMaxAddr = realSpecs->memSpecs[i]->start + (realSpecs->memSpecs[i]->len * realSpecs->memSpecs[i]->wordLen);
|
||||||
|
if (testMaxAddr > maxAddr)
|
||||||
|
{
|
||||||
|
maxAddr = testMaxAddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t pcSpecSegNum = specs->memSpecsCount;
|
||||||
|
|
||||||
|
|
||||||
|
realSpecs->pcAddr = memSegToGlobal(realSpecs, pcSpecSegNum, 0);
|
||||||
|
|
||||||
|
device_public_context_t* pubDevContext = malloc(sizeof(device_public_context_t));
|
||||||
|
if (pubDevContext == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate public context");
|
||||||
|
freeDevSpec(realSpecs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char initErrbuf[200];
|
||||||
|
device_info_t* devInfo = initSpecs(realSpecs, initErrbuf);
|
||||||
|
if (devInfo == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to init specs: %s", initErrbuf);
|
||||||
|
freeDevSpec(realSpecs);
|
||||||
|
free(pubDevContext);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pubDevContext->deviceInfo = (void*)devInfo;
|
||||||
|
pubDevContext->deviceMem = devInfo->deviceMem;
|
||||||
|
|
||||||
|
return pubDevContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pubDeviceType()
|
||||||
|
{
|
||||||
|
return EXTENDED_DEVICE_TYPE_DUMMY;
|
||||||
|
}
|
||||||
|
|
||||||
10
src/mem.c
Normal file
10
src/mem.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
// fallback handler that acts like &rawCells[addr]
|
||||||
|
void* default_addr_read_handler(uint64_t ident, uint64_t addr, void* rawCells)
|
||||||
|
{
|
||||||
|
return (rawCells + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty handler cuz void* data size depends on a usage context
|
||||||
|
void default_addr_write_handler(uint64_t ident, uint64_t addr, void* rawCells, void* data) {}
|
||||||
8
src/runner.c
Normal file
8
src/runner.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "runner.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t makeTick(device_mem_t* devMem)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user