1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +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
the value of @c this modulo @c divisor and @c divided by @c divisor is returned.
*/
forceinline T divide(const T &divisor) {
T result(length_ / divisor.length_);
length_ %= divisor.length_;
return result;
template <typename Result = T> forceinline Result divide(const T &divisor) {
Result r;
static_cast<T *>(this)->fill(r, divisor);
return r;
}
/*!
@ -177,6 +177,11 @@ class Cycles: public WrappedInt<Cycles> {
result.length_ = length_;
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.
@ -215,6 +220,16 @@ class HalfCycles: public WrappedInt<HalfCycles> {
result.length_ = length_;
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

View File

@ -21,7 +21,7 @@
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 = HalfCycles, class TargetTimeScale = LocalTimeScale> class JustInTimeActor {
template <class T, int divider = 1, class LocalTimeScale = HalfCycles, 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)...) {}
@ -44,8 +44,14 @@ template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = Lo
}
/// Flushes all accumulated time.
inline void flush() {
if(!is_flushed_) object_.run_for(time_since_update_.template flush<TargetTimeScale>());
void flush() {
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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