Bus: Calculation of memory timings for external devices
This commit is contained in:
parent
0b46a8cfc4
commit
fd1c4f1457
|
@ -51,14 +51,15 @@ void Bus::Reset()
|
||||||
m_ram.fill(static_cast<u8>(0));
|
m_ram.fill(static_cast<u8>(0));
|
||||||
m_MEMCTRL.exp1_base = 0x1F000000;
|
m_MEMCTRL.exp1_base = 0x1F000000;
|
||||||
m_MEMCTRL.exp2_base = 0x1F802000;
|
m_MEMCTRL.exp2_base = 0x1F802000;
|
||||||
m_MEMCTRL.exp1_delay_size = 0x0013243F;
|
m_MEMCTRL.exp1_delay_size.bits = 0x0013243F;
|
||||||
m_MEMCTRL.exp3_delay_size = 0x00003022;
|
m_MEMCTRL.exp3_delay_size.bits = 0x00003022;
|
||||||
m_MEMCTRL.bios_delay_size = 0x0013243F;
|
m_MEMCTRL.bios_delay_size.bits = 0x0013243F;
|
||||||
m_MEMCTRL.spu_delay_size = 0x200931E1;
|
m_MEMCTRL.spu_delay_size.bits = 0x200931E1;
|
||||||
m_MEMCTRL.cdrom_delay_size = 0x00020843;
|
m_MEMCTRL.cdrom_delay_size.bits = 0x00020843;
|
||||||
m_MEMCTRL.exp2_delay_size = 0x00070777;
|
m_MEMCTRL.exp2_delay_size.bits = 0x00070777;
|
||||||
m_MEMCTRL.common_delay_size = 0x00031125;
|
m_MEMCTRL.common_delay.bits = 0x00031125;
|
||||||
m_ram_size_reg = UINT32_C(0x00000B88);
|
m_ram_size_reg = UINT32_C(0x00000B88);
|
||||||
|
RecalculateMemoryTimings();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bus::DoState(StateWrapper& sw)
|
bool Bus::DoState(StateWrapper& sw)
|
||||||
|
@ -167,6 +168,61 @@ bool Bus::LoadBIOS()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<TickCount, TickCount, TickCount> Bus::CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay)
|
||||||
|
{
|
||||||
|
// from nocash spec
|
||||||
|
s32 first = 0, seq = 0, min = 0;
|
||||||
|
if (mem_delay.use_com0_time)
|
||||||
|
{
|
||||||
|
first += s32(common_delay.com0) - 1;
|
||||||
|
seq += s32(common_delay.com0) - 1;
|
||||||
|
}
|
||||||
|
if (mem_delay.use_com2_time)
|
||||||
|
{
|
||||||
|
first += s32(common_delay.com2);
|
||||||
|
seq += s32(common_delay.com2);
|
||||||
|
}
|
||||||
|
if (mem_delay.use_com3_time)
|
||||||
|
{
|
||||||
|
min = s32(common_delay.com3);
|
||||||
|
}
|
||||||
|
if (first < 6)
|
||||||
|
first++;
|
||||||
|
|
||||||
|
first = first + s32(mem_delay.access_time) + 2;
|
||||||
|
seq = seq + s32(mem_delay.access_time) + 2;
|
||||||
|
|
||||||
|
if (first < (min + 6))
|
||||||
|
first = min + 6;
|
||||||
|
if (seq < (min + 2))
|
||||||
|
seq = min + 2;
|
||||||
|
|
||||||
|
const TickCount byte_access_time = first;
|
||||||
|
const TickCount halfword_access_time = mem_delay.data_bus_16bit ? first : (first + seq);
|
||||||
|
const TickCount word_access_time = mem_delay.data_bus_16bit ? (first + seq) : (first + seq + seq + seq);
|
||||||
|
return std::tie(byte_access_time, halfword_access_time, word_access_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bus::RecalculateMemoryTimings()
|
||||||
|
{
|
||||||
|
std::tie(m_bios_access_time[0], m_bios_access_time[1], m_bios_access_time[2]) =
|
||||||
|
CalculateMemoryTiming(m_MEMCTRL.bios_delay_size, m_MEMCTRL.common_delay);
|
||||||
|
std::tie(m_cdrom_access_time[0], m_cdrom_access_time[1], m_cdrom_access_time[2]) =
|
||||||
|
CalculateMemoryTiming(m_MEMCTRL.cdrom_delay_size, m_MEMCTRL.common_delay);
|
||||||
|
std::tie(m_spu_access_time[0], m_spu_access_time[1], m_spu_access_time[2]) =
|
||||||
|
CalculateMemoryTiming(m_MEMCTRL.spu_delay_size, m_MEMCTRL.common_delay);
|
||||||
|
|
||||||
|
Log_DevPrintf("BIOS Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
||||||
|
m_MEMCTRL.bios_delay_size.data_bus_16bit ? 16 : 8, m_bios_access_time[0], m_bios_access_time[1],
|
||||||
|
m_bios_access_time[2]);
|
||||||
|
Log_DevPrintf("CDROM Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
||||||
|
m_MEMCTRL.cdrom_delay_size.data_bus_16bit ? 16 : 8, m_cdrom_access_time[0], m_cdrom_access_time[1],
|
||||||
|
m_cdrom_access_time[2]);
|
||||||
|
Log_DevPrintf("SPU Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
||||||
|
m_MEMCTRL.spu_delay_size.data_bus_16bit ? 16 : 8, m_spu_access_time[0], m_spu_access_time[1],
|
||||||
|
m_spu_access_time[2]);
|
||||||
|
}
|
||||||
|
|
||||||
bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value)
|
bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value)
|
||||||
{
|
{
|
||||||
SmallString str;
|
SmallString str;
|
||||||
|
@ -292,7 +348,16 @@ bool Bus::DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value)
|
||||||
bool Bus::DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value)
|
bool Bus::DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
FixupUnalignedWordAccessW32(offset, value);
|
FixupUnalignedWordAccessW32(offset, value);
|
||||||
m_MEMCTRL.regs[offset / 4] = value;
|
|
||||||
|
const u32 index = offset / 4;
|
||||||
|
const u32 write_mask = (index == 8) ? COMDELAY::WRITE_MASK : MEMDELAY::WRITE_MASK;
|
||||||
|
const u32 new_value = (m_MEMCTRL.regs[index] & ~write_mask) | (value & write_mask);
|
||||||
|
if (m_MEMCTRL.regs[index] != new_value)
|
||||||
|
{
|
||||||
|
m_MEMCTRL.regs[index] = new_value;
|
||||||
|
RecalculateMemoryTimings();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "YBaseLib/String.h"
|
#include "YBaseLib/String.h"
|
||||||
|
#include "common/bitfield.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
@ -95,6 +96,34 @@ private:
|
||||||
MEMCTRL_REG_COUNT = 9
|
MEMCTRL_REG_COUNT = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union MEMDELAY
|
||||||
|
{
|
||||||
|
u32 bits;
|
||||||
|
|
||||||
|
BitField<u32, u8, 4, 4> access_time; // cycles
|
||||||
|
BitField<u32, bool, 8, 1> use_com0_time;
|
||||||
|
BitField<u32, bool, 9, 1> use_com1_time;
|
||||||
|
BitField<u32, bool, 10, 1> use_com2_time;
|
||||||
|
BitField<u32, bool, 11, 1> use_com3_time;
|
||||||
|
BitField<u32, bool, 12, 1> data_bus_16bit;
|
||||||
|
BitField<u32, u8, 16, 5> memory_window_size;
|
||||||
|
|
||||||
|
static constexpr u32 WRITE_MASK = 0b10101111'00011111'11111111'11111111;
|
||||||
|
};
|
||||||
|
|
||||||
|
union COMDELAY
|
||||||
|
{
|
||||||
|
u32 bits;
|
||||||
|
|
||||||
|
BitField<u32, u8, 0, 4> com0;
|
||||||
|
BitField<u32, u8, 4, 4> com1;
|
||||||
|
BitField<u32, u8, 8, 4> com2;
|
||||||
|
BitField<u32, u8, 12, 4> com3;
|
||||||
|
BitField<u32, u8, 16, 2> comunk;
|
||||||
|
|
||||||
|
static constexpr u32 WRITE_MASK = 0b00000000'00000011'11111111'11111111;
|
||||||
|
};
|
||||||
|
|
||||||
union MEMCTRL
|
union MEMCTRL
|
||||||
{
|
{
|
||||||
u32 regs[MEMCTRL_REG_COUNT];
|
u32 regs[MEMCTRL_REG_COUNT];
|
||||||
|
@ -103,18 +132,21 @@ private:
|
||||||
{
|
{
|
||||||
u32 exp1_base;
|
u32 exp1_base;
|
||||||
u32 exp2_base;
|
u32 exp2_base;
|
||||||
u32 exp1_delay_size;
|
MEMDELAY exp1_delay_size;
|
||||||
u32 exp3_delay_size;
|
MEMDELAY exp3_delay_size;
|
||||||
u32 bios_delay_size;
|
MEMDELAY bios_delay_size;
|
||||||
u32 spu_delay_size;
|
MEMDELAY spu_delay_size;
|
||||||
u32 cdrom_delay_size;
|
MEMDELAY cdrom_delay_size;
|
||||||
u32 exp2_delay_size;
|
MEMDELAY exp2_delay_size;
|
||||||
u32 common_delay_size;
|
COMDELAY common_delay;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LoadBIOS();
|
bool LoadBIOS();
|
||||||
|
|
||||||
|
static std::tuple<TickCount, TickCount, TickCount> CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay);
|
||||||
|
void RecalculateMemoryTimings();
|
||||||
|
|
||||||
template<MemoryAccessType type, MemoryAccessSize size>
|
template<MemoryAccessType type, MemoryAccessSize size>
|
||||||
bool DoRAMAccess(u32 offset, u32& value);
|
bool DoRAMAccess(u32 offset, u32& value);
|
||||||
|
|
||||||
|
@ -172,6 +204,10 @@ private:
|
||||||
SPU* m_spu = nullptr;
|
SPU* m_spu = nullptr;
|
||||||
MDEC* m_mdec = nullptr;
|
MDEC* m_mdec = nullptr;
|
||||||
|
|
||||||
|
std::array<TickCount, 3> m_bios_access_time = {};
|
||||||
|
std::array<TickCount, 3> m_cdrom_access_time = {};
|
||||||
|
std::array<TickCount, 3> m_spu_access_time = {};
|
||||||
|
|
||||||
std::array<u8, 2097152> m_ram{}; // 2MB RAM
|
std::array<u8, 2097152> m_ram{}; // 2MB RAM
|
||||||
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM
|
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM
|
||||||
std::vector<u8> m_exp1_rom;
|
std::vector<u8> m_exp1_rom;
|
||||||
|
|
Loading…
Reference in New Issue