Skip to content

Commit

Permalink
md: refresh & bus timing fixes (#1269)
Browse files Browse the repository at this point in the history
1. Bus refreshes needed a clean up and readjustment. Timings were
compared against US Model 1 VA3 via Ti_'s test_inst_speed rom. Yellow
values are ok, as they normally skew lower due to refresh. Some reds
still remain (of the regular instruction tests) that appear to be off by
1.
2. Basic implementation of delays incurred on both main 68k and z80.
Delay values are tuned according to Ti_'s misc_test rom tests ("Z80
DELAY ON ROM READ", "M68K DELAY ON Z80 ROM READ"). Hardware tests
indicate that z80 delay may skew lower towards 170, while m68k delay
typically sticks to 460. This change puts ares at ~178 z80 delay & ~461
68k delay. Fixes #255.
3. Trivial readjustment of m68000 interrupt timing. Approx'd autovector
delay changed to 14 cycles, which happens to be the median of the
expected range (10-18).
  • Loading branch information
TascoDLX authored Oct 24, 2023
1 parent cd8d84e commit 77bfad9
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 36 deletions.
2 changes: 1 addition & 1 deletion ares/component/processor/m68000/m68000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ auto M68000::exception(u32 exception, u32 vector, u32 priority) -> void {
if(exception == Exception::Interrupt) {
// IACK vector number acquisition (+4 cyc normal or +10 to +18 cyc autovectored)
// & justify vector number (+4 cyc)
idle(16+4); // assuming autovector cycles (approximated for Megadrive)
idle(14+4); // assuming autovector cycles (approximated for Megadrive)
r.i = priority;
}

Expand Down
4 changes: 4 additions & 0 deletions ares/md/apu/bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ auto APU::write(n16 address, n8 data) -> void {
}

auto APU::readExternal(n24 address) -> n8 {
step(3); // approximate Z80 delay
while(MegaDrive::bus.acquired() && !scheduler.synchronizing()) step(1);
cpu.state.stolenMcycles += 68; // approximate 68K delay; 68 Mclk ~= 9.7 68k clk
MegaDrive::bus.acquire(MegaDrive::Bus::APU);

n8 data = 0xff;
Expand All @@ -54,7 +56,9 @@ auto APU::readExternal(n24 address) -> n8 {
}

auto APU::writeExternal(n24 address, n8 data) -> void {
step(3); // approximate Z80 delay
while(MegaDrive::bus.acquired() && !scheduler.synchronizing()) step(1);
cpu.state.stolenMcycles += 68; // approximate 68K delay; 68 Mclk ~= 9.7 68k clk
MegaDrive::bus.acquire(MegaDrive::Bus::APU);

if(address >= 0x000000 && address <= 0x9fffff
Expand Down
48 changes: 16 additions & 32 deletions ares/md/bus/inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,47 +121,31 @@ alwaysinline auto Bus::write(n1 upper, n1 lower, n24 address, n16 data) -> void
}

alwaysinline auto Bus::waitRefreshExternal() -> void {
if(state.acquired & VDPDMA) return; // refresh is synched with VDP during DMA
if(cpu.refresh.external < cpu.refresh.externalLowBound) return;

if(cpu.refresh.externalEnd == 0)
cpu.refresh.externalEnd = min(cpu.refresh.external + cpu.refresh.externalLength, cpu.refresh.externalHighBound);
if(cpu.refresh.external < cpu.refresh.externalEnd) {
while(cpu.refresh.external < cpu.refresh.externalEnd) {
if(cpu.active()) cpu.wait(1);
if(apu.active()) apu.step(1);
if(scheduler.synchronizing()) return;
if(vdp.active()) return;
}
cpu.refresh.external -= cpu.refresh.externalEnd;
cpu.refresh.externalEnd = 0;
}
if(vdp.active() || state.acquired & VDPDMA) return; // refresh is synched with VDP during DMA

while(cpu.refresh.external >= cpu.refresh.externalHighBound) {
cpu.refresh.external -= cpu.refresh.externalHighBound;
cpu.refresh.externalEnd = 0;
}

if(cpu.refresh.external < cpu.refresh.externalLowBound) return;

if(cpu.active()) cpu.wait(min(cpu.refresh.externalLength,cpu.refresh.externalHighBound-cpu.refresh.external));
if(apu.active()) apu.step(min(cpu.refresh.externalLength,cpu.refresh.externalHighBound-cpu.refresh.external));

cpu.refresh.external -= cpu.refresh.externalHighBound;
}

alwaysinline auto Bus::waitRefreshRAM() -> void {
if(state.acquired & VDPDMA) return; // refresh is synched with VDP during DMA
if(cpu.refresh.ram < cpu.refresh.ramLowBound) return;

if(cpu.refresh.ramEnd == 0)
cpu.refresh.ramEnd = min(cpu.refresh.ram + cpu.refresh.ramLength, cpu.refresh.ramHighBound);
if(cpu.refresh.ram < cpu.refresh.ramEnd) {
while(cpu.refresh.ram < cpu.refresh.ramEnd) {
if(cpu.active()) cpu.wait(1);
if(apu.active()) apu.step(1);
if(scheduler.synchronizing()) return;
if(vdp.active()) return;
}
cpu.refresh.ram -= cpu.refresh.ramEnd;
cpu.refresh.ramEnd = 0;
}
if(vdp.active() || state.acquired & VDPDMA) return; // refresh is synched with VDP during DMA

while(cpu.refresh.ram >= cpu.refresh.ramHighBound) {
cpu.refresh.ram -= cpu.refresh.ramHighBound;
cpu.refresh.ramEnd = 0;
}

if(cpu.refresh.ram < cpu.refresh.ramLowBound) return;

if(cpu.active()) cpu.wait(min(cpu.refresh.ramLength,cpu.refresh.ramHighBound-cpu.refresh.ram));
if(apu.active()) apu.step(min(cpu.refresh.ramLength,cpu.refresh.ramHighBound-cpu.refresh.ram));

cpu.refresh.ram = 0;
}
2 changes: 2 additions & 0 deletions ares/md/cpu/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ auto CPU::main() -> void {
}

auto CPU::step(u32 clocks) -> void {
clocks += state.stolenMcycles/7;
state.stolenMcycles -= state.stolenMcycles/7 * 7;
refresh.ram += clocks;
refresh.external += clocks;
Thread::step(clocks);
Expand Down
5 changes: 3 additions & 2 deletions ares/md/cpu/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,15 @@ struct CPU : M68000, Thread {
static constexpr int ramLowBound = 113;
static constexpr int ramHighBound = 132;
static constexpr int ramLength = 3;
static constexpr int externalLowBound = 126;
static constexpr int externalHighBound = 132;
static constexpr int externalLowBound = 121;
static constexpr int externalHighBound = 128;
static constexpr int externalLength = 2;

} refresh;

struct State {
n32 interruptPending;
int stolenMcycles = 0;
} state;

int cyclesUntilSync = 0;
Expand Down
1 change: 1 addition & 0 deletions ares/md/cpu/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ auto CPU::serialize(serializer& s) -> void {
s(refresh.external);
s(refresh.externalEnd);
s(state.interruptPending);
s(state.stolenMcycles);
}
2 changes: 1 addition & 1 deletion ares/md/system/serialization.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
static const string SerializerVersion = "v133";
static const string SerializerVersion = "v133.1";

auto System::serialize(bool synchronize) -> serializer {
if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);
Expand Down

0 comments on commit 77bfad9

Please sign in to comment.