Compare commits

...

3 Commits

5 changed files with 92 additions and 39 deletions

View File

@@ -1,6 +1,7 @@
import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.core.util.StatusPrinter import ch.qos.logback.core.util.StatusPrinter
import com.thequux.mcpdp.core.CPU import com.thequux.mcpdp.core.CPU
import com.thequux.mcpdp.debug.FlightRecorder
import com.thequux.mcpdp.debug.LoggingCollector import com.thequux.mcpdp.debug.LoggingCollector
import com.thequux.mcpdp.debug.NullTracer import com.thequux.mcpdp.debug.NullTracer
import com.thequux.mcpdp.debug.Tracer import com.thequux.mcpdp.debug.Tracer
@@ -24,7 +25,9 @@ fun main(args: Array<String>) {
var mbus = MemBus(65536) var mbus = MemBus(65536)
val tracer = Tracer() val tracer = Tracer()
val loggingCollector = LoggingCollector() val loggingCollector = LoggingCollector()
tracer.addCollector(loggingCollector) // tracer.addCollector(loggingCollector)
val recorder = FlightRecorder(3000)
tracer.addCollector(recorder)
var cpu = CPU(mbus, if (CPU.debugMode) tracer else NullTracer()) var cpu = CPU(mbus, if (CPU.debugMode) tracer else NullTracer())
val console = DL11(mbus.unibus, tb.input(), tb.output()).apply { mount(mbus.unibus) } val console = DL11(mbus.unibus, tb.input(), tb.output()).apply { mount(mbus.unibus) }
try { try {
@@ -34,19 +37,22 @@ fun main(args: Array<String>) {
console.start() console.start()
cpu.loadAbs(File(args[0])) cpu.loadAbs(File(args[0]))
cpu.core.setw(0x3C78u, 0u) // halt instead of restart
cpu.runState = CPU.RunState.RUNNING cpu.runState = CPU.RunState.RUNNING
cpu.pc = 0x80u cpu.pc = 0x80u
val start = System.nanoTime() val start = System.nanoTime()
// var ninsn = cpu.run(600000000) // var ninsn = cpu.run(60000000)
var ninsn = cpu.run(376670)
cpu.tracer = tracer cpu.tracer = tracer
ninsn += cpu.run(30) var ninsn = cpu.run(323227)
// var ninsn = cpu.run(13300)
// ninsn += cpu.run(10)
recorder.dump(System.out)
cpu.dumpReg() cpu.dumpReg()
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 / 1_000_000} MIPS") System.err.println("Executed ${ninsn} in ${time}s: ${ninsn / time / 1_000_000} MIPS")
} finally { } finally {
println("Exiting") println("Exiting")
console.stop() console.stop()

View File

@@ -82,7 +82,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
0x0001 -> runState = RunState.WAIT_FOR_INTERRUPT // WAIT 0x0001 -> runState = RunState.WAIT_FOR_INTERRUPT // WAIT
0x0002 -> { // RTI 0x0002 -> { // RTI
pc = stack_pop() pc = stack_pop()
psw = stack_pop() // TODO: check privilege on mode; check psw[11] setPSW(stack_pop(), cur_mode == 0) // TODO: check privilege on mode; check psw[11]
} // RTI } // RTI
0x0003 -> setTrap(TrapReason.BPT) // BPT 0x0003 -> setTrap(TrapReason.BPT) // BPT
0x0004 -> setTrap(TrapReason.IOT) // IOT 0x0004 -> setTrap(TrapReason.IOT) // IOT
@@ -94,7 +94,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
} // bus reset TODO: bus init } // bus reset TODO: bus init
0x0006 -> { 0x0006 -> {
pc = stack_pop() pc = stack_pop()
psw = stack_pop() setPSW(stack_pop(), cur_mode == 0)
allowT = false allowT = false
} // RTT } // RTT
in 0x40..0x7f -> { in 0x40..0x7f -> {
@@ -111,7 +111,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
registers[reg] = stack_pop() registers[reg] = stack_pop()
} // RTS } // RTS
in 0x98..0x9F -> { in 0x98..0x9F -> {
psw_priority = opcode and 0x7 if (cur_mode == 0) psw_priority = opcode and 0x7
} // SPL } // SPL
in 0xA0..0xBF -> { in 0xA0..0xBF -> {
val flag = opcode bit 4 val flag = opcode bit 4
@@ -768,7 +768,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
val core = PagingUnit(mbus, this) val core = PagingUnit(mbus, this)
var runState: RunState = RunState.HALTED var runState: RunState = RunState.HALTED
var psw: UShort val psw: UShort
get() { get() {
var res = 0 var res = 0
if (C) { res = res or 0x0001 } if (C) { res = res or 0x0001 }
@@ -781,26 +781,33 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
res = res or (registerSet shl 11) res = res or (registerSet shl 11)
return res.toUShort() return res.toUShort()
} }
set(value) {
var newpsw = value.toInt() fun setPSW(value: UShort, allowEsc: Boolean) {
C = value bit 0 var newpsw = value.toInt()
V = value bit 1 C = value bit 0
Z = value bit 2 V = value bit 1
N = value bit 3 Z = value bit 2
T = value bit 4 // TODO: handle suspended trap N = value bit 3
psw_priority = newpsw shr 5 and 7 T = value bit 4 // TODO: handle suspended trap
if (allowEsc) {
registerSet = newpsw shr 11 and 1 registerSet = newpsw shr 11 and 1
cur_mode = newpsw shr 14 cur_mode = newpsw shr 14
prv_mode = newpsw shr 12 and 3
psw_priority = newpsw shr 5 and 7
} else {
registerSet = registerSet or (newpsw shr 11 and 1)
cur_mode = cur_mode or (newpsw shr 14 and 3)
prv_mode = prv_mode or (newpsw shr 12 and 3)
} }
}
private var cur_mode: Int = 0 private var cur_mode: Int = 0
set(value) { set(value) {
prv_mode = field // prv_mode = field
shadow_r6[field] = sp shadow_r6[field] = sp
field = if (value == 2) 3 else value field = if (value == 2) 3 else value
sp = shadow_r6[field] sp = shadow_r6[field]
core.mode = value core.mode = field
} }
private var prv_mode: Int = 0 private var prv_mode: Int = 0
private var psw_priority: Int = 0 private var psw_priority: Int = 0
@@ -817,6 +824,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
private var registerSet: Int = 0 private var registerSet: Int = 0
set(value) { set(value) {
if (value == field) return
if (value !in 0..1) { if (value !in 0..1) {
throw ProgrammerError("Invalid register set number") throw ProgrammerError("Invalid register set number")
} }
@@ -830,9 +838,12 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
} }
private var cc: UShort private var cc: UShort
get() = psw and 0xFu get() = 0.bit(3, N).bit(2, Z).bit(1, C).bit(0, C).toUShort()
set(value) { set(value) {
psw = (psw and 0xFFFu) or (value and 0xFu) N = value bit 3
Z = value bit 2
V = value bit 1
C = value bit 0
} }
private var pirq: UShort = 0u private var pirq: UShort = 0u
set(value) { set(value) {
@@ -1031,11 +1042,11 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun trapRed() { fun trapRed() {
// This is handled separately because otherwise the stack push // This is handled separately because otherwise the stack push
// would itself trigger a red trap // would itself trigger a red trap
logger.warn("Stack RED") // logger.warn("Stack RED")
cpu_err = cpu_err or CPU_ERR_STK_RED cpu_err = cpu_err or CPU_ERR_STK_RED
val old_psw = psw val old_psw = psw
psw = core.getw(6u) setPSW(core.getw(6u), true)
core.setw(2u, psw) core.setw(2u, old_psw)
core.setw(0u, pc) core.setw(0u, pc)
sp = 0u sp = 0u
trapReq = trapReq and TrapReason.RED.clear.inv() trapReq = trapReq and TrapReason.RED.clear.inv()
@@ -1084,7 +1095,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
} else { } else {
val pirqLvl = pirq.toInt() shr 1 and 7; val pirqLvl = pirq.toInt() shr 1 and 7;
if (pirqLvl > psw_priority) { if (pirqLvl > psw_priority) {
// logger.debug("PIRQ{} trap to 0xA0", pirqLvl) logger.debug("PIRQ{} trap to 0xA0", pirqLvl)
callVector(0xA0u) callVector(0xA0u)
} }
} }
@@ -1124,7 +1135,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
setTrap(TrapReason.NXM) setTrap(TrapReason.NXM)
} }
} }
logger.warn("Threw error: $error") // logger.warn("Threw error: $error")
} catch (_: InvalidOpcodeException) { } catch (_: InvalidOpcodeException) {
setTrap(TrapReason.ILL) setTrap(TrapReason.ILL)
} catch (_: EndCycle) { } catch (_: EndCycle) {
@@ -1144,8 +1155,9 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
var ninsn: Long = 0 var ninsn: Long = 0
while (runState == RunState.RUNNING && ninsn < nstep) { while (runState == RunState.RUNNING && ninsn < nstep) {
ninsn++ ninsn++
if (pc == 0x344A.toUShort()) { if (pc == 0x3224.toUShort()) {
pc = pc runState = runState
runState = RunState.HALTED
} }
step() step()
} }
@@ -1154,8 +1166,8 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun callVector(vector: UShort) { fun callVector(vector: UShort) {
val old_psw = psw val old_psw = psw
// update PSW first so that this gets pushed to the val newPSW = core.getw((vector + 2u).toUShort()) and 0xCFFFu or (cur_mode shl 12).toUShort()
psw = core.getw((vector + 2u).toUShort()) setPSW(newPSW, true)
stack_push(old_psw) stack_push(old_psw)
stack_push(pc) stack_push(pc)
pc = core.getw(vector) pc = core.getw(vector)
@@ -1188,7 +1200,11 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
0x3_FFF6u -> cpu_err = value 0x3_FFF6u -> cpu_err = value
0x3_FFFAu -> pirq = value 0x3_FFFAu -> pirq = value
0x3_FFFCu -> stack_limit = value and 0xFF00u // stack limit 0x3_FFFCu -> stack_limit = value and 0xFF00u // stack limit
0x3_FFFEu -> psw = value or (cur_mode.toUShort() shl 14) // writing to PSW can only increase current mode 0x3_FFFEu -> {
setPSW(value, true)
// explicitly switch RS if necessary
// registerSet = (value shr 11 and 1u).toInt()
} // writing to PSW can only increase current mode
else -> { else -> {
println("Bus error at ${addr.toString(16)}: ${value.toString(16)}") println("Bus error at ${addr.toString(16)}: ${value.toString(16)}")
throw BusTimeoutError(addr) throw BusTimeoutError(addr)
@@ -1202,7 +1218,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
trapRed() trapRed()
throw EndCycle() throw EndCycle()
} else if (sp < stack_limit + 256u) { } else if (sp < stack_limit + 256u) {
logger.warn("Stack YLW") // logger.warn("Stack YLW")
// stack limit yellow // stack limit yellow
cpu_err = cpu_err or CPU_ERR_STK_YLW cpu_err = cpu_err or CPU_ERR_STK_YLW
setTrap(TrapReason.YEL) setTrap(TrapReason.YEL)

View File

@@ -5,6 +5,7 @@ import com.thequux.mcpdp.ext.bit.*
import com.thequux.mcpdp.peripheral.Unibus import com.thequux.mcpdp.peripheral.Unibus
import com.thequux.mcpdp.util.ProgrammerError import com.thequux.mcpdp.util.ProgrammerError
import kotlin.math.max import kotlin.math.max
import kotlin.math.min
enum class AccessAction { enum class AccessAction {
Allow, Allow,
@@ -77,8 +78,8 @@ class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
val unibusMap: PAddressSpace = UnibusMap() val unibusMap: PAddressSpace = UnibusMap()
private inner class PageTable(val mode: Int, val dspace: Boolean) { private inner class PageTable(val mode: Int, val dspace: Boolean) {
val par = UShortArray(16) { 0U } val par = UShortArray(8) { 0U }
val pdr = Array(16) { PDR() } val pdr = Array(8) { PDR() }
fun setMmr0(causeBit: Int, apf: Int, completed: Boolean = false) { fun setMmr0(causeBit: Int, apf: Int, completed: Boolean = false) {
@@ -121,7 +122,7 @@ class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
throw EndCycle() throw EndCycle()
} }
} }
val tmp1 = addr.toUInt() + (par.toUInt() shl 6) and mapMode.addrMask val tmp1 = addr.toUInt().and(0x1FFFu) + (par.toUInt() shl 6) and mapMode.addrMask
if (tmp1 and mapMode.hipageMask == mapMode.hipageMask) { if (tmp1 and mapMode.hipageMask == mapMode.hipageMask) {
return tmp1 or 0x3C_0000u return tmp1 or 0x3C_0000u
} else { } else {
@@ -142,7 +143,7 @@ class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
enable22bit -> MManMode.MM_22 enable22bit -> MManMode.MM_22
else -> MManMode.MM_18 else -> MManMode.MM_18
} }
modeSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace modeSpace = if (mapMode.mmanEnable) modeVTabs[min(mode, 2)] else noMmanSpace
} }
fun getSpace(mode: Int): VAddressSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace fun getSpace(mode: Int): VAddressSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace
@@ -172,7 +173,7 @@ class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
private inner class ModeVSpace(private val iSpace: PageTable, private val dSpace: PageTable, var useDSpace: Boolean): VAddressSpace { private inner class ModeVSpace(private val iSpace: PageTable, private val dSpace: PageTable, var useDSpace: Boolean): VAddressSpace {
private fun getSpace(dspace: Boolean): PageTable = if (dspace) dSpace else iSpace private fun getSpace(dspace: Boolean): PageTable = if (dspace && useDSpace) dSpace else iSpace
override fun getw(addr: UShort, dspace: Boolean): UShort = pspace.getw(getSpace(dspace).map(addr, write = false)) override fun getw(addr: UShort, dspace: Boolean): UShort = pspace.getw(getSpace(dspace).map(addr, write = false))
override fun getb(addr: UShort): UByte = pspace.getb(dSpace.map(addr, write = false)) override fun getb(addr: UShort): UByte = pspace.getb(dSpace.map(addr, write = false))

View File

@@ -86,7 +86,11 @@ class Disassembler {
fun dasm_at(loc: UShort, istream: UShortArray): String { fun dasm_at(loc: UShort, istream: UShortArray): String {
opc = loc opc = loc
this.istream = istream this.istream = istream
opcode = istream[0].toInt() try {
opcode = istream[0].toInt()
} catch(_: IndexOutOfBoundsException) {
return fmt("????")
}
vpc = 1 vpc = 1
try { try {

View File

@@ -0,0 +1,26 @@
package com.thequux.mcpdp.debug
import java.io.PrintStream
import java.io.Writer
@OptIn(ExperimentalUnsignedTypes::class)
class FlightRecorder(size: Int): Collector {
var trace: Array<TraceRecord?> = Array(size) { null }
var pos = 0
override fun invoke(record: TraceRecord) {
trace[pos++] = record
if (pos >= trace.size) pos -= trace.size
}
fun dump(os: PrintStream) {
val dis = Disassembler()
for (i in trace.indices) {
val i0 = (i + pos) % trace.size
val record = trace[i0]
if (record != null) {
os.println(record.report(dis))
}
}
}
}