Compare commits

...

2 Commits

6 changed files with 132 additions and 15 deletions

View File

@@ -33,5 +33,5 @@ kotlin {
}
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 control_reg: UShort = 0u
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 handlingStackRed: Boolean = false
private var trapReq: Int = 0
var breakpoint: UShort = 1u
val core = PagingUnit(mbus, this)
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
runState = RunState.RUNNING
val vector = source.vector
// logger.debug("Unibus interrupt at pri {} to {}", i, vector)
mbus.unibus.logger.debug("DATIP: {} @ {}", vector.toOctal(), i)
callVector(vector)
source.handled()
break
@@ -1095,7 +1097,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
} else {
val pirqLvl = pirq.toInt() shr 1 and 7;
if (pirqLvl > psw_priority) {
logger.debug("PIRQ{} trap to 0xA0", pirqLvl)
// logger.debug("PIRQ{} trap to 0xA0", pirqLvl)
callVector(0xA0u)
}
}
@@ -1145,21 +1147,26 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
fun run(): Long {
var ninsn: Long = 0
while (runState == RunState.RUNNING) {
atBreakpoint = false
while (runState == RunState.RUNNING && !atBreakpoint) {
ninsn += run(Long.MAX_VALUE)
}
return ninsn
}
fun run(nstep: Long): Long {
atBreakpoint = false
var ninsn: Long = 0
while (runState == RunState.RUNNING && ninsn < nstep) {
ninsn++
if (pc == 0x3224.toUShort()) {
runState = runState
runState = RunState.HALTED
while (runState == RunState.RUNNING && ninsn < nstep && !atBreakpoint) {
if (pc == breakpoint) {
atBreakpoint = true
ninsn = ninsn // Dummy statement to set debugger bkpt on
// continue
}
if (!atBreakpoint) {
ninsn++
step()
}
step()
}
return ninsn
}
@@ -1233,7 +1240,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
enum class RunState(val handleInterrupt: Boolean) {
RUNNING(handleInterrupt = true),
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()
unibus.run {
deviceView = UnibusMap()
attach(0x3_F480u, 6, PdPair(itabs[0], dtabs[0]))
attach(0x3_F4C0u, 6, PdPair(itabs[1], dtabs[1]))
attach(0x3_F480u, 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_FF7Au, 1, regs) // MMR0
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 }
}
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 -> {
val b = value.toInt() and 0xFF
if (xcsr bit 2) {

View File

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