1
0
mirror of https://github.com/livingcomputermuseum/sImlac.git synced 2026-01-11 23:53:24 +00:00

Tweaks for interrupt handling; added one instruction delay after ION before enabling interrupts, interrupts are now clocked on the leading edge of the processor Fetch cycle rather than on every clock cycle.

This commit is contained in:
Josh Dersch 2020-04-28 11:07:45 -07:00
parent aee6c5dc63
commit 3a7afbafc0
3 changed files with 33 additions and 13 deletions

View File

@ -69,7 +69,7 @@ namespace imlac.IO
public void Clock()
{
if (_interruptsEnabled)
if (_interruptsEnabled && _interruptEnableCount == 0)
{
// Collect up devices that want to interrupt us.
_interruptStatus = 0;
@ -172,6 +172,10 @@ namespace imlac.IO
Trace.Log(LogType.Interrupt, "Interrupt triggered (for device(s) {0})", Helpers.ToOctal((ushort)(_interruptMask & _interruptStatus)));
}
}
else if (_interruptsEnabled)
{
_interruptEnableCount--;
}
}
public int[] GetHandledIOTs()
@ -195,6 +199,8 @@ namespace imlac.IO
case 0x72:
_interruptsEnabled = true;
// Interrupts are enabled the second instruction after the ION.
_interruptEnableCount = 1;
Trace.Log(LogType.Interrupt, "Interrupts enabled");
break;
@ -220,6 +226,7 @@ namespace imlac.IO
}
}
private int _interruptEnableCount;
private bool _interruptsEnabled;
private bool _interruptPending;
private int _interruptMask;

View File

@ -76,15 +76,15 @@ namespace imlac.IO
_rxData = _dataChannel.Read();
Trace.Log(LogType.TTY, "i");
}
}
// Are we waiting to send something?
if (_dataBufferFull && _dataChannel.OutputReady)
{
_dataChannel.Write(_txData);
Trace.Log(LogType.TTY, "o {0}", Helpers.ToOctal(_txData));
_dataBufferFull = false;
_dataSentLatch = true;
// Are we waiting to send something?
if (_dataBufferFull && _dataChannel.OutputReady)
{
_dataChannel.Write(_txData);
Trace.Log(LogType.TTY, "o {0}", Helpers.ToOctal(_txData));
_dataBufferFull = false;
_dataSentLatch = true;
}
}
}

View File

@ -134,8 +134,12 @@ namespace imlac
_keyboard.Clock();
_clock.Clock();
// interrupts last so that devices that raise interrupts get clocked first
_interruptFacility.Clock();
// interrupts last so that devices that raise interrupts get clocked first.
// We clock interrupts on the leading edge of the processor's Fetch state.
if (_processor.InstructionState == ExecState.Fetch)
{
_interruptFacility.Clock();
}
}
//
@ -199,13 +203,22 @@ namespace imlac
return SystemExecutionState.UntilDisplayStart;
}
[DebuggerFunction("set bootstrap", "Loads the specified bootstrap into memory at 40", "<bootstrap>")]
private SystemExecutionState SetBootstrap(string bootstrap)
[DebuggerFunction("load bootstrap", "Loads the specified bootstrap into memory at 40", "<bootstrap>")]
private SystemExecutionState LoadBootstrap(string bootstrap)
{
LoadMemory(Paths.BuildBootPath(bootstrap), 0x20, 0x20);
return SystemExecutionState.Debugging;
}
[DebuggerFunction("boot", "Loads the specified bootstrap into memory at 40 and executes it", "<bootstrap>")]
private SystemExecutionState Boot(string bootstrap)
{
LoadMemory(Paths.BuildBootPath(bootstrap), 0x20, 0x20);
Processor.PC = 0x20;
Processor.State = ProcessorState.Running;
return SystemExecutionState.Running;
}
[DebuggerFunction("save memory", "Saves the specified range of memory to a file", "<file> <start> <length>")]
private SystemExecutionState SaveMemoryContents(string file, ushort start, ushort length)
{