diff options
Diffstat (limited to 'Q1.core')
| -rw-r--r-- | Q1.core/Arch/AddressingModes.cs | 2 | ||||
| -rw-r--r-- | Q1.core/Arch/Chip.cs | 2 | ||||
| -rw-r--r-- | Q1.core/Components/Bus.cs | 100 | ||||
| -rw-r--r-- | Q1.core/Components/IAddressable.cs (renamed from Q1.core/IAddressable.cs) | 17 | ||||
| -rw-r--r-- | Q1.core/Components/Memory.cs | 21 | ||||
| -rw-r--r-- | Q1.core/Memory.cs | 15 |
6 files changed, 135 insertions, 22 deletions
diff --git a/Q1.core/Arch/AddressingModes.cs b/Q1.core/Arch/AddressingModes.cs index 206ee4f..96b4475 100644 --- a/Q1.core/Arch/AddressingModes.cs +++ b/Q1.core/Arch/AddressingModes.cs @@ -1,5 +1,7 @@ namespace Q1.core.Arch; +using Components; + public static class AddressingModes { public static AddressingMode[] Lookup = new AddressingMode[8]; diff --git a/Q1.core/Arch/Chip.cs b/Q1.core/Arch/Chip.cs index 69a0877..9f5f109 100644 --- a/Q1.core/Arch/Chip.cs +++ b/Q1.core/Arch/Chip.cs @@ -1,5 +1,7 @@ namespace Q1.core.Arch; +using Components; + // Big endian public class Chip { diff --git a/Q1.core/Components/Bus.cs b/Q1.core/Components/Bus.cs new file mode 100644 index 0000000..02b20a7 --- /dev/null +++ b/Q1.core/Components/Bus.cs @@ -0,0 +1,100 @@ +namespace Q1.core.Components; + +using Q1.core.Arch; + +public class Bus : IAddressable +{ + private Chip? _chip; + private readonly List<IAddressable> _devices; + + public u16 AddressableStart { get; } + public u16 AddressableEnd { get; } + + public Bus(u16 addressableStart, u16 addressableEnd) + { + this.AddressableStart = addressableStart; + this.AddressableEnd = addressableEnd; + this._devices = new(); + } + + public void SendInterrupt(u16 code) + { + if (this._chip == null) + throw new InvalidOperationException("Chip is not attached to bus"); + + this._chip.Interrupt(code); + } + + public void AttachChip(Chip chip) + { + if (this._chip != null) + throw new InvalidOperationException("Bus already has a chip attached."); + + this._chip = chip; + chip.Bus = this; + } + + public void MountDevice(IAddressable device) + { + if (device.AddressableStart >= device.AddressableEnd) + throw new ArgumentException("Addressable range is invalid.", nameof(device)); + + int index = 0; + while (index < this._devices.Count && this._devices[index].AddressableStart < device.AddressableStart) + index++; + + if (index > 0) + { + IAddressable prev = this._devices[index - 1]; + if (device.AddressableStart < prev.AddressableEnd) + throw new InvalidOperationException("Address range overlaps with previous device."); + } + + if (index < this._devices.Count) + { + IAddressable next = this._devices[index]; + if (device.AddressableEnd > next.AddressableStart) + throw new InvalidOperationException("Address range overlaps with next device."); + } + + this._devices.Insert(index, device); + } + + private IAddressable? GetDevice(u16 address) + { + foreach (IAddressable device in this._devices) + { + if (address < device.AddressableStart) + break; + + if (address < device.AddressableEnd) + return device; + } + + return null; + } + + public u8 Read(u16 address) + { + IAddressable? device = this.GetDevice(address); + if (device == null) + return 0; + + return device.Read((u16) (address - device.AddressableStart)); + } + + public void Write(u16 address, u8 value) + { + IAddressable? device = this.GetDevice(address); + if (device == null) + return; + + device.Write((u16) (address - device.AddressableStart), value); + } + + public void Clock() + { + foreach (IAddressable addressable in this._devices) + addressable.Clock(); + } +}
\ No newline at end of file diff --git a/Q1.core/IAddressable.cs b/Q1.core/Components/IAddressable.cs index 49a697e..54218d9 100644 --- a/Q1.core/IAddressable.cs +++ b/Q1.core/Components/IAddressable.cs @@ -1,10 +1,13 @@ -namespace Q1.core; +namespace Q1.core.Components; public interface IAddressable { public u8 Read(u16 address); public void Write(u16 address, u8 value); public void Clock(); + + public u16 AddressableStart { get; } + public u16 AddressableEnd { get; } } public static class AddressableExtensions @@ -12,15 +15,15 @@ public static class AddressableExtensions public static u16 ReadWord(this IAddressable bus, u16 address) { u8 high = bus.Read(address); - u8 low = bus.Read((u16)(address + 1)); - return (u16)((high << 8) | low); + u8 low = bus.Read((u16) (address + 1)); + return (u16) ((high << 8) | low); } - + public static void WriteWord(this IAddressable bus, u16 address, u16 value) { - u8 high = (u8) (value & 0xFF); - u8 low = (u8)((value >> 8) & 0xFF); + u8 high = (u8) (value & 0xFF); + u8 low = (u8) ((value >> 8) & 0xFF); bus.Write(address, low); - bus.Write((u16)(address + 1), high); + bus.Write((u16) (address + 1), high); } }
\ No newline at end of file diff --git a/Q1.core/Components/Memory.cs b/Q1.core/Components/Memory.cs new file mode 100644 index 0000000..9d23c7a --- /dev/null +++ b/Q1.core/Components/Memory.cs @@ -0,0 +1,21 @@ +namespace Q1.core.Components; + +public class Memory : IAddressable +{ + private readonly u8[] _memory; + + public u16 AddressableStart { get; } + public u16 AddressableEnd { get; } + + public Memory(u16 start, u16 size) + { + this.AddressableStart = start; + this.AddressableEnd = (u16) (start + size); + + this._memory = new u8[size]; + } + + public u8 Read(u16 address) => this._memory[address]; + public void Write(u16 address, u8 value) => this._memory[address] = value; + public void Clock() { /* No timing behavior for simple memory */ } +}
\ No newline at end of file diff --git a/Q1.core/Memory.cs b/Q1.core/Memory.cs deleted file mode 100644 index d140809..0000000 --- a/Q1.core/Memory.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Q1.core; - -public class Memory : IAddressable -{ - private readonly u8[] _memory; - - public Memory(int size) - { - _memory = new u8[size]; - } - - public u8 Read(u16 address) => _memory[address]; - public void Write(u16 address, u8 value) => _memory[address] = value; - public void Clock() { /* No timing behavior for simple memory */ } -}
\ No newline at end of file |
