mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
Bus: Reduce RAM write delay
This commit is contained in:
parent
b3cf18b593
commit
aec01d3890
|
@ -225,7 +225,8 @@ std::tuple<TickCount, TickCount, TickCount> Bus::CalculateMemoryTiming(MEMDELAY
|
||||||
const TickCount byte_access_time = first;
|
const TickCount byte_access_time = first;
|
||||||
const TickCount halfword_access_time = mem_delay.data_bus_16bit ? first : (first + seq);
|
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);
|
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);
|
return std::tie(std::max(byte_access_time - 1, 0), std::max(halfword_access_time - 1, 0),
|
||||||
|
std::max(word_access_time - 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::RecalculateMemoryTimings()
|
void Bus::RecalculateMemoryTimings()
|
||||||
|
@ -238,14 +239,14 @@ void Bus::RecalculateMemoryTimings()
|
||||||
CalculateMemoryTiming(m_MEMCTRL.spu_delay_size, m_MEMCTRL.common_delay);
|
CalculateMemoryTiming(m_MEMCTRL.spu_delay_size, m_MEMCTRL.common_delay);
|
||||||
|
|
||||||
Log_TracePrintf("BIOS Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
Log_TracePrintf("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_MEMCTRL.bios_delay_size.data_bus_16bit ? 16 : 8, m_bios_access_time[0] + 1,
|
||||||
m_bios_access_time[2]);
|
m_bios_access_time[1] + 1, m_bios_access_time[2] + 1);
|
||||||
Log_TracePrintf("CDROM Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
Log_TracePrintf("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_MEMCTRL.cdrom_delay_size.data_bus_16bit ? 16 : 8, m_cdrom_access_time[0] + 1,
|
||||||
m_cdrom_access_time[2]);
|
m_cdrom_access_time[1] + 1, m_cdrom_access_time[2] + 1);
|
||||||
Log_TracePrintf("SPU Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d",
|
Log_TracePrintf("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_MEMCTRL.spu_delay_size.data_bus_16bit ? 16 : 8, m_spu_access_time[0] + 1, m_spu_access_time[1] + 1,
|
||||||
m_spu_access_time[2]);
|
m_spu_access_time[2] + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TickCount Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value)
|
TickCount Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value)
|
||||||
|
|
|
@ -134,10 +134,16 @@ private:
|
||||||
|
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
RAM_ACCESS_DELAY = 6, // Nocash docs say RAM takes 6 cycles to access.
|
|
||||||
MEMCTRL_REG_COUNT = 9
|
MEMCTRL_REG_COUNT = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum : TickCount
|
||||||
|
{
|
||||||
|
RAM_READ_ACCESS_DELAY = 5, // Nocash docs say RAM takes 6 cycles to access. Subtract one because we already add a
|
||||||
|
// tick for the instruction.
|
||||||
|
RAM_WRITE_ACCESS_DELAY = 0, // Writes are free unless we're executing more than 4 stores in a row.
|
||||||
|
};
|
||||||
|
|
||||||
union MEMDELAY
|
union MEMDELAY
|
||||||
{
|
{
|
||||||
u32 bits;
|
u32 bits;
|
||||||
|
|
|
@ -45,7 +45,7 @@ TickCount Bus::DoRAMAccess(u32 offset, u32& value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nocash docs say RAM takes 6 cycles to access.
|
// Nocash docs say RAM takes 6 cycles to access.
|
||||||
return RAM_ACCESS_DELAY;
|
return (type == MemoryAccessType::Read) ? RAM_READ_ACCESS_DELAY : RAM_WRITE_ACCESS_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<MemoryAccessType type, MemoryAccessSize size>
|
template<MemoryAccessType type, MemoryAccessSize size>
|
||||||
|
@ -92,11 +92,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else if (address < (EXP1_BASE + EXP1_SIZE))
|
else if (address < (EXP1_BASE + EXP1_SIZE))
|
||||||
{
|
{
|
||||||
if constexpr (type == MemoryAccessType::Read)
|
if constexpr (type == MemoryAccessType::Read)
|
||||||
|
{
|
||||||
value = DoReadEXP1(size, address & EXP1_MASK);
|
value = DoReadEXP1(size, address & EXP1_MASK);
|
||||||
|
return m_exp1_access_time[static_cast<u32>(size)];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DoWriteEXP1(size, address & EXP1_MASK, value);
|
DoWriteEXP1(size, address & EXP1_MASK, value);
|
||||||
|
return 0;
|
||||||
return m_exp1_access_time[static_cast<u32>(size)];
|
}
|
||||||
}
|
}
|
||||||
else if (address < MEMCTRL_BASE)
|
else if (address < MEMCTRL_BASE)
|
||||||
{
|
{
|
||||||
|
@ -109,7 +113,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteMemoryControl(size, address & PAD_MASK, value);
|
DoWriteMemoryControl(size, address & PAD_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (PAD_BASE + PAD_SIZE))
|
else if (address < (PAD_BASE + PAD_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -118,7 +122,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWritePad(size, address & PAD_MASK, value);
|
DoWritePad(size, address & PAD_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (SIO_BASE + SIO_SIZE))
|
else if (address < (SIO_BASE + SIO_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -127,7 +131,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteSIO(size, address & SIO_MASK, value);
|
DoWriteSIO(size, address & SIO_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (MEMCTRL2_BASE + MEMCTRL2_SIZE))
|
else if (address < (MEMCTRL2_BASE + MEMCTRL2_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -136,7 +140,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteMemoryControl2(size, address & PAD_MASK, value);
|
DoWriteMemoryControl2(size, address & PAD_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE))
|
else if (address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -145,7 +149,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value);
|
DoWriteInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (DMA_BASE + DMA_SIZE))
|
else if (address < (DMA_BASE + DMA_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -154,7 +158,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteDMA(size, address & DMA_MASK, value);
|
DoWriteDMA(size, address & DMA_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (TIMERS_BASE + TIMERS_SIZE))
|
else if (address < (TIMERS_BASE + TIMERS_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -163,7 +167,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteTimers(size, address & TIMERS_MASK, value);
|
DoWriteTimers(size, address & TIMERS_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < CDROM_BASE)
|
else if (address < CDROM_BASE)
|
||||||
{
|
{
|
||||||
|
@ -172,11 +176,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else if (address < (CDROM_BASE + GPU_SIZE))
|
else if (address < (CDROM_BASE + GPU_SIZE))
|
||||||
{
|
{
|
||||||
if constexpr (type == MemoryAccessType::Read)
|
if constexpr (type == MemoryAccessType::Read)
|
||||||
|
{
|
||||||
value = DoReadCDROM(size, address & CDROM_MASK);
|
value = DoReadCDROM(size, address & CDROM_MASK);
|
||||||
|
return m_cdrom_access_time[static_cast<u32>(size)];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DoWriteCDROM(size, address & CDROM_MASK, value);
|
DoWriteCDROM(size, address & CDROM_MASK, value);
|
||||||
|
return 0;
|
||||||
return m_cdrom_access_time[static_cast<u32>(size)];
|
}
|
||||||
}
|
}
|
||||||
else if (address < (GPU_BASE + GPU_SIZE))
|
else if (address < (GPU_BASE + GPU_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -185,7 +193,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteGPU(size, address & GPU_MASK, value);
|
DoWriteGPU(size, address & GPU_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < (MDEC_BASE + MDEC_SIZE))
|
else if (address < (MDEC_BASE + MDEC_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -194,7 +202,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
DoWriteMDEC(size, address & MDEC_MASK, value);
|
DoWriteMDEC(size, address & MDEC_MASK, value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (address < SPU_BASE)
|
else if (address < SPU_BASE)
|
||||||
{
|
{
|
||||||
|
@ -203,11 +211,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else if (address < (SPU_BASE + SPU_SIZE))
|
else if (address < (SPU_BASE + SPU_SIZE))
|
||||||
{
|
{
|
||||||
if constexpr (type == MemoryAccessType::Read)
|
if constexpr (type == MemoryAccessType::Read)
|
||||||
|
{
|
||||||
value = DoReadSPU(size, address & SPU_MASK);
|
value = DoReadSPU(size, address & SPU_MASK);
|
||||||
|
return m_spu_access_time[static_cast<u32>(size)];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DoWriteSPU(size, address & SPU_MASK, value);
|
DoWriteSPU(size, address & SPU_MASK, value);
|
||||||
|
return 0;
|
||||||
return m_spu_access_time[static_cast<u32>(size)];
|
}
|
||||||
}
|
}
|
||||||
else if (address < EXP2_BASE)
|
else if (address < EXP2_BASE)
|
||||||
{
|
{
|
||||||
|
@ -216,11 +228,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
|
||||||
else if (address < (EXP2_BASE + EXP2_SIZE))
|
else if (address < (EXP2_BASE + EXP2_SIZE))
|
||||||
{
|
{
|
||||||
if constexpr (type == MemoryAccessType::Read)
|
if constexpr (type == MemoryAccessType::Read)
|
||||||
|
{
|
||||||
value = DoReadEXP2(size, address & EXP2_MASK);
|
value = DoReadEXP2(size, address & EXP2_MASK);
|
||||||
|
return m_exp2_access_time[static_cast<u32>(size)];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DoWriteEXP2(size, address & EXP2_MASK, value);
|
DoWriteEXP2(size, address & EXP2_MASK, value);
|
||||||
|
return 0;
|
||||||
return m_exp2_access_time[static_cast<u32>(size)];
|
}
|
||||||
}
|
}
|
||||||
else if (address < BIOS_BASE)
|
else if (address < BIOS_BASE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,7 +123,7 @@ bool Core::ReadMemoryByte(VirtualMemoryAddress addr, u8* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
AddTicks(cycles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ bool Core::ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
AddTicks(cycles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ bool Core::ReadMemoryWord(VirtualMemoryAddress addr, u32* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
AddTicks(cycles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ bool Core::WriteMemoryByte(VirtualMemoryAddress addr, u8 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
DebugAssert(cycles == 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +188,8 @@ bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
DebugAssert(cycles == 0);
|
||||||
return cycles;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value)
|
bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value)
|
||||||
|
@ -204,7 +204,7 @@ bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTicks(cycles - 1);
|
DebugAssert(cycles == 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
|
||||||
if constexpr (type == MemoryAccessType::Write)
|
if constexpr (type == MemoryAccessType::Write)
|
||||||
{
|
{
|
||||||
if (m_cop0_regs.sr.Isc)
|
if (m_cop0_regs.sr.Isc)
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF);
|
const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF);
|
||||||
if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION)
|
if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION)
|
||||||
{
|
{
|
||||||
DoScratchpadAccess<type, size>(phys_addr, value);
|
DoScratchpadAccess<type, size>(phys_addr, value);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_bus->DispatchAccess<type, size>(phys_addr, value);
|
return m_bus->DispatchAccess<type, size>(phys_addr, value);
|
||||||
|
@ -41,14 +41,14 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
|
||||||
if constexpr (type == MemoryAccessType::Write)
|
if constexpr (type == MemoryAccessType::Write)
|
||||||
{
|
{
|
||||||
if (m_cop0_regs.sr.Isc)
|
if (m_cop0_regs.sr.Isc)
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF);
|
const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF);
|
||||||
if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION)
|
if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION)
|
||||||
{
|
{
|
||||||
DoScratchpadAccess<type, size>(phys_addr, value);
|
DoScratchpadAccess<type, size>(phys_addr, value);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_bus->DispatchAccess<type, size>(phys_addr, value);
|
return m_bus->DispatchAccess<type, size>(phys_addr, value);
|
||||||
|
@ -72,7 +72,7 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
|
||||||
else
|
else
|
||||||
WriteCacheControl(value);
|
WriteCacheControl(value);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@ u64 Thunks::ReadMemoryByte(Core* cpu, u32 address)
|
||||||
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddTicks(cycles - 1);
|
cpu->AddTicks(cycles);
|
||||||
return ZeroExtend64(temp);
|
return ZeroExtend64(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ u64 Thunks::ReadMemoryHalfWord(Core* cpu, u32 address)
|
||||||
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddTicks(cycles - 1);
|
cpu->AddTicks(cycles);
|
||||||
return ZeroExtend64(temp);
|
return ZeroExtend64(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ u64 Thunks::ReadMemoryWord(Core* cpu, u32 address)
|
||||||
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddTicks(cycles - 1);
|
cpu->AddTicks(cycles);
|
||||||
return ZeroExtend64(temp);
|
return ZeroExtend64(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue