diff --git a/src/main/java/li/cil/circuity/api/vm/MemoryMap.java b/src/main/java/li/cil/circuity/api/vm/MemoryMap.java
index 6e6e0ea2..d4c98c2d 100644
--- a/src/main/java/li/cil/circuity/api/vm/MemoryMap.java
+++ b/src/main/java/li/cil/circuity/api/vm/MemoryMap.java
@@ -4,6 +4,7 @@ import li.cil.circuity.api.vm.device.memory.MemoryAccessException;
import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice;
import javax.annotation.Nullable;
+import java.util.Optional;
import java.util.OptionalInt;
/**
@@ -20,11 +21,30 @@ public interface MemoryMap {
*/
OptionalInt findFreeRange(final int start, final int end, final int size);
+ /**
+ * Tries to add a new device to the mapping at the specified address.
+ *
+ * This can fail if the new device would overlap a memory range already occupied by
+ * an existing device. In that case this method will return false. Use
+ * {@link #findFreeRange(int, int, int)} to obtain an address the device can be
+ * added at.
+ *
+ * @param address the address to add the device add.
+ * @param device the device to add.
+ * @return true if the device was added; false otherwise.
+ */
boolean addDevice(final int address, final MemoryMappedDevice device);
+ /**
+ * Removes a device from the memory map.
+ *
+ * If the device is not in this map this is a no-op.
+ *
+ * @param device the device to remove.
+ */
void removeDevice(final MemoryMappedDevice device);
- int getDeviceAddress(final MemoryMappedDevice device);
+ Optional getMemoryRange(final MemoryMappedDevice device);
@Nullable
MemoryRange getMemoryRange(final int address);
diff --git a/src/main/java/li/cil/circuity/api/vm/MemoryRange.java b/src/main/java/li/cil/circuity/api/vm/MemoryRange.java
index baf23ffa..9882174c 100644
--- a/src/main/java/li/cil/circuity/api/vm/MemoryRange.java
+++ b/src/main/java/li/cil/circuity/api/vm/MemoryRange.java
@@ -22,6 +22,14 @@ public final class MemoryRange {
this(device, address, address + device.getLength() - 1);
}
+ public int address() {
+ return start;
+ }
+
+ public final int size() {
+ return end - start + 1;
+ }
+
public boolean contains(final int address) {
return Integer.compareUnsigned(address, start) >= 0 && Integer.compareUnsigned(address, end) <= 0;
}
diff --git a/src/main/java/li/cil/circuity/vm/SimpleMemoryMap.java b/src/main/java/li/cil/circuity/vm/SimpleMemoryMap.java
index e1eba63f..5d8fd6fc 100644
--- a/src/main/java/li/cil/circuity/vm/SimpleMemoryMap.java
+++ b/src/main/java/li/cil/circuity/vm/SimpleMemoryMap.java
@@ -8,6 +8,7 @@ import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import java.util.OptionalInt;
public final class SimpleMemoryMap implements MemoryMap {
@@ -65,13 +66,8 @@ public final class SimpleMemoryMap implements MemoryMap {
}
@Override
- public int getDeviceAddress(final MemoryMappedDevice device) {
- final MemoryRange range = devices.get(device);
- if (range != null) {
- return range.start;
- } else {
- return -1;
- }
+ public Optional getMemoryRange(final MemoryMappedDevice device) {
+ return Optional.ofNullable(devices.get(device));
}
@Nullable
diff --git a/src/main/java/li/cil/circuity/vm/devicetree/provider/CoreLocalInterrupterProvider.java b/src/main/java/li/cil/circuity/vm/devicetree/provider/CoreLocalInterrupterProvider.java
index 3b1b2261..a693cb14 100644
--- a/src/main/java/li/cil/circuity/vm/devicetree/provider/CoreLocalInterrupterProvider.java
+++ b/src/main/java/li/cil/circuity/vm/devicetree/provider/CoreLocalInterrupterProvider.java
@@ -1,6 +1,7 @@
package li.cil.circuity.vm.devicetree.provider;
import li.cil.circuity.api.vm.MemoryMap;
+import li.cil.circuity.api.vm.MemoryRange;
import li.cil.circuity.api.vm.device.Device;
import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice;
import li.cil.circuity.api.vm.devicetree.DeviceTree;
@@ -19,7 +20,8 @@ public final class CoreLocalInterrupterProvider implements DeviceTreeProvider {
@Override
public Optional createNode(final DeviceTree root, final MemoryMap memoryMap, final Device device, final String deviceName) {
- return Optional.of(root.find("/soc").getChild(deviceName, memoryMap.getDeviceAddress((MemoryMappedDevice) device)));
+ final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
+ return range.map(r -> root.find("/soc").getChild(deviceName, r.address()));
}
@Override
diff --git a/src/main/java/li/cil/circuity/vm/devicetree/provider/MemoryMappedDeviceProvider.java b/src/main/java/li/cil/circuity/vm/devicetree/provider/MemoryMappedDeviceProvider.java
index 54e3a1f2..49a98540 100644
--- a/src/main/java/li/cil/circuity/vm/devicetree/provider/MemoryMappedDeviceProvider.java
+++ b/src/main/java/li/cil/circuity/vm/devicetree/provider/MemoryMappedDeviceProvider.java
@@ -1,6 +1,7 @@
package li.cil.circuity.vm.devicetree.provider;
import li.cil.circuity.api.vm.MemoryMap;
+import li.cil.circuity.api.vm.MemoryRange;
import li.cil.circuity.api.vm.device.Device;
import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice;
import li.cil.circuity.api.vm.devicetree.DeviceTree;
@@ -14,15 +15,18 @@ public class MemoryMappedDeviceProvider implements DeviceTreeProvider {
@Override
public Optional createNode(final DeviceTree root, final MemoryMap memoryMap, final Device device, final String deviceName) {
- return Optional.of(root.getChild(deviceName, memoryMap.getDeviceAddress((MemoryMappedDevice) device)));
+ final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
+ return range.map(r -> root.getChild(deviceName, r.address()));
}
@Override
public void visit(final DeviceTree node, final MemoryMap memoryMap, final Device device) {
final MemoryMappedDevice mappedDevice = (MemoryMappedDevice) device;
+ final Optional range = memoryMap.getMemoryRange(mappedDevice);
+
// TODO in the future when we may want to change bus widths check parent for cell and size cell num.
- node.addProp(DeviceTreePropertyNames.REG,
- ((long) memoryMap.getDeviceAddress(mappedDevice)) & 0xFFFFFFFFL,
- ((long) mappedDevice.getLength()) & 0xFFFFFFFFL);
+ range.ifPresent(r -> node.addProp(DeviceTreePropertyNames.REG,
+ ((long) r.address()) & 0xFFFFFFFFL,
+ ((long) r.size()) & 0xFFFFFFFFL));
}
}
diff --git a/src/main/java/li/cil/circuity/vm/devicetree/provider/PhysicalMemoryProvider.java b/src/main/java/li/cil/circuity/vm/devicetree/provider/PhysicalMemoryProvider.java
index 0605f31e..8de1f002 100644
--- a/src/main/java/li/cil/circuity/vm/devicetree/provider/PhysicalMemoryProvider.java
+++ b/src/main/java/li/cil/circuity/vm/devicetree/provider/PhysicalMemoryProvider.java
@@ -19,6 +19,6 @@ public class PhysicalMemoryProvider implements DeviceTreeProvider {
@Override
public void visit(final DeviceTree node, final MemoryMap memoryMap, final Device device) {
- node.addProp(DeviceTreePropertyNames.DEVICE_TYPE, "memory");
+ node.addProp(DeviceTreePropertyNames.DEVICE_TYPE, DeviceNames.MEMORY);
}
}
diff --git a/src/main/java/li/cil/circuity/vm/devicetree/provider/PlatformLevelInterruptControllerProvider.java b/src/main/java/li/cil/circuity/vm/devicetree/provider/PlatformLevelInterruptControllerProvider.java
index 5ae86699..b8115cf7 100644
--- a/src/main/java/li/cil/circuity/vm/devicetree/provider/PlatformLevelInterruptControllerProvider.java
+++ b/src/main/java/li/cil/circuity/vm/devicetree/provider/PlatformLevelInterruptControllerProvider.java
@@ -1,6 +1,7 @@
package li.cil.circuity.vm.devicetree.provider;
import li.cil.circuity.api.vm.MemoryMap;
+import li.cil.circuity.api.vm.MemoryRange;
import li.cil.circuity.api.vm.device.Device;
import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice;
import li.cil.circuity.api.vm.devicetree.DeviceNames;
@@ -21,7 +22,8 @@ public final class PlatformLevelInterruptControllerProvider implements DeviceTre
@Override
public Optional createNode(final DeviceTree root, final MemoryMap memoryMap, final Device device, final String deviceName) {
- return Optional.of(root.find("/soc").getChild(deviceName, memoryMap.getDeviceAddress((MemoryMappedDevice) device)));
+ final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
+ return range.map(r -> root.find("/soc").getChild(deviceName, r.address()));
}
@Override