mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +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:
parent
0dc6f08deb
commit
5149f290d0
@ -149,8 +149,8 @@ template <class T> class WrappedInt {
|
||||
Flushes the value in @c this. The current value is returned, and the internal value
|
||||
is reset to zero.
|
||||
*/
|
||||
forceinline T flush() {
|
||||
T result(length_);
|
||||
template <typename Target> forceinline Target flush() {
|
||||
const Target result(length_);
|
||||
length_ = 0;
|
||||
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.
|
||||
forceinline Cycles flush_cycles() {
|
||||
Cycles result(length_ >> 1);
|
||||
template <typename Cycles> forceinline Cycles flush() {
|
||||
const Cycles result(length_ >> 1);
|
||||
length_ &= 1;
|
||||
return result;
|
||||
}
|
||||
@ -220,7 +220,7 @@ template <class T> class HalfClockReceiver: public T {
|
||||
|
||||
forceinline void run_for(const HalfCycles half_cycles) {
|
||||
half_cycles_ += half_cycles;
|
||||
T::run_for(half_cycles_.flush_cycles());
|
||||
T::run_for(half_cycles_.flush<Cycles>());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1,26 +1,26 @@
|
||||
//
|
||||
// ClockDeferrer.hpp
|
||||
// DeferredQueue.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 23/08/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef ClockDeferrer_h
|
||||
#define ClockDeferrer_h
|
||||
#ifndef DeferredQueue_h
|
||||
#define DeferredQueue_h
|
||||
|
||||
#include <functional>
|
||||
#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
|
||||
that occur between those actions, triggering each action when it is reached.
|
||||
*/
|
||||
template <typename TimeUnit> class ClockDeferrer {
|
||||
template <typename TimeUnit> class DeferredQueue {
|
||||
public:
|
||||
/// Constructs a ClockDeferrer that will call target(period) in between deferred actions.
|
||||
ClockDeferrer(std::function<void(TimeUnit)> &&target) : target_(std::move(target)) {}
|
||||
/// Constructs a DeferredQueue that will call target(period) in between deferred actions.
|
||||
DeferredQueue(std::function<void(TimeUnit)> &&target) : target_(std::move(target)) {}
|
||||
|
||||
/*!
|
||||
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_;
|
||||
};
|
||||
|
||||
#endif /* ClockDeferrer_h */
|
||||
#endif /* DeferredQueue_h */
|
55
ClockReceiver/JustInTime.hpp
Normal file
55
ClockReceiver/JustInTime.hpp
Normal 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 */
|
@ -77,7 +77,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
Cycles cycles_since_video_update_;
|
||||
|
||||
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;
|
||||
void update_audio() {
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include "../../../Outputs/CRT/CRT.hpp"
|
||||
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../../../ClockReceiver/ClockDeferrer.hpp"
|
||||
#include "../../../ClockReceiver/DeferredQueue.hpp"
|
||||
|
||||
#include <array>
|
||||
#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;
|
||||
|
||||
// Maintain a ClockDeferrer for delayed mode switches.
|
||||
ClockDeferrer<Cycles> deferrer_;
|
||||
// Maintain a DeferredQueue for delayed mode switches.
|
||||
DeferredQueue<Cycles> deferrer_;
|
||||
};
|
||||
|
||||
template <class BusHandler, bool is_iie> class Video: public VideoBase {
|
||||
|
@ -24,7 +24,7 @@ struct DeferredAudio {
|
||||
DeferredAudio() : audio(queue), speaker(audio) {}
|
||||
|
||||
void flush() {
|
||||
speaker.run_for(queue, time_since_update.flush_cycles());
|
||||
speaker.run_for(queue, time_since_update.flush<Cycles>());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "../../../Inputs/QuadratureMouse/QuadratureMouse.hpp"
|
||||
#include "../../../Outputs/Log.hpp"
|
||||
|
||||
#include "../../../ClockReceiver/JustInTime.hpp"
|
||||
|
||||
//#define LOG_TRACE
|
||||
|
||||
#include "../../../Components/6522/6522.hpp"
|
||||
@ -471,7 +473,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
Apple::IWM iwm;
|
||||
|
||||
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 time_since_video_update_;
|
||||
HalfCycles time_until_video_event_;
|
||||
HalfCycles time_since_iwm_update_;
|
||||
HalfCycles time_since_mouse_update_;
|
||||
|
||||
bool ROM_is_overlay_ = true;
|
||||
|
@ -55,13 +55,13 @@ class Bus {
|
||||
// video backlog accumulation counter
|
||||
Cycles cycles_since_video_update_;
|
||||
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
|
||||
Cycles cycles_since_6532_update_;
|
||||
inline void update_6532() {
|
||||
mos6532_.run_for(cycles_since_6532_update_.flush());
|
||||
mos6532_.run_for(cycles_since_6532_update_.flush<Cycles>());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -702,7 +702,7 @@ class ConcreteMachine:
|
||||
|
||||
private:
|
||||
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_;
|
||||
|
||||
|
@ -510,7 +510,7 @@ class ConcreteMachine:
|
||||
// MARK: - Work deferral updates.
|
||||
inline void update_display() {
|
||||
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>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
|
||||
|
||||
private:
|
||||
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_bc1_ = false;
|
||||
@ -585,7 +585,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
|
||||
uint8_t ram_[65536];
|
||||
Cycles cycles_since_video_update_;
|
||||
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
|
||||
@ -617,7 +617,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
|
||||
Apple::DiskII diskii_;
|
||||
Cycles cycles_since_diskii_update_;
|
||||
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::size_t pravetz_rom_base_pointer_ = 0;
|
||||
|
@ -983,6 +983,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1051,7 +1052,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -3383,10 +3384,11 @@
|
||||
4BF660691F281573002CB053 /* ClockReceiver */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B8A7E85212F988200F2BBC6 /* ClockDeferrer.hpp */,
|
||||
4BB146C61F49D7D700253439 /* ClockingHintSource.hpp */,
|
||||
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */,
|
||||
4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */,
|
||||
4BB06B211F316A3F00600C7A /* ForceInline.hpp */,
|
||||
4B80214322EE7C3E00068002 /* JustInTime.hpp */,
|
||||
4B449C942063389900A095C8 /* TimeTypes.hpp */,
|
||||
);
|
||||
name = ClockReceiver;
|
||||
|
Loading…
Reference in New Issue
Block a user