Introduce base class HWComponent.

This commit is contained in:
Maxim Poliakovski 2020-03-14 14:23:46 +01:00
parent 822f6cafd2
commit d53400ebae
14 changed files with 115 additions and 56 deletions

57
devices/hwcomponent.h Normal file
View File

@ -0,0 +1,57 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-20 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HW_COMPONENT_H
#define HW_COMPONENT_H
#include <string>
/** types of different HW components */
enum HWCompType : int {
UNKNOWN = 0, /* unknown component type */
MEM_CTRL = 10, /* memory controller */
ROM = 20, /* read-only memory */
RAM = 30, /* random access memory */
MMIO_DEV = 40, /* memory mapped I/O device */
PCI_HOST = 50, /* PCI host */
PCI_DEV = 51, /* PCI device */
I2C_HOST = 60, /* I2C host */
I2C_DEV = 61, /* I2C device */
ADB_HOST = 70, /* ADB host */
ADB_DEV = 71, /* ADB device */
};
/** Abstract base class for HW components. */
class HWComponent {
public:
virtual ~HWComponent() = default;
virtual std::string get_name(void) { return this->name; };
virtual void set_name(std::string name) { this->name = name; };
virtual bool supports_type(HWCompType type) = 0;
protected:
std::string name;
};
#endif /* HW_COMPONENT_H */

View File

@ -23,6 +23,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define MACHINE_ID_H
#include <cinttypes>
#include "hwcomponent.h"
#include "mmiodevice.h"
/**
@ -46,6 +47,10 @@ public:
GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; };
~GossamerID() = default;
bool supports_type(HWCompType type) {
return type == HWCompType::MMIO_DEV;
};
uint32_t read(uint32_t offset, int size) {
return ((!offset && size == 2) ? this->id : 0); };

View File

@ -52,6 +52,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define MACIO_H
#include <cinttypes>
#include "hwcomponent.h"
#include "pcidevice.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
@ -86,11 +87,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
class HeathrowIC : public PCIDevice
{
public:
using PCIDevice::name;
HeathrowIC();
~HeathrowIC();
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
void set_host(PCIHost *host_instance) {this->host_instance = host_instance;};
/* PCI device methods */

View File

@ -27,12 +27,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "memctrlbase.h"
MemCtrlBase::MemCtrlBase(std::string name)
{
this->name = name;
}
MemCtrlBase::~MemCtrlBase()
{
for (auto &reg : mem_regions) {

View File

@ -25,7 +25,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <string>
#include <vector>
#include "mmiodevice.h"
enum RangeType {
@ -49,7 +48,7 @@ typedef struct AddressMapEntry {
/** Base class for memory controllers. */
class MemCtrlBase {
public:
MemCtrlBase(std::string name);
MemCtrlBase() = default;
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);
@ -62,9 +61,8 @@ public:
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;
bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr,
uint32_t type, uint8_t init_val);
private:
std::vector<uint8_t *> mem_regions;

View File

@ -24,16 +24,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <string>
#include "hwcomponent.h"
/** Abstract class representing a simple, memory-mapped I/O device */
class MMIODevice {
class MMIODevice : public HWComponent {
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 */

View File

@ -32,11 +32,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "memreadwrite.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "hwcomponent.h"
#include "mpc106.h"
MPC106::MPC106() : MemCtrlBase("Grackle"), PCIDevice("Grackle PCI host bridge")
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
{
this->name = "Grackle";
/* add memory mapped I/O region for MPC106 registers */
add_mmio_region(0xFEC00000, 0x300000, this);
@ -48,6 +51,16 @@ MPC106::~MPC106()
this->pci_0_bus.clear();
}
bool MPC106::supports_type(HWCompType type)
{
if (type == HWCompType::MEM_CTRL || type == HWCompType::MMIO_DEV ||
type == HWCompType::PCI_HOST || type == HWCompType::PCI_DEV) {
return true;
} else {
return false;
}
}
uint32_t MPC106::read(uint32_t offset, int size)
{
if (offset >= 0x200000) {

View File

@ -37,6 +37,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <unordered_map>
#include "hwcomponent.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "pcidevice.h"
@ -46,10 +47,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost
{
public:
using MemCtrlBase::name;
MPC106();
~MPC106();
bool supports_type(HWCompType type);
uint32_t read(uint32_t offset, int size);
void write(uint32_t offset, uint32_t value, int size);

View File

@ -37,7 +37,7 @@ enum {
class PCIDevice : public MMIODevice {
public:
PCIDevice(std::string name) {this->name = name;};
PCIDevice(std::string name) { this->pci_name = name; };
virtual ~PCIDevice() = default;
/* configuration space access methods */
@ -47,9 +47,9 @@ public:
virtual void set_host(PCIHost *host_instance) = 0;
protected:
std::string name; // human-readable device name
std::string pci_name; // human-readable device name
PCIHost *host_instance; // host bridge instance to call back
uint32_t base_addr; // base address register 0
uint32_t base_addr; // base address register 0
};
#endif /* PCI_DEVICE_H */

View File

@ -35,6 +35,8 @@ using namespace std;
ViaCuda::ViaCuda()
{
this->name = "ViaCuda";
/* FIXME: is this the correct
VIA initialization? */
this->via_regs[VIA_A] = 0x80;

View File

@ -42,11 +42,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
firmware using bit banging (https://en.wikipedia.org/wiki/Bit_banging).
*/
#include "nvram.h"
#ifndef VIACUDA_H
#define VIACUDA_H
#include "hwcomponent.h"
#include "nvram.h"
/** VIA register offsets. */
enum {
VIA_B = 0x00, /* input/output register B */
@ -99,12 +100,16 @@ enum {
};
class ViaCuda
class ViaCuda : public HWComponent
{
public:
ViaCuda();
~ViaCuda();
bool supports_type(HWCompType type) {
return (type == HWCompType::ADB_HOST || type == HWCompType::I2C_HOST);
};
uint8_t read(int reg);
void write(int reg, uint8_t value);

View File

@ -2,6 +2,7 @@
#include <string>
#include <thirdparty/loguru.hpp>
#include "machinebase.h"
#include "devices/hwcomponent.h"
std::unique_ptr<MachineBase> gMachineObj = 0;
@ -12,7 +13,6 @@ MachineBase::MachineBase(std::string name)
/* initialize internal maps */
this->comp_map.clear();
this->name_to_type.clear();
this->aliases.clear();
}
@ -24,7 +24,7 @@ MachineBase::~MachineBase()
this->comp_map.clear();
}
bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *dev_obj)
bool MachineBase::add_component(std::string name, HWCompType type, HWComponent *dev_obj)
{
if (this->comp_map.count(name)) {
LOG_F(ERROR, "Component %s already exists!", name.c_str());
@ -32,7 +32,6 @@ bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *d
}
this->comp_map[name] = dev_obj;
this->name_to_type[name] = type;
return true;
}
@ -40,10 +39,9 @@ bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *d
void MachineBase::add_alias(std::string name, std::string alias, HWCompType type)
{
this->aliases[alias] = name;
this->name_to_type[alias] = type;
}
MMIODevice *MachineBase::get_comp_by_name(std::string name)
HWComponent *MachineBase::get_comp_by_name(std::string name)
{
if (this->aliases.count(name)) {
name = this->aliases[name];
@ -56,13 +54,13 @@ MMIODevice *MachineBase::get_comp_by_name(std::string name)
}
}
MMIODevice *MachineBase::get_comp_by_type(HWCompType type)
HWComponent *MachineBase::get_comp_by_type(HWCompType type)
{
std::string comp_name;
bool found = false;
for(auto it = this->name_to_type.begin(); it != this->name_to_type.end(); it++) {
if (it->second == type) {
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
if (it->second->supports_type(type)) {
comp_name = it->first;
found = true;
break;

View File

@ -30,20 +30,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <memory>
#include <string>
#include <map>
#include "devices/mmiodevice.h"
/** types of different HW components */
enum HWCompType : int {
UNKNOWN = 0, /* unknown component type */
MEM_CTRL = 1, /* memory controller */
ROM = 2, /* read-only memory */
RAM = 3, /* random access memory */
MMIO_DEV = 4, /* memory mapped I/O device */
PCI_HOST = 5, /* PCI host */
PCI_DEV = 6, /* PCI device */
I2C_DEV = 7, /* I2C device */
ADB_DEV = 8 /* ADB device */
};
#include "devices/hwcomponent.h"
class MachineBase
{
@ -51,15 +38,14 @@ public:
MachineBase(std::string name);
~MachineBase();
bool add_component(std::string name, HWCompType type, MMIODevice *dev_obj);
bool add_component(std::string name, HWCompType type, HWComponent *dev_obj);
void add_alias(std::string name, std::string alias, HWCompType type);
MMIODevice *get_comp_by_name(std::string name);
MMIODevice *get_comp_by_type(HWCompType type);
HWComponent *get_comp_by_name(std::string name);
HWComponent *get_comp_by_type(HWCompType type);
private:
std::string name;
std::map<std::string, MMIODevice *>comp_map;
std::map<std::string, int> name_to_type;
std::map<std::string, HWComponent *>comp_map;
std::map<std::string, std::string> aliases;
};

View File

@ -26,11 +26,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <thirdparty/loguru.hpp>
#include "machinebase.h"
#include "cpu/ppc/ppcemu.h"
#include "devices/mpc106.h"
#include "devices/machineid.h"
#include "devices/macio.h"
#include "cpu/ppc/ppcemu.h"
#include "machinebase.h"
#include "devices/viacuda.h"
int create_gossamer()
{
@ -55,7 +55,7 @@ int create_gossamer()
gMachineObj->add_component("MachineID", HWCompType::MMIO_DEV,
new GossamerID(0x3d8c));
grackle_obj->add_mmio_region(0xFF000004, 4096,
gMachineObj->get_comp_by_name("MachineID"));
dynamic_cast<MMIODevice *>(gMachineObj->get_comp_by_name("MachineID")));
/* add the Heathrow I/O controller */
gMachineObj->add_component("Heathrow", HWCompType::MMIO_DEV, new HeathrowIC);