Compare commits
2 Commits
3bbeaa9b8e
...
fa7108098b
| Author | SHA1 | Date | |
|---|---|---|---|
| fa7108098b | |||
| 308e3a9efa |
@@ -33,5 +33,5 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass.set("MainKt")
|
mainClass.set("com.thequux.mcpdp.cli.Cli")
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/main/kotlin/com/thequux/mcpdp/cli/Cli.kt
Normal file
107
src/main/kotlin/com/thequux/mcpdp/cli/Cli.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user