mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-23 02:47:48 +00:00
Fixed two microcode bugs related to task switching behavior. Dance, StarWars and *SMALLTALK* work!
This commit is contained in:
parent
b6e43080f2
commit
4cbb74c033
@ -47,7 +47,7 @@ namespace Contralto
|
||||
t.AutoReset = true;
|
||||
t.Interval = 1000;
|
||||
t.Elapsed += T_Elapsed;
|
||||
//t.Start();
|
||||
t.Start();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
|
||||
@ -121,18 +121,28 @@ namespace Contralto.CPU
|
||||
|
||||
public void Clock()
|
||||
{
|
||||
if (_currentTask.ExecuteNext())
|
||||
switch (_currentTask.ExecuteNext())
|
||||
{
|
||||
// Invoke the task switch, this will take effect after
|
||||
// the NEXT instruction, not this one.
|
||||
TaskSwitch();
|
||||
case InstructionCompletion.TaskSwitch:
|
||||
// Invoke the task switch, this will take effect after
|
||||
// the NEXT instruction completes, not this one.
|
||||
TaskSwitch();
|
||||
break;
|
||||
|
||||
case InstructionCompletion.Normal:
|
||||
if (_nextTask != null)
|
||||
{
|
||||
// If we have a new task, switch to it now.
|
||||
_currentTask = _nextTask;
|
||||
_nextTask = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionCompletion.MemoryWait:
|
||||
// We were waiting for memory on this cycle, we do nothing
|
||||
// (no task switch even if one is pending) in this case.
|
||||
break;
|
||||
}
|
||||
else if (_nextTask != null)
|
||||
{
|
||||
// If we have a new task, switch to it now.
|
||||
_currentTask = _nextTask;
|
||||
_nextTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Contralto.CPU
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// We put ourselves back to sleep immediately once we've started running
|
||||
_wakeup = false;
|
||||
|
||||
@ -21,11 +21,11 @@ namespace Contralto.CPU
|
||||
_diskController = _cpu._system.DiskController;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// Log.Write(LogComponent.Debug, "{0}: {1}", Conversion.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType));
|
||||
|
||||
bool task = base.ExecuteInstruction(instruction);
|
||||
InstructionCompletion completion = base.ExecuteInstruction(instruction);
|
||||
|
||||
// Deal with SECLATE semantics: If the Disk Sector task wakes up and runs before
|
||||
// the Disk Controller hits the SECLATE trigger time, then SECLATE remains false.
|
||||
@ -37,7 +37,7 @@ namespace Contralto.CPU
|
||||
_diskController.DisableSeclate();
|
||||
}
|
||||
|
||||
return task;
|
||||
return completion;
|
||||
}
|
||||
|
||||
protected override ushort GetBusSource(int bs)
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Contralto.CPU
|
||||
_displayController = _cpu._system.DisplayController;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// We put ourselves back to sleep immediately once we've started running
|
||||
_wakeup = false;
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Contralto.CPU
|
||||
_displayController = _cpu._system.DisplayController;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// We put ourselves back to sleep immediately once we've started running
|
||||
_wakeup = false;
|
||||
|
||||
@ -19,7 +19,7 @@ namespace Contralto.CPU
|
||||
_displayController = _cpu._system.DisplayController;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// We remove our wakeup only if there isn't a wakeup being generated for us by the
|
||||
// display controller.
|
||||
|
||||
@ -19,7 +19,7 @@ namespace Contralto.CPU
|
||||
_ethernetController = _cpu._system.EthernetController;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
// The Ethernet task only remains awake if there are pending data wakeups
|
||||
if (_ethernetController.CountdownWakeup)
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
protected override bool ExecuteInstruction(MicroInstruction instruction)
|
||||
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
//
|
||||
// Based on readings of the MRT microcode, the MRT keeps its wakeup
|
||||
|
||||
@ -7,6 +7,13 @@ namespace Contralto.CPU
|
||||
{
|
||||
public partial class AltoCPU
|
||||
{
|
||||
public enum InstructionCompletion
|
||||
{
|
||||
Normal,
|
||||
TaskSwitch,
|
||||
MemoryWait,
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -92,7 +99,7 @@ namespace Contralto.CPU
|
||||
_wakeup = true;
|
||||
}
|
||||
|
||||
public bool ExecuteNext()
|
||||
public InstructionCompletion ExecuteNext()
|
||||
{
|
||||
MicroInstruction instruction = UCodeMemory.GetInstruction(_mpc, _taskType);
|
||||
|
||||
@ -108,9 +115,9 @@ namespace Contralto.CPU
|
||||
/// 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)
|
||||
protected virtual InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
bool nextTask = false;
|
||||
InstructionCompletion completion = InstructionCompletion.Normal;
|
||||
bool swMode = false;
|
||||
bool block = false;
|
||||
ushort aluData;
|
||||
@ -135,7 +142,7 @@ namespace Contralto.CPU
|
||||
if (!_cpu._system.MemoryBus.Ready(instruction.MemoryOperation))
|
||||
{
|
||||
// Suspend operation for this cycle.
|
||||
return false;
|
||||
return InstructionCompletion.MemoryWait;
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +297,8 @@ namespace Contralto.CPU
|
||||
//
|
||||
//if (!_firstInstructionAfterSwitch)
|
||||
{
|
||||
nextTask = true; // Yield to other more important tasks
|
||||
// Yield to other more important tasks
|
||||
completion = InstructionCompletion.TaskSwitch;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -430,7 +438,12 @@ namespace Contralto.CPU
|
||||
if (instruction.LoadL)
|
||||
{
|
||||
_cpu._l = aluData;
|
||||
_cpu._m = aluData;
|
||||
|
||||
// Only RAM-related tasks can modify M. (Currently only the Emulator.)
|
||||
if (_taskType == TaskType.Emulator)
|
||||
{
|
||||
_cpu._m = aluData;
|
||||
}
|
||||
|
||||
// Save ALUC0 for use in the next ALUCY special function.
|
||||
_cpu._aluC0 = (ushort)ALU.Carry;
|
||||
@ -470,7 +483,7 @@ namespace Contralto.CPU
|
||||
}
|
||||
|
||||
_firstInstructionAfterSwitch = false;
|
||||
return nextTask;
|
||||
return completion;
|
||||
}
|
||||
|
||||
protected virtual ushort GetBusSource(int bs)
|
||||
|
||||
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.
@ -609,7 +609,8 @@ namespace Contralto.IO
|
||||
// From the Hardware Manual, pg 43:
|
||||
// "Seek time (approx.): 15 + 8.6 * sqrt(dt) (msec)
|
||||
//
|
||||
double seekTimeMsec = 15.0 + 8.6 * Math.Sqrt(dt);
|
||||
//double seekTimeMsec = 15.0 + 8.6 * Math.Sqrt(dt);
|
||||
double seekTimeMsec = 1.0; // why not just have this be fast for now.
|
||||
|
||||
return (ulong)(seekTimeMsec * Conversion.MsecToNsec);
|
||||
}
|
||||
|
||||
@ -808,6 +808,7 @@ namespace Contralto
|
||||
case ExecutionType.NextNovaInstruction:
|
||||
|
||||
// For debugging floating point microcode:
|
||||
#if FLOAT_DEBUG
|
||||
if (_system.CPU.CurrentTask.MPC == 0x10) // MPC is 20(octal) meaning a new Nova instruction.
|
||||
{
|
||||
if (_lastFPInstruction == 0)
|
||||
@ -823,7 +824,8 @@ namespace Contralto
|
||||
// And see if this new one is also a floating point instruction...
|
||||
FloatDebugPre(_system.MemoryBus.DebugReadWord(TaskType.Emulator, _system.CPU.R[6]));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// See if we need to stop here
|
||||
if (_execAbort || // The Stop button was hit
|
||||
@ -855,6 +857,7 @@ namespace Contralto
|
||||
return false;
|
||||
}
|
||||
|
||||
#if FLOAT_DEBUG
|
||||
// vars for float debug
|
||||
ushort _lastFPInstruction;
|
||||
ushort _ac0;
|
||||
@ -864,6 +867,8 @@ namespace Contralto
|
||||
ushort _fpRegAddr;
|
||||
ushort _fpRegCount;
|
||||
|
||||
int _fpInstructionCount;
|
||||
|
||||
/// <summary>
|
||||
/// Temporary, for debugging floating point ucode issues
|
||||
/// </summary>
|
||||
@ -874,6 +879,8 @@ namespace Contralto
|
||||
// Float instructions are from 70001-70022 octal
|
||||
if (instruction >= 0x7000 && instruction <= 0x7012)
|
||||
{
|
||||
_fpInstructionCount++;
|
||||
|
||||
// Save instruction
|
||||
_lastFPInstruction = instruction;
|
||||
|
||||
@ -883,7 +890,7 @@ namespace Contralto
|
||||
_ac2 = _system.CPU.R[1];
|
||||
_ac3 = _system.CPU.R[0];
|
||||
|
||||
Console.Write("FP: ");
|
||||
Console.Write("{0}:FP: ", _fpInstructionCount);
|
||||
switch (instruction)
|
||||
{
|
||||
case 0x7000:
|
||||
@ -967,7 +974,7 @@ namespace Contralto
|
||||
case 0x7012:
|
||||
Console.WriteLine("FEXP {0},{1} ({2})", _ac0, _ac1, GetFloat(_ac0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Console.WriteLine(" AC0={0} AC1={1} AC2={2} AC3={3}",
|
||||
@ -979,9 +986,9 @@ namespace Contralto
|
||||
}
|
||||
|
||||
private void FloatDebugPost()
|
||||
{
|
||||
{
|
||||
|
||||
Console.Write("Post: ");
|
||||
Console.Write("{0}:Post: ", _fpInstructionCount);
|
||||
switch (_lastFPInstruction)
|
||||
{
|
||||
case 0x7000:
|
||||
@ -1142,23 +1149,24 @@ namespace Contralto
|
||||
uint mantissa =
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 2)) << 16) |
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 3)));
|
||||
|
||||
double val = 0.0;
|
||||
|
||||
double valMantissa = 0.0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0;
|
||||
|
||||
val += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
valMantissa += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
}
|
||||
|
||||
val = sign * (val) * Math.Pow(2.0, exponent - 1);
|
||||
double val = sign * (valMantissa) * Math.Pow(2.0, exponent - 1);
|
||||
|
||||
if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
//if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
{
|
||||
Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}",
|
||||
Console.WriteLine(" Vec: sign {0} exp {1} mantissa {2:x} ({3}) value {4}",
|
||||
sign,
|
||||
exponent,
|
||||
mantissa,
|
||||
valMantissa,
|
||||
val);
|
||||
}
|
||||
|
||||
@ -1199,28 +1207,29 @@ namespace Contralto
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 2 * _fpRegCount)) << 16) |
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 3 * _fpRegCount)));
|
||||
|
||||
double val = 0.0;
|
||||
double valMantissa = 0.0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0;
|
||||
|
||||
val += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
valMantissa += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
}
|
||||
|
||||
val = sign * (val) * Math.Pow(2.0, exponent - 1);
|
||||
double val = sign * (valMantissa) * Math.Pow(2.0, exponent - 1);
|
||||
|
||||
if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
//if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
{
|
||||
Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}",
|
||||
Console.WriteLine(" UCode: sign {0} exp {1} mantissa {2:x} ({3}) value {4}",
|
||||
sign,
|
||||
exponent,
|
||||
mantissa,
|
||||
valMantissa,
|
||||
val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
private void SetExecutionState(ExecutionState state)
|
||||
{
|
||||
_execState = state;
|
||||
@ -1343,8 +1352,8 @@ namespace Contralto
|
||||
private bool[] _novaBreakpointEnabled;
|
||||
|
||||
private void HackButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Logging.Log.LogComponents |= Logging.LogComponent.TaskSwitch;
|
||||
{
|
||||
//_system.CPU.HAX = true;
|
||||
Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user