mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-09 15:39:08 +00:00
Continues walking very slowly towards cached execution.
This commit is contained in:
parent
8a74f5911c
commit
5ace61f9b9
@ -1,9 +0,0 @@
|
||||
//
|
||||
// CachingExecutor.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 16/01/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "CachingExecutor.hpp"
|
@ -12,6 +12,10 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace InstructionSet {
|
||||
|
||||
@ -57,20 +61,76 @@ template <
|
||||
uint64_t max_address,
|
||||
/// Indicates the maximum number of potential performers that will be provided.
|
||||
uint64_t max_performer_count,
|
||||
/// Indicates whether performers will acess their decoded instructions; if @c false then instructions are not retained.
|
||||
bool keep_instruction_structs
|
||||
/// Provides the type of Instruction to
|
||||
typename InstructionType
|
||||
> class CachingExecutor {
|
||||
public:
|
||||
|
||||
protected:
|
||||
using Performer = void (Executor::*)();
|
||||
using PerformerIndex = typename MinIntTypeValue<max_performer_count>::type;
|
||||
using ProgramCounterType = typename MinIntTypeValue<max_address>::type;
|
||||
|
||||
// Storage for the statically-allocated list of performers. It's a bit more
|
||||
// work for executors to fill this array, but subsequently performers can be
|
||||
// indexed by array position, which is a lot more compact than a generic pointer.
|
||||
std::array<Performer, max_performer_count> performers_;
|
||||
typename MinIntTypeValue<max_address>::type program_counter_;
|
||||
|
||||
// TODO: should I include a program counter at all? Are there platforms
|
||||
// for which the expense of retaining opcode length doesn't buy any benefit?
|
||||
ProgramCounterType program_counter_;
|
||||
|
||||
|
||||
/*!
|
||||
Moves the current point of execution to @c address, updating necessary performer caches
|
||||
and doing any translation as is necessary.
|
||||
*/
|
||||
void set_program_counter(ProgramCounterType address) {
|
||||
const auto page = find_page(address);
|
||||
const auto entry = page->entry_points.find(address);
|
||||
if(entry == page->entry_points.end()) {
|
||||
// Requested segment wasn't found; check whether it was
|
||||
// within the recently translated list and otherwise
|
||||
// translate it.
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PerformerIndex actions_[100];
|
||||
struct Page {
|
||||
std::map<ProgramCounterType, PerformerIndex> entry_points;
|
||||
|
||||
// TODO: can I statically these two? Should I?
|
||||
std::vector<PerformerIndex> actions_;
|
||||
// std::vector<typename std::enable_if<!std::is_same<InstructionType, void>::value, InstructionType>::type> instructions_;
|
||||
};
|
||||
|
||||
// Maps from page numbers to pages.
|
||||
std::unordered_map<ProgramCounterType, Page> cached_pages_;
|
||||
|
||||
// Maintains an LRU of recently-used pages in case of a need for reuse.
|
||||
std::list<ProgramCounterType> touched_pages_;
|
||||
|
||||
/*!
|
||||
Finds or creates the page that contains @c address.
|
||||
*/
|
||||
Page *find_page(ProgramCounterType address) {
|
||||
// TODO: are 1kb pages always appropriate? Is 64 the correct amount to keep?
|
||||
const auto page_address = address >> 10;
|
||||
constexpr size_t max_cached_pages = 64;
|
||||
|
||||
auto page = cached_pages_.find(page_address);
|
||||
if(page == cached_pages_.end()) {
|
||||
// Page wasn't found; either allocate a new one or
|
||||
// reuse one that already exists.
|
||||
if(cached_pages_.size() == max_cached_pages) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
// Page was found; LRU shuffle it.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -53,6 +53,11 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
program_counter_ += 2;
|
||||
return;
|
||||
|
||||
case AddressingMode::Relative:
|
||||
// These are all the branches...
|
||||
// address = program_counter_ + size(addressing_mode) + int8_t(next8());
|
||||
return;
|
||||
|
||||
// Addressing modes with a memory access.
|
||||
|
||||
case AddressingMode::Absolute: address = next16(); break;
|
||||
@ -82,7 +87,6 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
address = memory_[address] | (memory_[(address + 1) & 0x1fff] << 8);
|
||||
break;
|
||||
|
||||
|
||||
/* TODO:
|
||||
|
||||
ImmediateZeroPage (for LDM)
|
||||
@ -92,10 +96,6 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
BitXZeroPageRelative
|
||||
*/
|
||||
|
||||
case AddressingMode::Relative:
|
||||
address = program_counter_ + size(addressing_mode) + int8_t(next8());
|
||||
// TODO: should be a special case; doesn't become a read, write or read-modify-write.
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -18,14 +18,14 @@ namespace M50740 {
|
||||
|
||||
class Executor;
|
||||
|
||||
class Executor: public CachingExecutor<Executor, 0x2000, 256, false> {
|
||||
class Executor: public CachingExecutor<Executor, 0x2000, 256, void> {
|
||||
public:
|
||||
Executor();
|
||||
|
||||
private:
|
||||
// MARK: - CachingExecutor-facing interface.
|
||||
|
||||
friend CachingExecutor<Executor, 0x2000, 256, false>;
|
||||
friend CachingExecutor<Executor, 0x2000, 256, void>;
|
||||
|
||||
/*!
|
||||
Maps instructions to performers; called by the CachingExecutor and for this instruction set, extremely trivial.
|
||||
|
@ -934,9 +934,6 @@
|
||||
4BEDA43025B3C700000C2DBD /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA42F25B3C700000C2DBD /* Executor.cpp */; };
|
||||
4BEDA43125B3C700000C2DBD /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA42F25B3C700000C2DBD /* Executor.cpp */; };
|
||||
4BEDA43225B3C700000C2DBD /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA42F25B3C700000C2DBD /* Executor.cpp */; };
|
||||
4BEDA43D25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA43B25B3DE66000C2DBD /* CachingExecutor.cpp */; };
|
||||
4BEDA43E25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA43B25B3DE66000C2DBD /* CachingExecutor.cpp */; };
|
||||
4BEDA43F25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA43B25B3DE66000C2DBD /* CachingExecutor.cpp */; };
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6A1D72496600532C7B /* Cartridge.cpp */; };
|
||||
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; };
|
||||
4BEE149A227FC0EA00133682 /* IWM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE1498227FC0EA00133682 /* IWM.cpp */; };
|
||||
@ -1950,8 +1947,7 @@
|
||||
4BEDA42925B3C26B000C2DBD /* AccessType.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AccessType.hpp; sourceTree = "<group>"; };
|
||||
4BEDA42E25B3C613000C2DBD /* Executor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Executor.hpp; sourceTree = "<group>"; };
|
||||
4BEDA42F25B3C700000C2DBD /* Executor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Executor.cpp; sourceTree = "<group>"; };
|
||||
4BEDA43B25B3DE66000C2DBD /* CachingExecutor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CachingExecutor.cpp; sourceTree = "<group>"; };
|
||||
4BEDA43C25B3DE66000C2DBD /* CachingExecutor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CachingExecutor.hpp; sourceTree = "<group>"; };
|
||||
4BEDA45425B5ECAB000C2DBD /* CachingExecutor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CachingExecutor.hpp; sourceTree = "<group>"; };
|
||||
4BEE0A6A1D72496600532C7B /* Cartridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cartridge.cpp; sourceTree = "<group>"; };
|
||||
4BEE0A6B1D72496600532C7B /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
|
||||
4BEE0A6D1D72496600532C7B /* PRG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PRG.cpp; sourceTree = "<group>"; };
|
||||
@ -4370,9 +4366,8 @@
|
||||
4BEDA3B225B25563000C2DBD /* InstructionSets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BEDA43B25B3DE66000C2DBD /* CachingExecutor.cpp */,
|
||||
4BEDA42925B3C26B000C2DBD /* AccessType.hpp */,
|
||||
4BEDA43C25B3DE66000C2DBD /* CachingExecutor.hpp */,
|
||||
4BEDA45425B5ECAB000C2DBD /* CachingExecutor.hpp */,
|
||||
4BEDA3B625B25563000C2DBD /* README.md */,
|
||||
4BEDA40925B2844B000C2DBD /* M50740 */,
|
||||
4BEDA3B325B25563000C2DBD /* PowerPC */,
|
||||
@ -5093,7 +5088,6 @@
|
||||
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */,
|
||||
4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */,
|
||||
4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */,
|
||||
4BEDA43F25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */,
|
||||
4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */,
|
||||
4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */,
|
||||
4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */,
|
||||
@ -5287,7 +5281,6 @@
|
||||
4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */,
|
||||
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */,
|
||||
4BEDA3BF25B25563000C2DBD /* Decoder.cpp in Sources */,
|
||||
4BEDA43D25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */,
|
||||
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
|
||||
4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */,
|
||||
4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */,
|
||||
@ -5468,7 +5461,6 @@
|
||||
4B778F5523A5F2A70000D260 /* Keyboard.cpp in Sources */,
|
||||
4B778F5D23A5F3230000D260 /* Commodore.cpp in Sources */,
|
||||
4B98A05F1FFAD62400ADF63B /* CSROMFetcher.mm in Sources */,
|
||||
4BEDA43E25B3DE66000C2DBD /* CachingExecutor.cpp in Sources */,
|
||||
4BC0CB282446BC7B00A79DBB /* OPLTests.mm in Sources */,
|
||||
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */,
|
||||
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */,
|
||||
|
Loading…
x
Reference in New Issue
Block a user