commit 4b51e97a5b4dad1b5692fea66fdea72369d28bf7
parent d086bfd5b25d9697734e7a923817f78e4fa29c99
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sun, 11 Aug 2024 03:44:02 +0200
rework sync code for more accurate UC timing on slower CPUs
Diffstat:
5 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/source/hardwareLib/haltDSP.cpp b/source/hardwareLib/haltDSP.cpp
@@ -65,6 +65,8 @@ namespace hwLib
}
m_cvHalted.notify_one();
+ m_halting = true;
+
// halt and wait for resume or a wakeup call
m_blockSem.wait();
@@ -88,5 +90,7 @@ namespace hwLib
func();
m_blockSem.wait();
}
+
+ m_halting = false;
}
}
diff --git a/source/hardwareLib/haltDSP.h b/source/hardwareLib/haltDSP.h
@@ -21,7 +21,8 @@ namespace hwLib
void haltDSP(bool _wait = false);
bool resumeDSP();
- bool halted() const {return m_halted > 0; }
+ // only returns true if the last halt request has been serviced
+ bool isHalting() const { return m_halting && m_irqRequestCount == m_irqServedCount; }
dsp56k::DSP& getDSP() const { return m_dsp; }
@@ -46,6 +47,8 @@ namespace hwLib
uint32_t m_wakeUpCount = 0;
std::unordered_map<uint32_t, std::function<void()>> m_wakeUps;
+
+ bool m_halting = false;
};
class ScopedResumeDSP
diff --git a/source/nord/n2x/n2xLib/n2xdsp.cpp b/source/nord/n2x/n2xLib/n2xdsp.cpp
@@ -150,6 +150,7 @@ namespace n2x
{
if(_needMoreData)
{
+ hwLib::ScopedResumeDSP rA(m_hardware.getDSPA().getHaltDSP());
hwLib::ScopedResumeDSP rB(m_hardware.getDSPB().getHaltDSP());
while(dsp().hasPendingInterrupts())
@@ -166,10 +167,28 @@ namespace n2x
void DSP::hdiSendIrqToDSP(const uint8_t _irq)
{
+ if(m_hardware.requestingHaltDSPs() && getHaltDSP().isHalting())
+ {
+ // this is a very hacky way to execute a DSP interrupt even though the DSP is halted. This case happens if the DSPs run too fast
+ // and are halted by the sync code, but the UC wants to inject an interrupt, which needs to be executed immediately.
+ // In this case, we execute the interrupt without altering the DSP state
+
+ const auto numOps = dsp().getInstructionCounter();
+ const auto numCycles = dsp().getCycles();
+
+ const auto pc = dsp().getPC();
+ dsp().getJit().exec(_irq);
+ dsp().setPC(pc);
+
+ const_cast<uint32_t&>(dsp().getInstructionCounter()) = numOps;
+ const_cast<uint32_t&>(dsp().getCycles()) = numCycles;
+ }
+ else
{
dsp().injectExternalInterrupt(_irq);
dsp().injectExternalInterrupt(m_irqInterruptDone);
+ hwLib::ScopedResumeDSP rA(m_hardware.getDSPA().getHaltDSP());
hwLib::ScopedResumeDSP rB(m_hardware.getDSPB().getHaltDSP());
m_triggerInterruptDone.wait();
}
diff --git a/source/nord/n2x/n2xLib/n2xhardware.cpp b/source/nord/n2x/n2xLib/n2xhardware.cpp
@@ -319,6 +319,8 @@ namespace n2x
if(m_dspHalted)
return;
m_dspHalted = true;
+// LOG("Halt");
+ m_dspA.getHaltDSP().haltDSP();
m_dspB.getHaltDSP().haltDSP();
}
@@ -327,6 +329,8 @@ namespace n2x
if(!m_dspHalted)
return;
m_dspHalted = false;
+// LOG("Resume");
+ m_dspA.getHaltDSP().resumeDSP();
m_dspB.getHaltDSP().resumeDSP();
}
diff --git a/source/nord/n2x/n2xLib/n2xhardware.h b/source/nord/n2x/n2xLib/n2xhardware.h
@@ -33,6 +33,7 @@ namespace n2x
void haltDSPs();
void resumeDSPs();
+ bool requestingHaltDSPs() const { return m_dspHalted; }
bool getButtonState(ButtonType _type) const;
void setButtonState(ButtonType _type, bool _pressed);