Unified API of memory map a bit.

This commit is contained in:
Florian Nücke
2020-09-13 11:42:23 +02:00
parent 2b3399321e
commit fbcf484940
7 changed files with 47 additions and 15 deletions

View File

@@ -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.
* <p>
* 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 <code>false</code>. 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 <code>true</code> if the device was added; <code>false</code> otherwise.
*/
boolean addDevice(final int address, final MemoryMappedDevice device);
/**
* Removes a device from the memory map.
* <p>
* 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<MemoryRange> getMemoryRange(final MemoryMappedDevice device);
@Nullable
MemoryRange getMemoryRange(final int address);

View File

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

View File

@@ -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<MemoryRange> getMemoryRange(final MemoryMappedDevice device) {
return Optional.ofNullable(devices.get(device));
}
@Nullable

View File

@@ -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<DeviceTree> 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<MemoryRange> range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
return range.map(r -> root.find("/soc").getChild(deviceName, r.address()));
}
@Override

View File

@@ -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<DeviceTree> 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<MemoryRange> 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<MemoryRange> 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));
}
}

View File

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

View File

@@ -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<DeviceTree> 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<MemoryRange> range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
return range.map(r -> root.find("/soc").getChild(deviceName, r.address()));
}
@Override