diff --git a/src/main/java/li/cil/circuity/Main.java b/src/main/java/li/cil/circuity/Main.java index 6b93da77..73e21880 100644 --- a/src/main/java/li/cil/circuity/Main.java +++ b/src/main/java/li/cil/circuity/Main.java @@ -1,7 +1,7 @@ package li.cil.circuity; import li.cil.circuity.api.vm.device.memory.PhysicalMemory; -import li.cil.circuity.vm.device.memory.ByteBufferMemory; +import li.cil.circuity.vm.device.memory.UnsafeMemory; import li.cil.circuity.vm.riscv.R5Board; import java.io.BufferedInputStream; @@ -9,8 +9,8 @@ import java.io.FileInputStream; public final class Main { public static void main(final String[] args) throws Exception { - final PhysicalMemory rom = new ByteBufferMemory(128 * 1024); - final PhysicalMemory memory = new ByteBufferMemory(48 * 1014 * 1024); + final PhysicalMemory rom = new UnsafeMemory(128 * 1024); + final PhysicalMemory memory = new UnsafeMemory(128 * 1014 * 1024); final R5Board board = new R5Board(); board.addDevice(0x80000000, rom); board.addDevice(0x80000000 + 0x400000, memory); @@ -31,9 +31,26 @@ public final class Main { final long start = System.currentTimeMillis(); - final int n = 40000; + final long n = 400_000_000; + final int stepn = 10_000; + final int hz = 30_000_000; + + long remaining = 0; for (int i = 0; i < n; i++) { - board.step(10000); + final long stepStart = System.currentTimeMillis(); + remaining += hz; + while (remaining > 0) { + board.step(stepn); + remaining -= stepn; + } + + final long elapsed = System.currentTimeMillis() - stepStart; + final long sleep = 1000 - elapsed; + if (sleep > 0) { +// Thread.sleep(sleep); + } else { + System.out.println("Running behind by " + (-sleep) + "ms..."); + } } final long duration = System.currentTimeMillis() - start; diff --git a/src/main/java/li/cil/circuity/api/vm/device/memory/PhysicalMemory.java b/src/main/java/li/cil/circuity/api/vm/device/memory/PhysicalMemory.java index 1dad4f8f..b543f4bb 100644 --- a/src/main/java/li/cil/circuity/api/vm/device/memory/PhysicalMemory.java +++ b/src/main/java/li/cil/circuity/api/vm/device/memory/PhysicalMemory.java @@ -2,8 +2,6 @@ package li.cil.circuity.api.vm.device.memory; import li.cil.circuity.api.vm.MemoryMap; -import java.nio.ByteBuffer; - /** * Instances marked with this interface can be treated as random-access memory. *

@@ -11,5 +9,4 @@ import java.nio.ByteBuffer; * region can be stored in a translation lookaside buffer. */ public interface PhysicalMemory extends MemoryMappedDevice { - ByteBuffer slice(final int offset, final int length); } diff --git a/src/main/java/li/cil/circuity/vm/device/UART16550A.java b/src/main/java/li/cil/circuity/vm/device/UART16550A.java index 6c2daadf..417dfc4c 100644 --- a/src/main/java/li/cil/circuity/vm/device/UART16550A.java +++ b/src/main/java/li/cil/circuity/vm/device/UART16550A.java @@ -7,6 +7,7 @@ import li.cil.circuity.api.vm.device.InterruptSource; import li.cil.circuity.api.vm.device.Resettable; import li.cil.circuity.api.vm.device.Steppable; import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice; +import li.cil.circuity.api.vm.device.memory.Sizes; import java.util.Collections; @@ -221,7 +222,7 @@ public final class UART16550A implements Resettable, Steppable, MemoryMappedDevi @Override public int load(final int offset, final int sizeLog2) { - assert sizeLog2 == 0; + assert sizeLog2 == Sizes.SIZE_8_LOG2; switch (offset) { // case UART_DLL_OFFSET: case UART_RBR_OFFSET: { @@ -318,7 +319,7 @@ public final class UART16550A implements Resettable, Steppable, MemoryMappedDevi @Override public void store(final int offset, final int value, final int sizeLog2) { - assert sizeLog2 == 0; + assert sizeLog2 == Sizes.SIZE_8_LOG2; switch (offset) { // case UART_DLL_OFFSET: case UART_THR_OFFSET: { diff --git a/src/main/java/li/cil/circuity/vm/device/memory/ByteBufferMemory.java b/src/main/java/li/cil/circuity/vm/device/memory/ByteBufferMemory.java index 6ddb4bc3..86671897 100644 --- a/src/main/java/li/cil/circuity/vm/device/memory/ByteBufferMemory.java +++ b/src/main/java/li/cil/circuity/vm/device/memory/ByteBufferMemory.java @@ -62,14 +62,4 @@ public class ByteBufferMemory implements PhysicalMemory { } } - @Override - public ByteBuffer slice(final int offset, final int length) { - final int limit = data.limit(); - data.position(offset); - data.limit(offset + length); - final ByteBuffer result = data.slice(); - result.order(ByteOrder.LITTLE_ENDIAN); - data.limit(limit); - return result; - } } diff --git a/src/main/java/li/cil/circuity/vm/riscv/R5CPU.java b/src/main/java/li/cil/circuity/vm/riscv/R5CPU.java index 342b0cfa..8035eda4 100644 --- a/src/main/java/li/cil/circuity/vm/riscv/R5CPU.java +++ b/src/main/java/li/cil/circuity/vm/riscv/R5CPU.java @@ -1845,27 +1845,27 @@ public class R5CPU implements Steppable, InterruptController { } private byte load8(final int address) throws MemoryAccessException { - return (byte) load(address, 8, 0); + return (byte) load(address, Sizes.SIZE_8, Sizes.SIZE_8_LOG2); } private void store8(final int address, final byte value) throws MemoryAccessException { - store(address, value, 8, 0); + store(address, value, Sizes.SIZE_8, Sizes.SIZE_8_LOG2); } private short load16(final int address) throws MemoryAccessException { - return (short) load(address, 16, 1); + return (short) load(address, Sizes.SIZE_16, Sizes.SIZE_16_LOG2); } private void store16(final int address, final short value) throws MemoryAccessException { - store(address, value, 16, 1); + store(address, value, Sizes.SIZE_16, Sizes.SIZE_16_LOG2); } private int load32(final int address) throws MemoryAccessException { - return load(address, 32, 2); + return load(address, Sizes.SIZE_32, Sizes.SIZE_32_LOG2); } private void store32(final int address, final int value) throws MemoryAccessException { - store(address, value, 32, 2); + store(address, value, Sizes.SIZE_32, Sizes.SIZE_32_LOG2); } private int fetch(final int address) throws MemoryAccessException { @@ -1890,16 +1890,7 @@ public class R5CPU implements Steppable, InterruptController { final int virtualAddress = address & ~(R5.PAGE_ADDRESS_MASK & ~alignmentMask); final TLBEntry entry = tlb_read[tlbIndex]; if (entry.virtualAddress == virtualAddress) { - switch (sizeLog2) { - case 0: - return entry.memory.get(address + entry.toLocal); - case 1: - return entry.memory.getShort(address + entry.toLocal); - case 2: - return entry.memory.getInt(address + entry.toLocal); - default: - throw new AssertionError(); - } + return entry.device.load(address + entry.toOffset, sizeLog2); } else { return loadSlow(address, sizeLog2); } @@ -1912,19 +1903,7 @@ public class R5CPU implements Steppable, InterruptController { final int virtualAddress = address & ~(R5.PAGE_ADDRESS_MASK & ~alignmentMask); final TLBEntry entry = tlb_write[tlbIndex]; if (entry.virtualAddress == virtualAddress) { - switch (sizeLog2) { - case 0: - entry.memory.put(address + entry.toLocal, (byte) value); - break; - case 1: - entry.memory.putShort(address + entry.toLocal, (short) value); - break; - case 2: - entry.memory.putInt(address + entry.toLocal, value); - break; - default: - throw new AssertionError(); - } + entry.device.store(address + entry.toOffset, value, sizeLog2); } else { storeSlow(address, value, sizeLog2); } @@ -1954,17 +1933,7 @@ public class R5CPU implements Steppable, InterruptController { return 0; } else if (range.device instanceof PhysicalMemory) { final TLBEntry entry = updateTLB(tlb_read, address, physicalAddress, range); - final int offset = address + entry.toLocal; - switch (sizeLog2) { - case 0: - return entry.memory.get(offset); - case 1: - return entry.memory.getShort(offset); - case 2: - return entry.memory.getInt(offset); - default: - throw new AssertionError(); - } + return entry.device.load(address + entry.toOffset, sizeLog2); } else { return range.device.load(physicalAddress - range.start, sizeLog2); } @@ -1983,21 +1952,8 @@ public class R5CPU implements Steppable, InterruptController { LOGGER.debug("Trying to store to invalid physical address [{}].", address); } else if (range.device instanceof PhysicalMemory) { final TLBEntry entry = updateTLB(tlb_write, address, physicalAddress, range); - final int offset = address + entry.toLocal; - switch (sizeLog2) { - case 0: - entry.memory.put(offset, (byte) value); - break; - case 1: - entry.memory.putShort(offset, (short) value); - break; - case 2: - entry.memory.putInt(offset, value); - break; - default: - throw new AssertionError(); - } - + final int offset = address + entry.toOffset; + entry.device.store(offset, value, sizeLog2); physicalMemory.setDirty(range, offset); } else { range.device.store(physicalAddress - range.start, value, sizeLog2); @@ -2108,12 +2064,10 @@ public class R5CPU implements Steppable, InterruptController { final int tlbIndex = (address >>> R5.PAGE_ADDRESS_SHIFT) & (TLB_SIZE - 1); final int virtualAddress = address & ~R5.PAGE_ADDRESS_MASK; - // TODO Only grab a slice as big as the memory region covered by the TLB entry... I can't math right now. - final TLBEntry entry = tlb[tlbIndex]; entry.virtualAddress = virtualAddress; - entry.toLocal = physicalAddress - address - range.start; - entry.memory = ((PhysicalMemory) range.device).slice(0, range.end - range.start + 1); + entry.toOffset = physicalAddress - address - range.start; + entry.device = range.device; return entry; } @@ -2176,8 +2130,8 @@ public class R5CPU implements Steppable, InterruptController { private static final class TLBEntry { public int virtualAddress = -1; - public int toLocal; - public ByteBuffer memory; + public int toOffset; + public MemoryMappedDevice device; } public R5CPUStateSnapshot getState() { diff --git a/src/main/java/li/cil/circuity/vm/riscv/device/R5CoreLocalInterrupter.java b/src/main/java/li/cil/circuity/vm/riscv/device/R5CoreLocalInterrupter.java index cd6462c4..b9fe4bc7 100644 --- a/src/main/java/li/cil/circuity/vm/riscv/device/R5CoreLocalInterrupter.java +++ b/src/main/java/li/cil/circuity/vm/riscv/device/R5CoreLocalInterrupter.java @@ -4,6 +4,7 @@ import li.cil.circuity.api.vm.Interrupt; import li.cil.circuity.api.vm.device.InterruptSource; import li.cil.circuity.api.vm.device.Steppable; import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice; +import li.cil.circuity.api.vm.device.memory.Sizes; import li.cil.circuity.api.vm.device.rtc.RealTimeCounter; import li.cil.circuity.vm.riscv.R5; @@ -56,7 +57,7 @@ public final class R5CoreLocalInterrupter implements Steppable, InterruptSource, @Override public int load(final int offset, final int sizeLog2) { - assert sizeLog2 == 2; + assert sizeLog2 == Sizes.SIZE_32_LOG2; switch (offset) { case 0x4000: { return (int) mtimecmp; @@ -78,7 +79,7 @@ public final class R5CoreLocalInterrupter implements Steppable, InterruptSource, @Override public void store(final int offset, final int value, final int sizeLog2) { - assert sizeLog2 == 2; + assert sizeLog2 == Sizes.SIZE_32_LOG2; switch (offset) { case 0x4000: { mtimecmp = (mtimecmp & ~0xFFFFFFFFL) | (value & 0xFFFFFFFFL); diff --git a/src/main/java/li/cil/circuity/vm/riscv/device/R5HostTargetInterface.java b/src/main/java/li/cil/circuity/vm/riscv/device/R5HostTargetInterface.java index d6a6ebc8..83dc5fa2 100644 --- a/src/main/java/li/cil/circuity/vm/riscv/device/R5HostTargetInterface.java +++ b/src/main/java/li/cil/circuity/vm/riscv/device/R5HostTargetInterface.java @@ -1,6 +1,7 @@ package li.cil.circuity.vm.riscv.device; import li.cil.circuity.api.vm.device.memory.MemoryMappedDevice; +import li.cil.circuity.api.vm.device.memory.Sizes; public final class R5HostTargetInterface implements MemoryMappedDevice { public static final int COMMAND_POWER_OFF = 1; @@ -14,7 +15,7 @@ public final class R5HostTargetInterface implements MemoryMappedDevice { @Override public int load(final int offset, final int sizeLog2) { - assert sizeLog2 == 2; + assert sizeLog2 == Sizes.SIZE_32_LOG2; switch (offset) { case 0: { return (int) toHost; @@ -37,7 +38,7 @@ public final class R5HostTargetInterface implements MemoryMappedDevice { @Override public void store(final int offset, final int value, final int sizeLog2) { - assert sizeLog2 == 2; + assert sizeLog2 == Sizes.SIZE_32_LOG2; switch (offset) { case 0: { toHost = (toHost & ~0xFFFFFFFFL) | value;