Started implementing page tables

This commit is contained in:
2023-09-28 23:29:22 +02:00
parent 846c7aad39
commit d5a36eac84
4 changed files with 91 additions and 26 deletions

View File

@@ -37,10 +37,11 @@ fun main(args: Array<String>) {
cpu.runState = CPU.RunState.RUNNING
cpu.pc = 0x80u
val start = System.nanoTime()
val ninsn = cpu.run(600000000)
// var ninsn = cpu.run(17405)
// cpu.tracer = tracer
// ninsn += cpu.run(30)
// var ninsn = cpu.run(600000000)
var ninsn = cpu.run(376670)
cpu.tracer = tracer
ninsn += cpu.run(30)
cpu.dumpReg()
val end = System.nanoTime()
System.err.println("Halted at 0${cpu.pc.toString(8)}")

View File

@@ -9,7 +9,7 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.lang.StringBuilder
private enum class TrapReason(val vector: UShort, val load_mmr2: Boolean, val clear: Int) {
internal enum class TrapReason(val vector: UShort, val load_mmr2: Boolean, val clear: Int) {
/** Floating point error */
FPE(0xA4u, true, 0),
/** Power fail */
@@ -93,9 +93,9 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
mbus.unibus.reset()
} // bus reset TODO: bus init
0x0006 -> {
// TODO: handle suspending the trace trap
pc = stack_pop()
psw = stack_pop()
allowT = false
} // RTT
in 0x40..0x7f -> {
// jmp
@@ -747,6 +747,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
}
}
private var allowT: Boolean = true
private var control_reg: UShort = 0u
val logger: Logger = LoggerFactory.getLogger(this.javaClass)
private val flagStr: String
@@ -764,7 +765,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
private var stack_limit: UShort = 0u
private var handlingStackRed: Boolean = false
private var trapReq: Int = 0
val core = PagingUnit(mbus)
val core = PagingUnit(mbus, this)
var runState: RunState = RunState.HALTED
var psw: UShort
@@ -1005,10 +1006,12 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun step_int() {
try {
tracer.noteBegin(this)
core.newInsn(pc)
val opcode = core.getw(pc).toInt()
tracer.noteOpcode(opcode.toUShort())
pc = (pc + 2u).toUShort()
this.(insnTable[opcode shr 8])(opcode)
core.endInsn()
} finally {
tracer.noteEnd()
}
@@ -1034,6 +1037,8 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
psw = core.getw(6u)
core.setw(2u, psw)
core.setw(0u, pc)
sp = 0u
trapReq = trapReq and TrapReason.RED.clear.inv()
pc = core.getw(4u)
}
@@ -1046,8 +1051,11 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
for (cause in TrapReason.entries.reversed()) {
if (trapReq and cause.mask != 0) {
// logger.warn("Trapping because $cause")
callVector(cause.vector)
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
try {
callVector(cause.vector)
} finally {
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
}
// TODO: load MMR2 if necessary
break
}
@@ -1096,6 +1104,10 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
// Proceed to handling instruction
try {
step_int()
if (T && allowT) {
setTrap(TrapReason.TRC)
}
allowT = true
} catch (error: MemoryError) {
// TODO: fill in memory manager fields
when (error) {
@@ -1112,7 +1124,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
setTrap(TrapReason.NXM)
}
}
// logger.warn("Threw error: $error")
logger.warn("Threw error: $error")
} catch (_: InvalidOpcodeException) {
setTrap(TrapReason.ILL)
} catch (_: EndCycle) {
@@ -1132,7 +1144,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
var ninsn: Long = 0
while (runState == RunState.RUNNING && ninsn < nstep) {
ninsn++
if (pc == 0x1F76u.toUShort()) {
if (pc == 0x344A.toUShort()) {
pc = pc
}
step()
@@ -1149,7 +1161,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
pc = core.getw(vector)
}
private fun setTrap(reason: TrapReason) {
internal fun setTrap(reason: TrapReason) {
trapReq = trapReq or reason.mask
}
@@ -1187,7 +1199,6 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun checkSP(addr: UShort): UShort {
if (cur_mode != 0) return addr
if (sp < stack_limit + 224u || sp.toInt() and 0xFFFE == 0xFFFE) {
logger.warn("Stack RED")
trapRed()
throw EndCycle()
} else if (sp < stack_limit + 256u) {

View File

@@ -36,6 +36,9 @@ private data class PDR(val plf: UShort, var A: Boolean, var W: Boolean, var ed:
} else {
0U..< (plf.toUInt() shl 6)
}
val asU16: UShort
get() = (plf shl 7).bit(7, A).bit(6, W).bit(3, ed) or acf.ordinal.toUShort()
fun touched() { A = true }
fun written() { A = true; W = true }
}
@@ -47,11 +50,11 @@ private enum class MManMode(val mmanEnable: Boolean, val addrMask: UInt, val hip
}
@OptIn(ExperimentalUnsignedTypes::class)
class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
companion object {
private val MMR0: UInt = 0x3FF8Au
private val MMR1: UInt = 0x3FF8Cu
private val MMR2: UInt = 0x3FF8Eu
private val MMR0: UInt = 0x3FF7Au
private val MMR1: UInt = 0x3FF7Cu
private val MMR2: UInt = 0x3FF7Eu
private val MMR3: UInt = 0x3F54Eu
private val MEMORY_ERROR_REG: UInt = 0x3FFE4u
}
@@ -102,17 +105,20 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
if (addr and 0x1FFFU !in pdr.range) {
setMmr0(14, apf)
// TODO: handle rest of trap
throw Trap(0xA8)
cpu.setTrap(TrapReason.MME)
// TODO: check whether this is always an abort
throw EndCycle()
}
when (pdr.acf.action(write)) {
AccessAction.Allow -> {}
AccessAction.Trap -> {
setMmr0(12, apf, true)
trap = true
setMmr0(12, apf)
cpu.setTrap(TrapReason.MME)
}
AccessAction.Abort -> {
setMmr0(13, apf)
throw Trap(0xA8)
cpu.setTrap(TrapReason.MME)
throw EndCycle()
}
}
val tmp1 = addr.toUInt() + (par.toUInt() shl 6) and mapMode.addrMask
@@ -210,8 +216,36 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
override fun setb(addr: UShort, value: UByte) = withRecovery(addr) { modeSpace.setb(addr, value) }
private class PdPair(val ipt: PageTable, val dpt: PageTable): PAddressSpace {
override fun getw(addr: UInt): UShort {
val mode = addr.toInt() shr 4 and 3
val reg = addr.toInt() shr 1 and 7
return when (mode) {
0 -> ipt.pdr[reg].asU16
1 -> dpt.pdr[reg].asU16
2 -> ipt.par[reg]
3 -> dpt.par[reg]
else -> throw BusTimeoutError(addr)
}
}
override fun setw(addr: UInt, value: UShort) {
val mode = addr.toInt() shr 4 and 3
val reg = addr.toInt() shr 1 and 7
when (mode) {
0 -> ipt.pdr[reg] = PDR(value) // This clears A and W
1 -> dpt.pdr[reg] = PDR(value) // This clears A and W
2 -> ipt.par[reg] = value
3 -> dpt.par[reg] = value
else -> throw BusTimeoutError(addr)
}
}
}
private inner class ConfigRegisters: PAddressSpace {
override fun getw(addr: UInt): UShort {
return when (addr) {
MMR0 -> mmr0
@@ -232,6 +266,12 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
override fun setw(addr: UInt, value: UShort): Unit {
return when(addr) {
MMR0 -> {
mmr0 = value
updateMode()
}
MMR1 -> mmr1 = value
MMR2 -> mmr2 = value
MMR3 -> {
enableUnibusMap = value bit 5
enable22bit = value bit 4
@@ -260,16 +300,25 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
}
// Page space
// 772 200-217 = SUP I PDR
// 772 220-237 = SUP D PDR
// 772 240-257 = SUP I PAR
// 772 260-277 = SUP D PAR
//
// 772 300-377 = KRN same
// 777 600-677 = USR same
fun mount(unibus: Unibus) {
val regs = ConfigRegisters()
unibus.run {
deviceView = UnibusMap()
attach(0x3_FF80u, 6, regs) // User PAR/PDR
attach(0x3_F480u, 6, PdPair(itabs[0], dtabs[0]))
attach(0x3_F4C0u, 6, PdPair(itabs[1], dtabs[1]))
attach(0x3_FF80u, 6, PdPair(itabs[2], dtabs[2])) // User PAR/PDR
attach(0x3_FF7Au, 1, regs) // MMR0
attach(0x3_FF7Cu, 2, regs) // MMR1-2
attach(0x3_F54Eu, 1, regs) // MMR3
attach(0x3_F4C0u, 6, regs) // Kernal PAR/PDF
attach(0x3_F480u, 6, regs) // Supervisor PAR/PDR
attach(0x3_F080u, 7, regs) // Unibus map
attach(MEMORY_ERROR_REG, 1, regs)
}
@@ -286,6 +335,10 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
}
fun endInsn() {
mmr0 = mmr0 or 0x70u
}
private inner class UnibusMap: PAddressSpace {
// This implements an *18-bit* address space, for the view of unibus peripherals

View File

@@ -38,7 +38,7 @@ class MemBus(val size: Int) : PAddressSpace {
}
override fun getw(addr: UInt): UShort {
if (size bit 0) {
if (addr bit 0) {
throw OddAddressError(addr)
}
return when (addr.toInt()) {
@@ -49,7 +49,7 @@ class MemBus(val size: Int) : PAddressSpace {
}
override fun setw(addr: UInt, value: UShort) {
if (size bit 0) {
if (addr bit 0) {
throw OddAddressError(addr)
}
return when (addr.toInt()) {