diff --git a/CMakeLists.txt b/CMakeLists.txt index 61cfd55..88c347f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(SRC_FILES_COMMON source/peripherals/plic.cpp source/peripherals/ram.cpp source/peripherals/virtio.cpp + source/peripherals/syscon.cpp source/instructions/loadinsn.cpp source/instructions/otherinsn.cpp diff --git a/README.md b/README.md index 38a133e..8262dca 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ Welcome to the RV64GC Emulator repository, a RISC-V emulator project developed u - Raw framebuffer mode support: The firmware can write to memory-mapped locations to populate a framebuffer and display the contents on the screen. - PLIC - CLINT -- VIRTIO +- VIRTIO MMIO +- SYSCON - bios (firmware), kernel and dtb loading - Successfully completes all [RISCV imafdcsu ISA tests](https://github.com/riscv-software-src/riscv-tests), with some caveats (see [Testing](#testing)) diff --git a/main.cpp b/main.cpp index f388792..9bb23a5 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include "helper.hpp" #include "plic.hpp" #include "ram.hpp" +#include "syscon.hpp" #include "virtio.hpp" #include #include @@ -171,8 +172,9 @@ int main(int argc, char* argv[]) RamDevice dram = RamDevice(DRAM_BASE, ram_size_total, helper::load_file(bios_path)); gpu::GpuDevice gpu = gpu::GpuDevice("RISC V emulator", font_path, 960, 540); + SysconDevice syscon = SysconDevice(); - Cpu cpu = Cpu(&dram, &gpu, virtio_device); + Cpu cpu = Cpu(&dram, &gpu, virtio_device, &syscon); if (dtb_path) { diff --git a/source/cpu.cpp b/source/cpu.cpp index 8efae68..3e9754a 100644 --- a/source/cpu.cpp +++ b/source/cpu.cpp @@ -25,7 +25,7 @@ #include Cpu::Cpu(RamDevice* dram_device, gpu::GpuDevice* gpu_device, - virtio::VirtioBlkDevice* virtio_blk_device) + virtio::VirtioBlkDevice* virtio_blk_device, SysconDevice* syscon_device) : mmu(*this) { mode = cpu::Mode::Machine; @@ -57,9 +57,15 @@ Cpu::Cpu(RamDevice* dram_device, gpu::GpuDevice* gpu_device, bus.add_device(virtio_blk_device); } + if (syscon_device != nullptr) + { + bus.add_device(syscon_device); + } + this->dram_device = dram_device; this->gpu_device = gpu_device; this->virtio_blk_device = virtio_blk_device; + this->syscon_device = syscon_device; csr::init_handler_array(); } diff --git a/source/include/cpu.hpp b/source/include/cpu.hpp index 340689f..c13fe71 100644 --- a/source/include/cpu.hpp +++ b/source/include/cpu.hpp @@ -10,6 +10,7 @@ #include "mmu.hpp" #include "plic.hpp" #include "ram.hpp" +#include "syscon.hpp" #include "virtio.hpp" #include #include @@ -22,7 +23,8 @@ class Cpu { public: Cpu(RamDevice* dram_device, gpu::GpuDevice* gpu_device = nullptr, - virtio::VirtioBlkDevice* virtio_blk_device = nullptr); + virtio::VirtioBlkDevice* virtio_blk_device = nullptr, + SysconDevice* syscon_device = nullptr); void dump_registers(std::ostream& stream); @@ -171,6 +173,7 @@ class Cpu RamDevice* dram_device; gpu::GpuDevice* gpu_device; virtio::VirtioBlkDevice* virtio_blk_device; + SysconDevice* syscon_device; public: cpu::Mode mode; diff --git a/source/peripherals/include/syscon.hpp b/source/peripherals/include/syscon.hpp new file mode 100644 index 0000000..4d7cfb4 --- /dev/null +++ b/source/peripherals/include/syscon.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "bus.hpp" +#include +#include + +class SysconDevice : public BusDevice +{ + public: + SysconDevice() = default; + virtual ~SysconDevice() = default; + + uint64_t load(Bus& bus, uint64_t address, uint64_t length) override; + void store(Bus& bus, uint64_t address, uint64_t value, uint64_t length) override; + + public: + uint64_t get_base_address() const override; + uint64_t get_end_address() const override; + + void dump(std::ostream& stream) const override; + std::string_view get_peripheral_name() const override; + + public: + static constexpr uint64_t poweroff_addr = 0x5555; + + static constexpr uint64_t reboot_addr = 0x7777; + + static constexpr uint64_t base_addr = poweroff_addr; + + static constexpr uint64_t end_addr = reboot_addr; + + static constexpr std::string_view peripheral_name = "SYSCON"; +}; diff --git a/source/peripherals/syscon.cpp b/source/peripherals/syscon.cpp new file mode 100644 index 0000000..6d688e5 --- /dev/null +++ b/source/peripherals/syscon.cpp @@ -0,0 +1,38 @@ +#include "syscon.hpp" +#include + +uint64_t SysconDevice::load(Bus& bus, uint64_t address, uint64_t length) +{ + return 0; +} + +void SysconDevice::store(Bus& bus, uint64_t address, uint64_t value, uint64_t length) +{ + if (value == poweroff_addr) + { + std::exit(0); + } + else if (value == reboot_addr) + { + std::exit(0); + } +} + +void SysconDevice::dump(std::ostream& stream) const +{ +} + +uint64_t SysconDevice::get_base_address() const +{ + return base_addr; +} + +uint64_t SysconDevice::get_end_address() const +{ + return end_addr; +} + +std::string_view SysconDevice::get_peripheral_name() const +{ + return peripheral_name; +}