From 66de90675f9a56c05ccf6d0e86ec7c28660101e5 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 13 Jul 2017 15:35:18 +1000 Subject: [PATCH] Make device_memory_interface own its address_spaces --- src/emu/dimemory.cpp | 27 ++++-- src/emu/dimemory.h | 24 ++++- src/emu/emumem.cpp | 214 ++++++++++++++++++++----------------------- src/emu/emumem.h | 3 - 4 files changed, 138 insertions(+), 130 deletions(-) diff --git a/src/emu/dimemory.cpp b/src/emu/dimemory.cpp index ee610b65d71..43f05f6019c 100644 --- a/src/emu/dimemory.cpp +++ b/src/emu/dimemory.cpp @@ -163,15 +163,30 @@ void device_memory_interface::set_addrmap(int spacenum, address_map_constructor //------------------------------------------------- -// set_address_space - connect an address space -// to a device +// dump - dump memory tables to the given file in +// human-readable format //------------------------------------------------- -void device_memory_interface::set_address_space(int spacenum, address_space &space) +void device_memory_interface::dump(FILE *file) const { - if (spacenum >= int(m_addrspace.size())) - m_addrspace.resize(spacenum+1, nullptr); - m_addrspace[spacenum] = &space; + for (auto const &space : m_addrspace) + if (space) { + fprintf(file, + "\n\n" + "====================================================\n" + "Device '%s' %s address space read handler dump\n" + "====================================================\n", + device().tag(), space->name()); + space->dump_map(file, read_or_write::READ); + + fprintf(file, + "\n\n" + "====================================================\n" + "Device '%s' %s address space write handler dump\n" + "====================================================\n", + device().tag(), space->name()); + space->dump_map(file, read_or_write::WRITE); + } } diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h index 1daa5f19bf3..8abc5ff435d 100644 --- a/src/emu/dimemory.h +++ b/src/emu/dimemory.h @@ -92,9 +92,6 @@ public: bool has_configured_map(int index = 0) const { return index >= 0 && index < int(m_address_map.size()) && m_address_map[index]; } address_space &space(int index = 0) const { assert(index >= 0 && index < int(m_addrspace.size()) && m_addrspace[index]); return *m_addrspace[index]; } - // address space accessors - void set_address_space(int spacenum, address_space &space); - // address translation bool translate(int spacenum, int intention, offs_t &address) { return memory_translate(spacenum, intention, address); } @@ -102,6 +99,23 @@ public: // just use it device_memory_interface &memory() { return *this; } + // setup functions - these are called in sequence for all device_memory_interface by the memory manager + template void allocate(memory_manager &manager, int spacenum) + { + assert((0 <= spacenum) && (max_space_count() > spacenum)); + m_addrspace.resize(std::max(m_addrspace.size(), spacenum + 1)); + assert(!m_addrspace[spacenum]); + m_addrspace[spacenum] = std::make_unique(manager, *this, spacenum); + } + void prepare_maps() { for (auto const &space : m_addrspace) { if (space) { space->prepare_map(); } } } + void populate_from_maps() { for (auto const &space : m_addrspace) { if (space) { space->populate_from_map(); } } } + void allocate_memory() { for (auto const &space : m_addrspace) { if (space) { space->allocate_memory(); } } } + void locate_memory() { for (auto const &space : m_addrspace) { if (space) { space->locate_memory(); } } } + void set_log_unmap(bool log) { for (auto const &space : m_addrspace) { if (space) { space->set_log_unmap(log); } } } + + // diagnostic functions + void dump(FILE *file) const; + protected: using space_config_vector = std::vector>; @@ -120,8 +134,8 @@ protected: private: // internal state - std::vector m_address_config; // configuration for each space - std::vector m_addrspace; // reported address spaces + std::vector m_address_config; // configuration for each space + std::vector> m_addrspace; // reported address spaces }; // iterator diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp index cda6eae02d1..987208a76f8 100644 --- a/src/emu/emumem.cpp +++ b/src/emu/emumem.cpp @@ -1562,9 +1562,86 @@ void memory_manager::allocate(device_memory_interface &memory) for (int spacenum = 0; spacenum < memory.max_space_count(); ++spacenum) { // if there is a configuration for this space, we need an address space - const address_space_config *spaceconfig = memory.space_config(spacenum); - if (spaceconfig != nullptr) - address_space::allocate(m_spacelist, *this, *spaceconfig, memory, spacenum); + address_space_config const *const spaceconfig = memory.space_config(spacenum); + if (spaceconfig) + { + // allocate one of the appropriate type + bool const large(spaceconfig->addr2byte_end(0xffffffffUL >> (32 - spaceconfig->m_addrbus_width)) >= (1 << 18)); + + switch (spaceconfig->data_width()) + { + case 8: + if (spaceconfig->endianness() == ENDIANNESS_LITTLE) + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + else + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + break; + + case 16: + if (spaceconfig->endianness() == ENDIANNESS_LITTLE) + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + else + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + break; + + case 32: + if (spaceconfig->endianness() == ENDIANNESS_LITTLE) + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + else + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + break; + + case 64: + if (spaceconfig->endianness() == ENDIANNESS_LITTLE) + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + else + { + if (large) + memory.allocate(*this, spacenum); + else + memory.allocate(*this, spacenum); + } + break; + + default: + throw emu_fatalerror("Invalid width %d specified for memory_manager::allocate", spaceconfig->data_width()); + } + } } } @@ -1576,33 +1653,35 @@ void memory_manager::initialize() { // loop over devices and spaces within each device memory_interface_iterator iter(machine().root_device()); + std::vector memories; for (device_memory_interface &memory : iter) + { + memories.push_back(&memory); allocate(memory); + } allocate(m_machine.m_dummy_space); // construct and preprocess the address_map for each space - for (auto &space : m_spacelist) - space->prepare_map(); + for (auto const memory : memories) + memory->prepare_maps(); // create the handlers from the resulting address maps - for (auto &space : m_spacelist) - space->populate_from_map(); + for (auto const memory : memories) + memory->populate_from_maps(); // allocate memory needed to back each address space - for (auto &space : m_spacelist) - space->allocate_memory(); + for (auto const memory : memories) + memory->allocate_memory(); // find all the allocated pointers - for (auto &space : m_spacelist) - space->locate_memory(); + for (auto const memory : memories) + memory->locate_memory(); // disable logging of unmapped access when no one receives it - for (auto &space : m_spacelist) - { - if (!machine().options().log() && !machine().options().oslog() && !(machine().debug_flags & DEBUG_FLAG_ENABLED)) - space->set_log_unmap(false); - } + if (!machine().options().log() && !machine().options().oslog() && !(machine().debug_flags & DEBUG_FLAG_ENABLED)) + for (auto const memory : memories) + memory->set_log_unmap(false); // register a callback to reset banks when reloading state machine().save().register_postload(save_prepost_delegate(FUNC(memory_manager::bank_reattach), this)); @@ -1627,20 +1706,9 @@ void memory_manager::dump(FILE *file) return; // loop over address spaces - for (auto &space : m_spacelist) - { - fprintf(file, "\n\n" - "====================================================\n" - "Device '%s' %s address space read handler dump\n" - "====================================================\n", space->device().tag(), space->name()); - space->dump_map(file, read_or_write::READ); - - fprintf(file, "\n\n" - "====================================================\n" - "Device '%s' %s address space write handler dump\n" - "====================================================\n", space->device().tag(), space->name()); - space->dump_map(file, read_or_write::WRITE); - } + memory_interface_iterator iter(machine().root_device()); + for (device_memory_interface &memory : iter) + memory.dump(file); } @@ -1747,8 +1815,6 @@ address_space::address_space(memory_manager &manager, device_memory_interface &m m_manager(manager), m_machine(memory.device().machine()) { - // notify the device - memory.set_address_space(spacenum, *this); } @@ -1761,90 +1827,6 @@ address_space::~address_space() } -//------------------------------------------------- -// allocate - static smart allocator of subtypes -//------------------------------------------------- - -void address_space::allocate(std::vector> &space_list,memory_manager &manager, const address_space_config &config, device_memory_interface &memory, int spacenum) -{ - // allocate one of the appropriate type - bool large = (config.addr2byte_end(0xffffffffUL >> (32 - config.m_addrbus_width)) >= (1 << 18)); - - switch (config.data_width()) - { - case 8: - if (config.endianness() == ENDIANNESS_LITTLE) - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - else - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - break; - - case 16: - if (config.endianness() == ENDIANNESS_LITTLE) - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - else - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - break; - - case 32: - if (config.endianness() == ENDIANNESS_LITTLE) - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - else - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - break; - - case 64: - if (config.endianness() == ENDIANNESS_LITTLE) - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - else - { - if (large) - space_list.push_back(std::make_unique(manager, memory, spacenum)); - else - space_list.push_back(std::make_unique(manager, memory, spacenum)); - } - break; - default: - throw emu_fatalerror("Invalid width %d specified for address_space::allocate", config.data_width()); - } -} - - //------------------------------------------------- // adjust_addresses - adjust addresses for a // given address space in a standard fashion diff --git a/src/emu/emumem.h b/src/emu/emumem.h index dd6ff5df38e..3b6a9ea3d3e 100644 --- a/src/emu/emumem.h +++ b/src/emu/emumem.h @@ -226,8 +226,6 @@ protected: public: virtual ~address_space(); - // public allocator - static void allocate(std::vector> &space_list, memory_manager &manager, const address_space_config &config, device_memory_interface &memory, int spacenum); // getters memory_manager &manager() const { return m_manager; } @@ -673,7 +671,6 @@ private: u8 * m_bank_ptr[TOTAL_MEMORY_BANKS]; // array of bank pointers - std::vector> m_spacelist; // list of address spaces std::vector> m_blocklist; // head of the list of memory blocks std::unordered_map> m_banklist; // data gathered for each bank