1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-18 01:30:56 +00:00

Starts trying to formalise just-in-time execution.

Which, at least, simplifies Cycle/HalfCycle to Cycle run_for usage via template.
This commit is contained in:
Thomas Harte 2019-07-28 21:49:54 -04:00
parent 0dc6f08deb
commit 5149f290d0
12 changed files with 87 additions and 29 deletions

View File

@ -149,8 +149,8 @@ template <class T> class WrappedInt {
Flushes the value in @c this. The current value is returned, and the internal value Flushes the value in @c this. The current value is returned, and the internal value
is reset to zero. is reset to zero.
*/ */
forceinline T flush() { template <typename Target> forceinline Target flush() {
T result(length_); const Target result(length_);
length_ = 0; length_ = 0;
return result; return result;
} }
@ -185,8 +185,8 @@ class HalfCycles: public WrappedInt<HalfCycles> {
} }
/// Flushes the whole cycles in @c this, subtracting that many from the total stored here. /// Flushes the whole cycles in @c this, subtracting that many from the total stored here.
forceinline Cycles flush_cycles() { template <typename Cycles> forceinline Cycles flush() {
Cycles result(length_ >> 1); const Cycles result(length_ >> 1);
length_ &= 1; length_ &= 1;
return result; return result;
} }
@ -220,7 +220,7 @@ template <class T> class HalfClockReceiver: public T {
forceinline void run_for(const HalfCycles half_cycles) { forceinline void run_for(const HalfCycles half_cycles) {
half_cycles_ += half_cycles; half_cycles_ += half_cycles;
T::run_for(half_cycles_.flush_cycles()); T::run_for(half_cycles_.flush<Cycles>());
} }
private: private:

View File

@ -1,26 +1,26 @@
// //
// ClockDeferrer.hpp // DeferredQueue.hpp
// Clock Signal // Clock Signal
// //
// Created by Thomas Harte on 23/08/2018. // Created by Thomas Harte on 23/08/2018.
// Copyright © 2018 Thomas Harte. All rights reserved. // Copyright © 2018 Thomas Harte. All rights reserved.
// //
#ifndef ClockDeferrer_h #ifndef DeferredQueue_h
#define ClockDeferrer_h #define DeferredQueue_h
#include <functional> #include <functional>
#include <vector> #include <vector>
/*! /*!
A ClockDeferrer maintains a list of ordered actions and the times at which A DeferredQueue maintains a list of ordered actions and the times at which
they should happen, and divides a total execution period up into the portions they should happen, and divides a total execution period up into the portions
that occur between those actions, triggering each action when it is reached. that occur between those actions, triggering each action when it is reached.
*/ */
template <typename TimeUnit> class ClockDeferrer { template <typename TimeUnit> class DeferredQueue {
public: public:
/// Constructs a ClockDeferrer that will call target(period) in between deferred actions. /// Constructs a DeferredQueue that will call target(period) in between deferred actions.
ClockDeferrer(std::function<void(TimeUnit)> &&target) : target_(std::move(target)) {} DeferredQueue(std::function<void(TimeUnit)> &&target) : target_(std::move(target)) {}
/*! /*!
Schedules @c action to occur in @c delay units of time. Schedules @c action to occur in @c delay units of time.
@ -79,4 +79,4 @@ template <typename TimeUnit> class ClockDeferrer {
std::vector<DeferredAction> pending_actions_; std::vector<DeferredAction> pending_actions_;
}; };
#endif /* ClockDeferrer_h */ #endif /* DeferredQueue_h */

View File

@ -0,0 +1,55 @@
//
// JustInTime.hpp
// Clock Signal
//
// Created by Thomas Harte on 28/07/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef JustInTime_h
#define JustInTime_h
//#include "../Concurrency/AsyncTaskQueue.hpp"
/*!
A JustInTimeActor holds (i) an embedded object with a run_for method; and (ii) an amount
of time since run_for was last called.
Time can be added using the += operator. The -> operator can be used to access the
embedded object. All time accumulated will be pushed to object before the pointer is returned.
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
separate @c TargetTimeScale at template declaration.
*/
template <class T, class LocalTimeScale, class TargetTimeScale = LocalTimeScale> class JustInTimeActor {
public:
/// Constructs a new JustInTimeActor using the same construction arguments as the included object.
template<typename... Args> JustInTimeActor(Args&&... args) : object_(std::forward<Args>(args)...) {}
/// Adds time to the actor.
inline void operator += (const TimeScale &rhs) {
time_since_update_ += rhs;
}
/// Flushes all accumulated time and returns a pointer to the included object.
inline T *operator->() {
object_.run_for(time_since_update_.template flush<TargetTimeScale>());
return &object_;
}
private:
T object_;
LocalTimeScale time_since_update_;
};
/*!
A JustInTimeAsyncActor acts like a JustInTimeActor but additionally contains an AsyncTaskQueue.
Any time the amount of accumulated time crosses a threshold provided at construction time,
the object will be updated on the AsyncTaskQueue.
*/
template <class T, class TimeScale> class JustInTimeAsyncActor {
};
#endif /* JustInTime_h */

View File

@ -77,7 +77,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
Cycles cycles_since_video_update_; Cycles cycles_since_video_update_;
void update_video() { void update_video() {
video_.run_for(cycles_since_video_update_.flush()); video_.run_for(cycles_since_video_update_.flush<Cycles>());
} }
static const int audio_divider = 8; static const int audio_divider = 8;
void update_audio() { void update_audio() {

View File

@ -11,7 +11,7 @@
#include "../../../Outputs/CRT/CRT.hpp" #include "../../../Outputs/CRT/CRT.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp" #include "../../../ClockReceiver/ClockReceiver.hpp"
#include "../../../ClockReceiver/ClockDeferrer.hpp" #include "../../../ClockReceiver/DeferredQueue.hpp"
#include <array> #include <array>
#include <vector> #include <vector>
@ -251,8 +251,8 @@ class VideoBase {
*/ */
void output_fat_low_resolution(uint8_t *target, const uint8_t *source, size_t length, int column, int row) const; void output_fat_low_resolution(uint8_t *target, const uint8_t *source, size_t length, int column, int row) const;
// Maintain a ClockDeferrer for delayed mode switches. // Maintain a DeferredQueue for delayed mode switches.
ClockDeferrer<Cycles> deferrer_; DeferredQueue<Cycles> deferrer_;
}; };
template <class BusHandler, bool is_iie> class Video: public VideoBase { template <class BusHandler, bool is_iie> class Video: public VideoBase {

View File

@ -24,7 +24,7 @@ struct DeferredAudio {
DeferredAudio() : audio(queue), speaker(audio) {} DeferredAudio() : audio(queue), speaker(audio) {}
void flush() { void flush() {
speaker.run_for(queue, time_since_update.flush_cycles()); speaker.run_for(queue, time_since_update.flush<Cycles>());
} }
}; };

View File

@ -24,6 +24,8 @@
#include "../../../Inputs/QuadratureMouse/QuadratureMouse.hpp" #include "../../../Inputs/QuadratureMouse/QuadratureMouse.hpp"
#include "../../../Outputs/Log.hpp" #include "../../../Outputs/Log.hpp"
#include "../../../ClockReceiver/JustInTime.hpp"
//#define LOG_TRACE //#define LOG_TRACE
#include "../../../Components/6522/6522.hpp" #include "../../../Components/6522/6522.hpp"
@ -471,7 +473,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
Apple::IWM iwm; Apple::IWM iwm;
void flush() { void flush() {
iwm.run_for(time_since_update.flush_cycles()); iwm.run_for(time_since_update.flush<Cycles>());
} }
}; };
@ -610,7 +612,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
HalfCycles keyboard_clock_; HalfCycles keyboard_clock_;
HalfCycles time_since_video_update_; HalfCycles time_since_video_update_;
HalfCycles time_until_video_event_; HalfCycles time_until_video_event_;
HalfCycles time_since_iwm_update_;
HalfCycles time_since_mouse_update_; HalfCycles time_since_mouse_update_;
bool ROM_is_overlay_ = true; bool ROM_is_overlay_ = true;

View File

@ -55,13 +55,13 @@ class Bus {
// video backlog accumulation counter // video backlog accumulation counter
Cycles cycles_since_video_update_; Cycles cycles_since_video_update_;
inline void update_video() { inline void update_video() {
tia_.run_for(cycles_since_video_update_.flush()); tia_.run_for(cycles_since_video_update_.flush<Cycles>());
} }
// RIOT backlog accumulation counter // RIOT backlog accumulation counter
Cycles cycles_since_6532_update_; Cycles cycles_since_6532_update_;
inline void update_6532() { inline void update_6532() {
mos6532_.run_for(cycles_since_6532_update_.flush()); mos6532_.run_for(cycles_since_6532_update_.flush<Cycles>());
} }
}; };

View File

@ -702,7 +702,7 @@ class ConcreteMachine:
private: private:
void update_video() { void update_video() {
mos6560_.run_for(cycles_since_mos6560_update_.flush()); mos6560_.run_for(cycles_since_mos6560_update_.flush<Cycles>());
} }
CPU::MOS6502::Processor<CPU::MOS6502::Personality::P6502, ConcreteMachine, false> m6502_; CPU::MOS6502::Processor<CPU::MOS6502::Personality::P6502, ConcreteMachine, false> m6502_;

View File

@ -510,7 +510,7 @@ class ConcreteMachine:
// MARK: - Work deferral updates. // MARK: - Work deferral updates.
inline void update_display() { inline void update_display() {
if(cycles_since_display_update_ > 0) { if(cycles_since_display_update_ > 0) {
video_output_.run_for(cycles_since_display_update_.flush()); video_output_.run_for(cycles_since_display_update_.flush<Cycles>());
} }
} }

View File

@ -182,7 +182,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
private: private:
void update_ay() { void update_ay() {
speaker_.run_for(audio_queue_, cycles_since_ay_update_.flush_cycles()); speaker_.run_for(audio_queue_, cycles_since_ay_update_.flush<Cycles>());
} }
bool ay_bdir_ = false; bool ay_bdir_ = false;
bool ay_bc1_ = false; bool ay_bc1_ = false;
@ -585,7 +585,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
uint8_t ram_[65536]; uint8_t ram_[65536];
Cycles cycles_since_video_update_; Cycles cycles_since_video_update_;
inline void update_video() { inline void update_video() {
video_output_.run_for(cycles_since_video_update_.flush()); video_output_.run_for(cycles_since_video_update_.flush<Cycles>());
} }
// ROM bookkeeping // ROM bookkeeping
@ -617,7 +617,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
Apple::DiskII diskii_; Apple::DiskII diskii_;
Cycles cycles_since_diskii_update_; Cycles cycles_since_diskii_update_;
void flush_diskii() { void flush_diskii() {
diskii_.run_for(cycles_since_diskii_update_.flush()); diskii_.run_for(cycles_since_diskii_update_.flush<Cycles>());
} }
std::vector<uint8_t> pravetz_rom_; std::vector<uint8_t> pravetz_rom_;
std::size_t pravetz_rom_base_pointer_ = 0; std::size_t pravetz_rom_base_pointer_ = 0;

View File

@ -983,6 +983,7 @@
4B7F188D2154825D00388727 /* MasterSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MasterSystem.hpp; sourceTree = "<group>"; }; 4B7F188D2154825D00388727 /* MasterSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MasterSystem.hpp; sourceTree = "<group>"; };
4B7F1895215486A100388727 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; }; 4B7F1895215486A100388727 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; };
4B7F1896215486A100388727 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; }; 4B7F1896215486A100388727 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
4B80214322EE7C3E00068002 /* JustInTime.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JustInTime.hpp; sourceTree = "<group>"; };
4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BestEffortUpdater.cpp; path = ../../Concurrency/BestEffortUpdater.cpp; sourceTree = "<group>"; }; 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BestEffortUpdater.cpp; path = ../../Concurrency/BestEffortUpdater.cpp; sourceTree = "<group>"; };
4B80ACFF1F85CACA00176895 /* BestEffortUpdater.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = BestEffortUpdater.hpp; path = ../../Concurrency/BestEffortUpdater.hpp; sourceTree = "<group>"; }; 4B80ACFF1F85CACA00176895 /* BestEffortUpdater.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = BestEffortUpdater.hpp; path = ../../Concurrency/BestEffortUpdater.hpp; sourceTree = "<group>"; };
4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PartialMachineCycle.cpp; sourceTree = "<group>"; }; 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PartialMachineCycle.cpp; sourceTree = "<group>"; };
@ -1051,7 +1052,7 @@
4B894516201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; }; 4B894516201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
4B894517201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; }; 4B894517201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
4B894540201967D6007DE474 /* Machines.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Machines.hpp; sourceTree = "<group>"; }; 4B894540201967D6007DE474 /* Machines.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Machines.hpp; sourceTree = "<group>"; };
4B8A7E85212F988200F2BBC6 /* ClockDeferrer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ClockDeferrer.hpp; sourceTree = "<group>"; }; 4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredQueue.hpp; sourceTree = "<group>"; };
4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = "<group>"; }; 4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = "<group>"; };
4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMachine.hpp; sourceTree = "<group>"; }; 4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMachine.hpp; sourceTree = "<group>"; };
4B8EF6071FE5AF830076CCDD /* LowpassSpeaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LowpassSpeaker.hpp; sourceTree = "<group>"; }; 4B8EF6071FE5AF830076CCDD /* LowpassSpeaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LowpassSpeaker.hpp; sourceTree = "<group>"; };
@ -3383,10 +3384,11 @@
4BF660691F281573002CB053 /* ClockReceiver */ = { 4BF660691F281573002CB053 /* ClockReceiver */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4B8A7E85212F988200F2BBC6 /* ClockDeferrer.hpp */,
4BB146C61F49D7D700253439 /* ClockingHintSource.hpp */, 4BB146C61F49D7D700253439 /* ClockingHintSource.hpp */,
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */, 4BF6606A1F281573002CB053 /* ClockReceiver.hpp */,
4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */,
4BB06B211F316A3F00600C7A /* ForceInline.hpp */, 4BB06B211F316A3F00600C7A /* ForceInline.hpp */,
4B80214322EE7C3E00068002 /* JustInTime.hpp */,
4B449C942063389900A095C8 /* TimeTypes.hpp */, 4B449C942063389900A095C8 /* TimeTypes.hpp */,
); );
name = ClockReceiver; name = ClockReceiver;