From 05c0fd139e1a5101920d4a274f7c77097ffa58f9 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Mon, 5 Jun 2023 17:32:11 +0200 Subject: [PATCH] schedule pi dma --- src/backend/core/mmio/PI.cpp | 94 +++++++++++++++++++++++++++++------- src/backend/core/mmio/PI.hpp | 5 +- src/backend/core/mmio/SI.cpp | 11 ++--- src/backend/core/mmio/SI.hpp | 2 - 4 files changed, 86 insertions(+), 26 deletions(-) diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index efa5ad44..5c52285f 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "Scheduler.hpp" namespace n64 { PI::PI() { @@ -30,14 +31,85 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 { value |= (mi.miIntr.pi << 3); // PI interrupt? return value; } - case 0x04600014: case 0x04600018: case 0x0460001C: case 0x04600020: - case 0x04600024: case 0x04600028: case 0x0460002C: case 0x04600030: - return stub[(addr & 0xff) - 5]; + case 0x04600014: return pi_bsd_dom1_lat; + case 0x04600018: return pi_bsd_dom1_pwd; + case 0x0460001C: return pi_bsd_dom1_pgs; + case 0x04600020: return pi_bsd_dom1_rls; + case 0x04600024: return pi_bsd_dom2_lat; + case 0x04600028: return pi_bsd_dom2_pwd; + case 0x0460002C: return pi_bsd_dom2_pgs; + case 0x04600030: return pi_bsd_dom2_rls; default: Util::panic("Unhandled PI[{:08X}] read", addr); } } +FORCE_INLINE u8 PIGetDomain(u32 address) { + switch (address) { + case 0x6000000 ... 0x7FFFFFF: + case REGION_CART_1_2: + return 1; + case REGION_CART_2_1: + case REGION_CART_2_2: + return 2; + default: + logfatal("Unknown PI domain for address %08X!\n", address); + } +} + +FORCE_INLINE u32 PIAccessTiming(PI& pi, u8 domain, u32 length) { + uint32_t cycles = 0; + uint32_t latency = 0; + uint32_t pulse_width = 0; + uint32_t release = 0; + uint32_t page_size = 0; + uint32_t pages = 0; + + switch (domain) { + case 1: + latency = pi.pi_bsd_dom1_lat + 1; + pulse_width = pi.pi_bsd_dom1_pwd + 1; + release = pi.pi_bsd_dom1_rls + 1; + page_size = pow(2, (pi.pi_bsd_dom1_pgs + 2)); + break; + case 2: + latency = pi.pi_bsd_dom2_lat + 1; + pulse_width = pi.pi_bsd_dom2_pwd + 1; + release = pi.pi_bsd_dom2_rls + 1; + page_size = pow(2, (pi.pi_bsd_dom2_pgs + 2)); + break; + default: + Util::panic("Unknown PI domain: %d\n", domain); + } + + pages = ceil((double)length / page_size); + + cycles += (14 + latency) * pages; + cycles += (pulse_width + release) * (length / 2); + cycles += 5 * pages; + return cycles * 1.5; // Converting RCP clock speed to CPU clock speed +} + +template +FORCE_INLINE void DMA(Mem& mem, Registers& regs) { + MI& mi = mem.mmio.mi; + PI& pi = mem.mmio.pi; + u32 len = toCart ? pi.rdLen : pi.wrLen; + u32 cart_addr = pi.cartAddr & 0xFFFFFFFE; + u32 dram_addr = pi.dramAddr & 0x007FFFFE; + for(int i = 0; i < len; i++) { + if constexpr (toCart) { + mem.rom.cart[BYTE_ADDRESS(cart_addr + i) & mem.rom.mask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE]; + } else { + mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.rom.cart[BYTE_ADDRESS(cart_addr + i) & mem.rom.mask]; + } + } + pi.dramAddr = dram_addr + len; + pi.cartAddr = cart_addr + len; + InterruptRaise(mi, regs, Interrupt::PI); + Util::debug("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, pi.dramAddr, pi.cartAddr); +} + void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { MI& mi = mem.mmio.mi; switch(addr) { @@ -51,13 +123,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { len -= dram_addr & 0x7; } rdLen = len; - for(int i = 0; i < len; i++) { - mem.rom.cart[BYTE_ADDRESS(cart_addr + i) & mem.rom.mask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE]; - } - dramAddr = dram_addr + len; - cartAddr = cart_addr + len; - InterruptRaise(mi, regs, Interrupt::PI); - //Util::debug("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); + scheduler.enqueueRelative(Event{, DMA}); } break; case 0x0460000C: { u32 len = (val & 0x00FFFFFF) + 1; @@ -67,13 +133,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { len -= (dram_addr & 0x7); } wrLen = len; - for(int i = 0; i < len; i++) { - mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.rom.cart[BYTE_ADDRESS(cart_addr + i) & mem.rom.mask]; - } - dramAddr = dram_addr + len; - cartAddr = cart_addr + len; - InterruptRaise(mi, regs, Interrupt::PI); - //Util::debug("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cart_addr, dram_addr); + scheduler.enqueueRelative(Event{, DMA}); } break; case 0x04600010: if(val & 2) { diff --git a/src/backend/core/mmio/PI.hpp b/src/backend/core/mmio/PI.hpp index cc3e9c32..070b81ce 100644 --- a/src/backend/core/mmio/PI.hpp +++ b/src/backend/core/mmio/PI.hpp @@ -14,6 +14,9 @@ struct PI { void Write(Mem&, Registers&, u32, u32); u32 dramAddr{}, cartAddr{}; u32 rdLen{}, wrLen{}; - u32 stub[8]{}; + u32 pi_bsd_dom1_lat{}, pi_bsd_dom2_lat{}; + u32 pi_bsd_dom1_pwd{}, pi_bsd_dom2_pwd{}; + u32 pi_bsd_dom1_pgs{}, pi_bsd_dom2_pgs{}; + u32 pi_bsd_dom1_rls{}, pi_bsd_dom2_rls{}; }; } \ No newline at end of file diff --git a/src/backend/core/mmio/SI.cpp b/src/backend/core/mmio/SI.cpp index 210eb1ba..2e3c5365 100644 --- a/src/backend/core/mmio/SI.cpp +++ b/src/backend/core/mmio/SI.cpp @@ -34,10 +34,11 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 { } } -void DMA(Mem& mem, Registers& regs) { +template +FORCE_INLINE void DMA(Mem& mem, Registers& regs) { SI& si = mem.mmio.si; si.status.dmaBusy = false; - if(si.toDram) { + if constexpr(toDram) { si.pif.ProcessCommands(mem); for(int i = 0; i < 64; i++) { mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.Read(si.pifAddr + i); @@ -61,14 +62,12 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { case 0x04800004: { pifAddr = val & 0x1FFFFFFF; status.dmaBusy = true; - toDram = true; - scheduler.enqueueRelative({SI_DMA_DELAY, DMA}); + scheduler.enqueueRelative({SI_DMA_DELAY, DMA}); } break; case 0x04800010: { pifAddr = val & 0x1FFFFFFF; status.dmaBusy = true; - toDram = false; - scheduler.enqueueRelative({SI_DMA_DELAY, DMA}); + scheduler.enqueueRelative({SI_DMA_DELAY, DMA}); } break; case 0x04800018: InterruptLower(mem.mmio.mi, regs, Interrupt::SI); diff --git a/src/backend/core/mmio/SI.hpp b/src/backend/core/mmio/SI.hpp index 11c2a2bf..7d5ebd38 100644 --- a/src/backend/core/mmio/SI.hpp +++ b/src/backend/core/mmio/SI.hpp @@ -27,8 +27,6 @@ struct SI { u32 dramAddr{}; u32 pifAddr{}; - bool toDram = false; - auto Read(MI&, u32) const -> u32; void Write(Mem&, Registers&, u32, u32); PIF pif;