Early bail-out of DriveLoopReadNoFlux

A couple of small optimizations that shouldn't make a difference but do such as: Addressing tracks as a single array.  Caching a single byte instead of re-reading the array. (Note that caching 32bits did not improve but actually worsen things). Harsher interrupt disabling. Whitespace changes in main...

Plus, early bail out from DriveLoopReadNoFlux.
This commit is contained in:
Alexander Martinelle 2019-09-10 23:14:34 +02:00
parent 8875c55c25
commit 9b38fc6d32
7 changed files with 117 additions and 13 deletions

View file

@ -151,7 +151,12 @@ void DiskImage::Close()
void DiskImage::DumpTrack(unsigned track) void DiskImage::DumpTrack(unsigned track)
{ {
#if defined(EXPERIMENTALZERO)
unsigned char* src = &tracks[track << 13];
#else
unsigned char* src = tracks[track]; unsigned char* src = tracks[track];
#endif
unsigned trackLength = trackLengths[track]; unsigned trackLength = trackLengths[track];
DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength); DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength);
for (unsigned index = 0; index < trackLength; ++index) for (unsigned index = 0; index < trackLength; ++index)
@ -205,7 +210,11 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex) for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex)
{ {
unsigned char track = (halfTrackIndex >> 1); unsigned char track = (halfTrackIndex >> 1);
#if defined(EXPERIMENTALZERO)
unsigned char* dest = &tracks[halfTrackIndex << 13];
#else
unsigned char* dest = tracks[halfTrackIndex]; unsigned char* dest = tracks[halfTrackIndex];
#endif
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH; trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
@ -800,7 +809,11 @@ bool DiskImage::OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
//DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset); //DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset);
trackData += 2; trackData += 2;
trackLengths[track] = trackLength; trackLengths[track] = trackLength;
#if defined(EXPERIMENTALZERO)
memcpy(&tracks[track << 13], trackData, trackLength);
#else
memcpy(tracks[track], trackData, trackLength); memcpy(tracks[track], trackData, trackLength);
#endif
trackUsed[track] = true; trackUsed[track] = true;
//DEBUG_LOG("%d has data\r\n", track); //DEBUG_LOG("%d has data\r\n", track);
} }
@ -899,7 +912,11 @@ bool DiskImage::WriteG64(char* name)
gcr_track[0] = (BYTE)(track_len % 256); gcr_track[0] = (BYTE)(track_len % 256);
gcr_track[1] = (BYTE)(track_len / 256); gcr_track[1] = (BYTE)(track_len / 256);
#if defined(EXPERIMENTALZERO)
memcpy(buffer, &tracks[track << 13], track_len);
#else
memcpy(buffer, tracks[track], track_len); memcpy(buffer, tracks[track], track_len);
#endif
memcpy(gcr_track + 2, buffer, track_len); memcpy(gcr_track + 2, buffer, track_len);
bytesToWrite = G64_TRACK_MAXLEN + 2; bytesToWrite = G64_TRACK_MAXLEN + 2;
@ -965,11 +982,19 @@ bool DiskImage::OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsig
unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100; unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100;
int align; int align;
#if defined(EXPERIMENTALZERO)
trackLengths[track] = extract_GCR_track(&tracks[track << 13], nibdata, &align
//, ALIGN_GAP
, ALIGN_NONE
, capacity_min[trackDensity[track]],
capacity_max[trackDensity[track]]);
#else
trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align
//, ALIGN_GAP //, ALIGN_GAP
, ALIGN_NONE , ALIGN_NONE
, capacity_min[trackDensity[track]], , capacity_min[trackDensity[track]],
capacity_max[trackDensity[track]]); capacity_max[trackDensity[track]]);
#endif
trackUsed[track] = true; trackUsed[track] = true;
@ -1031,7 +1056,11 @@ bool DiskImage::WriteNIB()
{ {
if (trackUsed[track]) if (trackUsed[track])
{ {
#if defined(EXPERIMENTALZERO)
if (f_write(&fp, &tracks[track << 13], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
#else
if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten) if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
#endif
{ {
DEBUG_LOG("Cannot write track data.\r\n"); DEBUG_LOG("Cannot write track data.\r\n");
} }
@ -1250,10 +1279,18 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
unsigned char gcr[5]; unsigned char gcr[5];
unsigned char byte; unsigned char byte;
unsigned char* offset; unsigned char* offset;
#if defined(EXPERIMENTALZERO)
unsigned char* end = &tracks[track << 13] + trackLengths[track];
#else
unsigned char* end = tracks[track] + trackLengths[track]; unsigned char* end = tracks[track] + trackLengths[track];
#endif
shift = bitIndex & 7; shift = bitIndex & 7;
#if defined(EXPERIMENTALZERO)
offset = &tracks[track << 13] + (bitIndex >> 3);
#else
offset = tracks[track] + (bitIndex >> 3); offset = tracks[track] + (bitIndex >> 3);
#endif
byte = offset[0] << shift; byte = offset[0] << shift;
for (i = 0; i < num; i++, buf += 4) for (i = 0; i < num; i++, buf += 4)
@ -1262,7 +1299,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
{ {
offset++; offset++;
if (offset >= end) if (offset >= end)
#if defined(EXPERIMENTALZERO)
offset = &tracks[track << 13];
#else
offset = tracks[track]; offset = tracks[track];
#endif
if (shift) if (shift)
{ {
@ -1282,7 +1323,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex) int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex)
{ {
int readShiftRegister = 0; int readShiftRegister = 0;
#if defined(EXPERIMENTALZERO)
unsigned char byte = tracks[(track << 13) + (bitIndex >> 3)] << (bitIndex & 7);
#else
unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7); unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7);
#endif
bool prevBitZero = true; bool prevBitZero = true;
while (maxBits--) while (maxBits--)
@ -1314,7 +1359,11 @@ int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStar
bitIndex++; bitIndex++;
if (bitIndex >= MAX_TRACK_LENGTH * 8) if (bitIndex >= MAX_TRACK_LENGTH * 8)
bitIndex = 0; bitIndex = 0;
#if defined(EXPERIMENTALZERO)
byte = tracks[(track << 13)+(bitIndex >> 3)];
#else
byte = tracks[track][bitIndex >> 3]; byte = tracks[track][bitIndex >> 3];
#endif
} }
} }
return -1; return -1;

View file

@ -78,19 +78,48 @@ public:
bool GetDecodedSector(u32 track, u32 sector, u8* buffer); bool GetDecodedSector(u32 track, u32 sector, u8* buffer);
inline unsigned char GetNextByte(u32 track, u32 byte)
{
#if defined(EXPERIMENTALZERO)
return tracks[(track << 13) + byte];
#else
return tracks[track][byte];
#endif
}
inline bool GetNextBit(u32 track, u32 byte, u32 bit) inline bool GetNextBit(u32 track, u32 byte, u32 bit)
{ {
//if (attachedImageSize == 0) //if (attachedImageSize == 0)
// return 0; // return 0;
#if defined(EXPERIMENTALZERO)
return ((tracks[(track << 13) + byte] >> bit) & 1) != 0;
#else
return ((tracks[track][byte] >> bit) & 1) != 0; return ((tracks[track][byte] >> bit) & 1) != 0;
#endif
} }
inline void SetBit(u32 track, u32 byte, u32 bit, bool value) inline void SetBit(u32 track, u32 byte, u32 bit, bool value)
{ {
if (attachedImageSize == 0) if (attachedImageSize == 0)
return; return;
#if defined(EXPERIMENTALZERO)
u8 dataOld = tracks[(track << 13) + byte];
u8 bitMask = 1 << bit;
if (value)
{
TestDirty(track, (dataOld & bitMask) == 0);
tracks[(track << 13) + byte] |= bitMask;
}
else
{
TestDirty(track, (dataOld & bitMask) != 0);
tracks[(track << 13) + byte] &= bitMask;
}
#else
u8 dataOld = tracks[track][byte]; u8 dataOld = tracks[track][byte];
u8 bitMask = 1 << bit; u8 bitMask = 1 << bit;
if (value) if (value)
@ -103,6 +132,7 @@ public:
TestDirty(track, (dataOld & bitMask) != 0); TestDirty(track, (dataOld & bitMask) != 0);
tracks[track][byte] &= ~bitMask; tracks[track][byte] &= ~bitMask;
} }
#endif
} }
static const unsigned char SectorsPerTrack[42]; static const unsigned char SectorsPerTrack[42];
@ -160,7 +190,11 @@ public:
union union
{ {
#if defined(EXPERIMENTALZERO)
unsigned char tracks[HALF_TRACK_COUNT * MAX_TRACK_LENGTH];
#else
unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH]; unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH];
#endif
unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH]; unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH];
}; };

View file

@ -662,9 +662,17 @@ void Drive::DriveLoopReadNoFlux()
{ {
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
} }
if (cycles < UE7Counter)
{
UE7Counter -= cycles;
cyclesLeftForBit -= cycles;
return;
}
cyclesLeftForBit -= UE7Counter;
cycles -= UE7Counter;
} }
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. //if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
{ {
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
@ -749,6 +757,7 @@ void Drive::DriveLoopReadNoCycles()
} }
}; };
} }
void Drive::DriveLoopRead() void Drive::DriveLoopRead()
{ {
unsigned int minCycles; unsigned int minCycles;
@ -767,14 +776,9 @@ void Drive::DriveLoopRead()
if (cyclesLeftForBit == 0) if (cyclesLeftForBit == 0)
{ {
//which is faster? single loop ceil check or the 3 lines below?
cyclesForBitErrorCounter -= cyclesPerBitErrorConstant; cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant); cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
//cyclesForBit -= cyclesPerBit;
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
//cyclesForBit += cyclesLeftForBit;
if (GetNextBit()) if (GetNextBit())
{ {
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);

View file

@ -148,12 +148,24 @@ private:
++headBitOffset %= bitsInTrack; ++headBitOffset %= bitsInTrack;
return bit; return bit;
} }
unsigned cachedheadTrackPos = -1;
int cachedbyteOffset = -1;
unsigned char cachedByte = 0;
inline bool GetNextBit() inline bool GetNextBit()
{ {
int byteOffset; int byteOffset;
int bit = AdvanceSectorPositionR(byteOffset); int bit = AdvanceSectorPositionR(byteOffset);
return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
//Why is it faster to check both conditions here than to update the cache when moving the head?
if (byteOffset != cachedbyteOffset || cachedheadTrackPos != headTrackPos)
{
cachedByte = diskImage->GetNextByte(headTrackPos, byteOffset);
cachedbyteOffset = byteOffset;
cachedheadTrackPos = headTrackPos;
}
return ((cachedByte >> bit) & 1) != 0;
//return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
} }
inline void SetNextBit(bool value) inline void SetNextBit(bool value)

View file

@ -39,7 +39,9 @@ void InterruptSystemInitialize()
write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2)); write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2));
DataMemBarrier(); DataMemBarrier();
#ifndef EXPERIMENTALZERO #ifdef EXPERIMENTALZERO
DisableInterrupts();
#else
EnableInterrupts(); EnableInterrupts();
#endif #endif
} }

View file

@ -9,7 +9,7 @@ extern "C" {
#include "bcm2835int.h" #include "bcm2835int.h"
#define EnableInterrupts() __asm volatile ("cpsie i") #define EnableInterrupts() __asm volatile ("cpsie i")
#define DisableInterrupts() __asm volatile ("cpsid i") #define DisableInterrupts() __asm volatile ("cpsid ifa, #0x13")
typedef void IRQHandler(void* param); typedef void IRQHandler(void* param);

View file

@ -832,13 +832,16 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
do do
{ {
ctAfter = read32(ARM_SYSTIMER_CLO); ctAfter = read32(ARM_SYSTIMER_CLO);
} while (ctAfter == ctBefore); // Sync to the 1MHz clock } while (ctAfter == ctBefore); // Sync to the 1MHz clock
ctBefore = ctAfter; ctBefore = ctAfter;
IEC_Bus::ReadEmulationMode1541(); IEC_Bus::ReadEmulationMode1541();
IEC_Bus::RefreshOuts1541(); // Now output all outputs. IEC_Bus::RefreshOuts1541(); // Now output all outputs.
} }
return EXIT_UNKNOWN; return EXIT_UNKNOWN;
} }