1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Merge pull request #1357 from TomHarte/EasyWins

Improve MEMC speed.
This commit is contained in:
Thomas Harte 2024-04-17 22:47:04 -04:00 committed by GitHub
commit 2acb853021
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 51 additions and 43 deletions

View File

@ -42,7 +42,7 @@ struct NullStatusHandler {
template <Model model, typename MemoryT, typename StatusObserverT = NullStatusHandler> template <Model model, typename MemoryT, typename StatusObserverT = NullStatusHandler>
struct Executor { struct Executor {
template <typename... Args> template <typename... Args>
Executor(StatusObserverT &observer, Args &&...args) : status_observer_(observer), bus(std::forward<Args>(args)...) {} Executor(StatusObserverT &observer, Args &&...args) : bus(std::forward<Args>(args)...), status_observer_(observer) {}
template <typename... Args> template <typename... Args>
Executor(Args &&...args) : bus(std::forward<Args>(args)...) {} Executor(Args &&...args) : bus(std::forward<Args>(args)...) {}
@ -327,7 +327,7 @@ struct Executor {
} }
} else { } else {
bool did_read; bool did_read;
uint32_t value; uint32_t value = 0;
if constexpr (flags.transfer_byte()) { if constexpr (flags.transfer_byte()) {
uint8_t target; uint8_t target;
@ -480,7 +480,7 @@ struct Executor {
// undo the previous load. // undo the previous load.
struct { struct {
uint32_t *target = nullptr; uint32_t *target = nullptr;
uint32_t value; uint32_t value = 0;
} last_replacement; } last_replacement;
for(uint32_t c = 0; c < total; c++) { for(uint32_t c = 0; c < total; c++) {

View File

@ -272,6 +272,7 @@ struct Registers {
case Condition::GT: return !le(); case Condition::GT: return !le();
case Condition::LE: return le(); case Condition::LE: return le();
default:
case Condition::AL: return true; case Condition::AL: return true;
case Condition::NV: return false; case Condition::NV: return false;
} }
@ -351,6 +352,7 @@ struct Registers {
} }
switch(mode_) { switch(mode_) {
default:
case Mode::User: return active_[offset]; case Mode::User: return active_[offset];
case Mode::Supervisor: case Mode::Supervisor:

View File

@ -34,15 +34,13 @@
#include <set> #include <set>
#include <vector> #include <vector>
namespace {
Log::Logger<Log::Source::Archimedes> logger;
}
namespace Archimedes { namespace Archimedes {
#ifndef NDEBUG #ifndef NDEBUG
namespace {
Log::Logger<Log::Source::Archimedes> logger;
}
template <InstructionSet::ARM::Model model, typename Executor> template <InstructionSet::ARM::Model model, typename Executor>
struct HackyDebugger { struct HackyDebugger {
void notify(uint32_t address, uint32_t instruction, Executor &executor) { void notify(uint32_t address, uint32_t instruction, Executor &executor) {
@ -452,7 +450,7 @@ class ConcreteMachine:
int video_divider_ = 1; int video_divider_ = 1;
void tick_cpu() { void tick_cpu() {
uint32_t instruction; uint32_t instruction = 0;
if(!executor_.bus.read(executor_.pc(), instruction, executor_.registers().mode(), false)) { if(!executor_.bus.read(executor_.pc(), instruction, executor_.registers().mode(), false)) {
// logger.info().append("Prefetch abort at %08x; last good was at %08x", executor_.pc(), last_pc); // logger.info().append("Prefetch abort at %08x; last good was at %08x", executor_.pc(), last_pc);
executor_.prefetch_abort(); executor_.prefetch_abort();

View File

@ -71,13 +71,10 @@ struct MemoryController {
template <typename IntT> template <typename IntT>
bool write(uint32_t address, IntT source, InstructionSet::ARM::Mode, bool trans) { bool write(uint32_t address, IntT source, InstructionSet::ARM::Mode, bool trans) {
// User mode may only _write_ to logically-mapped RAM (subject to further testing below).
if(trans && address >= 0x200'0000) {
return false;
}
switch(write_zones_[(address >> 21) & 31]) { switch(write_zones_[(address >> 21) & 31]) {
case Zone::DMAAndMEMC: { case Zone::DMAAndMEMC: {
if(trans) return false;
const auto buffer_address = [](uint32_t source) -> uint32_t { const auto buffer_address = [](uint32_t source) -> uint32_t {
return (source & 0x1'fffc) << 2; return (source & 0x1'fffc) << 2;
}; };
@ -110,6 +107,25 @@ struct MemoryController {
high_rom_access_time_ = ROMAccessTime((address >> 6) & 3); high_rom_access_time_ = ROMAccessTime((address >> 6) & 3);
low_rom_access_time_ = ROMAccessTime((address >> 4) & 3); low_rom_access_time_ = ROMAccessTime((address >> 4) & 3);
page_size_ = PageSize((address >> 2) & 3); page_size_ = PageSize((address >> 2) & 3);
switch(page_size_) {
default:
case PageSize::kb4:
page_address_shift_ = 12;
page_adddress_mask_ = 0x0fff;
break;
case PageSize::kb8:
page_address_shift_ = 13;
page_adddress_mask_ = 0x1fff;
break;
case PageSize::kb16:
page_address_shift_ = 14;
page_adddress_mask_ = 0x3fff;
break;
case PageSize::kb32:
page_address_shift_ = 15;
page_adddress_mask_ = 0x7fff;
break;
}
logger.info().append("MEMC Control: %08x -> OS:%d sound:%d video:%d refresh:%d high:%d low:%d size:%d", address, os_mode_, sound_dma_enable_, video_dma_enable_, dynamic_ram_refresh_, high_rom_access_time_, low_rom_access_time_, page_size_); logger.info().append("MEMC Control: %08x -> OS:%d sound:%d video:%d refresh:%d high:%d low:%d size:%d", address, os_mode_, sound_dma_enable_, video_dma_enable_, dynamic_ram_refresh_, high_rom_access_time_, low_rom_access_time_, page_size_);
map_dirty_ = true; map_dirty_ = true;
@ -126,19 +142,23 @@ struct MemoryController {
} break; } break;
case Zone::IOControllers: case Zone::IOControllers:
if(trans) return false;
ioc_.template write<IntT>(address, source); ioc_.template write<IntT>(address, source);
break; break;
case Zone::VideoController: case Zone::VideoController:
if(trans) return false;
// TODO: handle byte writes correctly. // TODO: handle byte writes correctly.
ioc_.video().write(source); ioc_.video().write(source);
break; break;
case Zone::PhysicallyMappedRAM: case Zone::PhysicallyMappedRAM:
if(trans) return false;
physical_ram<IntT>(address) = source; physical_ram<IntT>(address) = source;
break; break;
case Zone::AddressTranslator: case Zone::AddressTranslator:
if(trans) return false;
// printf("Translator write at %08x; replaces %08x\n", address, pages_[address & 0x7f]); // printf("Translator write at %08x; replaces %08x\n", address, pages_[address & 0x7f]);
pages_[address & 0x7f] = address; pages_[address & 0x7f] = address;
map_dirty_ = true; map_dirty_ = true;
@ -154,13 +174,9 @@ struct MemoryController {
template <typename IntT> template <typename IntT>
bool read(uint32_t address, IntT &source, InstructionSet::ARM::Mode, bool trans) { bool read(uint32_t address, IntT &source, InstructionSet::ARM::Mode, bool trans) {
// User mode may only read logically-maped RAM and ROM.
if(trans && address >= 0x200'0000 && address < 0x380'0000) {
return false;
}
switch (read_zones_[(address >> 21) & 31]) { switch (read_zones_[(address >> 21) & 31]) {
case Zone::PhysicallyMappedRAM: case Zone::PhysicallyMappedRAM:
if(trans) return false;
source = physical_ram<IntT>(address); source = physical_ram<IntT>(address);
break; break;
@ -184,6 +200,7 @@ struct MemoryController {
break; break;
case Zone::IOControllers: case Zone::IOControllers:
if(trans) return false;
ioc_.template read<IntT>(address, source); ioc_.template read<IntT>(address, source);
break; break;
@ -298,6 +315,8 @@ struct MemoryController {
kb16 = 0b10, kb16 = 0b10,
kb32 = 0b11, kb32 = 0b11,
} page_size_ = PageSize::kb4; } page_size_ = PageSize::kb4;
int page_address_shift_ = 12;
uint32_t page_adddress_mask_ = 0xffff;
// Address translator. // Address translator.
// //
@ -339,33 +358,14 @@ struct MemoryController {
} }
address = aligned<IntT>(address); address = aligned<IntT>(address);
address &= 0x1ff'ffff; address &= 0x1ff'ffff;
size_t page; const size_t page = address >> page_address_shift_;
// TODO: eliminate switch here.
switch(page_size_) {
default:
case PageSize::kb4:
page = address >> 12;
address &= 0x0fff;
break;
case PageSize::kb8:
page = address >> 13;
address &= 0x1fff;
break;
case PageSize::kb16:
page = address >> 14;
address &= 0x3fff;
break;
case PageSize::kb32:
page = address >> 15;
address &= 0x7fff;
break;
}
const auto &map = mapping<is_read>(trans, os_mode_); const auto &map = mapping<is_read>(trans, os_mode_);
if(!map[page]) { if(!map[page]) {
return nullptr; return nullptr;
} }
address &= page_adddress_mask_;
return reinterpret_cast<IntT *>(&map[page][address]); return reinterpret_cast<IntT *>(&map[page][address]);
} }

View File

@ -62,7 +62,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Release" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"

View File

@ -31,14 +31,21 @@ PCMSegmentEventSource::PCMSegmentEventSource(const PCMSegment &segment) :
} }
PCMSegmentEventSource::PCMSegmentEventSource(const PCMSegmentEventSource &original) { PCMSegmentEventSource::PCMSegmentEventSource(const PCMSegmentEventSource &original) {
*this = original;
}
PCMSegmentEventSource &PCMSegmentEventSource::operator =(const PCMSegmentEventSource &original) {
// share underlying data with the original // share underlying data with the original
segment_ = original.segment_; segment_ = original.segment_;
// load up the clock rate and set initial conditions // load up the clock rate and set initial conditions
next_event_.length.clock_rate = segment_->length_of_a_bit.clock_rate; next_event_.length.clock_rate = segment_->length_of_a_bit.clock_rate;
reset(); reset();
return *this;
} }
void PCMSegmentEventSource::reset() { void PCMSegmentEventSource::reset() {
// start with the first bit to be considered the zeroth, and assume that it'll be // start with the first bit to be considered the zeroth, and assume that it'll be
// flux transitions for the foreseeable // flux transitions for the foreseeable

View File

@ -163,6 +163,7 @@ class PCMSegmentEventSource {
but a unique pointer into it. but a unique pointer into it.
*/ */
PCMSegmentEventSource(const PCMSegmentEventSource &); PCMSegmentEventSource(const PCMSegmentEventSource &);
PCMSegmentEventSource &operator =(const PCMSegmentEventSource &);
/*! /*!
@returns the next event that will occur in this event stream. @returns the next event that will occur in this event stream.