generated from rnentjes/kotlin-server-web-undertow
72 lines
1.8 KiB
Kotlin
72 lines
1.8 KiB
Kotlin
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()
|
|
}
|
|
}
|