Skip to content

Commit

Permalink
Redesign MemoryController
Browse files Browse the repository at this point in the history
  • Loading branch information
Argmaster committed Oct 31, 2024
1 parent 776a231 commit 4ab4784
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 206 deletions.
14 changes: 11 additions & 3 deletions src/Bytom.Hardware.Tests/Devices/MemoryTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

using System.Collections.Concurrent;
using System.Diagnostics;

namespace Bytom.Hardware.Tests
{
Expand Down Expand Up @@ -65,9 +66,16 @@ public static Memory createMemory(uint capacity = 128, uint bandwidth_bytes = 1)
public void TestPushIoPowerOff()
{
var memory = createMemory<MemT>();
Assert.Throws<InvalidOperationException>(
() => memory!.pushIoMessage(new WriteMessage(Address.zero, 1))
);
try
{
memory!.pushIoMessage(new WriteMessage(Address.zero, 1));
}
catch (Exception e)
{
StringAssert.Contains("Device is powered off", e.Message);
return;
}
Assert.Fail("Expected exception not thrown");
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion src/Bytom.Hardware.Tests/Devices/RAMTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class RAMTests : GenericMemoryTests<TestRAM, DebugRAM>
public void TestAllocateAddressRange()
{
var ram = new RAM(1024, 1000, 1, 1, 1);
var controller = new MemoryController([ram]);
var controller = new IoController([ram], []);

controller.powerOn(null);

Expand Down
Empty file.
4 changes: 2 additions & 2 deletions src/Bytom.Hardware.Tests/MotherboardTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class MotherboardTests
{

public RAM? ram;
public MemoryController? controller;
public IoController? controller;
public Core? core;
public Package? cpu;
public Motherboard? motherboard;
Expand All @@ -22,7 +22,7 @@ public void Setup()
write_latency_cycles: 0,
bandwidth_bytes: 1
);
controller = new MemoryController([ram]);
controller = new IoController([ram], []);
core = new Core(0, 500);
cpu = new Package([core], 128);
motherboard = new Motherboard(cpu, controller);
Expand Down
1 change: 1 addition & 0 deletions src/Bytom.Hardware/Address.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class Address
{
private long address { get; }
public static Address zero { get { return new Address(0); } }
public static Address max_address { get { return new Address(uint.MaxValue); } }
public Address(long address)
{
this.address = address;
Expand Down
2 changes: 1 addition & 1 deletion src/Bytom.Hardware/CPU/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public virtual void powerOnInit()
thread.Start();
}

public MemoryController GetMemoryController()
public IoController GetMemoryController()
{
return package!.motherboard!.controller;
}
Expand Down
1 change: 0 additions & 1 deletion src/Bytom.Hardware/Devices/BiosRom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace Bytom.Hardware
{
public class FirmwareRom : Memory
{

public FirmwareRom(
uint capacity_bytes,
uint clock_speed_hz,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;


namespace Bytom.Hardware
{
public class MessageReceiver : IDisposable
public class Device : IDisposable
{
public AddressRange? address_range { get; set; }
public Clock clock { get; }

// Queue for receiving read/write messages.
Expand All @@ -20,12 +20,12 @@ public class MessageReceiver : IDisposable
// dequeuing of read/write messages.
public uint max_tasks_running { get; }

public MemoryController? memory_controller;
public IoController? memory_controller;
public PowerStatus power_status = PowerStatus.OFF;
public bool requested_power_off = false;
public Thread? thread = null;

public MessageReceiver(uint max_tasks_running, Clock clock)
public Device(uint max_tasks_running, Clock clock)
{
this.clock = clock;
io_queue = new ConcurrentQueue<IoMessage>();
Expand All @@ -43,10 +43,7 @@ public void Dispose()

public void pushIoMessage(IoMessage message)
{
if (power_status != PowerStatus.ON)
{
throw new InvalidOperationException("Memory is not powered on");
}
Debug.Assert(power_status != PowerStatus.OFF, "Device is powered off");
io_queue.Enqueue(message);
}

Expand All @@ -55,20 +52,26 @@ public bool isDone()
return io_queue.IsEmpty && tasks_running.Count == 0;
}

public virtual void powerOn(MemoryController? controller)
public virtual void powerOn(IoController? controller)
{
if (power_status == PowerStatus.ON)
Debug.Assert(power_status == PowerStatus.OFF, "Device is already powered on");
Debug.Assert(power_status != PowerStatus.STARTING, "Device is already starting");
try
{
power_status = PowerStatus.STARTING;
memory_controller = controller;
powerOnInit();
}
catch (Exception e)
{
throw new InvalidOperationException("Memory is already powered on");
memory_controller = null;
power_status = PowerStatus.OFF;
throw e;
}
if (power_status == PowerStatus.STARTING)
finally
{
return;
power_status = PowerStatus.ON;
}
power_status = PowerStatus.STARTING;
memory_controller = controller;
powerOnInit();
power_status = PowerStatus.ON;
}

public virtual void powerOnInit()
Expand Down Expand Up @@ -102,7 +105,7 @@ public virtual void messageReceiverThread()

public virtual void tick()
{
runQueuedTasks();
scheduleQueuedTasks();
advanceRunningTasks();
}

Expand All @@ -124,7 +127,7 @@ private void advanceRunningTasks()
}
}

private void runQueuedTasks()
private void scheduleQueuedTasks()
{
while (tasks_running.Count < max_tasks_running)
{
Expand Down Expand Up @@ -160,39 +163,32 @@ public virtual IEnumerable read(ReadMessage message)

public virtual void powerOff()
{
if (power_status == PowerStatus.OFF)
{
throw new InvalidOperationException("Memory is already powered off");
}
Debug.Assert(power_status != PowerStatus.OFF, "Device is already powered off");

power_status = PowerStatus.STOPPING;
// Wait for message buffers to be empty.
while (!isDone())
{ }
powerOffTeardown();
powerOffCheck();

Debug.Assert(power_status == PowerStatus.OFF, "Device failed to power off");
Debug.Assert(thread?.IsAlive == false, "Device thread is still running");
}

public virtual void powerOffTeardown()
{
requested_power_off = true;
thread?.Join();
}
public virtual void powerOffCheck()
{
if (power_status != PowerStatus.OFF)
{
throw new InvalidOperationException("Memory failed to power off");
}
}

public PowerStatus getPowerStatus()
{
return power_status;
}

public bool isInMyAddressRange(Address address)
public virtual bool isInMyAddressRange(Address address)
{
return address_range?.contains(address) ?? false;
throw new NotImplementedException();
}
}
}
2 changes: 1 addition & 1 deletion src/Bytom.Hardware/Devices/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Bytom.Hardware
{
public class Memory : MessageReceiver
public class Memory : SingleAddressDevice
{
public uint capacity_bytes { get; }
public uint write_latency_cycles { get; }
Expand Down
20 changes: 20 additions & 0 deletions src/Bytom.Hardware/Devices/MultiAddressDevice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;

namespace Bytom.Hardware
{
public class MultiAddressDevice : Device
{
public List<AddressRange> address_ranges { get; set; }

public MultiAddressDevice(uint max_tasks_running, Clock clock)
: base(max_tasks_running, clock)
{
address_ranges = new List<AddressRange>();
}

public override bool isInMyAddressRange(Address address)
{
return address_ranges.Exists(range => range.contains(address));
}
}
}
5 changes: 0 additions & 5 deletions src/Bytom.Hardware/Devices/RAM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ uint bandwidth_bytes
Array.Fill<byte>(memory, 0);
}

public override void beforeThreadStart()
{
address_range = memory_controller!.allocateAddressRange(capacity_bytes);
}

public override void powerOff()
{
base.powerOff();
Expand Down
16 changes: 16 additions & 0 deletions src/Bytom.Hardware/Devices/SingleAddressDevice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Bytom.Hardware
{
public class SingleAddressDevice : Device
{
public AddressRange? address_range { get; set; }

public SingleAddressDevice(uint max_tasks_running, Clock clock)
: base(max_tasks_running, clock)
{ }

public override bool isInMyAddressRange(Address address)
{
return address_range?.contains(address) ?? false;
}
}
}
Empty file.
Loading

0 comments on commit 4ab4784

Please sign in to comment.