machinegazelle: Use specified DIMM sizes.

Previously, only the total size of all DIMMs was used. For example, four
8 MB DIMMs would behave as a single 32 MB DIMM.

This change forces handling of the individual DIMM sizes.

We currently do not emulate shuffling of 4MB pages. For example, the
data of the first page of bank 1 does not move if you move it to a
different page.

The important parts of this algorithm are:
1) DIMM sizes can be determined.
2) The final memory allocation will be a single contiguous block.
This commit is contained in:
joevt
2024-12-10 23:09:08 -08:00
committed by Maxim Poliakovski
parent 678b51ddfb
commit 59abb96caa
3 changed files with 60 additions and 21 deletions
+51 -11
View File
@@ -75,12 +75,15 @@ void PsxCtrl::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int siz
case PsxReg::Flash_Config:
this->flash_cfg = value;
break;
case PsxReg::Page1_Mapping:
case PsxReg::Page2_Mapping:
case PsxReg::Page3_Mapping:
case PsxReg::Page4_Mapping:
case PsxReg::Page5_Mapping:
this->pages_cfg[(offset >> 3) - PsxReg::Page1_Mapping] = value;
case PsxReg::Page_Mappings_1:
case PsxReg::Page_Mappings_2:
case PsxReg::Page_Mappings_3:
case PsxReg::Page_Mappings_4:
case PsxReg::Page_Mappings_5:
LOG_F(INFO, "PSX: write Page Mappings %d @%02x.%c = %0*x",
(offset >> 3) - PsxReg::Page_Mappings_1 + 1, offset, SIZE_ARG(size), size * 2, value);
this->pages_cfg[(offset >> 3) - PsxReg::Page_Mappings_1] = value;
this->map_phys_ram();
break;
default:
LOG_F(WARNING, "PSX: write to unsupported/read-only control register at 0x%X", offset);
@@ -96,12 +99,11 @@ void PsxCtrl::insert_ram_dimm(int slot_num, uint32_t capacity)
switch (capacity) {
case 0:
break;
case DRAM_CAP_2MB:
case DRAM_CAP_4MB:
case DRAM_CAP_8MB:
case DRAM_CAP_16MB:
case DRAM_CAP_32MB:
this->bank_sizes[slot_num] = capacity;
this->bank_size[slot_num] = capacity;
break;
default:
ABORT_F("PSX: unsupported DRAM capacity %d", capacity);
@@ -111,13 +113,51 @@ void PsxCtrl::insert_ram_dimm(int slot_num, uint32_t capacity)
void PsxCtrl::map_phys_ram()
{
uint32_t total_ram = 0;
uint32_t bank_size_remaining[5];
for (int i = 0; i < 5; i++) {
total_ram += this->bank_sizes[i];
bank_size_remaining[i] = this->bank_size[i];
total_ram += this->bank_size[i];
}
if (!add_ram_region(0x00000000, total_ram)) {
ABORT_F("PSX: could not allocate RAM storage");
if (!this->dram_ptr) {
this->dram_ptr = std::unique_ptr<uint8_t[]> (new uint8_t[total_ram]()); /* () intializer clears the memory to zero */
if (!this->dram_ptr) {
ABORT_F("%s: could not allocate RAM storage", this->name.c_str());
}
}
ram_map.erase(std::remove_if(ram_map.begin(), ram_map.end(),
[this](AddressMapEntry *entry) {
delete this->remove_region(entry);
return true;
}
), ram_map.end());
uint32_t ram_offset = -1;
uint32_t mem_start = 0;
for (int page = 0; page < 41; page++) {
int bank = page >= 40 ? 8 : (this->pages_cfg[page / 8] >> ((page % 8) * 4)) & 15;
//LOG_F(INFO, "page:%02d bank:%d", page, bank);
if ((ram_offset == -1) == (bank < 5 && bank_size_remaining[bank] > 0)) {
if (ram_offset == -1) {
ram_offset = page * DRAM_CAP_4MB;
//LOG_F(INFO, "ram_offset:%08x", ram_offset);
} else {
uint32_t mem_size = page * DRAM_CAP_4MB - ram_offset;
AddressMapEntry *entry = this->add_ram_region(ram_offset, mem_size, &dram_ptr[mem_start]);
mem_start += mem_size;
ram_offset = -1;
if (entry) {
ram_map.push_back(entry);
} else {
ABORT_F("%s: could not allocate RAM storage", this->name.c_str());
}
}
}
if (ram_offset != -1) {
bank_size_remaining[bank] -= DRAM_CAP_4MB;
}
}
}
+9 -7
View File
@@ -40,11 +40,11 @@ namespace PsxReg {
DRAM_Config = 4,
DRAM_Refresh = 5,
Flash_Config = 6,
Page1_Mapping = 8,
Page2_Mapping = 9,
Page3_Mapping = 10,
Page4_Mapping = 11,
Page5_Mapping = 12,
Page_Mappings_1 = 8,
Page_Mappings_2 = 9,
Page_Mappings_3 = 10,
Page_Mappings_4 = 11,
Page_Mappings_5 = 12,
Bus_Timeout = 13
};
} // namespace PsxReg
@@ -81,8 +81,10 @@ private:
uint32_t dram_cfg;
uint32_t dram_refresh;
uint32_t flash_cfg;
uint32_t pages_cfg[5];
uint32_t bank_sizes[5] = {};
uint32_t pages_cfg[5] = {0x88888888,0x88888888,0x88888888,0x88888888,0x88888888};
uint32_t bank_size[5] = {};
std::unique_ptr<uint8_t[]> dram_ptr = nullptr;
std::vector<AddressMapEntry*> ram_map;
};
#endif // PSX_MEMCTRL_H
-3
View File
@@ -90,9 +90,6 @@ int MachineGazelle::initialize(const std::string &id) {
psx_obj->insert_ram_dimm(3, GET_INT_PROP("rambank4_size") * DRAM_CAP_1MB);
psx_obj->insert_ram_dimm(4, GET_INT_PROP("rambank5_size") * DRAM_CAP_1MB);
// allocate and map physical RAM
psx_obj->map_phys_ram();
// configure CPU clocks
uint64_t bus_freq = 50000000ULL;
uint64_t timebase_freq = bus_freq / 4;