more write buffer work

This commit is contained in:
Jaklyy 2024-11-12 16:58:10 -05:00
parent 28d788f26d
commit 4099823af7
4 changed files with 58 additions and 34 deletions

View File

@ -218,6 +218,7 @@ void ARMv5::Reset()
WBReleaseTS = 0; WBReleaseTS = 0;
WBLastRegion = Mem9_Null; WBLastRegion = Mem9_Null;
WBWriting = false; WBWriting = false;
WBInitialTS = 0;
ARM::Reset(); ARM::Reset();
} }

View File

@ -681,7 +681,7 @@ public:
u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing
u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing
bool WBWriting; // whether the buffer is actively trying to perform a write u8 WBWriting; // whether the buffer is actively trying to perform a write
u32 WBCurAddr; // address the write buffer is currently writing to u32 WBCurAddr; // address the write buffer is currently writing to
u64 WBCurVal; // current value being written; 0-31: val | 61-63: flag; 0 = byte ns; 1 = halfword ns; 2 = word ns; 3 = word s; 4 = address (invalid in this variable) u64 WBCurVal; // current value being written; 0-31: val | 61-63: flag; 0 = byte ns; 1 = halfword ns; 2 = word ns; 3 = word s; 4 = address (invalid in this variable)
u32 storeaddr[16]; // temp until i figure out why using the fifo address entries directly didn't work u32 storeaddr[16]; // temp until i figure out why using the fifo address entries directly didn't work
@ -691,6 +691,7 @@ public:
u64 WBDelay; // timestamp in bus cycles use for the delay before next write to the write buffer can occur (seems to be a 1 cycle delay after a write to it) u64 WBDelay; // timestamp in bus cycles use for the delay before next write to the write buffer can occur (seems to be a 1 cycle delay after a write to it)
u32 WBLastRegion; // the last region written to by the write buffer u32 WBLastRegion; // the last region written to by the write buffer
u64 WBReleaseTS; // the timestamp on which the write buffer relinquished control of the bus back u64 WBReleaseTS; // the timestamp on which the write buffer relinquished control of the bus back
u64 WBInitialTS; // what cycle the entry was first sent in
#ifdef GDBSTUB_ENABLED #ifdef GDBSTUB_ENABLED
u32 ReadMem(u32 addr, int size) override; u32 ReadMem(u32 addr, int size) override;

View File

@ -293,7 +293,8 @@ void A_MCR(ARM* cpu)
return A_UNK(cpu); // TODO: check what kind of exception it really is return A_UNK(cpu); // TODO: check what kind of exception it really is
} }
cpu->AddCycles_CI(1 + 1); // TODO: checkme if (cpu->Num==0) cpu->AddCycles_CI(6); // checkme
else /* ARM7 */ cpu->AddCycles_CI(1 + 1); // TODO: checkme
} }
void A_MRC(ARM* cpu) void A_MRC(ARM* cpu)

View File

@ -780,7 +780,8 @@ u32 ARMv5::DCacheLookup(const u32 addr)
else else
{ {
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBTimestamp-1) && (DataRegion == WBLastRegion)) // check write buffer if (((NDS.ARM9Timestamp <= WBReleaseTS) && (NDS.ARM9Regions[addr>>14] == WBLastRegion)) // check write buffer
|| (Store && (NDS.ARM9Regions[addr>>14] == DataRegion))) //check the actual store
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
} }
} }
@ -1217,16 +1218,11 @@ inline bool ARMv5::WriteBufferHandle()
} }
} }
if ((NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) && (((MainRAMTimestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)) > WBTimestamp))
WBTimestamp = (MainRAMTimestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
// get the current timestamp // get the current timestamp
u64 ts; u64 ts = WBTimestamp + cycles;
if (((WBCurVal >> 61) != 3) && (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM))
ts = std::max(WBTimestamp, MainRAMTimestamp);
else
ts = WBTimestamp;
if ((WBCurVal >> 61) != 3) ts = (ts + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
ts += cycles;
if (!force && ts > NDS.ARM9Timestamp) return true; if (!force && ts > NDS.ARM9Timestamp) return true;
if ( force && ts > NDS.ARM9Timestamp) if ( force && ts > NDS.ARM9Timestamp)
@ -1245,6 +1241,7 @@ inline bool ARMv5::WriteBufferHandle()
WBTimestamp = ts; WBTimestamp = ts;
if (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) MainRAMTimestamp += 2 << NDS.ARM9ClockShift; if (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) MainRAMTimestamp += 2 << NDS.ARM9ClockShift;
} }
WBInitialTS = WBTimestamp;
switch (WBCurVal >> 61) switch (WBCurVal >> 61)
{ {
@ -1275,11 +1272,15 @@ inline bool ARMv5::WriteBufferHandle()
{ {
if (NDS.ARM9Regions[storeaddr[WBWritePointer]>>14] == Mem9_MainRAM) // main ram handling if (NDS.ARM9Regions[storeaddr[WBWritePointer]>>14] == Mem9_MainRAM) // main ram handling
{ {
if (!force && (MainRAMTimestamp > NDS.ARM9Timestamp)) return true; if (!force && (WBTimestamp > NDS.ARM9Timestamp)) return true;
if ( force && (MainRAMTimestamp > NDS.ARM9Timestamp)) if ( force && (WBTimestamp > NDS.ARM9Timestamp))
NDS.ARM9Timestamp = MainRAMTimestamp; NDS.ARM9Timestamp = WBTimestamp;
WBTimestamp = std::max(MainRAMTimestamp, WBTimestamp);
} }
WBTimestamp = (WBTimestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
WBCurVal = WriteBufferFifo[WBWritePointer]; WBCurVal = WriteBufferFifo[WBWritePointer];
WBCurAddr = storeaddr[WBWritePointer]; WBCurAddr = storeaddr[WBWritePointer];
WBWriting = true; WBWriting = true;
@ -1303,19 +1304,23 @@ void ARMv5::WriteBufferCheck()
{ {
while (!WriteBufferHandle<0>()); // loop until we've cleared out all writeable entries while (!WriteBufferHandle<0>()); // loop until we've cleared out all writeable entries
if constexpr (next == 1) // check if the next write is occuring if constexpr (next == 1 || next == 3) // check if the next write is occuring
{ {
if (WBWriting) if (NDS.ARM9Timestamp >= WBInitialTS)// + (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM)))// || ((NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) && WBWriting))
{ {
u64 tsold = NDS.ARM9Timestamp;
while(!WriteBufferHandle<2>()); while(!WriteBufferHandle<2>());
//if constexpr (next == 3) NDS.ARM9Timestamp = std::max(tsold, NDS.ARM9Timestamp - (2<<NDS.ARM9ClockShift));
} }
} }
else if constexpr (next == 2) else if constexpr (next == 2)
{ {
if (WBWriting) //if (NDS.ARM9Timestamp >= WBInitialTS)
while(!WriteBufferHandle<2>()); while(!WriteBufferHandle<2>());
} }
} }
template void ARMv5::WriteBufferCheck<3>();
template void ARMv5::WriteBufferCheck<2>(); template void ARMv5::WriteBufferCheck<2>();
template void ARMv5::WriteBufferCheck<1>(); template void ARMv5::WriteBufferCheck<1>();
template void ARMv5::WriteBufferCheck<0>(); template void ARMv5::WriteBufferCheck<0>();
@ -1326,10 +1331,14 @@ void ARMv5::WriteBufferWrite(u32 val, u8 flag, u32 addr)
if (WBFillPointer == WBWritePointer) // if the write buffer is full then we stall the cpu until room is made if (WBFillPointer == WBWritePointer) // if the write buffer is full then we stall the cpu until room is made
WriteBufferHandle<1>(); WriteBufferHandle<1>();
else if (WBWritePointer == 16) // indicates empty write buffer else if (WBWritePointer == 16 && (flag != 4)) // indicates empty write buffer
{ {
WBWritePointer = 0; WBWritePointer = 0;
if (!WBWriting && (WBTimestamp < (NDS.ARM9Timestamp+1))) WBTimestamp = (NDS.ARM9Timestamp+1); u64 ts = (NDS.ARM9Regions[addr>>14] == Mem9_MainRAM) ? std::max(MainRAMTimestamp, NDS.ARM9Timestamp + 1) : NDS.ARM9Timestamp + 1;
if (!WBWriting && (WBTimestamp < ((ts + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))))
WBInitialTS = WBTimestamp = (ts + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
WBInitialTS = WBTimestamp;
} }
WriteBufferFifo[WBFillPointer] = val | (u64)flag << 61; WriteBufferFifo[WBFillPointer] = val | (u64)flag << 61;
@ -1714,7 +1723,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
return; return;
case 0x7D1: case 0x7D1:
Log(LogLevel::Debug,"Prefetch instruction cache MVA\n"); //Log(LogLevel::Debug,"Prefetch instruction cache MVA\n");
// requires priv mode or causes UNKNOWN INSTRUCTION exception // requires priv mode or causes UNKNOWN INSTRUCTION exception
if (PU_Map != PU_PrivMap) if (PU_Map != PU_PrivMap)
{ {
@ -1723,7 +1732,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
// we force a fill by looking up the value from cache // we force a fill by looking up the value from cache
// if it wasn't cached yet, it will be loaded into cache // if it wasn't cached yet, it will be loaded into cache
ICacheLookup(val & ~0x03); ICacheLookup(val & ~0x03);
break; return;
case 0x7E0: case 0x7E0:
//Log(LogLevel::Debug,"clean & invalidate data cache\n"); //Log(LogLevel::Debug,"clean & invalidate data cache\n");
@ -1773,7 +1782,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
// The Cache is 4 way associative // The Cache is 4 way associative
// But all bits are r/w // But all bits are r/w
DCacheLockDown = val; DCacheLockDown = val;
Log(LogLevel::Debug,"ICacheLockDown\n"); Log(LogLevel::Debug,"DCacheLockDown\n");
return; return;
case 0x901: case 0x901:
// requires priv mode or causes UNKNOWN INSTRUCTION exception // requires priv mode or causes UNKNOWN INSTRUCTION exception
@ -2104,7 +2113,7 @@ u64 ARMv5::CodeRead32(u32 addr, bool branch)
if (PU_Map[addr>>12] & 0x30) if (PU_Map[addr>>12] & 0x30)
WriteBufferDrain(); WriteBufferDrain();
else else
WriteBufferCheck<1>(); WriteBufferCheck<3>();
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1); NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
@ -2128,9 +2137,11 @@ u64 ARMv5::CodeRead32(u32 addr, bool branch)
} }
Store = false; Store = false;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
if (NDS.ARM9Timestamp < TimestampActual) NDS.ARM9Timestamp = TimestampActual; if (NDS.ARM9Timestamp < TimestampActual) NDS.ARM9Timestamp = TimestampActual;
WBTimestamp = NDS.ARM9Timestamp;
DataRegion = Mem9_Null; DataRegion = Mem9_Null;
return BusRead32(addr); return BusRead32(addr);
} }
@ -2213,7 +2224,8 @@ bool ARMv5::DataRead8(u32 addr, u32* val)
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
} }
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead8(addr); *val = BusRead8(addr);
return true; return true;
} }
@ -2297,7 +2309,8 @@ bool ARMv5::DataRead16(u32 addr, u32* val)
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
} }
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead16(addr); *val = BusRead16(addr);
return true; return true;
} }
@ -2381,7 +2394,8 @@ bool ARMv5::DataRead32(u32 addr, u32* val)
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
} }
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr); *val = BusRead32(addr);
return true; return true;
} }
@ -2481,7 +2495,8 @@ bool ARMv5::DataRead32S(u32 addr, u32* val)
} }
} }
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr); *val = BusRead32(addr);
return true; return true;
} }
@ -2560,7 +2575,8 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
} }
else DataRegion = NDS.ARM9Regions[addr>>14]; else DataRegion = NDS.ARM9Regions[addr>>14];
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite8(addr, val); BusWrite8(addr, val);
} }
else else
@ -2652,7 +2668,8 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
} }
else DataRegion = NDS.ARM9Regions[addr>>14]; else DataRegion = NDS.ARM9Regions[addr>>14];
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite16(addr, val); BusWrite16(addr, val);
} }
else else
@ -2744,7 +2761,8 @@ bool ARMv5::DataWrite32(u32 addr, u32 val)
} }
else DataRegion = NDS.ARM9Regions[addr>>14]; else DataRegion = NDS.ARM9Regions[addr>>14];
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val); BusWrite32(addr, val);
} }
else else
@ -2839,6 +2857,8 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
} }
else // ns else // ns
{ {
NDS.ARM9Timestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
DataCycles = MemTimings[addr>>14][1]; DataCycles = MemTimings[addr>>14][1];
if ((addr >> 24) == 0x02) if ((addr >> 24) == 0x02)
@ -2851,7 +2871,8 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
else DataRegion = NDS.ARM9Regions[addr>>14]; else DataRegion = NDS.ARM9Regions[addr>>14];
} }
WBTimestamp = NDS.ARM9Timestamp; if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + DataCycles + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val); BusWrite32(addr, val);
} }
else else