1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-30 22:56:03 +00:00

Adopt PIT-centric timing.

This commit is contained in:
Thomas Harte 2023-11-21 22:02:24 -05:00
parent c11d3b61d6
commit 6329a1208a

View File

@ -525,8 +525,9 @@ class ConcreteMachine:
public MachineTypes::ScanProducer
{
public:
static constexpr int PitMultiplier = 1;
static constexpr int PitDivisor = 3;
// i.e. CPU clock rate is 1/3 * ~1.19Mhz ~= 0.4 MIPS.
static constexpr int CPUMultiplier = 1;
static constexpr int CPUDivisor = 3;
ConcreteMachine(
[[maybe_unused]] const Analyser::Static::Target &target,
@ -534,7 +535,7 @@ class ConcreteMachine:
) : pit_observer_(pic_), pit_(pit_observer_), ppi_(ppi_handler_), context(pit_, dma_, ppi_, pic_) {
// Use clock rate as a MIPS count; keeping it as a multiple or divisor of the PIT frequency is easy.
static constexpr int pit_frequency = 1'193'182;
set_clock_rate(double(pit_frequency) * double(PitMultiplier) / double(PitDivisor)); // i.e. almost 0.4 MIPS for an XT.
set_clock_rate(double(pit_frequency));
// Fetch the BIOS. [8088 only, for now]
const auto bios = ROM::Name::PCCompatibleGLaBIOS;
@ -552,16 +553,25 @@ class ConcreteMachine:
// MARK: - TimedMachine.
// bool log = false;
// std::string previous;
void run_for(const Cycles cycles) override {
auto instructions = cycles.as_integral();
while(instructions--) {
void run_for(const Cycles duration) override {
auto pit_ticks = duration.as_integral();
while(pit_ticks--) {
//
// First draft: all hardware runs in lockstep.
// First draft: all hardware runs in lockstep, as a multiple or divisor of the PIT frequency.
//
// Advance the PIT.
pit_.run_for(PitDivisor / PitMultiplier);
pit_.run_for(1);
// Advance the CPU.
cpu_divisor_ += CPUMultiplier;
int cycles = cpu_divisor_ / CPUDivisor;
cycles %= CPUDivisor;
// To consider: a Duff-esque switch table calling into a function templated on clock phase
// might alleviate a large part of the conditionality here?
while(cycles--) {
// Query for interrupts and apply if pending.
if(pic_.pending() && context.flags.flag<InstructionSet::x86::Flag::Interrupt>()) {
// Regress the IP if a REP is in-progress so as to resume it later.
@ -613,6 +623,7 @@ class ConcreteMachine:
);
}
}
}
// MARK: - ScanProducer.
void set_scan_target([[maybe_unused]] Outputs::Display::ScanTarget *scan_target) override {}
@ -661,6 +672,8 @@ class ConcreteMachine:
uint16_t decoded_ip_ = 0;
std::pair<int, InstructionSet::x86::Instruction<false>> decoded;
int cpu_divisor_ = 0;
};