18% speedup from interrupt optimization

This commit is contained in:
2023-09-20 10:44:24 +02:00
parent 7556dca4f6
commit f911a78d84
3 changed files with 54 additions and 28 deletions

View File

@@ -18,15 +18,16 @@ fun main(args: Array<String>) {
cpu.loadAbs(File(args[0])) cpu.loadAbs(File(args[0]))
cpu.runState = CPU.RunState.RUNNING cpu.runState = CPU.RunState.RUNNING
cpu.pc = 0x80u cpu.pc = 0x80u
val start = System.nanoTime() val start = System.nanoTime()
val ninsn = cpu.run() val ninsn = cpu.run(50000000)
val end = System.nanoTime() val end = System.nanoTime()
System.err.println("Halted at 0${cpu.pc.toString(8)}") System.err.println("Halted at 0${cpu.pc.toString(8)}")
val time = (end-start).toDouble() / 1_000_000_000.0 val time = (end - start).toDouble() / 1_000_000_000.0
println("Executed ${ninsn} in ${time}s: ${ninsn/time} i/s") println("Executed ${ninsn} in ${time}s: ${ninsn / time} i/s")
} finally { } finally {
println("Exiting") println("Exiting")
console.stop() console.stop()
} }
System.exit(0)
} }

View File

@@ -111,11 +111,11 @@ class CPU(val mbus: MemBus) {
val bitset = pirq shr 8 val bitset = pirq shr 8
var maxp: UShort = 0u var maxp: UShort = 0u
for (i in 7 downTo 1) { for (i in 7 downTo 1) {
if (bitset bit i) { if (bitset bit i) {
maxp = i.toUShort() shl 1 maxp = i.toUShort() shl 1
break break
} }
} }
field = value and 0xFE00u or maxp or (maxp shl 4) field = value and 0xFE00u or maxp or (maxp shl 4)
} }
@@ -828,21 +828,28 @@ class CPU(val mbus: MemBus) {
try { try {
if (runState == RunState.HALTED) return if (runState == RunState.HALTED) return
for (i in 7 downTo (psw_priority + 1)) { if (mbus.unibus.interruptPending) {
if (pirq bit 8+i) { for (i in 7 downTo (psw_priority + 1)) {
logger.debug("PIRQ{} trap to 0xA0", i) if (pirq bit 8 + i) {
trap(0xA0u) logger.debug("PIRQ{} trap to 0xA0", i)
break trap(0xA0u)
break
}
val source = mbus.unibus.checkInterrupt(i)
if (source != null) {
// we might have been waiting for an interrupt
runState = RunState.RUNNING
val vector = source.vector
logger.debug("Unibus interrupt at pri {} to {}", i, vector)
trap(vector)
source.handled()
break
}
} }
val source = mbus.unibus.checkInterrupt(i) } else {
if (source != null) { val pirqLvl = pirq.toInt() shr 1 and 7;
// we might have been waiting for an interrupt if (pirqLvl > psw_priority) {
runState = RunState.RUNNING trap(0xA0u)
val vector = source.vector
logger.debug("Unibus interrupt at pri {} to {}", i, vector)
trap(vector)
source.handled()
break
} }
} }
if (runState == RunState.WAIT_FOR_INTERRUPT) { if (runState == RunState.WAIT_FOR_INTERRUPT) {
@@ -865,12 +872,21 @@ class CPU(val mbus: MemBus) {
} }
fun run(): Long { fun run(): Long {
var ninsn: Long = 0 var ninsn: Long = 0
while (runState == RunState.RUNNING) { while (runState == RunState.RUNNING) {
ninsn++ ninsn += run(Long.MAX_VALUE)
step() step()
} }
return ninsn return ninsn
}
fun run(nstep: Long): Long {
var ninsn: Long = 0
while (runState == RunState.RUNNING && ninsn < nstep) {
ninsn++
step()
}
return ninsn
} }
fun trap(vector: UShort) { fun trap(vector: UShort) {

View File

@@ -77,6 +77,9 @@ class Unibus: PAddressSpace, Subregion(12, 6) {
private val logger = LoggerFactory.getLogger(this.javaClass) private val logger = LoggerFactory.getLogger(this.javaClass)
private val queue: Array<MutableList<InterruptSource>> = Array(8) { Vector(4) } private val queue: Array<MutableList<InterruptSource>> = Array(8) { Vector(4) }
private var interruptCount: Int = 0
val interruptPending: Boolean
get() = interruptCount > 0
override fun map(address: UInt): PAddressSpace = override fun map(address: UInt): PAddressSpace =
super.map(address) ?: throw BusTimeoutError(address) super.map(address) ?: throw BusTimeoutError(address)
@@ -101,11 +104,17 @@ class Unibus: PAddressSpace, Subregion(12, 6) {
/// to fetch the currently desired interrupt vector /// to fetch the currently desired interrupt vector
fun assertInterrupt(priority: Int, device: InterruptSource) { fun assertInterrupt(priority: Int, device: InterruptSource) {
val list = queue[priority] val list = queue[priority]
if (list.isEmpty()) {
interruptCount++
}
if (!list.contains(device)) list.add(device) if (!list.contains(device)) list.add(device)
} }
fun deassertInterrupt(priority: Int, device: InterruptSource) { fun deassertInterrupt(priority: Int, device: InterruptSource) {
queue[priority].remove(device) val lvlQueue = queue[priority]
if (lvlQueue.remove(device) && lvlQueue.isEmpty()) {
interruptCount--
}
} }
// Checks for an interrupt. The handler receives (priority, device) // Checks for an interrupt. The handler receives (priority, device)