Files

141 lines
4.8 KiB
C#

namespace CPUSimulation
{
public class MC // Memory Controller
{
MemoryBank[] _memoryBanks;
int _numberOfMemoryBanks;
int _memoryBankSize;
public MC(int numberOfMemoryBanks, int memoryBankSize = 1024)
{
_numberOfMemoryBanks = numberOfMemoryBanks;
_memoryBankSize = memoryBankSize;
Bit bit = new Bit();
Byte thisByte = new Byte(new Bit[8] { bit, bit, bit, bit, bit, bit, bit, bit });
_memoryBanks = new MemoryBank[numberOfMemoryBanks];
for(int i = 0; i < numberOfMemoryBanks; i++)
{
Byte[] newMemoryBank = new Byte[memoryBankSize];
for(int j = 0; j < memoryBankSize; j++)
{
newMemoryBank[j] = thisByte;
}
_memoryBanks[i] = new MemoryBank(newMemoryBank);
}
}
public string Read(Int16 address)
{
AddressOkay(address);
Byte[] byteData = new Byte[_numberOfMemoryBanks];
for (int i = 0; i < _numberOfMemoryBanks; i++)
{
byteData[i] = _memoryBanks[i].Read(new Address(address).ToString());
}
if (byteData.Length == 2)
{
return new Word(byteData).ToString();
}
else if (byteData.Length == 4)
{
return new DWord(new Word(byteData.Take(2).ToArray()), new Word(byteData.Skip(2).Take(2).ToArray())).ToString();
}
else if (byteData.Length == 8)
{
return new QWord(new DWord(new Word(byteData.Take(2).ToArray()), new Word(byteData.Skip(2).Take(2).ToArray())), new DWord(new Word(byteData.Skip(4).Take(2).ToArray()), new Word(byteData.Skip(6).Take(2).ToArray()))).ToString();
}
else
{
throw new ArgumentException($"Number of memory banks must be between 1 and 8 (inclusive).");
}
}
public void Write(Int16 address, Word data)
{
AddressOkay(address);
Byte[] byteData = data.GetBytes();
int byteCount = data.GetByteCount();
Byte[] bytesToWrite;
if (byteCount < _numberOfMemoryBanks)
{
bytesToWrite = GeneratePaddingBytes(byteData, byteCount);
}
else if (data.GetByteCount() > _numberOfMemoryBanks)
{
throw new ArgumentException($"Data must consist of {_numberOfMemoryBanks} bytes or less.");
}
else
{
bytesToWrite = byteData;
}
for (int i = 0; i < _numberOfMemoryBanks; i++)
{
_memoryBanks[i].Write(new Address(address).ToString(), bytesToWrite[i]);
}
}
public void Write(string address, string data)
{
if(address.Length != 16)
{
throw new ArgumentException("Address must be 16 bits long.");
}
if (data.Length % 8 != 0)
{
throw new ArgumentException("Data must be a multiple of 8 bits long.");
}
int byteCount = data.Length / 8;
if (byteCount > _numberOfMemoryBanks)
{
throw new ArgumentException($"Data must consist of {_numberOfMemoryBanks} bytes or less.");
}
if (byteCount < _numberOfMemoryBanks)
{
data = data.PadLeft(_numberOfMemoryBanks * 8, '0');
}
for (int i = 0; i < _numberOfMemoryBanks; i++)
{
string byteString = data.Substring(i * 8, 8);
Byte byteData = new Byte(byteString);
_memoryBanks[i].Write(address, byteData);
}
}
private void AddressOkay(Int16 address)
{
if (address < 0 || address >= _memoryBankSize)
{
throw new ArgumentOutOfRangeException(nameof(address), $"Received {address}. Address must be between 0 and {_memoryBankSize - 1}.");
}
}
private Byte[] GeneratePaddingBytes(Byte[] byteData, int byteCount)
{
Byte[] bytesToWrite;
int numberOfPaddingBytes = _numberOfMemoryBanks - byteCount;
bytesToWrite = new Byte[_numberOfMemoryBanks];
for (int i = 0; i < _numberOfMemoryBanks; i++)
{
if (i < numberOfPaddingBytes)
{
Bit bit = new Bit();
bytesToWrite[i] = new Byte(new Bit[8] { bit, bit, bit, bit, bit, bit, bit, bit });
}
else
{
bytesToWrite[i] = byteData[i - numberOfPaddingBytes];
}
}
return bytesToWrite;
}
}
}