1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-05-05 07:24:36 +00:00

Implemented more Disk functionality, fixed bug in ACSOURCE dispatch in Emulator task.

This commit is contained in:
Josh Dersch
2015-09-16 16:27:16 -07:00
parent 08d6063def
commit ee7c7fb035
14 changed files with 387 additions and 89 deletions

View File

@@ -22,7 +22,7 @@ namespace Contralto.CPU
DiskWord = 14,
}
public partial class AltoCPU
public partial class AltoCPU : IClockable
{
public AltoCPU(AltoSystem system)
{
@@ -115,25 +115,9 @@ namespace Contralto.CPU
}
public void ExecuteNext()
public void Clock()
{
if (_currentTask.ExecuteNext())
{
// Invoke the task switch, this will take effect after
// the NEXT instruction, not this one.
TaskSwitch();
}
else
{
// If we have a new task, switch to it now.
if (_nextTask != null)
{
_currentTask = _nextTask;
_nextTask = null;
}
}
_clocks++;
ExecuteNext();
}
/// <summary>
@@ -162,6 +146,27 @@ namespace Contralto.CPU
}
}
private void ExecuteNext()
{
if (_currentTask.ExecuteNext())
{
// Invoke the task switch, this will take effect after
// the NEXT instruction, not this one.
TaskSwitch();
}
else
{
// If we have a new task, switch to it now.
if (_nextTask != null)
{
_currentTask = _nextTask;
_nextTask = null;
}
}
_clocks++;
}
private void TaskSwitch()
{
// Select the highest-priority eligible task

View File

@@ -7,9 +7,9 @@ using System.Threading.Tasks;
namespace Contralto.CPU
{
static class ConstantMemory
static class ControlROM
{
static ConstantMemory()
static ControlROM()
{
Init();
}
@@ -17,6 +17,7 @@ namespace Contralto.CPU
private static void Init()
{
LoadConstants(_constantRoms);
LoadACSource(_acSourceRoms);
}
public static ushort[] ConstantROM
@@ -24,6 +25,11 @@ namespace Contralto.CPU
get { return _constantRom; }
}
public static byte[] ACSourceROM
{
get { return _acSourceRom; }
}
private static void LoadConstants(RomFile[] romInfo)
{
_constantRom = new ushort[256];
@@ -47,7 +53,7 @@ namespace Contralto.CPU
// OR in the data
for (int i = 0; i < length; i++)
{
_constantRom[file.StartingAddress + i] |= (ushort)((DataMap(data[AddressMap(i)]) & 0xf) << file.BitPosition);
_constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition);
}
}
}
@@ -59,7 +65,29 @@ namespace Contralto.CPU
}
}
private static int AddressMap(int address)
private static void LoadACSource(RomFile romInfo)
{
_acSourceRom = new byte[256];
using (FileStream fs = new FileStream(Path.Combine("ROM", romInfo.Filename), FileMode.Open, FileAccess.Read))
{
int length = (int)fs.Length;
if (length != 256)
{
throw new InvalidOperationException("ROM file should be 256 bytes in length");
}
byte[] data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
// Copy in the data, modifying the address as required.
for (int i = 0; i < length; i++)
{
_acSourceRom[i] = (byte)((~data[AddressMapACSourceRom(i)]) & 0xf);
}
}
}
private static int AddressMapConstantRom(int address)
{
// Descramble the address bits as they are in no sane order.
// (See 05a_AIM.pdf, pg. 5 (Page 9 of the orginal docs))
@@ -77,7 +105,7 @@ namespace Contralto.CPU
return mappedAddress;
}
private static int DataMap(int data)
private static int DataMapConstantRom(int data)
{
// Reverse bits 0-4.
int mappedData = 0;
@@ -93,6 +121,23 @@ namespace Contralto.CPU
return mappedData;
}
private static int AddressMapACSourceRom(int data)
{
// Reverse bits 0-7.
int mappedData = 0;
for (int i = 0; i < 8; i++)
{
if ((data & (1 << i)) != 0)
{
mappedData |= (1 << (7 - i));
}
}
// And invert.
return (~mappedData) & 0xff;
}
private static RomFile[] _constantRoms =
{
new RomFile("c0", 0x000, 12),
@@ -101,6 +146,9 @@ namespace Contralto.CPU
new RomFile("c3", 0x000, 0),
};
private static RomFile _acSourceRoms = new RomFile("2kctl.u3", 0x000, 0);
private static ushort[] _constantRom;
private static byte[] _acSourceRom;
}
}

View File

@@ -73,7 +73,7 @@ namespace Contralto.CPU
instruction.F2 == SpecialFunction2.Constant)
{
source += String.Format("C({0})",
OctalHelpers.ToOctal(ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)]));
OctalHelpers.ToOctal(ControlROM.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)]));
}
switch (instruction.ALUF)

View File

@@ -96,7 +96,75 @@ namespace Contralto.CPU
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.");
// From the US Patent (4148098):
// "..two multiplexers...allow the setting of the next field bits NEXT(05)-NEXT(09)
// to 1 after an error condition is detected and as soon as the word task active signal
// WDTASKACT is generated..."
// Is this always an error condition?
Console.WriteLine("Warning: assuming 0 for Disk F2 INIT (unimplemented stub)");
break;
case DiskF2.RWC:
// "NEXT<-NEXT OR (IF current record to be written THEN 3 ELSE IF
// current record to be checked THEN 2 ELSE 0.")
// Current record is in bits 8-9 of the command register; this is shifted
// by INCREC by the microcode to present the next set of bits.
int command = (_cpu._system.DiskController.KADR & 0x00c0) >> 6;
switch(command)
{
case 0:
// read, no modification.
break;
case 1:
// check, OR in 2
_nextModifier |= 0x2;
break;
case 2:
case 3:
// write, OR in 3
_nextModifier |= 0x3;
break;
}
break;
case DiskF2.XFRDAT:
// "NEXT <- NEXT OR (IF current command wants data transfer THEN 1 ELSE 0)
// TODO: need to get unshifted bit 14 of the command register. Disk controller should
// save this off somewhere.
if (_cpu._system.DiskController.DataXfer)
{
_nextModifier |= 0x1;
}
break;
case DiskF2.RECNO:
_nextModifier |= _cpu._system.DiskController.RECNO;
break;
case DiskF2.NFER:
// "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)"
// We assume success for now...
_nextModifier |= 0x1;
break;
case DiskF2.STROBON:
// "NEXT <- NEXT OR (IF seek strobe still on THEN 1 ELSE 0)"
if ((_cpu._system.DiskController.KSTAT & 0x0040) == 0x0040)
{
_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)
break;
default:
throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));

View File

@@ -192,54 +192,14 @@ namespace Contralto.CPU
// 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;
}
//
// NOTE: the above table from the Hardware Manual is incorrect (or at least incomplete / misleading).
// There is considerably more that goes into determining the dispatch, which is controlled by a 256x8
// PROM. We just use the PROM rather than implementing the above logic (because it works.)
//
_nextModifier = ControlROM.ACSourceROM[(_cpu._ir & 0xff00) >> 8];
break;
case EmulatorF2.ACDEST:

View File

@@ -185,7 +185,7 @@ namespace Contralto.CPU
else
{
// See also comments below.
_busData = ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
_busData = ControlROM.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Constant ROM access:
@@ -202,7 +202,7 @@ namespace Contralto.CPU
instruction.F1 == SpecialFunction1.Constant ||
instruction.F2 == SpecialFunction2.Constant)
{
_busData &= ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
_busData &= ControlROM.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
}
// Do ALU operation