diff --git a/labus/device.cc b/labus/device.cc index 78e4ba6..739abc8 100644 --- a/labus/device.cc +++ b/labus/device.cc @@ -1 +1,5 @@ -#include \ No newline at end of file +#include + +Device::Device(bool cacheable): cacheable_(cacheable) {} + +bool Device::is_cacheable() { return cacheable_; } \ No newline at end of file diff --git a/labus/include/device.hh b/labus/include/device.hh index a16e888..7351464 100644 --- a/labus/include/device.hh +++ b/labus/include/device.hh @@ -3,9 +3,15 @@ #include #include + class Device { +protected: + bool cacheable_ = false; + public: - Device() = default; + Device(bool cacheable); + + bool is_cacheable(); virtual const size_t &size() const = 0; @@ -29,7 +35,9 @@ public: template class WRDevice : public Device{ +protected: size_t devsiz; + public: WRDevice(size_t siz); diff --git a/labus/include/sysbus.hh b/labus/include/sysbus.hh index 2366e09..4da2b94 100644 --- a/labus/include/sysbus.hh +++ b/labus/include/sysbus.hh @@ -7,7 +7,7 @@ #include class SystemBus { - std::map iomap; + std::map iomap_; std::pair &finddev(uint64_t addr); diff --git a/labus/sysbus.cc b/labus/sysbus.cc index d547ddd..0472f18 100644 --- a/labus/sysbus.cc +++ b/labus/sysbus.cc @@ -3,8 +3,8 @@ std::pair &SystemBus::finddev(uint64_t addr) { Device *dev = nullptr; - auto &&iter = iomap.upper_bound(addr); - if (iter == iomap.begin()) + auto &&iter = iomap_.upper_bound(addr); + if (iter == iomap_.begin()) panic("device not found"); iter--; if (iter->first <= addr && iter->first + iter->second->size() > addr) @@ -13,7 +13,7 @@ std::pair &SystemBus::finddev(uint64_t addr) { return *iter; } -void SystemBus::regdev(Device *dev, uint64_t addr) { iomap.emplace(addr, dev); } +void SystemBus::regdev(Device *dev, uint64_t addr) { iomap_.emplace(addr, dev); } void SystemBus::write(char *buf, size_t addr, size_t len) { auto &&dev = finddev(addr); diff --git a/laos/Makefile b/laos/Makefile index f12ff63..542cdf4 100644 --- a/laos/Makefile +++ b/laos/Makefile @@ -7,23 +7,54 @@ OD := $(LA_BIN_PATH)/$(LA_PREFIX)objdump OC := $(LA_BIN_PATH)/$(LA_PREFIX)objcopy RE := $(LA_BIN_PATH)/$(LA_PREFIX)readelf +NPROC := $(shell nproc) + CMAKE := cmake -BUILD_DIR := build +BUILD_DIR := build +ABS_BUILD := $(CURDIR)/$(BUILD_DIR) $(shell mkdir -p $(BUILD_DIR)) -BIN := neula-os -COMMON_DIR := COMMON +BIN := neula-os +BINARY := $(BUILD_DIR)/$(BIN) -FILES := $(shell find src -name *.c) +TOP_SRC_DIR := src +SOURCE_DIRS := $(shell ls $(TOP_SRC_DIR)/* -d) +MK_DIRS := $(addprefix MAKE/,$(SOURCE_DIRS)) +ALL_SRCS := $(shell find . -name '*.c') +LD_CSRIPT := kernel.ld -.PHONY: build clean +EXTRA_MACRO := # NDEBUG -build: - $(CC) $(FILES) -static --no-pic -march=loongarch32r -o $(BUILD_DIR)/$(BIN) - $(OD) -D $(BUILD_DIR)/$(BIN) > $(BUILD_DIR)/$(BIN).dump - $(RE) -a $(BUILD_DIR)/$(BIN) > $(BUILD_DIR)/$(BIN).info - $(OC) $(BUILD_DIR)/$(BIN) -O binary $(BUILD_DIR)/$(BIN).bin +EXTRA_FLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2 +EXTRA_FLAGS += -MD +EXTRA_FLAGS += -ffreestanding -fno-common -nostdlib +EXTRA_FLAGS += -I. +EXTRA_FLAGS += -fno-pie -no-pie +EXTRA_FLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) + +COMMONFLAGS := $(EXTRA_FLAGS) -march=loongarch32r +CPPFLAGS += $(addprefix -D,$(EXTRA_MACRO)) -I$(CURDIR)/include +CFLAGS += $(COMMONFLAGS) -O +LDFLAGS += $(COMMONFLAGS) -z max-page-size=4096 -T$(LD_CSRIPT) + +.PHONY: all build clean + +all: build + +$(MK_DIRS): MAKE/%:% $(shell find $(%) -name '*.c') + @TOP_BUILD_DIR=$(ABS_BUILD) \ + CC=$(CC) \ + CPPFLAGS="$(CPPFLAGS)" \ + CFLAGS="$(CFLAGS)" \ + LDFLAGS="$(LDFLAGS)" \ + $(MAKE) -C $< -j$(NPROC) + +build: $(MK_DIRS) + @$(CC) -o $(BINARY) $(shell find $(BUILD_DIR) -name '*.o') $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) + @$(OD) -D $(BINARY) > $(BINARY).dump + @$(RE) -a $(BINARY) > $(BINARY).info + @$(OC) $(BINARY) -O binary $(BINARY).bin clean: rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/laos/include/asm.h b/laos/include/asm.h new file mode 100644 index 0000000..b188ff2 --- /dev/null +++ b/laos/include/asm.h @@ -0,0 +1,8 @@ +#include "defs.h" + +#ifndef ASM_H__ +#define ASM_H__ + +#define CPUID 0x020 + +#endif \ No newline at end of file diff --git a/laos/include/common.h b/laos/include/common.h index 02461ab..9749f1a 100644 --- a/laos/include/common.h +++ b/laos/include/common.h @@ -1,5 +1,10 @@ +#include "defs.h" + #ifndef COMMON_H__ #define COMMON_H__ +void main(); +void start(); +void _entry() __attribute__ ((section (".entry"))); #endif // COMMON_H__ \ No newline at end of file diff --git a/laos/include/defs.h b/laos/include/defs.h new file mode 100644 index 0000000..d87766b --- /dev/null +++ b/laos/include/defs.h @@ -0,0 +1,6 @@ +#ifndef DEFS_H__ +#define DEFS_H__ + +#define NCPU 1 + +#endif \ No newline at end of file diff --git a/laos/src/common/common.c b/laos/include/la32r.h similarity index 100% rename from laos/src/common/common.c rename to laos/include/la32r.h diff --git a/laos/include/util.h b/laos/include/util.h new file mode 100644 index 0000000..e69de29 diff --git a/laos/kernel.ld b/laos/kernel.ld new file mode 100644 index 0000000..2ecfb57 --- /dev/null +++ b/laos/kernel.ld @@ -0,0 +1,41 @@ +OUTPUT_ARCH( "loongarch32r" ) +ENTRY( _entry ) + +SECTIONS +{ + /* + * ensure that entry.S / _entry is at 0x1C000000, + */ + . = 0x1C000000; + + .text : { + *(.entry) + . = ALIGN(0x1000); + *(.text .text.*) + . = ALIGN(0x1000); + PROVIDE(etext = .); + } + + .rodata : { + . = ALIGN(16); + *(.srodata .srodata.*) /* do not need to distinguish this from .rodata */ + . = ALIGN(16); + *(.rodata .rodata.*) + } + + .data : { + . = ALIGN(16); + *(.sdata .sdata.*) /* do not need to distinguish this from .data */ + . = ALIGN(16); + *(.data .data.*) + } + + .bss : { + . = ALIGN(16); + *(.sbss .sbss.*) /* do not need to distinguish this from .bss */ + . = ALIGN(16); + *(.bss .bss.*) + } + + PROVIDE(end = .); +} diff --git a/laos/src/kernel/Makefile b/laos/src/kernel/Makefile new file mode 100644 index 0000000..855baa0 --- /dev/null +++ b/laos/src/kernel/Makefile @@ -0,0 +1,28 @@ +CURNAME := kernel +BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME) + +CSRC := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC)) +BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) + +ASSRC := $(wildcard *.S) +ASOBJ := $(patsubst %.S,%.o,$(ASSRC)) +BUILD_ASOBJ := $(addprefix $(BUILD_DIR)/,$(ASOBJ)) + +.PHONY: build all message + +all: message build + +$(BUILD_DIR): + @mkdir -p $(BUILD_DIR) + +$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +$(BUILD_ASOBJ): $(BUILD_DIR)/%.o:%.S $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +build: $(BUILD_OBJS) $(BUILD_ASOBJ) + +message: + @echo "building $(CURNAME)" diff --git a/laos/src/kernel/entry.S b/laos/src/kernel/entry.S new file mode 100644 index 0000000..268c030 --- /dev/null +++ b/laos/src/kernel/entry.S @@ -0,0 +1,20 @@ +#include "asm.h" + +.section .entry +.global _entry +_entry: + # set up a stack for C. + # stack0 is declared in start.c, + # with a 4096-byte stack per CPU. + # sp = stack0 + (hartid * 4096) + la.global $sp, stack0 + lu12i.w $a0, (1024*4 >> 12) & 0xfffff + addi.w $a0, $a0, 1024*4 & 0xfff + csrrd $a1, CPUID + addi.w $a1, $a1, 1 + mul.w $a0, $a0, $a1 + add.w $sp, $sp, $a0 + # jump to start() in start.c + bl start +spin: + b spin \ No newline at end of file diff --git a/laos/src/kernel/kalloc.c b/laos/src/kernel/kalloc.c new file mode 100644 index 0000000..cf7e1f6 --- /dev/null +++ b/laos/src/kernel/kalloc.c @@ -0,0 +1 @@ +extern char end[]; \ No newline at end of file diff --git a/laos/src/kernel/main.c b/laos/src/kernel/main.c new file mode 100644 index 0000000..52794b1 --- /dev/null +++ b/laos/src/kernel/main.c @@ -0,0 +1,3 @@ +void main() { + +} \ No newline at end of file diff --git a/laos/src/kernel/start.c b/laos/src/kernel/start.c new file mode 100644 index 0000000..544d556 --- /dev/null +++ b/laos/src/kernel/start.c @@ -0,0 +1,7 @@ +#include "common.h" + +__attribute__ ((aligned (16))) char stack0[4096 * NCPU]; + +void start() { + +} \ No newline at end of file diff --git a/laos/src/kernel/vm.c b/laos/src/kernel/vm.c new file mode 100644 index 0000000..be20fda --- /dev/null +++ b/laos/src/kernel/vm.c @@ -0,0 +1 @@ +extern char etext[]; \ No newline at end of file diff --git a/laos/src/main.c b/laos/src/main.c deleted file mode 100644 index 93ebade..0000000 --- a/laos/src/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main() { - printf("%d", 123); - return 0; -} \ No newline at end of file diff --git a/laos/src/util/Makefile b/laos/src/util/Makefile new file mode 100644 index 0000000..cc66e2f --- /dev/null +++ b/laos/src/util/Makefile @@ -0,0 +1,21 @@ +CURNAME := util +BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME) + +CSRC := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC)) +BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) + +.PHONY: build all message + +all: message build + +$(BUILD_DIR): + @mkdir -p $(BUILD_DIR) + +$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +build: $(BUILD_OBJS) + +message: + @echo "building $(CURNAME)" \ No newline at end of file diff --git a/laos/src/util/memops.c b/laos/src/util/memops.c new file mode 100644 index 0000000..9f55920 --- /dev/null +++ b/laos/src/util/memops.c @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/lasim/la32r.cc b/lasim/la32r.cc index 6c0e3a6..abbc1dc 100644 --- a/lasim/la32r.cc +++ b/lasim/la32r.cc @@ -134,6 +134,266 @@ struct CSRBaseInfo { // ----- ----- class defines ----- ----- // + +/** + * @bug no cached flag set +*/ +class Cache { +private: + // mem addr + // ------------------------------------------------------- + // | tag | idx 5bit | byte sel 5 bit | + // ------------------------------------------------------- + + // info + // ------------------------------------------------------- + // | | MAT | PLV | cached | dirty | + // ------------------------------------------------------- + using lane = u32[8]; + lane mem_ck1[32]; + u32 tags_ck1[32]; + u32 info_ck1[32]; + + lane mem_ck2[32]; + u32 tags_ck2[32]; + u32 info_ck2[32]; + + // common info + // ------------------------------------------------------- + // | | recent | + // ------------------------------------------------------- + // recent => 1: recent use blk1, 0: recent use blk2 + u32 info[32]; + + u32 load(u32 addr) { + auto word_sel = (addr >> 2) & 0b111; + auto idx = (addr >> 5) & 0b11111; + auto tag = addr >> 10; + + if (tags_ck1[idx] == tag) { + // 将 recent 为设置为 1 + info[idx] |= 0b1; + return mem_ck1[idx][word_sel]; + } else if (tags_ck2[idx] == tag) { + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + return mem_ck2[idx][word_sel]; + } + + u32 laneaddr = addr << 10 | idx << 5; + u32 trans = 0; + + if (info[idx] & 0b1) { + // 最近使用块 1 + // 将块 2 替换下去 + + if (info_ck2[idx] & 0b1) { + u32 oldlaneaddr = tags_ck2[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck2[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck2[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck2[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + // 设置脏位 + info_ck1[idx] &= ~0b1; + + return mem_ck2[idx][word_sel]; + } else { + // 最近使用块 2 + // 将块 1 替换下去 + + if (info_ck1[idx] & 0b1) { + u32 oldlaneaddr = tags_ck1[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck1[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck1[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck1[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 1 + info[idx] |= 0b1; + // 设置脏位 + info_ck1[idx] &= ~0b1; + + return mem_ck1[idx][word_sel]; + } + + } + + void store(u32 addr, u32 data, u32 bytemsk) { + auto word_sel = (addr >> 2) & 0b111; + auto idx = (addr >> 5) & 0b11111; + auto tag = addr >> 10; + + data = bytemsk & data; + + if (tags_ck1[idx] == tag) { + // 将 recent 为设置为 1 + info[idx] |= 0b1; + // 设置脏位 + info_ck1[idx] |= 0b1; + + mem_ck1[idx][word_sel] = data | (mem_ck1[idx][word_sel] & ~bytemsk); + return; + } else if (tags_ck2[idx] == tag) { + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + // 设置脏位 + info_ck2[idx] |= 0b1; + + mem_ck2[idx][word_sel] = data | (mem_ck2[idx][word_sel] & ~bytemsk); + return; + } + + u32 laneaddr = addr << 10 | idx << 5; + u32 trans = 0; + + if (info[idx] & 0b1) { + // 最近使用块 1 + // 将块 2 替换下去 + + if (info_ck2[idx] & 0b1) { + u32 oldlaneaddr = tags_ck2[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck2[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck2[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck2[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + // 设置脏位 + info_ck2[idx] |= 0b1; + + mem_ck2[idx][word_sel] = data | (mem_ck2[idx][word_sel] & ~bytemsk); + } else { + // 最近使用块 2 + // 将块 1 替换下去 + + if (info_ck1[idx] & 0b1) { + u32 oldlaneaddr = tags_ck1[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck1[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck1[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck1[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 1 + info[idx] |= 0b1; + // 设置脏位 + info_ck1[idx] |= 0b1; + + mem_ck1[idx][word_sel] = data | (mem_ck1[idx][word_sel] & ~bytemsk); + } + } + + void prefetch(u32 addr, u32 hint) { + auto word_sel = (addr >> 2) & 0b111; + auto idx = (addr >> 5) & 0b11111; + auto tag = addr >> 10; + + if (tags_ck1[idx] == tag) { + // 将 recent 为设置为 1 + info[idx] |= 0b1; + return; + } else if (tags_ck2[idx] == tag) { + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + return; + } + + u32 laneaddr = addr << 10 | idx << 5; + u32 trans = 0; + + if (info[idx] & 0b1) { + // 最近使用块 1 + // 将块 2 替换下去 + + if (info_ck2[idx] & 0b1) { + u32 oldlaneaddr = tags_ck2[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck2[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck2[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck2[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 0 + info[idx] &= ~0b1; + } else { + // 最近使用块 2 + // 将块 1 替换下去 + + if (info_ck1[idx] & 0b1) { + u32 oldlaneaddr = tags_ck1[idx] << 10 | idx << 5; + for (size_t i = 0; i < 8; ++i) { + trans = mem_ck1[idx][i]; + sysbus->write32(trans, oldlaneaddr); + oldlaneaddr += 4; + } + } + + tags_ck1[idx] = tag; + + for (size_t i = 0; i < 8; ++i) { + sysbus->read32(trans, laneaddr); + mem_ck1[idx][i] = trans; + laneaddr += 4; + } + + // 将 recent 为设置为 1 + info[idx] |= 0b1; + } + } +}; + class Registers { private: u32 regs_[31] = {0}; @@ -165,6 +425,7 @@ public: } u32 &operator[](u32 idx) { + _ = 0; panicifnot(0 <= idx && 32 >= idx); if (idx == 0) { return _;