1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-17 08:34:15 +00:00

Refactored Task code into separate files for readability; added breakpoint support and basic Memory window to debugger. Initial implementation (mostly stubs) of Disk hardware and Tasks.

This commit is contained in:
Josh Dersch 2015-09-14 11:27:16 -07:00
parent 24d7a5a8fe
commit 08d6063def
11 changed files with 1469 additions and 941 deletions

View File

@ -22,13 +22,15 @@ namespace Contralto.CPU
DiskWord = 14,
}
public class AltoCPU
public partial class AltoCPU
{
public AltoCPU(AltoSystem system)
{
_system = system;
_tasks[(int)TaskType.Emulator] = new EmulatorTask(this);
_tasks[(int)TaskType.DiskSector] = new DiskTask(this, true);
_tasks[(int)TaskType.DiskWord] = new DiskTask(this, false);
Reset();
}
@ -78,7 +80,6 @@ namespace Contralto.CPU
get { return _aluC0; }
}
public void Reset()
{
// Reset registers
@ -169,769 +170,11 @@ namespace Contralto.CPU
if (_tasks[i] != null && _tasks[i].Wakeup)
{
_nextTask = _tasks[i];
break;
}
}
}
// Task:
// Base task class: provides implementation for non-task-specific microcode execution and
// state. Task subclasses implement and execute Task-specific behavior and are called into
// by the base class as necessary.
public abstract class Task
{
public Task(AltoCPU cpu)
{
_wakeup = false;
_mpc = 0xffff; // invalid, for sanity checking
_taskType = TaskType.Invalid;
_cpu = cpu;
}
public int Priority
{
get { return (int)_taskType; }
}
public bool Wakeup
{
get { return _wakeup; }
}
public ushort MPC
{
get { return _mpc; }
}
public virtual void Reset()
{
// From The Alto Hardware Manual (section 2, "Initialization"):
// "...each task start[s] at the location which is its task number"
//
_mpc = (ushort)_taskType;
}
public virtual void BlockTask()
{
_wakeup = false;
}
public virtual void WakeupTask()
{
_wakeup = true;
}
public bool ExecuteNext()
{
// TODO: cache microinstructions (or pre-decode them) to save consing all these up every time.
MicroInstruction instruction = new MicroInstruction(UCodeMemory.UCodeROM[_mpc]);
return ExecuteInstruction(instruction);
}
/// <summary>
/// ExecuteInstruction causes the Task to execute the next instruction (the one
/// _mpc is pointing to). The base implementation covers non-task specific logic; subclasses may
/// provide their own overrides.
/// </summary>
/// <returns>True if a task switch has been requested by a TASK instruction, false otherwise.</returns>
protected virtual bool ExecuteInstruction(MicroInstruction instruction)
{
bool nextTask = false;
bool loadR = false;
ushort aluData = 0;
ushort nextModifier = 0;
_loadS = false;
_rSelect = 0;
_busData = 0;
Shifter.SetMagic(false);
//
// Wait for memory state machine if a memory operation is requested by this instruction and
// the memory isn't ready yet.
// TODO: this needs to be seriously cleaned up.
//
if (instruction.BS == BusSource.ReadMD ||
instruction.F1 == SpecialFunction1.LoadMAR ||
instruction.F2 == SpecialFunction2.StoreMD)
{
MemoryOperation op;
if (instruction.BS == BusSource.ReadMD)
{
op = MemoryOperation.Read;
}
else if(instruction.F1 == SpecialFunction1.LoadMAR)
{
op = MemoryOperation.LoadAddress;
}
else
{
op = MemoryOperation.Store;
}
if (!_cpu._system.MemoryBus.Ready(op))
{
// Suspend operation for this cycle.
return false;
}
}
// If we have a modified next field from the last instruction, make sure it gets applied to this one.
nextModifier = _nextModifier;
_nextModifier = 0;
_rSelect = instruction.RSELECT;
// Give tasks the chance to modify parameters early on (like RSELECT)
ExecuteSpecialFunction2Early((int)instruction.F2);
// Select BUS data.
if (instruction.F1 != SpecialFunction1.Constant &&
instruction.F2 != SpecialFunction2.Constant)
{
// Normal BUS data (not constant ROM access).
switch (instruction.BS)
{
case BusSource.ReadR:
_busData = _cpu._r[_rSelect];
break;
case BusSource.LoadR:
_busData = 0; // "Loading R forces the BUS to 0 so that an ALU function of 0 and T may be executed simultaneously"
loadR = true;
break;
case BusSource.None:
_busData = 0xffff; // "Enables no source to the BUS, leaving it all ones"
break;
case BusSource.TaskSpecific1:
case BusSource.TaskSpecific2:
_busData = GetBusSource((int)instruction.BS); // task specific -- call into specific implementation
break;
case BusSource.ReadMD:
_busData = _cpu._system.MemoryBus.ReadMD();
break;
case BusSource.ReadMouse:
//throw new NotImplementedException("ReadMouse bus source not implemented.");
_busData = 0; // TODO: implement;
break;
case BusSource.ReadDisp:
// "The high-order bits of IR cannot be read directly, but the displacement field of IR (8 low order bits),
// may be read with the <-DISP bus source. If the X field of the instruction is zero (i.e. it specifies page 0
// addressing) then the DISP field of the instruction is put on BUS[8-15] and BUS[0-7] is zeroed. If the X
// field of the instruction is nonzero (i.e. it specifies PC-relative or base-register addressing) then the DISP
// field is sign-extended and put on the bus."
// NB: the "X" field of the NOVA instruction is IR[6-7]
_busData = (ushort)(_cpu._ir & 0xff);
if ((_cpu._ir & 0x300) != 0)
{
// sign extend if necessary
if ((_cpu._ir & 0x80) == 0x80)
{
_busData |= (0xff00);
}
}
break;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}.", instruction.BS));
break;
}
}
else
{
// See also comments below.
_busData = ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Constant ROM access:
// The constant memory is gated to the bus by F1=7, F2=7, or BS>4. The constant memory is addressed by the
// (8 bit) concatenation of RSELECT and BS. The intent in enabling constants with BS>4 is to provide a masking
// facility, particularly for the <-MOUSE and <-DISP bus sources. This works because the processor bus ANDs if
// more than one source is gated to it. Up to 32 such mask contans can be provided for each of the four bus sources
// > 4.
// NOTE also:
// "Note that the [emulator task F2] functions which replace the low bits of RSELECT with IR aaffect only the
// selection of R; they do not affect the address supplied to the constant ROM."
// Hence we use the unmodified RSELECT value here and above.
if ((int)instruction.BS > 4 ||
instruction.F1 == SpecialFunction1.Constant ||
instruction.F2 == SpecialFunction2.Constant)
{
_busData &= ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Do ALU operation
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
// Reset shifter op
Shifter.SetOperation(ShifterOp.None, 0);
//
// Do Special Functions
//
switch(instruction.F1)
{
case SpecialFunction1.None:
// Do nothing. Well, that was easy.
break;
case SpecialFunction1.LoadMAR:
_cpu._system.MemoryBus.LoadMAR(aluData); // Start main memory reference
break;
case SpecialFunction1.Task:
nextTask = true; // Yield to other more important tasks
break;
case SpecialFunction1.Block:
// Technically this is to be invoked by the hardware device associated with a task.
// That logic would be circituous and unless there's a good reason not to that is discovered
// later, I'm just going to directly block the current task here.
_cpu.BlockTask(this._taskType);
break;
case SpecialFunction1.LLSH1:
Shifter.SetOperation(ShifterOp.ShiftLeft, 1);
break;
case SpecialFunction1.LRSH1:
Shifter.SetOperation(ShifterOp.ShiftRight, 1);
break;
case SpecialFunction1.LLCY8:
Shifter.SetOperation(ShifterOp.RotateLeft, 8);
break;
case SpecialFunction1.Constant:
// Ignored here; handled by Constant ROM access logic above.
break;
default:
// Let the specific task implementation take a crack at this.
ExecuteSpecialFunction1((int)instruction.F1);
break;
}
switch(instruction.F2)
{
case SpecialFunction2.None:
// Nothing!
break;
case SpecialFunction2.BusEq0:
if (_busData == 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.ShLt0:
//
// Note:
// "the value of SHIFTER OUTPUT is determined by the value of L as the microinstruction
// *begins* execution and the shifter function specified during the *current* microinstruction.
//
// Since we haven't modifed L yet, and we've selected the shifter function above, we're good to go here.
//
if ((short)Shifter.DoOperation(_cpu._l, _cpu._t) < 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.ShEq0:
// See note above.
if (Shifter.DoOperation(_cpu._l, _cpu._t) == 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.Bus:
// Select bits 6-15 (bits 0-9 in modern parlance) of the bus
_nextModifier = (ushort)(_busData & 0x3ff);
break;
case SpecialFunction2.ALUCY:
// ALUC0 is the carry produced by the ALU during the most recent microinstruction
// that loaded L. It is *not* the carry produced during the execution of the microinstruction
// that contains the ALUCY function.
_nextModifier = _cpu._aluC0;
break;
case SpecialFunction2.StoreMD:
_cpu._system.MemoryBus.LoadMD(_busData);
break;
case SpecialFunction2.Constant:
// Ignored here; handled by Constant ROM access logic above.
break;
default:
// Let the specific task implementation take a crack at this.
ExecuteSpecialFunction2((int)instruction.F2);
break;
}
//
// Write back to registers:
//
// Load T
if (instruction.LoadT)
{
// Does this operation change the source for T?
bool loadTFromALU = false;
switch(instruction.ALUF)
{
case AluFunction.Bus:
case AluFunction.BusOrT:
case AluFunction.BusPlus1:
case AluFunction.BusMinus1:
case AluFunction.BusPlusTPlus1:
case AluFunction.BusPlusSkip:
case AluFunction.AluBusAndT:
loadTFromALU = true;
break;
}
_cpu._t = loadTFromALU ? aluData : _busData;
}
// Do writeback to selected R register from shifter output
if (loadR)
{
_cpu._r[_rSelect] = Shifter.DoOperation(_cpu._l, _cpu._t);
}
// Do writeback to selected R register from M
if (_loadS)
{
_cpu._s[_cpu._rb][_rSelect] = _cpu._m;
}
// Load L (and M) from ALU
if (instruction.LoadL)
{
_cpu._l = aluData;
_cpu._m = aluData;
// Save ALUC0 for use in the next ALUCY special function.
_cpu._aluC0 = (ushort)ALU.Carry;
}
//
// Select next address, using the address modifier from the last instruction.
//
_mpc = (ushort)(instruction.NEXT | nextModifier);
return nextTask;
}
protected abstract ushort GetBusSource(int bs);
protected abstract void ExecuteSpecialFunction1(int f1);
/// <summary>
/// Used to allow Task-specific F2s that need to modify RSELECT to do so.
/// </summary>
/// <param name="f2"></param>
protected virtual void ExecuteSpecialFunction2Early(int f2)
{
// Nothing by default.
}
protected abstract void ExecuteSpecialFunction2(int f2);
//
// Per uInstruction Task Data:
// Modified by both the base Task implementation and any subclasses
//
// TODO: maybe instead of these being shared (which feels kinda bad)
// these could be encapsulated in an object and passed to subclass implementations?
protected ushort _busData; // Data placed onto the bus (ANDed from multiple sources)
protected ushort _nextModifier; // Bits ORed onto the NEXT field of the current instruction
protected uint _rSelect; // RSELECT field from current instruction, potentially modified by task
protected bool _loadS; // Whether to load S from M at and of cycle
//
// Global Task Data
//
protected AltoCPU _cpu;
protected ushort _mpc;
protected TaskType _taskType;
protected bool _wakeup;
// Emulator Task-specific data. This is placed here because it is used by the ALU and it's easier to reference in the
// base class even if it does break encapsulation. See notes in the EmulatorTask class for meaning.
protected int _skip;
}
/// <summary>
/// EmulatorTask provides emulator (NOVA instruction set) specific operations.
/// </summary>
private class EmulatorTask : Task
{
public EmulatorTask(AltoCPU cpu) : base(cpu)
{
_taskType = TaskType.Emulator;
// The Wakeup signal is always true for the Emulator task.
_wakeup = true;
}
public override void BlockTask()
{
throw new InvalidOperationException("The emulator task cannot be blocked.");
}
public override void WakeupTask()
{
throw new InvalidOperationException("The emulator task is always in wakeup state.");
}
protected override ushort GetBusSource(int bs)
{
EmulatorBusSource ebs = (EmulatorBusSource)bs;
switch(ebs)
{
case EmulatorBusSource.ReadSLocation:
return _cpu._s[_cpu._rb][_rSelect];
case EmulatorBusSource.LoadSLocation:
_loadS = true;
return 0; // TODO: technically this is an "undefined value" not zero.
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
}
}
protected override void ExecuteSpecialFunction1(int f1)
{
EmulatorF1 ef1 = (EmulatorF1)f1;
switch (ef1)
{
case EmulatorF1.RSNF:
// TODO: make configurable
// "...decoded by the Ethernet interface, which gates the host address wired on the
// backplane onto BUS[8-15]. BUS[0-7] is not driven and will therefore be -1. If
// no Ethernet interface is present, BUS will be -1.
//
_busData &= (0xff00 | 0x42);
break;
case EmulatorF1.STARTF:
// Dispatch function to I/O based on contents of AC0... (TBD: what are these?)
throw new NotImplementedException();
break;
case EmulatorF1.SWMODE:
// nothing! for now.
break;
default:
throw new InvalidOperationException(String.Format("Unhandled emulator F1 {0}.", ef1));
}
}
protected override void ExecuteSpecialFunction2Early(int f2)
{
EmulatorF2 ef2 = (EmulatorF2)f2;
switch (ef2)
{
case EmulatorF2.ACSOURCE:
// Early: modify R select field:
// "...it replaces the two-low order bits of the R select field with
// the complement of the SrcAC field of IR, (IR[1-2] XOR 3), allowing the emulator
// to address its accumulators (which are assigned to R0-R3)."
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x6000) >> 13) ^ 3);
break;
case EmulatorF2.ACDEST:
// "...causes (IR[3-4] XOR 3) to be used as the low-order two bits of the RSELECT field.
// This address the accumulators from the destination field of the instruction. The selected
// register may be loaded or read."
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
break;
}
}
protected override void ExecuteSpecialFunction2(int f2)
{
EmulatorF2 ef2 = (EmulatorF2)f2;
switch (ef2)
{
case EmulatorF2.LoadIR:
// based on block diagram, this always comes from the bus
_cpu._ir = _busData;
// "IR<- also merges bus bits 0, 5, 6 and 7 into NEXT[6-9] which does a first level
// instruction dispatch."
// TODO: is this an AND or an OR operation? (how is the "merge" done?)
// Assuming for now this is an OR operation like everything else that modifies NEXT.
_nextModifier = (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));
// "IR<- clears SKIP"
_skip = 0;
break;
case EmulatorF2.IDISP:
// "The IDISP function (F2=15B) does a 16 way dispatch under control of a PROM and a
// multiplexer. The values are tabulated below:
// Conditions ORed onto NEXT Comment
//
// if IR[0] = 1 3-IR[8-9] complement of SH field of IR
// elseif IR[1-2] = 0 IR[3-4] JMP, JSR, ISZ, DSZ
// elseif IR[1-2] = 1 4 LDA
// elseif IR[1-2] = 2 5 STA
// elseif IR[4-7] = 0 1
// elseif IR[4-7] = 1 0
// elseif IR[4-7] = 6 16B CONVERT
// elseif IR[4-7] = 16B 6
// else IR[4-7]
// NB: as always, Xerox labels bits in the opposite order from modern convention;
// (bit 0 is the msb...)
if ((_cpu._ir & 0x8000) != 0)
{
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else if((_cpu._ir & 0x6000) == 0)
{
_nextModifier = (ushort)((_cpu._ir & 0x1800) >> 11);
}
else if((_cpu._ir & 0x6000) == 0x4000)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x6000) == 0x6000)
{
_nextModifier = 5;
}
else if ((_cpu._ir & 0x0f00) == 0)
{
_nextModifier = 1;
}
else if ((_cpu._ir & 0x0f00) == 0x0100)
{
_nextModifier = 0;
}
else if ((_cpu._ir & 0x0f00) == 0x0600)
{
_nextModifier = 0xe;
}
else if ((_cpu._ir & 0x0f00) == 0x0e00)
{
_nextModifier = 0x6;
}
else
{
_nextModifier = (ushort)((_cpu._ir & 0x0f00) >> 8);
}
break;
case EmulatorF2.ACSOURCE:
// Late:
// "...a dispatch is performed:
// Conditions ORed onto NEXT Comment
//
// if IR[0] = 1 3-IR[8-9] complement of SH field of IR
// if IR[1-2] = 3 IR[5] the Indirect bit of R
// if IR[3-7] = 0 2 CYCLE
// if IR[3-7] = 1 5 RAMTRAP
// if IR[3-7] = 2 3 NOPAR -- parameterless opcode group
// if IR[3-7] = 3 6 RAMTRAP
// if IR[3-7] = 4 7 RAMTRAP
// if IR[3-7] = 11B 4 JSRII
// if IR[3-7] = 12B 4 JSRIS
// if IR[3-7] = 16B 1 CONVERT
// if IR[3-7] = 37B 17B ROMTRAP -- used by Swat, the debugger
// else 16B ROMTRAP
if ((_cpu._ir & 0x8000) != 0)
{
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else if ((_cpu._ir & 0xc000) == 0xc000)
{
_nextModifier = (ushort)((_cpu._ir & 0x400) >> 10);
}
else if ((_cpu._ir & 0x1f00) == 0)
{
_nextModifier = 2;
}
else if ((_cpu._ir & 0x1f00) == 0x0100)
{
_nextModifier = 5;
}
else if ((_cpu._ir & 0x1f00) == 0x0200)
{
_nextModifier = 3;
}
else if ((_cpu._ir & 0x1f00) == 0x0300)
{
_nextModifier = 6;
}
else if ((_cpu._ir & 0x1f00) == 0x0400)
{
_nextModifier = 7;
}
else if ((_cpu._ir & 0x1f00) == 0x0900)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x1f00) == 0x0a00)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x1f00) == 0x0e00)
{
_nextModifier = 1;
}
else if ((_cpu._ir & 0x1f00) == 0x1f00)
{
_nextModifier = 0xf;
}
else
{
_nextModifier = 0xe;
}
break;
case EmulatorF2.ACDEST:
// Handled in early handler
break;
case EmulatorF2.BUSODD:
// "...merges BUS[15] into NEXT[9]."
// TODO: is this an AND or an OR?
_nextModifier |= (ushort)(_busData & 0x1);
break;
case EmulatorF2.MAGIC:
Shifter.SetMagic(true);
break;
default:
throw new InvalidOperationException(String.Format("Unhandled emulator F2 {0}.", ef2));
}
}
// From Section 3, Pg. 31:
// "The emulator has two additional bits of state, the SKIP and CARRY flip flops. CARRY is distinct from the
// microprocessors ALUC0 bit, tested by the ALUCY function. CARRY is set or cleared as a function of IR and
// many other things(see section 3.1) when the DNS<-(do novel shifts, F2= 12B) function is executed. In
// particular, if IR[12] is true, CARRY will not change. DNS also addresses R from (3-IR[3 - 4]), causes a store
// into R unless IR[12] is set, and sets the SKIP flip flop if appropriate(see section 3.1). The emulator
// microcode increments PC by 1 at the beginning of the next emulated instruction if SKIP is set, using
// BUS+SKIP(ALUF= 13B). IR_ clears SKIP."
//
// NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it.
private int _carry;
}
/// <summary>
/// DiskSectorTask provides implementation for disk-specific special functions
/// </summary>
private class DiskSectorTask : Task
{
public DiskSectorTask(AltoCPU cpu) : base(cpu)
{
_taskType = TaskType.DiskSector;
_wakeup = false;
}
protected override ushort GetBusSource(int bs)
{
DiskBusSource dbs = (DiskBusSource)bs;
switch (dbs)
{
case DiskBusSource.ReadKSTAT:
return _cpu._system.DiskController.KSTAT;
case DiskBusSource.ReadKDATA:
return _cpu._system.DiskController.KDATA;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
}
}
protected override void ExecuteSpecialFunction1(int f1)
{
DiskF1 df1 = (DiskF1)f1;
switch(df1)
{
case DiskF1.LoadKDATA:
// "The KDATA register is loaded from BUS[0-15]."
_cpu._system.DiskController.KDATA = _busData;
break;
case DiskF1.LoadKADR:
// "This causes the KADR register to be loaded from BUS[8-14].
// in addition, it causes the head address bit to be loaded from KDATA[13]."
// TODO: do the latter (likely inside the controller)
_cpu._system.DiskController.KADR = (ushort)((_busData & 0xfe) >> 1);
break;
case DiskF1.LoadKCOMM:
_cpu._system.DiskController.KCOM = (ushort)((_busData & 0x7c00) >> 10);
break;
case DiskF1.CLRSTAT:
_cpu._system.DiskController.ClearStatus();
break;
case DiskF1.INCRECNO:
_cpu._system.DiskController.IncrementRecord();
break;
case DiskF1.LoadKSTAT:
// "KSTAT[12-15] are loaded from BUS[12-15]. (Actually BUS[13] is ORed onto
// KSTAT[13].)"
// OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
_cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | (_busData & 0xf));
break;
case DiskF1.STROBE:
_cpu._system.DiskController.Strobe();
break;
default:
throw new InvalidOperationException(String.Format("Unhandled disk special function 1 {0}", df1));
}
}
protected override void ExecuteSpecialFunction2(int f2)
{
DiskF2 df2 = (DiskF2)f2;
switch(df2)
{
case DiskF2.INIT:
// "NEXT<-NEXT OR (if WDTASKACT AND WDINIT) then 37B else 0
// TODO: figure out how WDTASKACT and WDINIT work.
throw new NotImplementedException("INIT not implemented.");
default:
throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));
}
}
}
// AltoCPU registers
ushort _t;
ushort _l;

View File

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contralto.Memory;
namespace Contralto.CPU
{
public partial class AltoCPU
{
/// <summary>
/// DiskTask provides implementation for disk-specific special functions
/// (for both Disk Sector and Disk Word tasks, since the special functions are
/// identical between the two)
/// </summary>
private class DiskTask : Task
{
public DiskTask(AltoCPU cpu, bool diskSectorTask) : base(cpu)
{
_taskType = diskSectorTask ? TaskType.DiskSector : TaskType.DiskWord;
_wakeup = false;
}
protected override ushort GetBusSource(int bs)
{
DiskBusSource dbs = (DiskBusSource)bs;
switch (dbs)
{
case DiskBusSource.ReadKSTAT:
return _cpu._system.DiskController.KSTAT;
case DiskBusSource.ReadKDATA:
return _cpu._system.DiskController.KDATA;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
}
}
protected override void ExecuteSpecialFunction1(int f1)
{
DiskF1 df1 = (DiskF1)f1;
switch (df1)
{
case DiskF1.LoadKDATA:
// "The KDATA register is loaded from BUS[0-15]."
_cpu._system.DiskController.KDATA = _busData;
break;
case DiskF1.LoadKADR:
// "This causes the KADR register to be loaded from BUS[8-14].
// in addition, it causes the head address bit to be loaded from KDATA[13]."
// (the latter is done by DiskController)
_cpu._system.DiskController.KADR = (ushort)((_busData & 0xfe) >> 1);
break;
case DiskF1.LoadKCOMM:
_cpu._system.DiskController.KCOM = (ushort)((_busData & 0x7c00) >> 10);
break;
case DiskF1.CLRSTAT:
_cpu._system.DiskController.ClearStatus();
break;
case DiskF1.INCRECNO:
_cpu._system.DiskController.IncrementRecord();
break;
case DiskF1.LoadKSTAT:
// "KSTAT[12-15] are loaded from BUS[12-15]. (Actually BUS[13] is ORed onto
// KSTAT[13].)"
// OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
_cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | (_busData & 0xf));
break;
case DiskF1.STROBE:
_cpu._system.DiskController.Strobe();
break;
default:
throw new InvalidOperationException(String.Format("Unhandled disk special function 1 {0}", df1));
}
}
protected override void ExecuteSpecialFunction2(int f2)
{
DiskF2 df2 = (DiskF2)f2;
switch (df2)
{
case DiskF2.INIT:
// "NEXT<-NEXT OR (if WDTASKACT AND WDINIT) then 37B else 0
// TODO: figure out how WDTASKACT and WDINIT work.
throw new NotImplementedException("INIT not implemented.");
default:
throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));
}
}
}
}
}

View File

@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contralto.Memory;
namespace Contralto.CPU
{
public partial class AltoCPU
{
/// <summary>
/// EmulatorTask provides emulator (NOVA instruction set) specific operations.
/// </summary>
private class EmulatorTask : Task
{
public EmulatorTask(AltoCPU cpu) : base(cpu)
{
_taskType = TaskType.Emulator;
// The Wakeup signal is always true for the Emulator task.
_wakeup = true;
}
public override void BlockTask()
{
throw new InvalidOperationException("The emulator task cannot be blocked.");
}
public override void WakeupTask()
{
throw new InvalidOperationException("The emulator task is always in wakeup state.");
}
protected override ushort GetBusSource(int bs)
{
EmulatorBusSource ebs = (EmulatorBusSource)bs;
switch (ebs)
{
case EmulatorBusSource.ReadSLocation:
return _cpu._s[_cpu._rb][_rSelect];
case EmulatorBusSource.LoadSLocation:
_loadS = true;
return 0; // TODO: technically this is an "undefined value," not zero.
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
}
}
protected override void ExecuteSpecialFunction1(int f1)
{
EmulatorF1 ef1 = (EmulatorF1)f1;
switch (ef1)
{
case EmulatorF1.RSNF:
// TODO: make configurable
// "...decoded by the Ethernet interface, which gates the host address wired on the
// backplane onto BUS[8-15]. BUS[0-7] is not driven and will therefore be -1. If
// no Ethernet interface is present, BUS will be -1.
//
_busData &= (0xff00 | 0x42);
break;
case EmulatorF1.STARTF:
// Dispatch function to I/O based on contents of AC0... (TBD: what are these?)
throw new NotImplementedException();
break;
case EmulatorF1.SWMODE:
// nothing! for now.
break;
default:
throw new InvalidOperationException(String.Format("Unhandled emulator F1 {0}.", ef1));
}
}
protected override void ExecuteSpecialFunction2Early(int f2)
{
EmulatorF2 ef2 = (EmulatorF2)f2;
switch (ef2)
{
case EmulatorF2.ACSOURCE:
// Early: modify R select field:
// "...it replaces the two-low order bits of the R select field with
// the complement of the SrcAC field of IR, (IR[1-2] XOR 3), allowing the emulator
// to address its accumulators (which are assigned to R0-R3)."
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x6000) >> 13) ^ 3);
break;
case EmulatorF2.ACDEST:
// "...causes (IR[3-4] XOR 3) to be used as the low-order two bits of the RSELECT field.
// This address the accumulators from the destination field of the instruction. The selected
// register may be loaded or read."
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
break;
}
}
protected override void ExecuteSpecialFunction2(int f2)
{
EmulatorF2 ef2 = (EmulatorF2)f2;
switch (ef2)
{
case EmulatorF2.LoadIR:
// based on block diagram, this always comes from the bus
_cpu._ir = _busData;
// "IR<- also merges bus bits 0, 5, 6 and 7 into NEXT[6-9] which does a first level
// instruction dispatch."
// TODO: is this an AND or an OR operation? (how is the "merge" done?)
// Assuming for now this is an OR operation like everything else that modifies NEXT.
_nextModifier = (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));
// "IR<- clears SKIP"
_skip = 0;
break;
case EmulatorF2.IDISP:
// "The IDISP function (F2=15B) does a 16 way dispatch under control of a PROM and a
// multiplexer. The values are tabulated below:
// Conditions ORed onto NEXT Comment
//
// if IR[0] = 1 3-IR[8-9] complement of SH field of IR
// elseif IR[1-2] = 0 IR[3-4] JMP, JSR, ISZ, DSZ
// elseif IR[1-2] = 1 4 LDA
// elseif IR[1-2] = 2 5 STA
// elseif IR[4-7] = 0 1
// elseif IR[4-7] = 1 0
// elseif IR[4-7] = 6 16B CONVERT
// elseif IR[4-7] = 16B 6
// else IR[4-7]
// NB: as always, Xerox labels bits in the opposite order from modern convention;
// (bit 0 is the msb...)
if ((_cpu._ir & 0x8000) != 0)
{
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else if ((_cpu._ir & 0x6000) == 0)
{
_nextModifier = (ushort)((_cpu._ir & 0x1800) >> 11);
}
else if ((_cpu._ir & 0x6000) == 0x4000)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x6000) == 0x6000)
{
_nextModifier = 5;
}
else if ((_cpu._ir & 0x0f00) == 0)
{
_nextModifier = 1;
}
else if ((_cpu._ir & 0x0f00) == 0x0100)
{
_nextModifier = 0;
}
else if ((_cpu._ir & 0x0f00) == 0x0600)
{
_nextModifier = 0xe;
}
else if ((_cpu._ir & 0x0f00) == 0x0e00)
{
_nextModifier = 0x6;
}
else
{
_nextModifier = (ushort)((_cpu._ir & 0x0f00) >> 8);
}
break;
case EmulatorF2.ACSOURCE:
// Late:
// "...a dispatch is performed:
// Conditions ORed onto NEXT Comment
//
// if IR[0] = 1 3-IR[8-9] complement of SH field of IR
// if IR[1-2] = 3 IR[5] the Indirect bit of R
// if IR[3-7] = 0 2 CYCLE
// if IR[3-7] = 1 5 RAMTRAP
// if IR[3-7] = 2 3 NOPAR -- parameterless opcode group
// if IR[3-7] = 3 6 RAMTRAP
// if IR[3-7] = 4 7 RAMTRAP
// if IR[3-7] = 11B 4 JSRII
// if IR[3-7] = 12B 4 JSRIS
// if IR[3-7] = 16B 1 CONVERT
// if IR[3-7] = 37B 17B ROMTRAP -- used by Swat, the debugger
// else 16B ROMTRAP
if ((_cpu._ir & 0x8000) != 0)
{
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else if ((_cpu._ir & 0xc000) == 0xc000)
{
_nextModifier = (ushort)((_cpu._ir & 0x400) >> 10);
}
else if ((_cpu._ir & 0x1f00) == 0)
{
_nextModifier = 2;
}
else if ((_cpu._ir & 0x1f00) == 0x0100)
{
_nextModifier = 5;
}
else if ((_cpu._ir & 0x1f00) == 0x0200)
{
_nextModifier = 3;
}
else if ((_cpu._ir & 0x1f00) == 0x0300)
{
_nextModifier = 6;
}
else if ((_cpu._ir & 0x1f00) == 0x0400)
{
_nextModifier = 7;
}
else if ((_cpu._ir & 0x1f00) == 0x0900)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x1f00) == 0x0a00)
{
_nextModifier = 4;
}
else if ((_cpu._ir & 0x1f00) == 0x0e00)
{
_nextModifier = 1;
}
else if ((_cpu._ir & 0x1f00) == 0x1f00)
{
_nextModifier = 0xf;
}
else
{
_nextModifier = 0xe;
}
break;
case EmulatorF2.ACDEST:
// Handled in early handler
break;
case EmulatorF2.BUSODD:
// "...merges BUS[15] into NEXT[9]."
// TODO: is this an AND or an OR?
_nextModifier |= (ushort)(_busData & 0x1);
break;
case EmulatorF2.MAGIC:
Shifter.SetMagic(true);
break;
default:
throw new InvalidOperationException(String.Format("Unhandled emulator F2 {0}.", ef2));
}
}
// From Section 3, Pg. 31:
// "The emulator has two additional bits of state, the SKIP and CARRY flip flops. CARRY is distinct from the
// microprocessors ALUC0 bit, tested by the ALUCY function. CARRY is set or cleared as a function of IR and
// many other things(see section 3.1) when the DNS<-(do novel shifts, F2= 12B) function is executed. In
// particular, if IR[12] is true, CARRY will not change. DNS also addresses R from (3-IR[3 - 4]), causes a store
// into R unless IR[12] is set, and sets the SKIP flip flop if appropriate(see section 3.1). The emulator
// microcode increments PC by 1 at the beginning of the next emulated instruction if SKIP is set, using
// BUS+SKIP(ALUF= 13B). IR_ clears SKIP."
//
// NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it.
private int _carry;
}
}
}

413
Contralto/CPU/Tasks/Task.cs Normal file
View File

@ -0,0 +1,413 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contralto.Memory;
namespace Contralto.CPU
{
public partial class AltoCPU
{
// Task:
// Base task class: provides implementation for non-task-specific microcode execution and
// state. Task subclasses implement and execute Task-specific behavior and are called into
// by the base class as necessary.
public abstract class Task
{
public Task(AltoCPU cpu)
{
_wakeup = false;
_mpc = 0xffff; // invalid, for sanity checking
_taskType = TaskType.Invalid;
_cpu = cpu;
}
public int Priority
{
get { return (int)_taskType; }
}
public bool Wakeup
{
get { return _wakeup; }
}
public ushort MPC
{
get { return _mpc; }
}
public virtual void Reset()
{
// From The Alto Hardware Manual (section 2, "Initialization"):
// "...each task start[s] at the location which is its task number"
//
_mpc = (ushort)_taskType;
}
public virtual void BlockTask()
{
_wakeup = false;
}
public virtual void WakeupTask()
{
_wakeup = true;
}
public bool ExecuteNext()
{
// TODO: cache microinstructions (or pre-decode them) to save consing all these up every time.
MicroInstruction instruction = new MicroInstruction(UCodeMemory.UCodeROM[_mpc]);
return ExecuteInstruction(instruction);
}
/// <summary>
/// ExecuteInstruction causes the Task to execute the next instruction (the one
/// _mpc is pointing to). The base implementation covers non-task specific logic; subclasses may
/// provide their own overrides.
/// </summary>
/// <returns>True if a task switch has been requested by a TASK instruction, false otherwise.</returns>
protected virtual bool ExecuteInstruction(MicroInstruction instruction)
{
bool nextTask = false;
bool loadR = false;
ushort aluData = 0;
ushort nextModifier = 0;
_loadS = false;
_rSelect = 0;
_busData = 0;
Shifter.SetMagic(false);
//
// Wait for memory state machine if a memory operation is requested by this instruction and
// the memory isn't ready yet.
// TODO: this needs to be seriously cleaned up.
//
if (instruction.BS == BusSource.ReadMD ||
instruction.F1 == SpecialFunction1.LoadMAR ||
instruction.F2 == SpecialFunction2.StoreMD)
{
MemoryOperation op;
if (instruction.BS == BusSource.ReadMD)
{
op = MemoryOperation.Read;
}
else if (instruction.F1 == SpecialFunction1.LoadMAR)
{
op = MemoryOperation.LoadAddress;
}
else
{
op = MemoryOperation.Store;
}
if (!_cpu._system.MemoryBus.Ready(op))
{
// Suspend operation for this cycle.
return false;
}
}
// If we have a modified next field from the last instruction, make sure it gets applied to this one.
nextModifier = _nextModifier;
_nextModifier = 0;
_rSelect = instruction.RSELECT;
// Give tasks the chance to modify parameters early on (like RSELECT)
ExecuteSpecialFunction2Early((int)instruction.F2);
// Select BUS data.
if (instruction.F1 != SpecialFunction1.Constant &&
instruction.F2 != SpecialFunction2.Constant)
{
// Normal BUS data (not constant ROM access).
switch (instruction.BS)
{
case BusSource.ReadR:
_busData = _cpu._r[_rSelect];
break;
case BusSource.LoadR:
_busData = 0; // "Loading R forces the BUS to 0 so that an ALU function of 0 and T may be executed simultaneously"
loadR = true;
break;
case BusSource.None:
_busData = 0xffff; // "Enables no source to the BUS, leaving it all ones"
break;
case BusSource.TaskSpecific1:
case BusSource.TaskSpecific2:
_busData = GetBusSource((int)instruction.BS); // task specific -- call into specific implementation
break;
case BusSource.ReadMD:
_busData = _cpu._system.MemoryBus.ReadMD();
break;
case BusSource.ReadMouse:
//throw new NotImplementedException("ReadMouse bus source not implemented.");
_busData = 0; // TODO: implement;
break;
case BusSource.ReadDisp:
// "The high-order bits of IR cannot be read directly, but the displacement field of IR (8 low order bits),
// may be read with the <-DISP bus source. If the X field of the instruction is zero (i.e. it specifies page 0
// addressing) then the DISP field of the instruction is put on BUS[8-15] and BUS[0-7] is zeroed. If the X
// field of the instruction is nonzero (i.e. it specifies PC-relative or base-register addressing) then the DISP
// field is sign-extended and put on the bus."
// NB: the "X" field of the NOVA instruction is IR[6-7]
_busData = (ushort)(_cpu._ir & 0xff);
if ((_cpu._ir & 0x300) != 0)
{
// sign extend if necessary
if ((_cpu._ir & 0x80) == 0x80)
{
_busData |= (0xff00);
}
}
break;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}.", instruction.BS));
break;
}
}
else
{
// See also comments below.
_busData = ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Constant ROM access:
// The constant memory is gated to the bus by F1=7, F2=7, or BS>4. The constant memory is addressed by the
// (8 bit) concatenation of RSELECT and BS. The intent in enabling constants with BS>4 is to provide a masking
// facility, particularly for the <-MOUSE and <-DISP bus sources. This works because the processor bus ANDs if
// more than one source is gated to it. Up to 32 such mask contans can be provided for each of the four bus sources
// > 4.
// NOTE also:
// "Note that the [emulator task F2] functions which replace the low bits of RSELECT with IR aaffect only the
// selection of R; they do not affect the address supplied to the constant ROM."
// Hence we use the unmodified RSELECT value here and above.
if ((int)instruction.BS > 4 ||
instruction.F1 == SpecialFunction1.Constant ||
instruction.F2 == SpecialFunction2.Constant)
{
_busData &= ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Do ALU operation
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
// Reset shifter op
Shifter.SetOperation(ShifterOp.None, 0);
//
// Do Special Functions
//
switch (instruction.F1)
{
case SpecialFunction1.None:
// Do nothing. Well, that was easy.
break;
case SpecialFunction1.LoadMAR:
_cpu._system.MemoryBus.LoadMAR(aluData); // Start main memory reference
break;
case SpecialFunction1.Task:
nextTask = true; // Yield to other more important tasks
break;
case SpecialFunction1.Block:
// Technically this is to be invoked by the hardware device associated with a task.
// That logic would be circituous and unless there's a good reason not to that is discovered
// later, I'm just going to directly block the current task here.
_cpu.BlockTask(this._taskType);
break;
case SpecialFunction1.LLSH1:
Shifter.SetOperation(ShifterOp.ShiftLeft, 1);
break;
case SpecialFunction1.LRSH1:
Shifter.SetOperation(ShifterOp.ShiftRight, 1);
break;
case SpecialFunction1.LLCY8:
Shifter.SetOperation(ShifterOp.RotateLeft, 8);
break;
case SpecialFunction1.Constant:
// Ignored here; handled by Constant ROM access logic above.
break;
default:
// Let the specific task implementation take a crack at this.
ExecuteSpecialFunction1((int)instruction.F1);
break;
}
switch (instruction.F2)
{
case SpecialFunction2.None:
// Nothing!
break;
case SpecialFunction2.BusEq0:
if (_busData == 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.ShLt0:
//
// Note:
// "the value of SHIFTER OUTPUT is determined by the value of L as the microinstruction
// *begins* execution and the shifter function specified during the *current* microinstruction.
//
// Since we haven't modifed L yet, and we've selected the shifter function above, we're good to go here.
//
if ((short)Shifter.DoOperation(_cpu._l, _cpu._t) < 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.ShEq0:
// See note above.
if (Shifter.DoOperation(_cpu._l, _cpu._t) == 0)
{
_nextModifier = 1;
}
break;
case SpecialFunction2.Bus:
// Select bits 6-15 (bits 0-9 in modern parlance) of the bus
_nextModifier = (ushort)(_busData & 0x3ff);
break;
case SpecialFunction2.ALUCY:
// ALUC0 is the carry produced by the ALU during the most recent microinstruction
// that loaded L. It is *not* the carry produced during the execution of the microinstruction
// that contains the ALUCY function.
_nextModifier = _cpu._aluC0;
break;
case SpecialFunction2.StoreMD:
_cpu._system.MemoryBus.LoadMD(_busData);
break;
case SpecialFunction2.Constant:
// Ignored here; handled by Constant ROM access logic above.
break;
default:
// Let the specific task implementation take a crack at this.
ExecuteSpecialFunction2((int)instruction.F2);
break;
}
//
// Write back to registers:
//
// Do writeback to selected R register from shifter output
if (loadR)
{
_cpu._r[_rSelect] = Shifter.DoOperation(_cpu._l, _cpu._t);
}
// Do writeback to selected R register from M
if (_loadS)
{
_cpu._s[_cpu._rb][_rSelect] = _cpu._m;
}
// Load T
if (instruction.LoadT)
{
// Does this operation change the source for T?
bool loadTFromALU = false;
switch (instruction.ALUF)
{
case AluFunction.Bus:
case AluFunction.BusOrT:
case AluFunction.BusPlus1:
case AluFunction.BusMinus1:
case AluFunction.BusPlusTPlus1:
case AluFunction.BusPlusSkip:
case AluFunction.AluBusAndT:
loadTFromALU = true;
break;
}
_cpu._t = loadTFromALU ? aluData : _busData;
}
// Load L (and M) from ALU outputs.
if (instruction.LoadL)
{
_cpu._l = aluData;
_cpu._m = aluData;
// Save ALUC0 for use in the next ALUCY special function.
_cpu._aluC0 = (ushort)ALU.Carry;
}
//
// Select next address, using the address modifier from the last instruction.
//
_mpc = (ushort)(instruction.NEXT | nextModifier);
return nextTask;
}
protected abstract ushort GetBusSource(int bs);
protected abstract void ExecuteSpecialFunction1(int f1);
/// <summary>
/// Used to allow Task-specific F2s that need to modify RSELECT to do so.
/// </summary>
/// <param name="f2"></param>
protected virtual void ExecuteSpecialFunction2Early(int f2)
{
// Nothing by default.
}
protected abstract void ExecuteSpecialFunction2(int f2);
//
// Per uInstruction Task Data:
// Modified by both the base Task implementation and any subclasses
//
// TODO: maybe instead of these being shared (which feels kinda bad)
// these could be encapsulated in an object and passed to subclass implementations?
protected ushort _busData; // Data placed onto the bus (ANDed from multiple sources)
protected ushort _nextModifier; // Bits ORed onto the NEXT field of the current instruction
protected uint _rSelect; // RSELECT field from current instruction, potentially modified by task
protected bool _loadS; // Whether to load S from M at and of cycle
//
// Global Task Data
//
protected AltoCPU _cpu;
protected ushort _mpc;
protected TaskType _taskType;
protected bool _wakeup;
// Emulator Task-specific data. This is placed here because it is used by the ALU and it's easier to reference in the
// base class even if it does break encapsulation. See notes in the EmulatorTask class for meaning.
protected int _skip;
}
}
}

View File

@ -48,8 +48,11 @@
<Compile Include="CPU\ConstantMemory.cs" />
<Compile Include="CPU\CPU.cs" />
<Compile Include="CPU\Disassembler.cs" />
<Compile Include="CPU\Tasks\DiskTask.cs" />
<Compile Include="CPU\Tasks\EmulatorTask.cs" />
<Compile Include="CPU\MicroInstruction.cs" />
<Compile Include="CPU\Shifter.cs" />
<Compile Include="CPU\Tasks\Task.cs" />
<Compile Include="CPU\UCodeMemory.cs" />
<Compile Include="Debugger.cs">
<SubType>Form</SubType>

View File

@ -28,38 +28,41 @@
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle23 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle24 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle25 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle26 = new System.Windows.Forms.DataGridViewCellStyle();
this.Microcode = new System.Windows.Forms.GroupBox();
this._sourceViewer = new System.Windows.Forms.DataGridView();
this.Breakpoint = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.T = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Addr = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Source = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.StepButton = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this._registerData = new System.Windows.Forms.DataGridView();
this.RegNum = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.R = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.S = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.StepButton = new System.Windows.Forms.Button();
this.AutoStep = new System.Windows.Forms.Button();
this.RunButton = new System.Windows.Forms.Button();
this.StopButton = new System.Windows.Forms.Button();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this._taskData = new System.Windows.Forms.DataGridView();
this.TaskName = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.TaskState = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.TaskPC = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.T = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Addr = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Source = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this._otherRegs = new System.Windows.Forms.DataGridView();
this.Reg = new System.Windows.Forms.DataGridViewTextBoxColumn();
@ -68,6 +71,14 @@
this._memoryData = new System.Windows.Forms.DataGridView();
this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.label1 = new System.Windows.Forms.Label();
this.ExecutionStateLabel = new System.Windows.Forms.Label();
this.JumpToAddress = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.groupBox5 = new System.Windows.Forms.GroupBox();
this._diskData = new System.Windows.Forms.DataGridView();
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Microcode.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).BeginInit();
this.groupBox1.SuspendLayout();
@ -78,10 +89,14 @@
((System.ComponentModel.ISupportInitialize)(this._otherRegs)).BeginInit();
this.groupBox4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this._memoryData)).BeginInit();
this.groupBox5.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this._diskData)).BeginInit();
this.SuspendLayout();
//
// Microcode
//
this.Microcode.Controls.Add(this.label2);
this.Microcode.Controls.Add(this.JumpToAddress);
this.Microcode.Controls.Add(this._sourceViewer);
this.Microcode.Location = new System.Drawing.Point(3, 3);
this.Microcode.Name = "Microcode";
@ -96,11 +111,12 @@
this._sourceViewer.AllowUserToDeleteRows = false;
this._sourceViewer.AllowUserToResizeColumns = false;
this._sourceViewer.AllowUserToResizeRows = false;
dataGridViewCellStyle14.BackColor = System.Drawing.Color.Silver;
this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle14;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.Silver;
this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
this._sourceViewer.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleVertical;
this._sourceViewer.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._sourceViewer.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Breakpoint,
this.T,
this.Addr,
this.Source});
@ -109,14 +125,14 @@
this._sourceViewer.Name = "_sourceViewer";
this._sourceViewer.ReadOnly = true;
this._sourceViewer.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
dataGridViewCellStyle18.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle18.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle18.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle18.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle18.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle18.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle18.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle18;
dataGridViewCellStyle5.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle5.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle5.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle5.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle5.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle5.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle5.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle5;
this._sourceViewer.RowHeadersVisible = false;
this._sourceViewer.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
this._sourceViewer.RowTemplate.Height = 18;
@ -124,9 +140,58 @@
this._sourceViewer.ShowCellErrors = false;
this._sourceViewer.ShowEditingIcon = false;
this._sourceViewer.ShowRowErrors = false;
this._sourceViewer.Size = new System.Drawing.Size(584, 600);
this._sourceViewer.Size = new System.Drawing.Size(584, 571);
this._sourceViewer.TabIndex = 1;
this._sourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
this._sourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.SourceViewCellClick);
//
// Breakpoint
//
this.Breakpoint.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
this.Breakpoint.FalseValue = "false";
this.Breakpoint.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.Breakpoint.HeaderText = "B";
this.Breakpoint.IndeterminateValue = "null";
this.Breakpoint.Name = "Breakpoint";
this.Breakpoint.ReadOnly = true;
this.Breakpoint.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Breakpoint.TrueValue = "true";
this.Breakpoint.Width = 20;
//
// T
//
this.T.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
dataGridViewCellStyle2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.T.DefaultCellStyle = dataGridViewCellStyle2;
this.T.HeaderText = "T";
this.T.Name = "T";
this.T.ReadOnly = true;
this.T.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.T.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.T.Width = 5;
//
// Addr
//
this.Addr.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
dataGridViewCellStyle3.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Addr.DefaultCellStyle = dataGridViewCellStyle3;
this.Addr.HeaderText = "Addr";
this.Addr.Name = "Addr";
this.Addr.ReadOnly = true;
this.Addr.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Addr.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.Addr.Width = 5;
//
// Source
//
this.Source.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
dataGridViewCellStyle4.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Source.DefaultCellStyle = dataGridViewCellStyle4;
this.Source.HeaderText = "Source Code";
this.Source.Name = "Source";
this.Source.ReadOnly = true;
this.Source.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Source.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
//
// groupBox1
//
@ -138,64 +203,27 @@
this.groupBox1.TabStop = false;
this.groupBox1.Text = "General Registers";
//
// StepButton
//
this.StepButton.Location = new System.Drawing.Point(3, 634);
this.StepButton.Name = "StepButton";
this.StepButton.Size = new System.Drawing.Size(44, 23);
this.StepButton.TabIndex = 3;
this.StepButton.Text = "Step";
this.StepButton.UseVisualStyleBackColor = true;
this.StepButton.Click += new System.EventHandler(this.OnStepButtonClicked);
//
// button2
//
this.button2.Location = new System.Drawing.Point(54, 634);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(47, 23);
this.button2.TabIndex = 4;
this.button2.Text = "Auto";
this.button2.UseVisualStyleBackColor = true;
//
// button3
//
this.button3.Location = new System.Drawing.Point(108, 634);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(53, 23);
this.button3.TabIndex = 5;
this.button3.Text = "Run";
this.button3.UseVisualStyleBackColor = true;
//
// button4
//
this.button4.Location = new System.Drawing.Point(168, 634);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(49, 23);
this.button4.TabIndex = 6;
this.button4.Text = "Stop";
this.button4.UseVisualStyleBackColor = true;
//
// _registerData
//
this._registerData.AllowUserToAddRows = false;
this._registerData.AllowUserToDeleteRows = false;
this._registerData.AllowUserToResizeColumns = false;
this._registerData.AllowUserToResizeRows = false;
dataGridViewCellStyle19.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle19;
dataGridViewCellStyle6.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle6;
this._registerData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._registerData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.RegNum,
this.R,
this.S});
dataGridViewCellStyle20.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle20.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle20.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle20.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle20.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle20.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle20.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._registerData.DefaultCellStyle = dataGridViewCellStyle20;
dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle7.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle7.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle7.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle7.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle7.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._registerData.DefaultCellStyle = dataGridViewCellStyle7;
this._registerData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this._registerData.Location = new System.Drawing.Point(7, 19);
this._registerData.MultiSelect = false;
@ -242,6 +270,46 @@
this.S.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.S.Width = 50;
//
// StepButton
//
this.StepButton.Location = new System.Drawing.Point(0, 954);
this.StepButton.Name = "StepButton";
this.StepButton.Size = new System.Drawing.Size(44, 23);
this.StepButton.TabIndex = 3;
this.StepButton.Text = "Step";
this.StepButton.UseVisualStyleBackColor = true;
this.StepButton.Click += new System.EventHandler(this.OnStepButtonClicked);
//
// AutoStep
//
this.AutoStep.Location = new System.Drawing.Point(50, 954);
this.AutoStep.Name = "AutoStep";
this.AutoStep.Size = new System.Drawing.Size(47, 23);
this.AutoStep.TabIndex = 4;
this.AutoStep.Text = "Auto";
this.AutoStep.UseVisualStyleBackColor = true;
this.AutoStep.Click += new System.EventHandler(this.OnAutoStepButtonClicked);
//
// RunButton
//
this.RunButton.Location = new System.Drawing.Point(103, 954);
this.RunButton.Name = "RunButton";
this.RunButton.Size = new System.Drawing.Size(53, 23);
this.RunButton.TabIndex = 5;
this.RunButton.Text = "Run";
this.RunButton.UseVisualStyleBackColor = true;
this.RunButton.Click += new System.EventHandler(this.RunButton_Click);
//
// StopButton
//
this.StopButton.Location = new System.Drawing.Point(164, 954);
this.StopButton.Name = "StopButton";
this.StopButton.Size = new System.Drawing.Size(49, 23);
this.StopButton.TabIndex = 6;
this.StopButton.Text = "Stop";
this.StopButton.UseVisualStyleBackColor = true;
this.StopButton.Click += new System.EventHandler(this.OnStopButtonClicked);
//
// groupBox2
//
this.groupBox2.Controls.Add(this._taskData);
@ -256,21 +324,21 @@
//
this._taskData.AllowUserToAddRows = false;
this._taskData.AllowUserToDeleteRows = false;
dataGridViewCellStyle21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle21;
dataGridViewCellStyle8.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle8;
this._taskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._taskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.TaskName,
this.TaskState,
this.TaskPC});
dataGridViewCellStyle22.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle22.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle22.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle22.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle22.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle22.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle22.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._taskData.DefaultCellStyle = dataGridViewCellStyle22;
dataGridViewCellStyle9.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle9.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle9.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle9.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle9.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle9.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle9.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._taskData.DefaultCellStyle = dataGridViewCellStyle9;
this._taskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this._taskData.Location = new System.Drawing.Point(7, 19);
this._taskData.MultiSelect = false;
@ -312,42 +380,6 @@
this.TaskPC.Name = "TaskPC";
this.TaskPC.ReadOnly = true;
//
// T
//
this.T.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
dataGridViewCellStyle15.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.T.DefaultCellStyle = dataGridViewCellStyle15;
this.T.HeaderText = "T";
this.T.Name = "T";
this.T.ReadOnly = true;
this.T.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.T.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.T.Width = 5;
//
// Addr
//
this.Addr.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
dataGridViewCellStyle16.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Addr.DefaultCellStyle = dataGridViewCellStyle16;
this.Addr.HeaderText = "Addr";
this.Addr.Name = "Addr";
this.Addr.ReadOnly = true;
this.Addr.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Addr.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.Addr.Width = 5;
//
// Source
//
this.Source.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
dataGridViewCellStyle17.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Source.DefaultCellStyle = dataGridViewCellStyle17;
this.Source.HeaderText = "Source Code";
this.Source.Name = "Source";
this.Source.ReadOnly = true;
this.Source.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Source.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
//
// groupBox3
//
this.groupBox3.Controls.Add(this._otherRegs);
@ -362,20 +394,20 @@
//
this._otherRegs.AllowUserToAddRows = false;
this._otherRegs.AllowUserToDeleteRows = false;
dataGridViewCellStyle23.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle23;
dataGridViewCellStyle10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle10;
this._otherRegs.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._otherRegs.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Reg,
this.RegValue});
dataGridViewCellStyle24.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle24.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle24.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle24.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle24.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle24.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle24.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._otherRegs.DefaultCellStyle = dataGridViewCellStyle24;
dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle11.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle11.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle11.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle11.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle11.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._otherRegs.DefaultCellStyle = dataGridViewCellStyle11;
this._otherRegs.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this._otherRegs.Location = new System.Drawing.Point(7, 19);
this._otherRegs.MultiSelect = false;
@ -416,9 +448,9 @@
// groupBox4
//
this.groupBox4.Controls.Add(this._memoryData);
this.groupBox4.Location = new System.Drawing.Point(223, 634);
this.groupBox4.Location = new System.Drawing.Point(319, 634);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(240, 344);
this.groupBox4.Size = new System.Drawing.Size(144, 344);
this.groupBox4.TabIndex = 8;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Memory";
@ -427,22 +459,22 @@
//
this._memoryData.AllowUserToAddRows = false;
this._memoryData.AllowUserToDeleteRows = false;
dataGridViewCellStyle25.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle25;
dataGridViewCellStyle12.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle12;
this._memoryData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._memoryData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Address,
this.Data});
dataGridViewCellStyle26.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle26.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle26.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle26.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle26.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle26.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle26.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._memoryData.DefaultCellStyle = dataGridViewCellStyle26;
dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle13.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle13.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle13.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle13.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle13.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle13.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._memoryData.DefaultCellStyle = dataGridViewCellStyle13;
this._memoryData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this._memoryData.Location = new System.Drawing.Point(7, 19);
this._memoryData.Location = new System.Drawing.Point(6, 19);
this._memoryData.MultiSelect = false;
this._memoryData.Name = "_memoryData";
this._memoryData.ReadOnly = true;
@ -454,7 +486,7 @@
this._memoryData.ShowCellToolTips = false;
this._memoryData.ShowEditingIcon = false;
this._memoryData.ShowRowErrors = false;
this._memoryData.Size = new System.Drawing.Size(227, 319);
this._memoryData.Size = new System.Drawing.Size(132, 319);
this._memoryData.TabIndex = 0;
//
// Address
@ -474,17 +506,116 @@
this.Data.Name = "Data";
this.Data.ReadOnly = true;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(0, 935);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(85, 13);
this.label1.TabIndex = 9;
this.label1.Text = "Execution State:";
//
// ExecutionStateLabel
//
this.ExecutionStateLabel.AutoSize = true;
this.ExecutionStateLabel.Location = new System.Drawing.Point(92, 935);
this.ExecutionStateLabel.Name = "ExecutionStateLabel";
this.ExecutionStateLabel.Size = new System.Drawing.Size(33, 13);
this.ExecutionStateLabel.TabIndex = 10;
this.ExecutionStateLabel.Text = "unset";
//
// JumpToAddress
//
this.JumpToAddress.Location = new System.Drawing.Point(59, 596);
this.JumpToAddress.Name = "JumpToAddress";
this.JumpToAddress.Size = new System.Drawing.Size(48, 20);
this.JumpToAddress.TabIndex = 12;
this.JumpToAddress.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnJumpAddressKeyDown);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(11, 599);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(47, 13);
this.label2.TabIndex = 13;
this.label2.Text = "Jump to:";
//
// groupBox5
//
this.groupBox5.Controls.Add(this._diskData);
this.groupBox5.Location = new System.Drawing.Point(3, 634);
this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(163, 298);
this.groupBox5.TabIndex = 11;
this.groupBox5.TabStop = false;
this.groupBox5.Text = "Disk";
//
// _diskData
//
this._diskData.AllowUserToAddRows = false;
this._diskData.AllowUserToDeleteRows = false;
dataGridViewCellStyle14.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this._diskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle14;
this._diskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._diskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2});
dataGridViewCellStyle15.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle15.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle15.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle15.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle15.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle15.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this._diskData.DefaultCellStyle = dataGridViewCellStyle15;
this._diskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this._diskData.Location = new System.Drawing.Point(6, 19);
this._diskData.MultiSelect = false;
this._diskData.Name = "_diskData";
this._diskData.ReadOnly = true;
this._diskData.RowHeadersVisible = false;
this._diskData.RowTemplate.DefaultCellStyle.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this._diskData.RowTemplate.Height = 18;
this._diskData.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this._diskData.ShowCellErrors = false;
this._diskData.ShowCellToolTips = false;
this._diskData.ShowEditingIcon = false;
this._diskData.ShowRowErrors = false;
this._diskData.Size = new System.Drawing.Size(147, 273);
this._diskData.TabIndex = 1;
//
// dataGridViewTextBoxColumn1
//
this.dataGridViewTextBoxColumn1.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
this.dataGridViewTextBoxColumn1.HeaderText = "Data";
this.dataGridViewTextBoxColumn1.MinimumWidth = 16;
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
this.dataGridViewTextBoxColumn1.ReadOnly = true;
this.dataGridViewTextBoxColumn1.Width = 55;
//
// dataGridViewTextBoxColumn2
//
this.dataGridViewTextBoxColumn2.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.dataGridViewTextBoxColumn2.HeaderText = "Value";
this.dataGridViewTextBoxColumn2.MinimumWidth = 16;
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
this.dataGridViewTextBoxColumn2.ReadOnly = true;
//
// Debugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(753, 997);
this.Controls.Add(this.groupBox5);
this.Controls.Add(this.ExecutionStateLabel);
this.Controls.Add(this.label1);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.StopButton);
this.Controls.Add(this.RunButton);
this.Controls.Add(this.AutoStep);
this.Controls.Add(this.StepButton);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.Microcode);
@ -492,6 +623,7 @@
this.Text = "Debugger";
this.Load += new System.EventHandler(this.Debugger_Load);
this.Microcode.ResumeLayout(false);
this.Microcode.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).EndInit();
this.groupBox1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this._registerData)).EndInit();
@ -501,7 +633,10 @@
((System.ComponentModel.ISupportInitialize)(this._otherRegs)).EndInit();
this.groupBox4.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this._memoryData)).EndInit();
this.groupBox5.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this._diskData)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -511,9 +646,9 @@
private System.Windows.Forms.DataGridView _sourceViewer;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button StepButton;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button AutoStep;
private System.Windows.Forms.Button RunButton;
private System.Windows.Forms.Button StopButton;
private System.Windows.Forms.DataGridView _registerData;
private System.Windows.Forms.DataGridViewTextBoxColumn RegNum;
private System.Windows.Forms.DataGridViewTextBoxColumn R;
@ -523,9 +658,6 @@
private System.Windows.Forms.DataGridViewTextBoxColumn TaskName;
private System.Windows.Forms.DataGridViewTextBoxColumn TaskState;
private System.Windows.Forms.DataGridViewTextBoxColumn TaskPC;
private System.Windows.Forms.DataGridViewTextBoxColumn T;
private System.Windows.Forms.DataGridViewTextBoxColumn Addr;
private System.Windows.Forms.DataGridViewTextBoxColumn Source;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.DataGridView _otherRegs;
private System.Windows.Forms.DataGridViewTextBoxColumn Reg;
@ -534,5 +666,17 @@
private System.Windows.Forms.DataGridView _memoryData;
private System.Windows.Forms.DataGridViewTextBoxColumn Address;
private System.Windows.Forms.DataGridViewTextBoxColumn Data;
private System.Windows.Forms.DataGridViewCheckBoxColumn Breakpoint;
private System.Windows.Forms.DataGridViewTextBoxColumn T;
private System.Windows.Forms.DataGridViewTextBoxColumn Addr;
private System.Windows.Forms.DataGridViewTextBoxColumn Source;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label ExecutionStateLabel;
private System.Windows.Forms.TextBox JumpToAddress;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.GroupBox groupBox5;
private System.Windows.Forms.DataGridView _diskData;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
}
}

View File

@ -9,6 +9,7 @@ using System.Text;
using System.Windows.Forms;
using Contralto.CPU;
using System.Threading;
namespace Contralto
{
@ -17,6 +18,7 @@ namespace Contralto
public Debugger(AltoSystem system)
{
_system = system;
_breakpointEnabled = new bool[1024];
InitializeComponent();
InitControls();
@ -39,6 +41,7 @@ namespace Contralto
SourceLine src = new SourceLine(line);
int i = _sourceViewer.Rows.Add(
false, // breakpoint
GetTextForTask(src.Task),
src.Address,
src.Text);
@ -80,7 +83,7 @@ namespace Contralto
_taskData.Rows[i].Cells[0].Value = GetTextForTask((TaskType)i);
_taskData.Rows[i].Cells[1].Value = GetTextForTaskState(_system.CPU.Tasks[i]);
_taskData.Rows[i].Cells[2].Value =
_system.CPU.Tasks[i] != null ? OctalHelpers.ToOctal(_system.CPU.Tasks[i].MPC, 4) : String.Empty;
_system.CPU.Tasks[i] != null ? OctalHelpers.ToOctal(_system.CPU.Tasks[i].MPC, 4) : String.Empty;
}
// Other registers
@ -93,17 +96,48 @@ namespace Contralto
_otherRegs.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.MD, 6);
_otherRegs.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.Cycle, 2);
// Find the right source line
foreach(DataGridViewRow row in _sourceViewer.Rows)
// Disk info
_diskData.Rows[0].Cells[1].Value = _system.DiskController.ClocksUntilNextSector.ToString("0.00");
_diskData.Rows[1].Cells[1].Value = _system.DiskController.Cylinder.ToString();
_diskData.Rows[2].Cells[1].Value = _system.DiskController.SeekCylinder.ToString();
_diskData.Rows[3].Cells[1].Value = _system.DiskController.Head.ToString();
_diskData.Rows[4].Cells[1].Value = _system.DiskController.Sector.ToString();
_diskData.Rows[5].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KDATA, 6);
_diskData.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KADR, 6);
_diskData.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KCOM, 6);
_diskData.Rows[8].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KSTAT, 6);
_diskData.Rows[9].Cells[1].Value = _system.DiskController.RECNO.ToString();
for (ushort i = 0; i < 1024; i++)
{
if (row.Tag != null &&
(ushort)(row.Tag) == _system.CPU.CurrentTask.MPC)
{
_sourceViewer.ClearSelection();
row.Selected = true;
_sourceViewer.CurrentCell = row.Cells[0];
_memoryData.Rows[i].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6);
}
// Find the right source line
HighlightSourceLine(_system.CPU.CurrentTask.MPC);
// Exec state
switch(_execState)
{
case ExecutionState.Stopped:
ExecutionStateLabel.Text = "Stopped";
break;
case ExecutionState.SingleStep:
ExecutionStateLabel.Text = "Stepping";
break;
case ExecutionState.AutoStep:
ExecutionStateLabel.Text = "Stepping (auto)";
break;
case ExecutionState.Running:
ExecutionStateLabel.Text = "Running";
break;
case ExecutionState.BreakpointStop:
ExecutionStateLabel.Text = "Stopped (bkpt)";
break;
}
}
}
@ -119,11 +153,11 @@ namespace Contralto
_taskData.Rows.Add("0", "0", "0");
}
/*
for (int i=0;i<65536;i++)
for (ushort i=0;i<1024;i++)
{
_memoryData.Rows.Add();
} */
_memoryData.Rows.Add(OctalHelpers.ToOctal(i, 6), OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6));
}
_otherRegs.Rows.Add("L", "0");
_otherRegs.Rows.Add("T", "0");
@ -133,11 +167,61 @@ namespace Contralto
_otherRegs.Rows.Add("MAR", "0");
_otherRegs.Rows.Add("MD", "0");
_otherRegs.Rows.Add("MCycle", "0");
_diskData.Rows.Add("Cycles", "0");
_diskData.Rows.Add("Cylinder", "0");
_diskData.Rows.Add("D.Cylinder", "0");
_diskData.Rows.Add("Head", "0");
_diskData.Rows.Add("Sector", "0");
_diskData.Rows.Add("KDATA", "0");
_diskData.Rows.Add("KADR", "0");
_diskData.Rows.Add("KCOM", "0");
_diskData.Rows.Add("KSTAT", "0");
_diskData.Rows.Add("RECNO", "0");
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
/// <summary>
/// Handle breakpoint placement on column 0.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
{
// Check for breakpoint column click.
if (e.ColumnIndex == 0)
{
// See if this is a source line, if so check/uncheck the box
// and set/unset a breakpoint for the line
if (_sourceViewer.Rows[e.RowIndex].Tag != null)
{
bool value = (bool)_sourceViewer.Rows[e.RowIndex].Cells[0].Value;
_sourceViewer.Rows[e.RowIndex].Cells[0].Value = !value;
ModifyBreakpoint((UInt16)_sourceViewer.Rows[e.RowIndex].Tag, !value);
}
}
}
private void HighlightSourceLine(UInt16 address)
{
foreach (DataGridViewRow row in _sourceViewer.Rows)
{
if (row.Tag != null &&
(ushort)(row.Tag) == address)
{
_sourceViewer.ClearSelection();
row.Selected = true;
_sourceViewer.CurrentCell = row.Cells[0];
break;
}
}
}
private void ModifyBreakpoint(UInt16 address, bool set)
{
_breakpointEnabled[address] = set;
}
private string GetTextForTaskState(AltoCPU.Task task)
@ -148,8 +232,16 @@ namespace Contralto
}
else
{
// TODO: block status
return task.Wakeup ? "W" : String.Empty;
// Wakeup bit
string status = task.Wakeup ? "W" : String.Empty;
// Run bit
if (task == _system.CPU.CurrentTask)
{
status += "R";
}
return status;
}
}
@ -331,17 +423,177 @@ namespace Contralto
}
private void JumpToButton_Click(object sender, EventArgs e)
{
try
{
UInt16 address = Convert.ToUInt16(JumpToAddress.Text, 8);
// find the source address that matches this, if any.
HighlightSourceLine(address);
}
catch
{
// eh, just do nothing for now
}
}
private void OnJumpAddressKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return ||
e.KeyCode == Keys.Enter)
{
try
{
UInt16 address = Convert.ToUInt16(JumpToAddress.Text, 8);
// find the source address that matches this, if any.
HighlightSourceLine(address);
}
catch
{
// eh, just do nothing for now
}
}
}
private void OnStepButtonClicked(object sender, EventArgs e)
{
SetExecutionState(ExecutionState.SingleStep);
ExecuteStep();
SetExecutionState(ExecutionState.Stopped);
}
private void OnAutoStepButtonClicked(object sender, EventArgs e)
{
//
// Continuously step (and update the UI)
// until the "Stop" button is pressed or something bad happens.
//
_execThread = new Thread(new System.Threading.ParameterizedThreadStart(ExecuteProc));
_execThread.Start(ExecutionType.Auto);
SetExecutionState(ExecutionState.AutoStep);
}
private void RunButton_Click(object sender, EventArgs e)
{
//
// Continuously execute, but do not update UI
// until the "Stop" button is pressed or something bad happens.
//
_execThread = new Thread(new System.Threading.ParameterizedThreadStart(ExecuteProc));
_execThread.Start(ExecutionType.Normal);
SetExecutionState(ExecutionState.Running);
}
private void OnStopButtonClicked(object sender, EventArgs e)
{
if (_execThread != null &&
_execThread.IsAlive)
{
// Signal for the exec thread to end
_execAbort = true;
// Wait for the thread to exit.
_execThread.Join();
_execThread = null;
}
SetExecutionState(ExecutionState.Stopped);
}
private void ExecuteStep()
{
_system.SingleStep();
Refresh();
}
private void ExecuteProc(object param)
{
ExecutionType execType = (ExecutionType)param;
StepDelegate refUI = new StepDelegate(RefreshUI);
StepDelegate inv = new StepDelegate(Invalidate);
while (true)
{
if (execType == ExecutionType.Auto)
{
// Execute a single step, then update UI and
// sleep to give messages time to run.
_system.SingleStep();
this.BeginInvoke(refUI);
this.BeginInvoke(inv);
System.Threading.Thread.Sleep(10);
}
else
{
// Just execute one step, do not update UI.
_system.SingleStep();
}
if (_execAbort ||
_breakpointEnabled[_system.CPU.CurrentTask.MPC])
{
// Stop here as we've hit a breakpoint or have been stopped Update UI
// to indicate where we stopped.
this.BeginInvoke(refUI);
this.BeginInvoke(inv);
if (!_execAbort)
{
SetExecutionState(ExecutionState.BreakpointStop);
}
_execAbort = false;
break;
}
}
}
private void SetExecutionState(ExecutionState state)
{
_execState = state;
this.BeginInvoke(new StepDelegate(RefreshUI));
}
private enum ExecutionType
{
None = 0,
Step,
Auto,
Normal,
}
private enum ExecutionState
{
Stopped = 0,
SingleStep,
AutoStep,
Running,
BreakpointStop,
}
private delegate void StepDelegate();
private AltoSystem _system;
// Unicode character for the Arrow used by Alto microcode
private const char _arrowChar = (char)0x2190;
// Thread used for execution other than single-step
private Thread _execThread;
private bool _execAbort;
private ExecutionState _execState;
// Debugger breakpoints; one entry per address since we only need
// to worry about a 10 bit address space, this is fast and uses little memory.
private bool[] _breakpointEnabled;
}
}

View File

@ -117,6 +117,9 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="Breakpoint.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="T.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@ -156,4 +159,10 @@
<metadata name="Data.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -659,7 +659,7 @@ EM00517> INXE: T<-EIOffset, :INXCom; ***X21 addition.
EM00520> INXCom: MAR<-T<-IR<- SAD+T; *** X21 addition.
EM00521> PC<- L, L<- 0+T+1; *** X21 change.
EM00522> INXB: SAD<- L;
EM00522> INXB: SAD<- L; **NB (JDersch 9/14 -- this is actually MD<-PC !)
EM00523> SINK<- DISP, BUS,TASK;
EM00524> SAD<- L, :Q0;

View File

@ -41,7 +41,12 @@ namespace Contralto.IO
{
_kCom = value;
//
// Read control bits (pg. 47 of hw manual)
_xferOff = (_kCom & 0x10) == 0x10;
_wdInhib = (_kCom & 0x08) == 0x08;
_bClkSource = (_kCom & 0x04) == 0x04;
_wffo = (_kCom & 0x02) == 0x02;
_sendAdr = (_kCom & 0x01) == 0x01;
}
}
@ -56,6 +61,36 @@ namespace Contralto.IO
get { return _recMap[_recNo]; }
}
public int Cylinder
{
get { return _cylinder; }
}
public int SeekCylinder
{
get { return _destCylinder; }
}
public int Head
{
get { return _head; }
}
public int Sector
{
get { return _sector; }
}
public int Drive
{
get { return 0; }
}
public double ClocksUntilNextSector
{
get { return _sectorClocks - _elapsedSectorTime; }
}
public void Reset()
{
ClearStatus();
@ -100,7 +135,7 @@ namespace Contralto.IO
{
_cylinder++;
}
else
else if (_cylinder > _destCylinder)
{
_cylinder--;
}
@ -113,6 +148,33 @@ namespace Contralto.IO
}
}
}
//
// Select data word based on elapsed time in this sector, if data transfer is not inhibited.
// On a new word, wake up the disk word task if not inhibited
// TODO: the exact mechanics of this are still kind of mysterious.
// Things to examine the schematics / uCode for:
// - Use of WFFO bit -- is this related to the "sync word" that the docs mention?
// - how does WFFO work -- I assume the "1 bit" mentioned in the docs indicates the MFM bit
// and indicates the start of the next data word (or is at least used to wait for the next
// data word)
// - How does the delaying work
// The microcode word-copying code works basically as:
// On wakeup:
// - read word, store into memory.
// - block task (remove wakeup)
// - task switch (let something else run)
// - repeat until all words read
// that is, the microcode expects to be woken up on a per-word basis, and it only reads in one word
// per wakeup.
//
// pseudocode so far:
// if (elapsed word time > word time)
// {
// elapsed word time = 0 (modulo remainder)
// _kData = next word
// if (!_wdInhib) DiskSectorTask.Wakeup();
// }
}
public void ClearStatus()
@ -148,16 +210,16 @@ namespace Contralto.IO
// sanity check: see if SENDADR bit is set, if not we'll signal an error (since I'm trusting that
// the official Xerox uCode is doing the right thing, this will help ferret out emulation issues.
// eventually this can be removed.)
if ((_kCom & 0x1) != 1)
if (!_sendAdr)
{
throw new InvalidOperationException("STROBE while SENDADR bit of KCOMM not 1. Unexpected.");
throw new InvalidOperationException("STROBE while SENDADR bit of KCOM not 1. Unexpected.");
}
_destCylinder = (_kData & 0x0ff8) >> 3;
// set "seek fail" bit based on selected cylinder (if out of bounds) and do not
// commence a seek if so.
if (_destCylinder < 203)
if (_destCylinder > 202)
{
_kStat |= 0x0080;
}
@ -202,6 +264,13 @@ namespace Contralto.IO
0, 2, 3, 1
};
// KCOM bits
private bool _xferOff;
private bool _wdInhib;
private bool _bClkSource;
private bool _wffo;
private bool _sendAdr;
// Current disk position
private int _cylinder;
private int _destCylinder;

View File

@ -73,6 +73,15 @@ namespace Contralto.Memory
get { return _memoryOperationActive; }
}
/// <summary>
/// Used for debugging only -- returns the (correctly mapped)
/// word at the specified address
/// </summary>
public ushort DebugReadWord(ushort address)
{
return ReadFromBus(address);
}
public void Clock()
{
_memoryCycle++;