From ac1f770f92afd9d4eeee3b4534be34df3a420870 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 19 Aug 2019 01:34:24 +0200 Subject: [PATCH] Create base class for memory controller devices. Create 'devices' directory for virtual device sources and move MPC106 source to it. --- devices/memctrlbase.cpp | 131 +++++++++++++++++++++++++++++++ devices/memctrlbase.h | 53 +++++++++++++ devices/mmiodevice.h | 21 +++++ mpc106.cpp => devices/mpc106.cpp | 6 +- mpc106.h => devices/mpc106.h | 0 main.cpp | 2 +- makefile | 27 ++++--- ppcmemory.cpp | 2 +- 8 files changed, 228 insertions(+), 14 deletions(-) create mode 100644 devices/memctrlbase.cpp create mode 100644 devices/memctrlbase.h create mode 100644 devices/mmiodevice.h rename mpc106.cpp => devices/mpc106.cpp (96%) rename mpc106.h => devices/mpc106.h (100%) diff --git a/devices/memctrlbase.cpp b/devices/memctrlbase.cpp new file mode 100644 index 0000000..cd4af99 --- /dev/null +++ b/devices/memctrlbase.cpp @@ -0,0 +1,131 @@ +#include +#include + +#include "memctrlbase.h" + + +MemCtrlBase::MemCtrlBase(std::string name) +{ + this->name = name; +} + + +MemCtrlBase::~MemCtrlBase() +{ + for (auto ® : mem_regions) { + if (reg) + delete(reg); + } + this->mem_regions.clear(); + this->address_map.clear(); +} + + +AddressMapEntry *MemCtrlBase::find_range(uint32_t addr) +{ + for (auto &entry : address_map) { + if (addr >= entry.start && addr <= entry.end) + return &entry; + } + + return 0; +} + + +bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size, + uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) +{ + AddressMapEntry entry; + + /* error if a memory region for the given range already exists */ + if (find_range(start_addr) || find_range(start_addr + size)) + return false; + + uint8_t *reg_content = new uint8_t[size]; + if (!reg_content) + return false; + + this->mem_regions.push_back(reg_content); + + entry.start = start_addr; + entry.end = start_addr + size - 1; + entry.mirror = dest_addr; + entry.type = type; + entry.devobj = 0; + entry.mem_ptr = reg_content; + + this->address_map.push_back(entry); + + return true; +} + + +bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size) +{ + return add_mem_region(start_addr, size, 0, RT_ROM); +} + + +bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size) +{ + return add_mem_region(start_addr, size, 0, RT_RAM); +} + + +bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) +{ + AddressMapEntry entry, *ref_entry; + + ref_entry = find_range(dest_addr); + if (!ref_entry) + return false; + + entry.start = start_addr; + entry.end = start_addr + (ref_entry->end - ref_entry->start) + 1; + entry.mirror = dest_addr; + entry.type = ref_entry->type | RT_MIRROR; + entry.devobj = 0; + entry.mem_ptr = ref_entry->mem_ptr; + + this->address_map.push_back(entry); + + return true; +} + + +bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size) +{ + AddressMapEntry *ref_entry; + uint32_t cpy_size; + + ref_entry = find_range(reg_addr); + if (!ref_entry) + return false; + + cpy_size = std::min(ref_entry->end - ref_entry->start + 1, size); + memcpy(ref_entry->mem_ptr, data, cpy_size); + + return true; +} + + +bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, + MMIODevice *dev_instance) +{ + AddressMapEntry entry; + + /* error if another region for the given range already exists */ + if (find_range(start_addr) || find_range(start_addr + size)) + return false; + + entry.start = start_addr; + entry.end = start_addr + size - 1; + entry.mirror = 0; + entry.type = RT_MMIO; + entry.devobj = dev_instance; + entry.mem_ptr = 0; + + this->address_map.push_back(entry); + + return true; +} diff --git a/devices/memctrlbase.h b/devices/memctrlbase.h new file mode 100644 index 0000000..75e5c66 --- /dev/null +++ b/devices/memctrlbase.h @@ -0,0 +1,53 @@ +#ifndef MEMORY_CONTROLLER_BASE_H +#define MEMORY_CONTROLLER_BASE_H + +#include +#include +#include + +#include "mmiodevice.h" + +enum RangeType { + RT_ROM = 1, /* read-only memory */ + RT_RAM = 2, /* random access memory */ + RT_MMIO = 4, /* memory mapped I/O */ + RT_MIRROR = 8 /* region mirror (content of another region is acessible + at some other address) */ +}; + +typedef struct AddressMapEntry { + uint32_t start; /* first address of the corresponding range */ + uint32_t end; /* last address of the corresponding range */ + uint32_t mirror; /* mirror address for RT_MIRROR */ + uint32_t type; /* range type */ + MMIODevice *devobj; /* pointer to device object */ + unsigned char *mem_ptr; /* direct pointer to data for memory objects */ +} AddressMapEntry; + + +/** Base class for memory controllers. */ +class MemCtrlBase { +public: + MemCtrlBase(std::string name); + virtual ~MemCtrlBase(); + virtual bool add_rom_region(uint32_t start_addr, uint32_t size); + virtual bool add_ram_region(uint32_t start_addr, uint32_t size); + virtual bool add_mem_mirror(uint32_t start_addr, uint32_t dest_addr); + + virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice *dev_instance); + + virtual bool set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size); + + AddressMapEntry *find_range(uint32_t addr); + +protected: + bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val); + + std::string name; + +private: + std::vector mem_regions; + std::vector address_map; +}; + +#endif /* MEMORY_CONTROLLER_BASE_H */ diff --git a/devices/mmiodevice.h b/devices/mmiodevice.h new file mode 100644 index 0000000..454d1af --- /dev/null +++ b/devices/mmiodevice.h @@ -0,0 +1,21 @@ +#ifndef MMIO_DEVICE_H +#define MMIO_DEVICE_H + +#include +#include + +#define READ_WORD_BE(addr) ((addr)[0] << 16) | (addr)[1] +#define READ_DWORD_BE(addr) ((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3] + +/** Abstract class representing a simple, memory-mapped I/O device */ +class MMIODevice { +public: + virtual uint32_t read(uint32_t offset, int size) = 0; + virtual void write(uint32_t offset, uint32_t value, int size) = 0; + virtual ~MMIODevice() = default; + +protected: + std::string name; +}; + +#endif /* MMIO_DEVICE_H */ diff --git a/mpc106.cpp b/devices/mpc106.cpp similarity index 96% rename from mpc106.cpp rename to devices/mpc106.cpp index e4ea06f..903ffc3 100644 --- a/mpc106.cpp +++ b/devices/mpc106.cpp @@ -10,10 +10,10 @@ #include #include #include -#include "viacuda.h" +#include "../viacuda.h" #include "mpc106.h" -#include "ppcemumain.h" -#include "ppcmemory.h" +#include "../ppcemumain.h" +#include "../ppcmemory.h" bool mpc106_membound_change; bool mpc106_mem_approve; //Confirm memory transaction diff --git a/mpc106.h b/devices/mpc106.h similarity index 100% rename from mpc106.h rename to devices/mpc106.h diff --git a/main.cpp b/main.cpp index 0971a97..bf0c7fd 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,7 @@ #include "macswim3.h" #include "ppcmemory.h" #include "viacuda.h" -#include "mpc106.h" +#include "devices/mpc106.h" #include "openpic.h" #include "debugger.h" //#include diff --git a/makefile b/makefile index e7d185c..0978439 100644 --- a/makefile +++ b/makefile @@ -1,17 +1,26 @@ -OBJS = main.o macioserial.o macscsi.o macswim3.o mpc106.o openpic.o poweropcodes.o \ - ppcfpopcodes.o ppcgekkoopcodes.o ppcmemory.o ppcopcodes.o viacuda.o davbus.o \ - debugger.o +EXE := dingusppc +MODULES := . devices +SRCS := $(foreach sdir,$(MODULES),$(wildcard $(sdir)/*.cpp)) +#SRCS = $(wildcard *.cpp) +OBJS := $(patsubst %.cpp, %.o, $(SRCS)) -OUT = dingusppc CXX = g++ CXXFLAGS = -g -c -Wall -std=c++11 LFLAGS = -all: $(OBJS) - $(CXX) -g $(OBJS) -o $(OUT) $(LFLAGS) +VPATH := devices -*.o : *.cpp - $(CXX) $(CXXFLAGS) -c $(input) -o $(output) +DEPS = $(OBJS:.o=.d) + +all: $(EXE) + +$(EXE) : $(OBJS) + $(CXX) -o $@ $^ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -MMD -o $@ $< clean: - rm -f *.o $(OUT) + rm -rf *.o *.d devices/*.o devices/*.d $(EXE) + +-include $(DEPS) diff --git a/ppcmemory.cpp b/ppcmemory.cpp index ccea6c5..ce55785 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -20,7 +20,7 @@ #include "ppcemumain.h" #include "ppcmemory.h" #include "openpic.h" -#include "mpc106.h" +#include "devices/mpc106.h" #include "davbus.h" std::vector pte_storage;