Make device_memory_interface own its address_spaces

This commit is contained in:
Vas Crabb 2017-07-13 15:35:18 +10:00
parent e42bb7d2f1
commit 66de90675f
4 changed files with 138 additions and 130 deletions

View File

@ -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);
}
}

View File

@ -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 <typename Space> void allocate(memory_manager &manager, int spacenum)
{
assert((0 <= spacenum) && (max_space_count() > spacenum));
m_addrspace.resize(std::max<std::size_t>(m_addrspace.size(), spacenum + 1));
assert(!m_addrspace[spacenum]);
m_addrspace[spacenum] = std::make_unique<Space>(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<std::pair<int, const address_space_config *>>;
@ -120,8 +134,8 @@ protected:
private:
// internal state
std::vector<const address_space_config *> m_address_config; // configuration for each space
std::vector<address_space *> m_addrspace; // reported address spaces
std::vector<const address_space_config *> m_address_config; // configuration for each space
std::vector<std::unique_ptr<address_space>> m_addrspace; // reported address spaces
};
// iterator

View File

@ -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<address_space_8le_large>(*this, spacenum);
else
memory.allocate<address_space_8le_small>(*this, spacenum);
}
else
{
if (large)
memory.allocate<address_space_8be_large>(*this, spacenum);
else
memory.allocate<address_space_8be_small>(*this, spacenum);
}
break;
case 16:
if (spaceconfig->endianness() == ENDIANNESS_LITTLE)
{
if (large)
memory.allocate<address_space_16le_large>(*this, spacenum);
else
memory.allocate<address_space_16le_small>(*this, spacenum);
}
else
{
if (large)
memory.allocate<address_space_16be_large>(*this, spacenum);
else
memory.allocate<address_space_16be_small>(*this, spacenum);
}
break;
case 32:
if (spaceconfig->endianness() == ENDIANNESS_LITTLE)
{
if (large)
memory.allocate<address_space_32le_large>(*this, spacenum);
else
memory.allocate<address_space_32le_small>(*this, spacenum);
}
else
{
if (large)
memory.allocate<address_space_32be_large>(*this, spacenum);
else
memory.allocate<address_space_32be_small>(*this, spacenum);
}
break;
case 64:
if (spaceconfig->endianness() == ENDIANNESS_LITTLE)
{
if (large)
memory.allocate<address_space_64le_large>(*this, spacenum);
else
memory.allocate<address_space_64le_small>(*this, spacenum);
}
else
{
if (large)
memory.allocate<address_space_64be_large>(*this, spacenum);
else
memory.allocate<address_space_64be_small>(*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<device_memory_interface *> 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<std::unique_ptr<address_space>> &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<address_space_8le_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_8le_small>(manager, memory, spacenum));
}
else
{
if (large)
space_list.push_back(std::make_unique<address_space_8be_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_8be_small>(manager, memory, spacenum));
}
break;
case 16:
if (config.endianness() == ENDIANNESS_LITTLE)
{
if (large)
space_list.push_back(std::make_unique<address_space_16le_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_16le_small>(manager, memory, spacenum));
}
else
{
if (large)
space_list.push_back(std::make_unique<address_space_16be_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_16be_small>(manager, memory, spacenum));
}
break;
case 32:
if (config.endianness() == ENDIANNESS_LITTLE)
{
if (large)
space_list.push_back(std::make_unique<address_space_32le_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_32le_small>(manager, memory, spacenum));
}
else
{
if (large)
space_list.push_back(std::make_unique<address_space_32be_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_32be_small>(manager, memory, spacenum));
}
break;
case 64:
if (config.endianness() == ENDIANNESS_LITTLE)
{
if (large)
space_list.push_back(std::make_unique<address_space_64le_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_64le_small>(manager, memory, spacenum));
}
else
{
if (large)
space_list.push_back(std::make_unique<address_space_64be_large>(manager, memory, spacenum));
else
space_list.push_back(std::make_unique<address_space_64be_small>(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

View File

@ -226,8 +226,6 @@ protected:
public:
virtual ~address_space();
// public allocator
static void allocate(std::vector<std::unique_ptr<address_space>> &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<std::unique_ptr<address_space>> m_spacelist; // list of address spaces
std::vector<std::unique_ptr<memory_block>> m_blocklist; // head of the list of memory blocks
std::unordered_map<std::string,std::unique_ptr<memory_bank>> m_banklist; // data gathered for each bank