1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-24 11:21:26 +00:00
2015-08-20 18:02:01 -07:00

137 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contralto.Memory
{
public static class MemoryBus
{
static MemoryBus()
{
_mem = new Memory();
_memoryCycle = 0;
_memoryAddress = 0;
_memoryData = 0;
_memoryOperationActive = false;
}
public static void Clock()
{
if (_memoryOperationActive)
{
_memoryCycle++;
switch (_memoryCycle)
{
case 3:
_memoryData = ReadFromBus(_memoryAddress);
break;
case 4:
_memoryData2 = ReadFromBus(_memoryAddress ^ 1);
break;
case 6:
_memoryOperationActive = false;
_doubleWordStore = false;
_memoryCycle = 0;
break;
}
}
}
public static void LoadMAR(ushort address)
{
if (_memoryOperationActive)
{
// TODO: stall CPU
}
else
{
_memoryOperationActive = true;
_doubleWordStore = false;
_memoryAddress = address;
_memoryCycle = 1;
}
}
public static ushort ReadMD()
{
if (_memoryOperationActive)
{
switch (_memoryCycle)
{
case 1:
case 2:
// TODO: good microcode should never do this
throw new InvalidOperationException("Unexpected microcode behavior -- ReadMD too soon after start of memory cycle.");
case 3:
case 4:
// TODO: not ready yet; need to tell CPU to wait.
break;
case 5:
// Single word read
return _memoryData;
case 6: // TODO: rectify with timing (doubleword read extends cycle to 6)
// Doubleword read:
return _memoryData2;
default:
// Invalid state.
throw new InvalidOperationException(string.Format("Unexpected memory cycle {0} in memory state machine.", _memoryCycle));
}
}
else
{
// not running, just return last latched contents
return _memoryData;
}
}
public static void LoadMD(ushort data)
{
if (_memoryOperationActive)
{
switch (_memoryCycle)
{
case 1:
case 2:
case 5:
// TODO: good microcode should never do this
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD too soon after start of memory cycle.");
break;
case 3:
// Start of doubleword write:
WriteToBus(_memoryAddress, data);
_doubleWordStore = true;
break;
case 4:
WriteToBus(_doubleWordStore ? _memoryAddress ^ 1 : _memoryAddress, data);
break;
}
}
}
private static Memory _mem;
private static bool _memoryOperationActive;
private static int _memoryCycle;
private static ushort _memoryAddress;
// Buffered read data (on cycles 3 and 4)
private static ushort _memoryData;
private static ushort _memoryData2;
// Indicates a double-word store (started on cycle 3)
private static bool _doubleWordStore;
}
}