1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Relocated ClockReceiver.hpp as it's a dependency for parts of the static analyser, and therefore needs to be distinct from the actual emulation parts.

This commit is contained in:
Thomas Harte 2017-07-25 20:20:55 -04:00
parent a1e9a54765
commit 75d67ee770
18 changed files with 210 additions and 24 deletions

View File

@ -0,0 +1,171 @@
//
// ClockReceiver.hpp
// Clock Signal
//
// Created by Thomas Harte on 22/07/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef ClockReceiver_hpp
#define ClockReceiver_hpp
/*!
Provides a class that wraps a plain int, providing most of the basic arithmetic and
Boolean operators, but forcing callers and receivers to be explicit as to usage.
*/
template <class T> class WrappedInt {
public:
inline WrappedInt(int l) : length_(l) {}
inline WrappedInt() : length_(0) {}
inline T &operator =(const T &rhs) {
length_ = rhs.length_;
return *this;
}
inline T &operator +=(const T &rhs) {
length_ += rhs.length_;
return *static_cast<T *>(this);
}
inline T &operator -=(const T &rhs) {
length_ -= rhs.length_;
return *static_cast<T *>(this);
}
inline T &operator ++() {
++ length_;
return *static_cast<T *>(this);
}
inline T &operator ++(int) {
length_ ++;
return *static_cast<T *>(this);
}
inline T &operator --() {
-- length_;
return *static_cast<T *>(this);
}
inline T &operator --(int) {
length_ --;
return *static_cast<T *>(this);
}
inline T &operator %=(const T &rhs) {
length_ %= rhs.length_;
return *static_cast<T *>(this);
}
inline T operator +(const T &rhs) const { return T(length_ + rhs.length_); }
inline T operator -(const T &rhs) const { return T(length_ - rhs.length_); }
inline bool operator <(const T &rhs) const { return length_ < rhs.length_; }
inline bool operator >(const T &rhs) const { return length_ > rhs.length_; }
inline bool operator <=(const T &rhs) const { return length_ <= rhs.length_; }
inline bool operator >=(const T &rhs) const { return length_ >= rhs.length_; }
inline bool operator ==(const T &rhs) const { return length_ == rhs.length_; }
inline bool operator !=(const T &rhs) const { return length_ != rhs.length_; }
inline bool operator !() const { return !length_; }
inline operator bool() const { return !!length_; }
inline int as_int() const { return length_; }
/*!
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.
*/
inline T divide(const T &divisor) {
T result(length_ / divisor.length_);
length_ %= divisor.length_;
return result;
}
/*!
Flushes the value in @c this. The current value is returned, and the internal value
is reset to zero.
*/
inline T flush() {
T result(length_);
length_ = 0;
return result;
}
// operator int() is deliberately not provided, to avoid accidental subtitution of
// classes that use this template.
protected:
int length_;
};
/// Describes an integer number of whole cycles — pairs of clock signal transitions.
class Cycles: public WrappedInt<Cycles> {
public:
inline Cycles(int l) : WrappedInt<Cycles>(l) {}
inline Cycles() : WrappedInt<Cycles>() {}
inline Cycles(const Cycles &cycles) : WrappedInt<Cycles>(cycles.length_) {}
};
/// Describes an integer number of half cycles — single clock signal transitions.
class HalfCycles: public WrappedInt<HalfCycles> {
public:
inline HalfCycles(int l) : WrappedInt<HalfCycles>(l) {}
inline HalfCycles() : WrappedInt<HalfCycles>() {}
inline HalfCycles(const Cycles &cycles) : WrappedInt<HalfCycles>(cycles.as_int() << 1) {}
inline HalfCycles(const HalfCycles &half_cycles) : WrappedInt<HalfCycles>(half_cycles.length_) {}
};
/*!
ClockReceiver is a template for components that receove a clock, measured either
in cycles or in half cycles. They are expected to implement either of the run_for
methods and to declare that they are `using` the other; buying into the template
means that the other run_for will automatically map appropriately to the implemented
one, so callers may use either.
Alignment rule:
run_for(Cycles) may be called only at the start of a cycle. E.g. the following
sequence will have undefined results:
run_for(HalfCycles(1))
run_for(Cycles(1))
An easy way to ensure this as a caller is to pick only one of run_for(Cycles) and
run_for(HalfCycles) to use.
Reasoning:
Users of this template may with to implement run_for(Cycles) and run_for(HalfCycles)
where there is a need to implement at half-cycle precision but a faster execution
path can be offered for full-cycle precision. Those users are permitted to assume
phase in run_for(Cycles) and should do so to be compatible with callers that use
only run_for(Cycles).
Corollary:
Starting from nothing, the first run_for(HalfCycles(1)) will do the **first** half
of a full cycle. The second will do the second half. Etc.
*/
template <class T> class ClockReceiver {
public:
ClockReceiver() : half_cycle_carry_(0) {}
inline void run_for(const Cycles &cycles) {
static_cast<T *>(this)->run_for(HalfCycles(cycles));
}
inline void run_for(const HalfCycles &half_cycles) {
int cycles = half_cycles.as_int() + half_cycle_carry_;
half_cycle_carry_ = cycles & 1;
static_cast<T *>(this)->run_for(Cycles(cycles >> 1));
}
private:
int half_cycle_carry_;
};
#endif /* ClockReceiver_hpp */

View File

@ -13,7 +13,7 @@
#include <typeinfo>
#include <cstdio>
#include "../ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace MOS {

View File

@ -11,7 +11,8 @@
#include <cstdint>
#include <cstdio>
#include "../ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace MOS {

View File

@ -11,7 +11,7 @@
#include "../../Outputs/CRT/CRT.hpp"
#include "../../Outputs/Speaker.hpp"
#include "../ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace MOS {

View File

@ -13,7 +13,8 @@
#include "PIA.hpp"
#include "Speaker.hpp"
#include "TIA.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace Atari2600 {

View File

@ -10,8 +10,9 @@
#define TIA_hpp
#include <cstdint>
#include "../CRTMachine.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace Atari2600 {

View File

@ -11,7 +11,7 @@
#include "../Outputs/CRT/CRT.hpp"
#include "../Outputs/Speaker.hpp"
#include "../Components/ClockReceiver.hpp"
#include "../ClockReceiver/ClockReceiver.hpp"
namespace CRTMachine {

View File

@ -9,12 +9,12 @@
#ifndef Electron_Tape_h
#define Electron_Tape_h
#include <cstdint>
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../Storage/Tape/Tape.hpp"
#include "../../Storage/Tape/Parsers/Acorn.hpp"
#include "Interrupts.hpp"
#include "../../Components/ClockReceiver.hpp"
#include <cstdint>
namespace Electron {

View File

@ -10,7 +10,7 @@
#define Machines_Electron_Video_hpp
#include "../../Outputs/CRT/CRT.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "Interrupts.hpp"
namespace Electron {

View File

@ -10,7 +10,7 @@
#define Machines_Oric_Video_hpp
#include "../../Outputs/CRT/CRT.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace Oric {

View File

@ -10,7 +10,7 @@
#define Machines_ZX8081_Video_hpp
#include "../../Outputs/CRT/CRT.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace ZX8081 {

View File

@ -563,7 +563,6 @@
4B4DC8271D2C2470003C5BF8 /* C1540.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = C1540.hpp; sourceTree = "<group>"; };
4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialBus.cpp; sourceTree = "<group>"; };
4B4DC82A1D2C27A4003C5BF8 /* SerialBus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialBus.hpp; sourceTree = "<group>"; };
4B4EA7E01F24349400C216B4 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBuilder.cpp; sourceTree = "<group>"; };
4B5073061DDD3B9400C48FBD /* ArrayBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ArrayBuilder.hpp; sourceTree = "<group>"; };
4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ArrayBuilderTests.mm; sourceTree = "<group>"; };
@ -1021,6 +1020,7 @@
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StaticAnalyser.cpp; path = ../../StaticAnalyser/StaticAnalyser.cpp; sourceTree = "<group>"; };
4BF1354B1D6D2C300054B2EA /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/StaticAnalyser.hpp; sourceTree = "<group>"; };
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
4BF8295B1D8F048B001BAE39 /* MFM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MFM.cpp; path = Encodings/MFM.cpp; sourceTree = "<group>"; };
4BF8295C1D8F048B001BAE39 /* MFM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = MFM.hpp; path = Encodings/MFM.hpp; sourceTree = "<group>"; };
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRC.hpp; path = ../../NumberTheory/CRC.hpp; sourceTree = "<group>"; };
@ -1810,6 +1810,7 @@
4BB73EA01B587A5100552FC2 /* Clock Signal */,
4BB73EB51B587A5100552FC2 /* Clock SignalTests */,
4BB73EC01B587A5100552FC2 /* Clock SignalUITests */,
4BF660691F281573002CB053 /* ClockReceiver */,
4BC9DF4A1D04691600F44158 /* Components */,
4B3940E81DA83C8700427841 /* Concurrency */,
4BB73EDC1B587CA500552FC2 /* Machines */,
@ -1989,7 +1990,6 @@
4BC9DF4A1D04691600F44158 /* Components */ = {
isa = PBXGroup;
children = (
4B4EA7E01F24349400C216B4 /* ClockReceiver.hpp */,
4BD468F81D8DF4290084958B /* 1770 */,
4BC9DF4B1D04691600F44158 /* 6522 */,
4B1E85791D174DEC001EF87D /* 6532 */,
@ -2158,6 +2158,15 @@
name = StaticAnalyser;
sourceTree = "<group>";
};
4BF660691F281573002CB053 /* ClockReceiver */ = {
isa = PBXGroup;
children = (
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */,
);
name = ClockReceiver;
path = ../../ClockReceiver;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */

View File

@ -9,9 +9,9 @@
#ifndef Speaker_hpp
#define Speaker_hpp
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <cstdint>
#include <cstdio>
#include <ctime>
#include <memory>
#include <list>
@ -20,7 +20,7 @@
#include "../SignalProcessing/Stepper.hpp"
#include "../SignalProcessing/FIRFilter.hpp"
#include "../Concurrency/AsyncTaskQueue.hpp"
#include "../Components/ClockReceiver.hpp"
#include "../ClockReceiver/ClockReceiver.hpp"
namespace Outputs {

View File

@ -13,7 +13,7 @@
#include <cstdint>
#include "../RegisterSizes.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace CPU {
namespace MOS6502 {

View File

@ -15,7 +15,7 @@
#include <vector>
#include "../RegisterSizes.hpp"
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace CPU {
namespace Z80 {

View File

@ -11,7 +11,8 @@
#include <memory>
#include <vector>
#include "../../Components/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace Storage {

View File

@ -10,8 +10,9 @@
#define Tape_hpp
#include <memory>
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../TimedEventLoop.hpp"
#include "../../Components/ClockReceiver.hpp"
namespace Storage {
namespace Tape {

View File

@ -11,9 +11,10 @@
#include "Storage.hpp"
#include <memory>
#include "../ClockReceiver/ClockReceiver.hpp"
#include "../SignalProcessing/Stepper.hpp"
#include "../Components/ClockReceiver.hpp"
#include <memory>
namespace Storage {