Compare commits

...

2 Commits

6 changed files with 132 additions and 15 deletions

View File

@@ -33,5 +33,5 @@ kotlin {
} }
application { application {
mainClass.set("MainKt") mainClass.set("com.thequux.mcpdp.cli.Cli")
} }

View File

@@ -0,0 +1,107 @@
package com.thequux.mcpdp.cli
import ch.qos.logback.classic.LoggerContext
import com.thequux.mcpdp.core.CPU
import com.thequux.mcpdp.debug.FlightRecorder
import com.thequux.mcpdp.debug.LoggingCollector
import com.thequux.mcpdp.debug.NullTracer
import com.thequux.mcpdp.debug.Tracer
import com.thequux.mcpdp.loadAbs
import com.thequux.mcpdp.peripheral.DL11
import com.thequux.mcpdp.peripheral.MemBus
import org.jline.utils.Log
import org.slf4j.LoggerFactory
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.ITypeConverter
import picocli.CommandLine.Option
import picocli.CommandLine.Parameters
import java.io.File
import java.util.concurrent.Callable
import kotlin.system.exitProcess
@Command(name="jdp11", mixinStandardHelpOptions = true)
class Cli: Callable<Int> {
@Option(names = ["-l", "--load"], description = ["The paper tape image to load"])
private var load: File? = null
@Option(names = ["-t", "--trace"])
private var traceLength: Int = 0
@Option(names = ["--live"])
private var liveTrace = false
@Option(names = ["-g", "--go"], description = ["Start address in octal. Ignored if odd"], converter = [ OctalParamConverter::class ])
private var startAddress: Int = 1
@Option(names = ["-b", "--break"], description = ["Breakpoint address"], converter = [ OctalParamConverter::class ])
private var breakpoint: Int = 1
@Option(names = ["-c", "--count"], description = ["Max number of instructions to run. 0 is infinite"])
private var maxInsns: Long = 0
override fun call(): Int {
val tb = org.jline.terminal.TerminalBuilder.terminal()
var mbus = MemBus(65536)
val tracer = Tracer()
if (CPU.debugMode)
tracer.addCollector(LoggingCollector())
val recorder = FlightRecorder(traceLength)
if (traceLength > 0) {
tracer.addCollector(recorder)
}
var cpu = CPU(mbus, if (traceLength > 0 || CPU.debugMode) tracer else NullTracer())
val console = DL11(mbus.unibus, tb.input(), tb.output()).apply { mount(mbus.unibus) }
try {
tb.enterRawMode()
console.start()
if (load != null) {
cpu.loadAbs(load!!)
}
// cpu.core.setw(0x3C78u, 0u) // halt instead of restart
if (startAddress % 2 == 0) {
cpu.pc = startAddress.toUShort()
cpu.runState = CPU.RunState.RUNNING
}
cpu.breakpoint = breakpoint.toUShort()
// var ninsn = cpu.run(60000000)
if (cpu.runState == CPU.RunState.RUNNING) {
val start = System.nanoTime()
var ninsn = if (maxInsns > 0) cpu.run(maxInsns) else cpu.run()
// var ninsn = cpu.run(13300)
// ninsn += cpu.run(10)
recorder.dump(System.out)
cpu.dumpReg()
val end = System.nanoTime()
System.err.println("Halted at 0${cpu.pc.toString(8)}")
val time = (end - start).toDouble() / 1_000_000_000.0
System.err.println("Executed ${ninsn} in ${time}s: ${ninsn / time / 1_000_000} MIPS")
}
} finally {
println("Exiting")
console.stop()
}
val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
loggerContext.stop()
return 0
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
exitProcess(CommandLine(Cli()).execute(*args))
}
}
}
class OctalParamConverter: ITypeConverter<Int> {
override fun convert(value: String): Int {
return value.toInt(8)
}
}

View File

@@ -747,6 +747,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
} }
} }
private var atBreakpoint: Boolean = false
private var allowT: Boolean = true private var allowT: Boolean = true
private var control_reg: UShort = 0u private var control_reg: UShort = 0u
val logger: Logger = LoggerFactory.getLogger(this.javaClass) val logger: Logger = LoggerFactory.getLogger(this.javaClass)
@@ -765,6 +766,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
private var stack_limit: UShort = 0u private var stack_limit: UShort = 0u
private var handlingStackRed: Boolean = false private var handlingStackRed: Boolean = false
private var trapReq: Int = 0 private var trapReq: Int = 0
var breakpoint: UShort = 1u
val core = PagingUnit(mbus, this) val core = PagingUnit(mbus, this)
var runState: RunState = RunState.HALTED var runState: RunState = RunState.HALTED
@@ -1086,7 +1088,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
// we might have been waiting for an interrupt // we might have been waiting for an interrupt
runState = RunState.RUNNING runState = RunState.RUNNING
val vector = source.vector val vector = source.vector
// logger.debug("Unibus interrupt at pri {} to {}", i, vector) mbus.unibus.logger.debug("DATIP: {} @ {}", vector.toOctal(), i)
callVector(vector) callVector(vector)
source.handled() source.handled()
break break
@@ -1095,7 +1097,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)
} }
} }
@@ -1145,21 +1147,26 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun run(): Long { fun run(): Long {
var ninsn: Long = 0 var ninsn: Long = 0
while (runState == RunState.RUNNING) { atBreakpoint = false
while (runState == RunState.RUNNING && !atBreakpoint) {
ninsn += run(Long.MAX_VALUE) ninsn += run(Long.MAX_VALUE)
} }
return ninsn return ninsn
} }
fun run(nstep: Long): Long { fun run(nstep: Long): Long {
atBreakpoint = false
var ninsn: Long = 0 var ninsn: Long = 0
while (runState == RunState.RUNNING && ninsn < nstep) { while (runState == RunState.RUNNING && ninsn < nstep && !atBreakpoint) {
ninsn++ if (pc == breakpoint) {
if (pc == 0x3224.toUShort()) { atBreakpoint = true
runState = runState ninsn = ninsn // Dummy statement to set debugger bkpt on
runState = RunState.HALTED // continue
}
if (!atBreakpoint) {
ninsn++
step()
} }
step()
} }
return ninsn return ninsn
} }
@@ -1233,7 +1240,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
enum class RunState(val handleInterrupt: Boolean) { enum class RunState(val handleInterrupt: Boolean) {
RUNNING(handleInterrupt = true), RUNNING(handleInterrupt = true),
HALTED(handleInterrupt = false), HALTED(handleInterrupt = false),
WAIT_FOR_INTERRUPT(handleInterrupt = true) WAIT_FOR_INTERRUPT(handleInterrupt = true),
} }
} }

View File

@@ -314,8 +314,8 @@ class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
val regs = ConfigRegisters() val regs = ConfigRegisters()
unibus.run { unibus.run {
deviceView = UnibusMap() deviceView = UnibusMap()
attach(0x3_F480u, 6, PdPair(itabs[0], dtabs[0])) attach(0x3_F480u, 6, PdPair(itabs[1], dtabs[1]))
attach(0x3_F4C0u, 6, PdPair(itabs[1], dtabs[1])) attach(0x3_F4C0u, 6, PdPair(itabs[0], dtabs[0]))
attach(0x3_FF80u, 6, PdPair(itabs[2], dtabs[2])) // User PAR/PDR attach(0x3_FF80u, 6, PdPair(itabs[2], dtabs[2])) // User PAR/PDR
attach(0x3_FF7Au, 1, regs) // MMR0 attach(0x3_FF7Au, 1, regs) // MMR0
attach(0x3_FF7Cu, 2, regs) // MMR1-2 attach(0x3_FF7Cu, 2, regs) // MMR1-2

View File

@@ -76,7 +76,10 @@ class DL11(private var istr: InputStream, private val ostr: OutputStream, val re
if (value bit 0) {rcsr = rcsr bic 7 } if (value bit 0) {rcsr = rcsr bic 7 }
} }
2 -> { rcsr = rcsr bic 7 } 2 -> { rcsr = rcsr bic 7 }
4 -> xcsr = xcsr.maskSet(value, 0x0045u) 4 -> {
xcsr = xcsr.maskSet(value, 0x0045u)
if (!(xcsr bit 6)) intrXmit.level = false
}
6 -> { 6 -> {
val b = value.toInt() and 0xFF val b = value.toInt() and 0xFF
if (xcsr bit 2) { if (xcsr bit 2) {

View File

@@ -74,7 +74,7 @@ class Unibus: PAddressSpace, Subregion(12, 6) {
/// The view of the unibus from a device /// The view of the unibus from a device
var deviceView: PAddressSpace = this var deviceView: PAddressSpace = this
internal set internal set
private val logger = LoggerFactory.getLogger(this.javaClass) internal 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 val devices: HashSet<Peripheral> = HashSet() private val devices: HashSet<Peripheral> = HashSet()