1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 23:29:06 +00:00

JustInTimeActors can now specify a clock divider.

This commit is contained in:
Thomas Harte 2019-10-13 18:19:39 -04:00
parent 516d78f5a8
commit d7982aa84e
8 changed files with 53 additions and 26 deletions

View File

@ -139,10 +139,10 @@ template <class T> class WrappedInt {
Severs from @c this the effect of dividing by @c divisor; @c this will end up with Severs from @c this the effect of dividing by @c divisor; @c this will end up with
the value of @c this modulo @c divisor and @c divided by @c divisor is returned. the value of @c this modulo @c divisor and @c divided by @c divisor is returned.
*/ */
forceinline T divide(const T &divisor) { template <typename Result = T> forceinline Result divide(const T &divisor) {
T result(length_ / divisor.length_); Result r;
length_ %= divisor.length_; static_cast<T *>(this)->fill(r, divisor);
return result; return r;
} }
/*! /*!
@ -177,6 +177,11 @@ class Cycles: public WrappedInt<Cycles> {
result.length_ = length_; result.length_ = length_;
length_ = 0; length_ = 0;
} }
void fill(Cycles &result, const Cycles &divisor) {
result.length_ = length_ / divisor.length_;
length_ %= divisor.length_;
}
}; };
/// Describes an integer number of half cycles: single clock signal transitions. /// Describes an integer number of half cycles: single clock signal transitions.
@ -215,6 +220,16 @@ class HalfCycles: public WrappedInt<HalfCycles> {
result.length_ = length_; result.length_ = length_;
length_ = 0; length_ = 0;
} }
void fill(Cycles &result, const HalfCycles &divisor) {
result = Cycles(length_ / (divisor.length_ << 1));
length_ %= (divisor.length_ << 1);
}
void fill(HalfCycles &result, const HalfCycles &divisor) {
result.length_ = length_ / divisor.length_;
length_ %= divisor.length_;
}
}; };
// Create a specialisation of WrappedInt::flush for converting HalfCycles to Cycles // Create a specialisation of WrappedInt::flush for converting HalfCycles to Cycles

View File

@ -21,7 +21,7 @@
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
separate @c TargetTimeScale at template declaration. separate @c TargetTimeScale at template declaration.
*/ */
template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale> class JustInTimeActor { template <class T, int divider = 1, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale> class JustInTimeActor {
public: public:
/// Constructs a new JustInTimeActor using the same construction arguments as the included object. /// Constructs a new JustInTimeActor using the same construction arguments as the included object.
template<typename... Args> JustInTimeActor(Args&&... args) : object_(std::forward<Args>(args)...) {} template<typename... Args> JustInTimeActor(Args&&... args) : object_(std::forward<Args>(args)...) {}
@ -44,8 +44,14 @@ template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = Lo
} }
/// Flushes all accumulated time. /// Flushes all accumulated time.
inline void flush() { void flush() {
if(!is_flushed_) object_.run_for(time_since_update_.template flush<TargetTimeScale>()); if(!is_flushed_) {
if(divider == 1) {
object_.run_for(time_since_update_.template flush<TargetTimeScale>());
} else {
object_.run_for(time_since_update_.template divide<TargetTimeScale>(LocalTimeScale(divider)));
}
}
is_flushed_ = true; is_flushed_ = true;
} }

View File

@ -89,18 +89,20 @@ void ACIA::run_for(HalfCycles length) {
const int transmit_advance = length.as_int(); const int transmit_advance = length.as_int();
const auto write_data_time_remaining = transmit.write_data_time_remaining(); const auto write_data_time_remaining = transmit.write_data_time_remaining();
if(transmit_advance > write_data_time_remaining) { if(write_data_time_remaining) {
if(next_transmission_ != NoTransmission) { if(transmit_advance > write_data_time_remaining) {
transmit.flush_writing(); if(next_transmission_ != NoTransmission) {
consider_transmission(); transmit.flush_writing();
transmit.advance_writer(transmit_advance - write_data_time_remaining); consider_transmission();
transmit.advance_writer(transmit_advance - write_data_time_remaining);
} else {
transmit.advance_writer(transmit_advance);
update_clocking_observer();
interrupt_request_ |= transmit_interrupt_enabled_;
}
} else { } else {
transmit.advance_writer(transmit_advance); transmit.advance_writer(transmit_advance);
update_clocking_observer();
interrupt_request_ |= transmit_interrupt_enabled_;
} }
} else {
transmit.advance_writer(transmit_advance);
} }
// Reception. // Reception.

View File

@ -656,9 +656,11 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
return mouse_; return mouse_;
} }
using IWMActor = JustInTimeActor<IWM, 1, HalfCycles, Cycles>;
class VIAPortHandler: public MOS::MOS6522::PortHandler { class VIAPortHandler: public MOS::MOS6522::PortHandler {
public: public:
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, JustInTimeActor<IWM, HalfCycles, Cycles> &iwm, Inputs::QuadratureMouse &mouse) : VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, IWMActor &iwm, Inputs::QuadratureMouse &mouse) :
machine_(machine), clock_(clock), keyboard_(keyboard), audio_(audio), iwm_(iwm), mouse_(mouse) {} machine_(machine), clock_(clock), keyboard_(keyboard), audio_(audio), iwm_(iwm), mouse_(mouse) {}
using Port = MOS::MOS6522::Port; using Port = MOS::MOS6522::Port;
@ -764,14 +766,14 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
RealTimeClock &clock_; RealTimeClock &clock_;
Keyboard &keyboard_; Keyboard &keyboard_;
DeferredAudio &audio_; DeferredAudio &audio_;
JustInTimeActor<IWM, HalfCycles, Cycles> &iwm_; IWMActor &iwm_;
Inputs::QuadratureMouse &mouse_; Inputs::QuadratureMouse &mouse_;
}; };
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_; CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
DriveSpeedAccumulator drive_speed_accumulator_; DriveSpeedAccumulator drive_speed_accumulator_;
JustInTimeActor<IWM, HalfCycles, Cycles> iwm_; IWMActor iwm_;
DeferredAudio audio_; DeferredAudio audio_;
Video video_; Video video_;

View File

@ -347,6 +347,8 @@ class ConcreteMachine:
forceinline void advance_time(HalfCycles length) { forceinline void advance_time(HalfCycles length) {
cycles_since_audio_update_ += length; cycles_since_audio_update_ += length;
mfp_ += length; mfp_ += length;
keyboard_acia_ += length;
midi_acia_ += length;
while(length >= cycles_until_video_event_) { while(length >= cycles_until_video_event_) {
length -= cycles_until_video_event_; length -= cycles_until_video_event_;
@ -366,12 +368,12 @@ class ConcreteMachine:
} }
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_; CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
JustInTimeActor<Video, HalfCycles> video_; JustInTimeActor<Video> video_;
HalfCycles cycles_until_video_event_; HalfCycles cycles_until_video_event_;
JustInTimeActor<Motorola::MFP68901::MFP68901, HalfCycles> mfp_; JustInTimeActor<Motorola::MFP68901::MFP68901> mfp_;
JustInTimeActor<Motorola::ACIA::ACIA, HalfCycles> keyboard_acia_; JustInTimeActor<Motorola::ACIA::ACIA, 10> keyboard_acia_;
JustInTimeActor<Motorola::ACIA::ACIA, HalfCycles> midi_acia_; JustInTimeActor<Motorola::ACIA::ACIA, 10> midi_acia_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
GI::AY38910::AY38910 ay_; GI::AY38910::AY38910 ay_;

View File

@ -397,7 +397,7 @@ class ConcreteMachine:
} }
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_; JustInTimeActor<TI::TMS::TMS9918, 1, HalfCycles> vdp_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
TI::SN76489 sn76489_; TI::SN76489 sn76489_;

View File

@ -752,7 +752,7 @@ class ConcreteMachine:
}; };
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_; JustInTimeActor<TI::TMS::TMS9918> vdp_;
Intel::i8255::i8255<i8255PortHandler> i8255_; Intel::i8255::i8255<i8255PortHandler> i8255_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;

View File

@ -414,7 +414,7 @@ class ConcreteMachine:
Target::Region region_; Target::Region region_;
Target::PagingScheme paging_scheme_; Target::PagingScheme paging_scheme_;
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_; JustInTimeActor<TI::TMS::TMS9918> vdp_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
TI::SN76489 sn76489_; TI::SN76489 sn76489_;