Skip to content

Commit

Permalink
implement memorybus interface for abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
jnosek committed Jul 11, 2020
1 parent 193613e commit f2d0008
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 57 deletions.
16 changes: 16 additions & 0 deletions AGC/Memory/IMemoryBus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Apollo.Virtual.AGC.Memory
{
public interface IMemoryBus
{
OnesCompliment this[ushort a] { get; set; }
int MaxAddress { get; }

/// <summary>
/// The AGC has memory mapped registerss, so they need a method to regiser themselves to the MemoryBus
/// </summary>
/// <typeparam name="RegisterType"></typeparam>
/// <param name="address"></param>
/// <returns></returns>
RegisterType MapRegister<RegisterType>(ushort address) where RegisterType : MemoryWord;
}
}
26 changes: 13 additions & 13 deletions AGC/MemoryMap.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Apollo.Virtual.AGC.Memory;
using System;
using System.Diagnostics;

namespace Apollo.Virtual.AGC
{
public class MemoryMap
public class MemoryMap : IMemoryBus
{
const uint EB_Address = 0x03;
const uint FB_Address = 0x04;
Expand Down Expand Up @@ -34,7 +36,7 @@ public class MemoryMap
///
/// Divided into 8 (E0 - E7) banks controlled by register EB or BB
/// </summary>
private MemoryBank[] switchedErasable = new MemoryBank[]
private MemoryBank[] switchedErasable = new MemoryBank[]
{
new MemoryBank(256, 0x300),
new MemoryBank(256, 0x300),
Expand Down Expand Up @@ -79,19 +81,15 @@ public class MemoryMap
/// </summary>
private MemoryBank ioChannels = new MemoryBank(512);

public int MaxAddress => throw new NotImplementedException();

public OnesCompliment this[ushort a]
{
get
{
return GetWord(a).Read();
}
set
{
GetWord(a).Write(value);
}
get => GetWord(a).Read();
set => GetWord(a).Write(value);
}

public IWord GetWord(ushort address)
private IWord GetWord(ushort address)
{
// registers
if (address <= 0x031)
Expand All @@ -100,7 +98,7 @@ public IWord GetWord(ushort address)
int bank = 0;

// look at bits in address to determine appropriate bank and memory type
switch(address & 0xF00)
switch (address & 0xF00)
{
case 0x000:
case 0x100:
Expand Down Expand Up @@ -144,11 +142,13 @@ public IWord GetWord(ushort address)
/// <typeparam name="RegisterType"></typeparam>
/// <param name="address"></param>
/// <returns></returns>
internal RegisterType AddRegister<RegisterType>(ushort address) where RegisterType : MemoryWord
RegisterType IMemoryBus.MapRegister<RegisterType>(ushort address)
{
// reflectively get constructor that takes memory bank and call it
var constructor = typeof(RegisterType).GetConstructor(new[] { typeof(ushort), typeof(MemoryBank) });

Debug.Assert(constructor != null, $"Register of type {typeof(RegisterType).Name} does not have usable constructor");

var r = constructor.Invoke(new object[] { address, unswitchedErasable }) as RegisterType;

// add to memory space and return the object created
Expand Down
90 changes: 46 additions & 44 deletions AGC/Processor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Apollo.Virtual.AGC.Memory;
using AGC;
using Apollo.Virtual.AGC.Instructions;
using Apollo.Virtual.AGC.Memory;
using Apollo.Virtual.AGC.Registers;

namespace Apollo.Virtual.AGC
Expand All @@ -10,10 +12,10 @@ namespace Apollo.Virtual.AGC
/// </summary>
public class Processor
{
internal MemoryMap Memory;
internal IMemoryBus Memory;

private InstructionSet instructions;
private ExtraCodeInstructionSet extraCodeInstructions;
private readonly InstructionList standardInstructions;
private readonly InstructionList extraCodeInstructions;

/// <summary>
/// used to allow more than 8 instruction codes
Expand Down Expand Up @@ -215,60 +217,60 @@ public class Processor

#endregion

public Processor(MemoryMap memory)
public Processor(IMemoryBus memory)
{
this.Memory = memory;
instructions = new InstructionSet();
extraCodeInstructions = new ExtraCodeInstructionSet();
standardInstructions = StandardInstructions.Build(this);
extraCodeInstructions = ExtraInstructions.Build(this);

// configure registers

// main registers?
A = memory.AddRegister<Accumulator>(0x00);
L = memory.AddRegister<ErasableMemory>(0x01);
Q = memory.AddRegister<FullRegister>(0x02);
EB = memory.AddRegister<ErasableBankRegister>(0x03);
FB = memory.AddRegister<FixedBankRegister>(0x4);
Z = memory.AddRegister<ProgramCounter>(0x05);
BB = memory.AddRegister<BothBanksRegister>(0x06);
A = memory.MapRegister<Accumulator>(0x00);
L = memory.MapRegister<ErasableMemory>(0x01);
Q = memory.MapRegister<FullRegister>(0x02);
EB = memory.MapRegister<ErasableBankRegister>(0x03);
FB = memory.MapRegister<FixedBankRegister>(0x4);
Z = memory.MapRegister<ProgramCounter>(0x05);
BB = memory.MapRegister<BothBanksRegister>(0x06);

//memory[0x7] = 0; // this is always set to 0, TODO: need to hard code?

// interrupt helper registers
ARUPT = memory.AddRegister<ErasableMemory>(0x08);
LRUPT = memory.AddRegister<ErasableMemory>(0x09);
QRUPT = memory.AddRegister<ErasableMemory>(0x0A);
ARUPT = memory.MapRegister<ErasableMemory>(0x08);
LRUPT = memory.MapRegister<ErasableMemory>(0x09);
QRUPT = memory.MapRegister<ErasableMemory>(0x0A);
// 0XB, 0XC are spares. not used?
ZRUPT = memory.AddRegister<ErasableMemory>(0x0D);
BBRUPT = memory.AddRegister<ErasableMemory>(0x0E);
BRUPT = memory.AddRegister<ErasableMemory>(0x0F);
ZRUPT = memory.MapRegister<ErasableMemory>(0x0D);
BBRUPT = memory.MapRegister<ErasableMemory>(0x0E);
BRUPT = memory.MapRegister<ErasableMemory>(0x0F);

// editing registers
CYR = memory.AddRegister<CycleRightRegister>(0x10);
SR = memory.AddRegister<ShiftRightRegister>(0x11);
CYL = memory.GetWord(0x12);
EDOP = memory.GetWord(0x13);
CYR = memory.MapRegister<CycleRightRegister>(0x10);
SR = memory.MapRegister<ShiftRightRegister>(0x11);
CYL = memory.MapRegister<ErasableMemory>(0x12); // temp
EDOP = memory.MapRegister<ErasableMemory>(0x13); // temp

// time registers
TIME2 = memory.GetWord(0x14);
TIME1 = memory.GetWord(0x15);
TIME3 = memory.GetWord(0x16);
TIME4 = memory.GetWord(0x17);
TIME5 = memory.GetWord(0x18);
TIME6 = memory.GetWord(0x19);
TIME2 = memory.MapRegister<ErasableMemory>(0x14); // temp
TIME1 = memory.MapRegister<ErasableMemory>(0x15); // temp
TIME3 = memory.MapRegister<ErasableMemory>(0x16); // temp
TIME4 = memory.MapRegister<ErasableMemory>(0x17); // temp
TIME5 = memory.MapRegister<ErasableMemory>(0x18); // temp
TIME6 = memory.MapRegister<ErasableMemory>(0x19); // temp

// orientation registers
CDUX = memory.AddRegister<ErasableMemory>(0x1A);
CDUY = memory.AddRegister<ErasableMemory>(0x1B);
CDUZ = memory.AddRegister<ErasableMemory>(0x1C);
OPTY = memory.AddRegister<ErasableMemory>(0x1D);
OPTX = memory.AddRegister<ErasableMemory>(0x1E);
PIPAX = memory.AddRegister<ErasableMemory>(0x1F);
PIPAY = memory.AddRegister<ErasableMemory>(0x20);
PIPAZ = memory.AddRegister<ErasableMemory>(0x21);
CDUX = memory.MapRegister<ErasableMemory>(0x1A);
CDUY = memory.MapRegister<ErasableMemory>(0x1B);
CDUZ = memory.MapRegister<ErasableMemory>(0x1C);
OPTY = memory.MapRegister<ErasableMemory>(0x1D);
OPTX = memory.MapRegister<ErasableMemory>(0x1E);
PIPAX = memory.MapRegister<ErasableMemory>(0x1F);
PIPAY = memory.MapRegister<ErasableMemory>(0x20);
PIPAZ = memory.MapRegister<ErasableMemory>(0x21);
// LM Only Pitch, Yaw, and Roll registers

INLINK = memory.AddRegister<ErasableMemory>(0x25);
INLINK = memory.MapRegister<ErasableMemory>(0x25);

// prime Z to start at the boot interrupt
Z.Write(new OnesCompliment(0x800));
Expand All @@ -277,13 +279,15 @@ public Processor(MemoryMap memory)
public void Execute()
{
// get address of instruction to run
var address = Memory.GetWord(Z.Read().NativeValue);
ushort address = Z.Read().NativeValue;

// update Z
Z.Increment();

// get instruction
ushort instruction = Memory[address].NativeValue;
// we only care about 15-bit instructions
var instruction = address.Read() & 0x7FFF;
instruction &= 0x7FFF;

var code = (ushort)(instruction >> 12);
var K = (ushort)(instruction & 0xFFF);
Expand All @@ -292,7 +296,6 @@ public void Execute()
if (ExtraCodeFlag)
{
// reset CPU for instruction to execute
extraCodeInstructions[code].CPU = this;
extraCodeInstructions[code].Execute(K);

// clear the extra code flag
Expand All @@ -301,8 +304,7 @@ public void Execute()
else
{
// reset CPU for instruction to execute
instructions[code].CPU = this;
instructions[code].Execute(K);
standardInstructions[code].Execute(K);
}
}
}
Expand Down

0 comments on commit f2d0008

Please sign in to comment.