mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-19 01:18:00 +00:00
Fix for soft-reset emulator uPC and device reset; CopyDisk now executes correctly.
This commit is contained in:
parent
8361f287e3
commit
30ed445764
@ -1,5 +1,7 @@
|
||||
using System.Timers;
|
||||
|
||||
using Contralto.Logging;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
public enum TaskType
|
||||
@ -145,22 +147,30 @@ namespace Contralto.CPU
|
||||
/// </summary>
|
||||
public void SoftReset()
|
||||
{
|
||||
// Reset tasks.
|
||||
// Soft-Reset tasks.
|
||||
for (int i = 0; i < _tasks.Length; i++)
|
||||
{
|
||||
if (_tasks[i] != null)
|
||||
{
|
||||
_tasks[i].Reset();
|
||||
_tasks[i].SoftReset();
|
||||
}
|
||||
}
|
||||
|
||||
UCodeMemory.LoadBanksFromRMR(_rmr);
|
||||
_rmr = 0xffff; // Reset RMR (all tasks start in ROM0)
|
||||
|
||||
// Start in Emulator
|
||||
_currentTask = _tasks[0];
|
||||
|
||||
// Execute the initial task switch.
|
||||
TaskSwitch();
|
||||
|
||||
_currentTask = _nextTask;
|
||||
_nextTask = null;
|
||||
//
|
||||
// TODO:
|
||||
// This is a hack of sorts, it ensures that the sector task initializes
|
||||
// itself as soon as the Emulator task yields after the reset. (CopyDisk is broken otherwise due to the
|
||||
// sector task stomping over the KBLK CopyDisk sets up after the reset. This is a race of sorts.)
|
||||
// Unsure if there is a deeper issue here or if there are other reset semantics
|
||||
// in play here.
|
||||
//
|
||||
WakeupTask(CPU.TaskType.DiskSector);
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr));
|
||||
}
|
||||
@ -173,7 +183,8 @@ namespace Contralto.CPU
|
||||
public void WakeupTask(TaskType task)
|
||||
{
|
||||
if (_tasks[(int)task] != null)
|
||||
{
|
||||
{
|
||||
Log.Write(LogComponent.TaskSwitch, "Wakeup enabled for Task {0}", task);
|
||||
_tasks[(int)task].WakeupTask();
|
||||
}
|
||||
}
|
||||
@ -186,7 +197,8 @@ namespace Contralto.CPU
|
||||
public void BlockTask(TaskType task)
|
||||
{
|
||||
if (_tasks[(int)task] != null)
|
||||
{
|
||||
{
|
||||
Log.Write(LogComponent.TaskSwitch, "Removed wakeup for Task {0}", task);
|
||||
_tasks[(int)task].BlockTask();
|
||||
}
|
||||
}
|
||||
@ -218,8 +230,15 @@ namespace Contralto.CPU
|
||||
for (int i = _tasks.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (_tasks[i] != null && _tasks[i].Wakeup)
|
||||
{
|
||||
{
|
||||
_nextTask = _tasks[i];
|
||||
|
||||
if (_nextTask != _currentTask && _currentTask != null)
|
||||
{
|
||||
Log.Write(LogComponent.TaskSwitch, "TASK: Next task will be {0} (pri {1}); current task {2} (pri {3})",
|
||||
(TaskType)_nextTask.Priority, _nextTask.Priority,
|
||||
(TaskType)_currentTask.Priority, _currentTask.Priority);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Contralto.IO;
|
||||
using Contralto.Logging;
|
||||
using System;
|
||||
|
||||
namespace Contralto.CPU
|
||||
@ -22,6 +23,8 @@ namespace Contralto.CPU
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// Log.Write(LogComponent.Debug, "{0}: {1}", Conversion.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType));
|
||||
|
||||
bool task = base.ExecuteInstruction(instruction);
|
||||
|
||||
// Deal with SECLATE semantics: If the Disk Sector task wakes up and runs before
|
||||
@ -32,13 +35,7 @@ namespace Contralto.CPU
|
||||
{
|
||||
// Sector task is running; clear enable for seclate signal
|
||||
_diskController.DisableSeclate();
|
||||
}
|
||||
|
||||
/*
|
||||
if (_taskType == TaskType.DiskWord)
|
||||
{
|
||||
_wakeup = false;
|
||||
} */
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
@ -170,32 +167,32 @@ namespace Contralto.CPU
|
||||
// "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)"
|
||||
_nextModifier |= GetInitModifier(instruction);
|
||||
|
||||
if (true) //!_diskController.FatalError)
|
||||
if (!_diskController.FatalError)
|
||||
{
|
||||
_nextModifier |= 0x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("fatal disk error");
|
||||
Console.WriteLine("fatal disk error on disk {0}", _diskController.Drive);
|
||||
}
|
||||
break;
|
||||
|
||||
case DiskF2.STROBON:
|
||||
// "NEXT <- NEXT OR (IF seek strobe still on THEN 1 ELSE 0)"
|
||||
_nextModifier |= GetInitModifier(instruction);
|
||||
if ((_diskController.KSTAT & 0x0040) == 0x0040)
|
||||
if ((_diskController.KSTAT & DiskController.STROBE) != 0)
|
||||
{
|
||||
_nextModifier |= 0x1;
|
||||
}
|
||||
break;
|
||||
|
||||
case DiskF2.SWRNRDY:
|
||||
// "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
|
||||
// for now, always zero (not sure when this would be 1 yet)
|
||||
// "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
|
||||
_nextModifier |= GetInitModifier(instruction);
|
||||
if (!_diskController.Ready)
|
||||
{
|
||||
_nextModifier |= 1;
|
||||
Console.WriteLine("disk {0} not ready", _diskController.Drive);
|
||||
_nextModifier |= 0x1;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -105,6 +105,11 @@ namespace Contralto.CPU
|
||||
// BOOT (soft-reset) operation.
|
||||
// Reset the CPU using the current RMR (start tasks in RAM or ROM as specified.)
|
||||
_cpu.SoftReset();
|
||||
|
||||
// Since this is a soft reset, we don't want MPC to be taken from the NEXT
|
||||
// field at the end of the cycle, setting this flag causes the main Task
|
||||
// implementation to skip updating _mpc at the end of this instruction.
|
||||
_softReset = true;
|
||||
}
|
||||
else if(_busData != 0)
|
||||
{
|
||||
@ -139,11 +144,17 @@ namespace Contralto.CPU
|
||||
break;
|
||||
|
||||
case EmulatorF1.LoadESRB:
|
||||
// For now, this is always 0; we do not yet support the 3K RAM system with 8 banks of S registers.
|
||||
_rb = 0;
|
||||
Logging.Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "ESRB<- ({0}) not fully implemented.",
|
||||
Conversion.ToOctal((_busData & 0xe) >> 1));
|
||||
//_rb = (ushort)((_busData & 0xe) >> 1);
|
||||
// For now, this is always 0; we do not yet support the 3K RAM system with 8 banks of S registers.
|
||||
_rb = (ushort)((_busData & 0xe) >> 1);
|
||||
|
||||
if (_rb != 0)
|
||||
{
|
||||
_rb = 0;
|
||||
Logging.Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "ESRB<- ({0}) not fully implemented.",
|
||||
Conversion.ToOctal((_busData & 0xe) >> 1));
|
||||
|
||||
throw new NotImplementedException("ESRB<-");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -56,6 +56,14 @@ namespace Contralto.CPU
|
||||
_rb = 0;
|
||||
}
|
||||
|
||||
public virtual void SoftReset()
|
||||
{
|
||||
//
|
||||
// As above but we leave all other state alone.
|
||||
//
|
||||
_mpc = (ushort)_taskType;
|
||||
}
|
||||
|
||||
public virtual void BlockTask()
|
||||
{
|
||||
_wakeup = false;
|
||||
@ -98,6 +106,7 @@ namespace Contralto.CPU
|
||||
_rSelect = 0;
|
||||
_srSelect = 0;
|
||||
_busData = 0;
|
||||
_softReset = false;
|
||||
|
||||
|
||||
Shifter.SetMagic(false);
|
||||
@ -414,9 +423,8 @@ namespace Contralto.CPU
|
||||
// this depends on the value of the NEXT field in this instruction
|
||||
//
|
||||
if (swMode)
|
||||
{
|
||||
//Console.WriteLine("SWMODE NEXT {0} Modifier {1}", Conversion.ToOctal(instruction.NEXT), Conversion.ToOctal(nextModifier));
|
||||
UCodeMemory.SwitchMode((ushort)(instruction.NEXT), _taskType);
|
||||
{
|
||||
UCodeMemory.SwitchMode(instruction.NEXT, _taskType);
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1}", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier));
|
||||
}
|
||||
|
||||
@ -430,8 +438,12 @@ namespace Contralto.CPU
|
||||
|
||||
//
|
||||
// Select next address, using the address modifier from the last instruction.
|
||||
// (Unless a soft reset occurred during this instruction)
|
||||
//
|
||||
_mpc = (ushort)(instruction.NEXT | nextModifier);
|
||||
if (!_softReset)
|
||||
{
|
||||
_mpc = (ushort)(instruction.NEXT | nextModifier);
|
||||
}
|
||||
|
||||
return nextTask;
|
||||
}
|
||||
@ -486,15 +498,16 @@ namespace Contralto.CPU
|
||||
//
|
||||
// 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 uint _srSelect; // RSELECT field as used by S register access (not modified in the same way as normal _rSelect).
|
||||
protected bool _loadS; // Whether to load S from M at and of cycle
|
||||
protected bool _loadR; // Whether to load R from shifter at end of cycle.
|
||||
protected bool _rdRam; // Whether to load uCode RAM onto the bus during the next cycle.
|
||||
protected bool _wrtRam; // Whether to write uCode RAM from M and ALU outputs during the next cycle.
|
||||
protected bool _swMode; // Whether to switch uCode banks during the next cycle.
|
||||
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 uint _srSelect; // RSELECT field as used by S register access (not modified in the same way as normal _rSelect).
|
||||
protected bool _loadS; // Whether to load S from M at and of cycle
|
||||
protected bool _loadR; // Whether to load R from shifter at end of cycle.
|
||||
protected bool _rdRam; // Whether to load uCode RAM onto the bus during the next cycle.
|
||||
protected bool _wrtRam; // Whether to write uCode RAM from M and ALU outputs during the next cycle.
|
||||
protected bool _swMode; // Whether to switch uCode banks during the next cycle.
|
||||
protected bool _softReset; // Whether this instruction caused a soft reset (so MPC should not come from instruction's NEXT field)
|
||||
|
||||
|
||||
//
|
||||
|
||||
@ -72,7 +72,7 @@ namespace Contralto.CPU
|
||||
public static void LoadBanksFromRMR(ushort rmr)
|
||||
{
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
{
|
||||
_microcodeBank[i] = (rmr & (1 << i)) == 0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Disk\st76boot.dsk">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Disk\tdisk4.dsk">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
53
Contralto/Debugger.Designer.cs
generated
53
Contralto/Debugger.Designer.cs
generated
@ -97,6 +97,8 @@
|
||||
this.Reg = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.RegValue = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||
this.MemoryJumpToAddress = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this._memoryData = new System.Windows.Forms.DataGridView();
|
||||
this.Bkpt = new System.Windows.Forms.DataGridViewCheckBoxColumn();
|
||||
this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
@ -116,8 +118,7 @@
|
||||
this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.MemoryJumpToAddress = new System.Windows.Forms.TextBox();
|
||||
this.HackButton = new System.Windows.Forms.Button();
|
||||
this.Microcode.SuspendLayout();
|
||||
this.SourceTabs.SuspendLayout();
|
||||
this.Rom0Page.SuspendLayout();
|
||||
@ -270,7 +271,7 @@
|
||||
this.Rom1Page.Location = new System.Drawing.Point(4, 22);
|
||||
this.Rom1Page.Name = "Rom1Page";
|
||||
this.Rom1Page.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.Rom1Page.Size = new System.Drawing.Size(582, 545);
|
||||
this.Rom1Page.Size = new System.Drawing.Size(582, 554);
|
||||
this.Rom1Page.TabIndex = 1;
|
||||
this.Rom1Page.Text = "ROM1";
|
||||
this.Rom1Page.UseVisualStyleBackColor = true;
|
||||
@ -369,7 +370,7 @@
|
||||
this.Rom2Page.Location = new System.Drawing.Point(4, 22);
|
||||
this.Rom2Page.Name = "Rom2Page";
|
||||
this.Rom2Page.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.Rom2Page.Size = new System.Drawing.Size(582, 545);
|
||||
this.Rom2Page.Size = new System.Drawing.Size(582, 554);
|
||||
this.Rom2Page.TabIndex = 2;
|
||||
this.Rom2Page.Text = "RAM0";
|
||||
this.Rom2Page.UseVisualStyleBackColor = true;
|
||||
@ -750,6 +751,24 @@
|
||||
this.groupBox4.TabStop = false;
|
||||
this.groupBox4.Text = "Memory";
|
||||
//
|
||||
// MemoryJumpToAddress
|
||||
//
|
||||
this.MemoryJumpToAddress.Location = new System.Drawing.Point(53, 276);
|
||||
this.MemoryJumpToAddress.Name = "MemoryJumpToAddress";
|
||||
this.MemoryJumpToAddress.Size = new System.Drawing.Size(48, 20);
|
||||
this.MemoryJumpToAddress.TabIndex = 15;
|
||||
this.MemoryJumpToAddress.TabStop = false;
|
||||
this.MemoryJumpToAddress.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnMemoryJumpAddressKeyDown);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 279);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(47, 13);
|
||||
this.label3.TabIndex = 14;
|
||||
this.label3.Text = "Jump to:";
|
||||
//
|
||||
// _memoryData
|
||||
//
|
||||
this._memoryData.AllowUserToAddRows = false;
|
||||
@ -1026,29 +1045,22 @@
|
||||
this.dataGridViewTextBoxColumn11.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.dataGridViewTextBoxColumn11.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// label3
|
||||
// HackButton
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 279);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(47, 13);
|
||||
this.label3.TabIndex = 14;
|
||||
this.label3.Text = "Jump to:";
|
||||
//
|
||||
// MemoryJumpToAddress
|
||||
//
|
||||
this.MemoryJumpToAddress.Location = new System.Drawing.Point(53, 276);
|
||||
this.MemoryJumpToAddress.Name = "MemoryJumpToAddress";
|
||||
this.MemoryJumpToAddress.Size = new System.Drawing.Size(48, 20);
|
||||
this.MemoryJumpToAddress.TabIndex = 15;
|
||||
this.MemoryJumpToAddress.TabStop = false;
|
||||
this.MemoryJumpToAddress.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnMemoryJumpAddressKeyDown);
|
||||
this.HackButton.Location = new System.Drawing.Point(295, 955);
|
||||
this.HackButton.Name = "HackButton";
|
||||
this.HackButton.Size = new System.Drawing.Size(36, 23);
|
||||
this.HackButton.TabIndex = 15;
|
||||
this.HackButton.Text = "hack";
|
||||
this.HackButton.UseVisualStyleBackColor = true;
|
||||
this.HackButton.Click += new System.EventHandler(this.HackButton_Click);
|
||||
//
|
||||
// Debugger
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(949, 997);
|
||||
this.Controls.Add(this.HackButton);
|
||||
this.Controls.Add(this.groupBox6);
|
||||
this.Controls.Add(this.NovaStep);
|
||||
this.Controls.Add(this.RunToNextTaskButton);
|
||||
@ -1165,5 +1177,6 @@
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11;
|
||||
private System.Windows.Forms.TextBox MemoryJumpToAddress;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Button HackButton;
|
||||
}
|
||||
}
|
||||
@ -919,6 +919,10 @@ namespace Contralto
|
||||
// Nova Debugger breakpoints; same as above
|
||||
private bool[] _novaBreakpointEnabled;
|
||||
|
||||
|
||||
private void HackButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Logging.Log.LogComponents |= Logging.LogComponent.TaskSwitch;
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -110,9 +110,7 @@ namespace Contralto.IO
|
||||
// Select disk if _sendAdr is true
|
||||
_disk = (_kAdr & 0x1);
|
||||
_seeking = false;
|
||||
|
||||
/*
|
||||
|
||||
|
||||
// Clear the NOTREADY flag depending on whether the drive is loaded or not
|
||||
if (_drives[_disk].IsLoaded)
|
||||
{
|
||||
@ -121,7 +119,7 @@ namespace Contralto.IO
|
||||
else
|
||||
{
|
||||
_kStat |= NOTREADY;
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -182,7 +180,7 @@ namespace Contralto.IO
|
||||
|
||||
public int Drive
|
||||
{
|
||||
get { return 0; }
|
||||
get { return _disk; }
|
||||
}
|
||||
|
||||
public double ClocksUntilNextSector
|
||||
@ -198,7 +196,7 @@ namespace Contralto.IO
|
||||
// This is true if the drive is:
|
||||
// - powered on, loaded with a disk, spun up
|
||||
// - not actively seeking
|
||||
return _drives[0].IsLoaded;
|
||||
return _drives[_disk].IsLoaded && !_seeking;
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +251,7 @@ namespace Contralto.IO
|
||||
_drives[0].Reset();
|
||||
_drives[1].Reset();
|
||||
|
||||
// Create events to be reused during execution
|
||||
// Create events to be reused during execution
|
||||
|
||||
// Schedule the first sector immediately.
|
||||
_sectorEvent = new Event(0, null, SectorCallback);
|
||||
@ -278,7 +276,7 @@ namespace Contralto.IO
|
||||
//
|
||||
// Next sector; move to next sector and wake up Disk Sector task.
|
||||
//
|
||||
_sector = (_sector + 1) % 12;
|
||||
_sector = (_sector + 1) % 12;
|
||||
|
||||
_kStat = (ushort)((_kStat & 0x0fff) | (_sector << 12));
|
||||
|
||||
@ -295,6 +293,8 @@ namespace Contralto.IO
|
||||
if ((_kStat & STROBE) == 0)
|
||||
{
|
||||
Log.Write(LogType.Verbose, LogComponent.DiskController, "Waking up sector task for C/H/S {0}/{1}/{2}", SelectedDrive.Cylinder, SelectedDrive.Head, _sector);
|
||||
Log.Write(LogType.Verbose, LogComponent.DiskController, "KADR is {0}", Conversion.ToOctal(_kAdr));
|
||||
Log.Write(LogType.Verbose, LogComponent.DiskController, "KDATA is {0}", Conversion.ToOctal(_kDataWrite));
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
|
||||
|
||||
// Reset SECLATE
|
||||
@ -403,7 +403,7 @@ namespace Contralto.IO
|
||||
Log.Write(LogComponent.DiskController, "Seek failed, specified cylinder {0} is out of range.", destCylinder);
|
||||
_seeking = false;
|
||||
}
|
||||
else
|
||||
else if (destCylinder != SelectedDrive.Cylinder)
|
||||
{
|
||||
// Otherwise, start a seek.
|
||||
_destCylinder = destCylinder;
|
||||
@ -423,6 +423,12 @@ namespace Contralto.IO
|
||||
|
||||
Log.Write(LogComponent.DiskController, "Seek to {0} from {1} commencing. Will take {2} nsec.", _destCylinder, SelectedDrive.Cylinder, _seekDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear the fail bit.
|
||||
_kStat &= (ushort)~SEEKFAIL;
|
||||
Log.Write(LogComponent.DiskController, "Seek is a no op ({0} to {1}).", destCylinder, SelectedDrive.Cylinder);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -685,7 +691,7 @@ namespace Contralto.IO
|
||||
|
||||
// SECLATE data.
|
||||
// 8.5uS for seclate delay (approx. 50 clocks)
|
||||
private static ulong _seclateDuration = (ulong)(85.0 * Conversion.UsecToNsec * _scale);
|
||||
private static ulong _seclateDuration = (ulong)(20.0 * Conversion.UsecToNsec * _scale);
|
||||
private bool _seclateEnable;
|
||||
private bool _seclate;
|
||||
private Event _seclateEvent;
|
||||
@ -698,10 +704,10 @@ namespace Contralto.IO
|
||||
private bool _debugRead;
|
||||
|
||||
// KSTAT bitfields
|
||||
private readonly ushort SECLATE = 0x10;
|
||||
private readonly ushort NOTREADY = 0x20;
|
||||
private readonly ushort STROBE = 0x40;
|
||||
private readonly ushort SEEKFAIL = 0x80;
|
||||
public static readonly ushort SECLATE = 0x10;
|
||||
public static readonly ushort NOTREADY = 0x20;
|
||||
public static readonly ushort STROBE = 0x40;
|
||||
public static readonly ushort SEEKFAIL = 0x80;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using System;
|
||||
#define LOGGING_ENABLED
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Contralto.Logging
|
||||
{
|
||||
@ -21,8 +24,10 @@ namespace Contralto.Logging
|
||||
CPU = 0x200,
|
||||
EthernetController = 0x400,
|
||||
EthernetTask = 0x800,
|
||||
TaskSwitch = 0x1000,
|
||||
|
||||
All = 0x7fffffff
|
||||
Debug = 0x40000000,
|
||||
All = 0x7fffffff
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -47,10 +52,19 @@ namespace Contralto.Logging
|
||||
static Log()
|
||||
{
|
||||
// TODO: make configurable
|
||||
_components = LogComponent.None; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
|
||||
_type = LogType.Normal | LogType.Warning | LogType.Error;
|
||||
_components = LogComponent.CPU; // LogComponent.DiskController | LogComponent.DiskSectorTask | LogComponent.Debug | LogComponent.CPU; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
|
||||
_type = LogType.Normal | LogType.Warning | LogType.Error | LogType.Verbose;
|
||||
|
||||
_logStream = new StreamWriter("log.txt");
|
||||
}
|
||||
|
||||
public static LogComponent LogComponents
|
||||
{
|
||||
get { return _components; }
|
||||
set { _components = value; }
|
||||
}
|
||||
|
||||
#if LOGGING_ENABLED
|
||||
/// <summary>
|
||||
/// Logs a message without specifying type/severity for terseness;
|
||||
/// will not log if Type has been set to None.
|
||||
@ -72,10 +86,28 @@ namespace Contralto.Logging
|
||||
// My log has something to tell you...
|
||||
// TODO: color based on type, etc.
|
||||
Console.WriteLine(component.ToString() + ": " + message, args);
|
||||
|
||||
if (_logStream != null)
|
||||
{
|
||||
_logStream.WriteLine(component.ToString() + ": " + message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
public static void Write(LogComponent component, string message, params object[] args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void Write(LogType type, LogComponent component, string message, params object[] args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private static LogComponent _components;
|
||||
private static LogType _type;
|
||||
private static StreamWriter _logStream;
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ namespace Contralto.Memory
|
||||
_memoryAddress = address;
|
||||
_extendedMemoryReference = extendedMemoryReference;
|
||||
_task = task;
|
||||
_memoryCycle = 1;
|
||||
_memoryCycle = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +190,13 @@ namespace Contralto.Memory
|
||||
case 5:
|
||||
// Single word read
|
||||
//Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (cycle 5)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress ^ 1));
|
||||
|
||||
// debug
|
||||
/*
|
||||
if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData);
|
||||
} */
|
||||
return _memoryData;
|
||||
|
||||
// ***
|
||||
@ -212,11 +219,23 @@ namespace Contralto.Memory
|
||||
|
||||
//Log.Write(LogType.Verbose, LogComponent.Memory, "Double-word read of {0} from {1} (cycle 6)", Conversion.ToOctal(_memoryData2), Conversion.ToOctal(_memoryAddress ^ 1));
|
||||
_doubleWordMixed = false;
|
||||
// debug
|
||||
/*
|
||||
if ((_memoryAddress ^ 1) == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData2);
|
||||
} */
|
||||
return _memoryData2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_doubleWordMixed = false;
|
||||
// debug
|
||||
/*
|
||||
if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData);
|
||||
} */
|
||||
//Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (post cycle 6)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress));
|
||||
return _memoryData;
|
||||
}
|
||||
@ -236,12 +255,21 @@ namespace Contralto.Memory
|
||||
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD during incorrect memory cycle.");
|
||||
|
||||
case 3:
|
||||
|
||||
// debug
|
||||
if (_memoryAddress == 0xfc90 || _memoryAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "++> Task {0} wrote {1} to {3} (was {2}).", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, _memoryAddress)), Conversion.ToOctal(_memoryAddress));
|
||||
}
|
||||
|
||||
_memoryData = data; // Only really necessary to show in debugger
|
||||
// Start of doubleword write:
|
||||
WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference);
|
||||
_doubleWordStore = true;
|
||||
_doubleWordMixed = true;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Log.Write(
|
||||
LogType.Verbose,
|
||||
@ -262,7 +290,22 @@ namespace Contralto.Memory
|
||||
Conversion.ToOctal(data),
|
||||
_doubleWordStore ? Conversion.ToOctal(_memoryAddress ^ 1) : Conversion.ToOctal(_memoryAddress));
|
||||
*/
|
||||
WriteToBus(_doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress, data, _task, _extendedMemoryReference);
|
||||
// debug
|
||||
ushort actualAddress = _doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress;
|
||||
|
||||
/*
|
||||
if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} wrote {1} to {4} (was {2}). Extd {3}", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, actualAddress)), _extendedMemoryReference, Conversion.ToOctal(actualAddress));
|
||||
} */
|
||||
|
||||
WriteToBus(actualAddress, data, _task, _extendedMemoryReference);
|
||||
|
||||
/*
|
||||
if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "--> Now {0}.", Conversion.ToOctal(DebugReadWord(_task, actualAddress)));
|
||||
} */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user