package mtmc.emulator import mtmc.emulator.MonTanaMiniComputer.ComputerStatus import kotlin.math.max /** * * @author jbanes */ class MTMCClock (private val computer: MonTanaMiniComputer) { fun run() { var instructions: Long = 0 var ips: Long = 0 var expected: Long = 0 var virtual: Long = 0 var startTime = System.currentTimeMillis() var deltaStart: Long var delta: Long var speed: Long = 0 var pulse: Long var ms: Long = 10 while (computer.getStatus() == ComputerStatus.EXECUTING) { speed = max(computer.speed, 0).toLong() pulse = (if (speed <= 0) 1000000 else max(speed / 100, 1)) ms = (if (pulse < 10) 1000 / speed else 10) deltaStart = System.currentTimeMillis() delta = ms - (System.currentTimeMillis() - deltaStart) /* We've lost more than a second. Recalibrate. */ if ((expected - virtual) > pulse * 100) { startTime = deltaStart virtual = 0 } /* Throttles to every 10ms, but "catches up" if we're behind */ if (delta > 0 && (expected - virtual) < pulse && speed != 0L) { try { Thread.sleep(delta) } catch (e: InterruptedException) { } } instructions += computer.pulse(pulse) virtual += pulse ips = (virtual * 1000) / max(1, System.currentTimeMillis() - startTime) expected = (System.currentTimeMillis() - startTime) * speed / 1000 } System.err.println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")") } fun step() { computer.fetchAndExecute() computer.fetchCurrentInstruction() computer.notifyOfStepExecution() } fun back() { computer.rewind() computer.fetchCurrentInstruction() computer.notifyOfStepExecution() } }