initial commit
This commit is contained in:
commit
c8a56a78ec
9 changed files with 221 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.vscode/
|
||||||
|
build/
|
28
Makefile
Normal file
28
Makefile
Normal file
|
@ -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)
|
12
include/address_space.h
Normal file
12
include/address_space.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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);
|
12
include/cpu.h
Normal file
12
include/cpu.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include "address_space.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct CPU_s {
|
||||||
|
uint32_t registers[32];
|
||||||
|
uint32_t programCounter;
|
||||||
|
AddressSpace *addressSpace;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct CPU_s CPU;
|
||||||
|
|
||||||
|
CPU create_cpu(AddressSpace *addressSpace);
|
3
include/program_loader.h
Normal file
3
include/program_loader.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include "address_space.h"
|
||||||
|
|
||||||
|
int load_to_rom(const char filename[], AddressSpace *addressSpace);
|
87
src/address_space.c
Normal file
87
src/address_space.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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; i<n; i++) {
|
||||||
|
dest[i] = addressSpace->rom[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; i<n; i++) {
|
||||||
|
dest[i] = addressSpace->ram[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; i<n; i++) {
|
||||||
|
addressSpace->rom[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; i<n; i++) {
|
||||||
|
addressSpace->ram[address + i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO IO
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
26
src/cpu.c
Normal file
26
src/cpu.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#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;
|
||||||
|
}
|
24
src/main.c
Normal file
24
src/main.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "program_loader.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc == 0) {
|
||||||
|
fprintf(stderr, "Usage: criscv <binary program>\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;
|
||||||
|
}
|
27
src/program_loader.c
Normal file
27
src/program_loader.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in a new issue