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; } } }