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