From c8a56a78ec1305aeda201c0cad976e42556bcbc6 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 14 Oct 2024 19:48:56 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + Makefile | 28 +++++++++++++ include/address_space.h | 12 ++++++ include/cpu.h | 12 ++++++ include/program_loader.h | 3 ++ src/address_space.c | 87 ++++++++++++++++++++++++++++++++++++++++ src/cpu.c | 26 ++++++++++++ src/main.c | 24 +++++++++++ src/program_loader.c | 27 +++++++++++++ 9 files changed, 221 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/address_space.h create mode 100644 include/cpu.h create mode 100644 include/program_loader.h create mode 100644 src/address_space.c create mode 100644 src/cpu.c create mode 100644 src/main.c create mode 100644 src/program_loader.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..608b1d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ +build/ \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8ecd889 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +CC := gcc +CFLAGS := -Wall -Wextra -std=gnu23 -I include -O3 +SRC_DIR := src +BUILD_DIR := build +PROGRAM_NAME := criscv + +# Find all .c files in src directory +SRCS := $(wildcard $(SRC_DIR)/*.c) +# Generate corresponding .o file names in obj directory +OBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/obj/%.o,$(SRCS)) +# Name of the final executable +TARGET := $(BUILD_DIR)/$(PROGRAM_NAME) + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJS) | $(BUILD_DIR) + $(CC) $(CFLAGS) $^ -o $@ + +$(BUILD_DIR)/obj/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)/obj + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR) $(BUILD_DIR)/obj: + mkdir -p $@ + +clean: + rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/include/address_space.h b/include/address_space.h new file mode 100644 index 0000000..b69fb66 --- /dev/null +++ b/include/address_space.h @@ -0,0 +1,12 @@ +#include + +struct AddressSpace_s { + uint8_t *rom; + uint32_t romSize; + uint8_t *ram; + uint32_t ramSize; +}; + +typedef struct AddressSpace_s AddressSpace; + +AddressSpace create_address_space(int romSize, int ramSize); \ No newline at end of file diff --git a/include/cpu.h b/include/cpu.h new file mode 100644 index 0000000..793c5e9 --- /dev/null +++ b/include/cpu.h @@ -0,0 +1,12 @@ +#include "address_space.h" +#include + +struct CPU_s { + uint32_t registers[32]; + uint32_t programCounter; + AddressSpace *addressSpace; +}; + +typedef struct CPU_s CPU; + +CPU create_cpu(AddressSpace *addressSpace); \ No newline at end of file diff --git a/include/program_loader.h b/include/program_loader.h new file mode 100644 index 0000000..eb0e43b --- /dev/null +++ b/include/program_loader.h @@ -0,0 +1,3 @@ +#include "address_space.h" + +int load_to_rom(const char filename[], AddressSpace *addressSpace); \ No newline at end of file diff --git a/src/address_space.c b/src/address_space.c new file mode 100644 index 0000000..601508a --- /dev/null +++ b/src/address_space.c @@ -0,0 +1,87 @@ +#include +#include + +struct AddressSpace_s { + // A pointer to a ROM array. The array can vary in length. + uint8_t *rom; + // The size of ROM. + uint32_t romSize; + + // A pointer to a RAM array. The array can vary in length. + uint8_t *ram; + // The size of RAM. + uint32_t ramSize; +}; + +typedef struct AddressSpace_s AddressSpace; + + +AddressSpace create_address_space(int romSize, int ramSize) { + uint8_t rom[romSize]; + uint8_t ram[ramSize]; + + AddressSpace addressSpace = { rom, romSize, ram, ramSize }; + + return addressSpace; +} + +int read_address_space(const AddressSpace *addressSpace, uint32_t address, const int n, uint8_t *dest) { + uint32_t romSize = addressSpace->romSize; + uint32_t ramSize = addressSpace->ramSize; + + if (address < romSize) { + if (address + n < romSize) { + fprintf(stderr, "Reading %d bytes from %d will exceed ROM address space of %d\n", n, address, romSize); // TODO maybe move to perror + return 1; + } else { + for (int i=0; irom[address + i]; + } + } + } else if (address < romSize + ramSize) { + if (address + n < romSize + ramSize) { + fprintf(stderr, "Reading %d bytes from %d (total %d) will exceed RAM address space of %d (total %d)\n", n, address, address + romSize, ramSize, romSize + ramSize); + return 1; + } else { + address -= romSize; + for (int i=0; iram[address + i]; + } + } + + } else { + // TODO IO + } + + return 0; +} + +int write_address_space(const AddressSpace *addressSpace, uint32_t address, const int n, uint8_t *src) { + uint32_t romSize = addressSpace->romSize; + uint32_t ramSize = addressSpace->ramSize; + + if (address < romSize) { + if (address + n < romSize) { + fprintf(stderr, "Writing %d bytes to %d will exceed ROM address space of %d\n", n, address, romSize); + return 1; + } else { + for (int i=0; irom[address + i] = src[i]; + } + } + } else if (address < romSize + ramSize) { + if (address + n < romSize + ramSize) { + fprintf(stderr, "Writing %d bytes to %d (total %d) will exceed RAM address space of %d (total %d)\n", n, address, address + romSize, ramSize, romSize + ramSize); + return 1; + } else { + address -= romSize; + for (int i=0; iram[address + i] = src[i]; + } + } + } else { + // TODO IO + } + + return 0; +} \ No newline at end of file diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 0000000..58d32a4 --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,26 @@ +#include +#include "address_space.h" + +struct CPU_s { + // [32] of 32bit (uint32_t) registers + uint32_t registers[32]; + + // Points to the byte of current instruction. Also known as pc + uint32_t programCounter; + + // The address space + AddressSpace *addressSpace; +} cpu_default = { + .registers = {0}, + .programCounter = 0 +}; + +typedef struct CPU_s CPU; + + +CPU create_cpu(AddressSpace *addressSpace) { + CPU cpu = cpu_default; + cpu.addressSpace = addressSpace; + + return cpu; +} \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c5a0a9a --- /dev/null +++ b/src/main.c @@ -0,0 +1,24 @@ +#include + +#include "program_loader.h" +#include "cpu.h" + +int main(int argc, char *argv[]) { + if (argc == 0) { + fprintf(stderr, "Usage: criscv \n"); + return 1; + } + + AddressSpace addressSpace = create_address_space(1024, 1024); + printf("Address space: %dB ROM, %dB RAM\n", addressSpace.romSize, addressSpace.ramSize); + + if (load_to_rom(argv[1], &addressSpace) != 0) { + fprintf(stderr, "Error loading program\n"); + return 1; + } + + CPU cpu = create_cpu(&addressSpace); + + + return 0; +} \ No newline at end of file diff --git a/src/program_loader.c b/src/program_loader.c new file mode 100644 index 0000000..827c75d --- /dev/null +++ b/src/program_loader.c @@ -0,0 +1,27 @@ +#include +#include "address_space.h" + +int load_to_rom(const char filename[], AddressSpace *addressSpace) { + FILE *file = fopen(filename, "rb"); + + if (file == NULL) { + perror("Error opening file\n"); + return 1; + } + + int romSize = addressSpace->romSize; + uint8_t buffer[romSize]; + fread(buffer, 1, romSize, file); + + fseek(file, 0, SEEK_END); + int fileLen = ftell(file); + + if (fileLen > romSize) { + fprintf(stderr, "File has %d bytes, and won't fit in ROM of capacity %d bytes\n", fileLen, romSize); + return 1; + } + + addressSpace->rom = buffer; + + return 0; +} \ No newline at end of file