Moved main memory to machine module
authorChristian Femers <femers@in.tum.de>
Fri, 23 Aug 2019 02:42:13 +0000 (04:42 +0200)
committerChristian Femers <femers@in.tum.de>
Fri, 23 Aug 2019 02:42:13 +0000 (04:42 +0200)
Maybe there is some better structure possible?

13 files changed:
net.mograsim.logic.core/META-INF/MANIFEST.MF
net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemory.java [deleted file]
net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemoryComponent.java [deleted file]
net.mograsim.logic.core/test/net/mograsim/logic/core/tests/ComponentTest.java
net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/GUIMemoryWA.java [deleted file]
net.mograsim.logic.model/src/net/mograsim/logic/model/modeladapter/componentadapters/WordAddressableMemoryAdapter.java [deleted file]
net.mograsim.machine/.classpath
net.mograsim.machine/META-INF/MANIFEST.MF
net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java [new file with mode: 0644]
net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java [new file with mode: 0644]
net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java [new file with mode: 0644]
net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryComponent.java [new file with mode: 0644]
net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java [new file with mode: 0644]

index 7312d95..2aff2ab 100644 (file)
@@ -6,7 +6,6 @@ Bundle-Version: 0.1.0.qualifier
 Export-Package: net.mograsim.logic.core,
  net.mograsim.logic.core.components,
  net.mograsim.logic.core.components.gates,
- net.mograsim.logic.core.components.memory,
  net.mograsim.logic.core.timeline,
  net.mograsim.logic.core.types,
  net.mograsim.logic.core.wires
diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemory.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemory.java
deleted file mode 100644 (file)
index 3e83832..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-package net.mograsim.logic.core.components.memory;
-
-import java.util.Arrays;
-import java.util.HashMap;
-
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-
-public class WordAddressableMemory
-{
-       private final int cellWidth;
-       private final long minimalAddress, maximalAddress;
-       private final int pageSize = 64;
-
-       private HashMap<Long, Page> pages;
-
-       public WordAddressableMemory(int cellWidth, long minimalAddress, long maximalAddress)
-       {
-               super();
-               this.cellWidth = cellWidth;
-               this.minimalAddress = minimalAddress;
-               this.maximalAddress = maximalAddress;
-               this.pages = new HashMap<>();
-       }
-
-       public void setCell(long address, BitVector b)
-       {
-               if (address < minimalAddress || address > maximalAddress)
-                       throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d",
-                                       minimalAddress, maximalAddress, address));
-               long page = address / pageSize;
-               int offset = (int) (address % pageSize);
-               Page p = pages.get(Long.valueOf(page));
-               if (p == null)
-                       pages.put(page, p = new Page());
-               p.setCell(offset, b);
-       }
-
-       public BitVector getCell(long address)
-       {
-               long page = address / pageSize;
-               int offset = (int) (address % pageSize);
-               Page p = pages.get(Long.valueOf(page));
-               if (p == null)
-                       return BitVector.of(Bit.U, cellWidth);
-               return p.getCell(offset);
-       }
-
-       private class Page
-       {
-               private BitVector[] memory;
-
-               public Page()
-               {
-                       memory = new BitVector[pageSize];
-               }
-
-               public BitVector getCell(int index)
-               {
-                       BitVector b = memory[index];
-                       if (b == null)
-                               return BitVector.of(Bit.U, cellWidth);
-                       return memory[index];
-               }
-
-               public void setCell(int index, BitVector bits)
-               {
-                       if (bits.length() != cellWidth)
-                               throw new IllegalArgumentException(String.format(
-                                               "BitVector to be saved in memory cell has unexpected length. Expected: %d Actual: %d", cellWidth, bits.length()));
-                       memory[index] = bits;
-               }
-
-               @Override
-               public String toString()
-               {
-                       return Arrays.deepToString(memory);
-               }
-       }
-}
diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemoryComponent.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemoryComponent.java
deleted file mode 100644 (file)
index 3326271..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-package net.mograsim.logic.core.components.memory;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-/**
- * A memory component that only allows access to words of a specific length
- */
-public class WordAddressableMemoryComponent extends BasicComponent
-{
-       private final WordAddressableMemory memory;
-       private final static Bit read = Bit.ONE;
-
-       private ReadWriteEnd data;
-       private ReadEnd rWBit, address;
-
-       /**
-        * @param data    The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
-        *                a memory word
-        * @param rWBit   The value of the 0th bit dictates the mode: 0: Write, 1: Read
-        * @param address The bits of this ReadEnd address the memory cell to read/write
-        */
-       public WordAddressableMemoryComponent(Timeline timeline, int processTime, long minimalAddress, long maximalAddress, ReadWriteEnd data,
-                       ReadEnd rWBit, ReadEnd address)
-       {
-               super(timeline, processTime);
-               this.data = data;
-               this.rWBit = rWBit;
-               this.address = address;
-               data.registerObserver(this);
-               rWBit.registerObserver(this);
-               address.registerObserver(this);
-
-               memory = new WordAddressableMemory(data.length(), minimalAddress, maximalAddress);
-       }
-
-       @Override
-       protected void compute()
-       {
-               if (!address.hasNumericValue())
-               {
-                       if (read.equals(rWBit.getValue()))
-                               data.feedSignals(BitVector.of(Bit.U, data.length()));
-                       else
-                               data.clearSignals();
-                       return;
-               }
-               long addressed = address.getUnsignedValue();
-               if (read.equals(rWBit.getValue()))
-                       data.feedSignals(memory.getCell(addressed));
-               else
-               {
-                       data.clearSignals();
-                       memory.setCell(addressed, data.getValues());
-               }
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(data, rWBit, address);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(data);
-       }
-}
\ No newline at end of file
index 6055296..d0ae8c5 100644 (file)
@@ -23,7 +23,6 @@ import net.mograsim.logic.core.components.gates.NorGate;
 import net.mograsim.logic.core.components.gates.NotGate;
 import net.mograsim.logic.core.components.gates.OrGate;
 import net.mograsim.logic.core.components.gates.XorGate;
-import net.mograsim.logic.core.components.memory.WordAddressableMemoryComponent;
 import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.Bit;
 import net.mograsim.logic.core.types.BitVector;
@@ -519,47 +518,6 @@ class ComponentTest
                test2.assertAfterSimulationIs(Bit.ONE);
        }
 
-       @Test
-       public void wordAddressableMemoryLargeTest()
-       {
-               Wire rW = new Wire(t, 1, 2);
-               Wire data = new Wire(t, 16, 2);
-               Wire address = new Wire(t, 64, 2);
-               ReadWriteEnd rWI = rW.createReadWriteEnd();
-               ReadWriteEnd dataI = data.createReadWriteEnd();
-               ReadWriteEnd addressI = address.createReadWriteEnd();
-
-               WordAddressableMemoryComponent memory = new WordAddressableMemoryComponent(t, 4, 4096L, Long.MAX_VALUE, data.createReadWriteEnd(),
-                               rW.createReadOnlyEnd(), address.createReadOnlyEnd());
-
-               Random r = new Random();
-               for (long j = 1; j > 0; j *= 2)
-               {
-                       for (int i = 0; i < 50; i++)
-                       {
-                               String sAddress = String.format("%64s", BigInteger.valueOf(4096 + i + j).toString(2)).replace(' ', '0');
-                               sAddress = new StringBuilder(sAddress).reverse().toString();
-                               BitVector bAddress = BitVector.parse(sAddress);
-                               addressI.feedSignals(bAddress);
-                               t.executeAll();
-                               String random = BigInteger.valueOf(Math.abs(r.nextInt())).toString(5);
-                               random = random.substring(Integer.max(0, random.length() - 16));
-                               random = String.format("%16s", random).replace(' ', '0');
-                               random = random.replace('2', 'X').replace('3', 'Z').replace('4', 'U');
-                               BitVector vector = BitVector.parse(random);
-                               dataI.feedSignals(vector);
-                               rWI.feedSignals(Bit.ZERO);
-                               t.executeAll();
-                               rWI.feedSignals(Bit.ONE);
-                               t.executeAll();
-                               dataI.clearSignals();
-                               t.executeAll();
-
-                               assertBitArrayEquals(dataI.getValues(), vector.getBits());
-                       }
-               }
-       }
-
        private static void assertBitArrayEquals(BitVector actual, Bit... expected)
        {
                assertArrayEquals(expected, actual.getBits());
diff --git a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/GUIMemoryWA.java b/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/GUIMemoryWA.java
deleted file mode 100644 (file)
index 464a8b1..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-package net.mograsim.logic.model.model.components.atomic;
-
-import org.eclipse.swt.graphics.Color;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import net.haspamelodica.swt.helper.gcs.GeneralGC;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
-import net.mograsim.logic.model.model.ViewModelModifiable;
-import net.mograsim.logic.model.model.components.GUIComponent;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter;
-import net.mograsim.logic.model.modeladapter.componentadapters.WordAddressableMemoryAdapter;
-import net.mograsim.logic.model.serializing.IdentifierGetter;
-import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
-import net.mograsim.preferences.Preferences;
-
-public class GUIMemoryWA extends GUIComponent
-{
-       private final static String paramAddr = "addrBits", paramWordWidth = "wordWidth", paramMaxAddr = "maxAddr", paramMinAddr = "minAddr";
-       private final int addressBits, wordWidth;
-       public final long maximalAddress, minimalAddress;
-       private final Pin addrPin, dataPin, rWPin;
-       private final static int width = 100, height = 300;
-
-       public GUIMemoryWA(ViewModelModifiable model, int addressBits, int wordWidth, long maximalAddress, long minimalAddress, String name)
-       {
-               super(model, name);
-               this.addressBits = addressBits;
-               this.wordWidth = wordWidth;
-               this.maximalAddress = maximalAddress;
-               this.minimalAddress = minimalAddress;
-               setSize(width, height);
-               addPin(addrPin = new Pin(this, "A", addressBits, 0, 10));
-               addPin(dataPin = new Pin(this, "D", wordWidth, 0, 30));
-               addPin(rWPin = new Pin(this, "RW", 1, 0, 50));
-       }
-
-       public Pin getAddressPin()
-       {
-               return addrPin;
-       }
-
-       public Pin getDataPin()
-       {
-               return dataPin;
-       }
-
-       public Pin getReadWritePin()
-       {
-               return rWPin;
-       }
-
-       @Override
-       public void render(GeneralGC gc, Rectangle visibleRegion)
-       {
-               // TODO This is copied from SimpleRectangularGUIGate; do this via delegation instead
-               Color foreground = Preferences.current().getColor("net.mograsim.logic.model.color.foreground");
-               if (foreground != null)
-                       gc.setForeground(foreground);
-               gc.drawRectangle(getPosX(), getPosY(), width, height);
-               Font oldFont = gc.getFont();
-               Font labelFont = new Font(oldFont.getName(), 24, oldFont.getStyle());
-               gc.setFont(labelFont);
-               String label = "RAM";
-               Point textExtent = gc.textExtent(label);
-               Color textColor = Preferences.current().getColor("net.mograsim.logic.model.color.text");
-               if (textColor != null)
-                       gc.setForeground(textColor);
-               gc.drawText(label, getPosX() + (width - textExtent.x) / 2, getPosY() + (height - textExtent.y) / 2, true);
-               gc.setFont(oldFont);
-       }
-
-       @Override
-       public JsonElement getParamsForSerializing(IdentifierGetter idGetter)
-       {
-               JsonObject obj = new JsonObject();
-               obj.addProperty(paramAddr, addressBits);
-               obj.addProperty(paramWordWidth, wordWidth);
-               obj.addProperty(paramMaxAddr, maximalAddress);
-               obj.addProperty(paramMinAddr, minimalAddress);
-               return obj;
-       }
-
-       static
-       {
-               ViewLogicModelAdapter.addComponentAdapter(new WordAddressableMemoryAdapter());
-               IndirectGUIComponentCreator.setComponentSupplier(GUIAndGate.class.getCanonicalName(), (m, p, n) ->
-               {
-                       JsonObject obj = p.getAsJsonObject();
-                       return new GUIMemoryWA(m, obj.get(paramAddr).getAsInt(), obj.get(paramWordWidth).getAsInt(), obj.get(paramMaxAddr).getAsLong(),
-                                       obj.get(paramMinAddr).getAsLong(), n);
-               });
-       }
-}
diff --git a/net.mograsim.logic.model/src/net/mograsim/logic/model/modeladapter/componentadapters/WordAddressableMemoryAdapter.java b/net.mograsim.logic.model/src/net/mograsim/logic/model/modeladapter/componentadapters/WordAddressableMemoryAdapter.java
deleted file mode 100644 (file)
index 339c238..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.mograsim.logic.model.modeladapter.componentadapters;
-
-import java.util.Map;
-
-import net.mograsim.logic.core.components.memory.WordAddressableMemoryComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-import net.mograsim.logic.model.model.components.atomic.GUIMemoryWA;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.LogicModelParameters;
-
-public class WordAddressableMemoryAdapter implements ComponentAdapter<GUIMemoryWA>
-{
-
-       @Override
-       public Class<GUIMemoryWA> getSupportedClass()
-       {
-               return GUIMemoryWA.class;
-       }
-
-       @SuppressWarnings("unused")
-       @Override
-       public void createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIMemoryWA guiComponent,
-                       Map<Pin, Wire> logicWiresPerPin)
-       {
-               ReadWriteEnd data = logicWiresPerPin.get(guiComponent.getDataPin()).createReadWriteEnd();
-               ReadEnd address = logicWiresPerPin.get(guiComponent.getAddressPin()).createReadOnlyEnd();
-               ReadEnd mode = logicWiresPerPin.get(guiComponent.getReadWritePin()).createReadOnlyEnd();
-               new WordAddressableMemoryComponent(timeline, 2, guiComponent.maximalAddress, guiComponent.minimalAddress, data, mode, address);
-       }
-
-}
index e801ebf..c9d880b 100644 (file)
@@ -1,7 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+       <classpathentry kind="src" output="bin/src" path="src"/>
+       <classpathentry kind="src" output="bin/test" path="test">
+               <attributes>
+                       <attribute name="test" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+               <attributes>
+                       <attribute name="module" value="true"/>
+               </attributes>
+       </classpathentry>
        <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
index 3be14f8..518b6a1 100644 (file)
@@ -7,5 +7,9 @@ Bundle-Vendor: Mograsim Team
 Automatic-Module-Name: net.mograsim.machine
 Bundle-RequiredExecutionEnvironment: JavaSE-11
 Require-Bundle: net.mograsim.logic.core;bundle-version="0.1.0",
- net.mograsim.logic.model;bundle-version="0.1.0"
-Export-Package: net.mograsim.machine.isa
+ net.mograsim.logic.model;bundle-version="0.1.0",
+ net.mograsim.preferences
+Export-Package: net.mograsim.machine,
+ net.mograsim.machine.isa,
+ net.mograsim.machine.isa.types,
+ net.mograsim.machine.standard.memory
diff --git a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java
new file mode 100644 (file)
index 0000000..3d63b47
--- /dev/null
@@ -0,0 +1,98 @@
+package net.mograsim.machine.standard.memory;
+
+import org.eclipse.swt.graphics.Color;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import net.haspamelodica.swt.helper.gcs.GeneralGC;
+import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
+import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
+import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
+import net.mograsim.logic.model.model.ViewModelModifiable;
+import net.mograsim.logic.model.model.components.GUIComponent;
+import net.mograsim.logic.model.model.components.atomic.GUIAndGate;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter;
+import net.mograsim.logic.model.serializing.IdentifierGetter;
+import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
+import net.mograsim.preferences.Preferences;
+
+public class GUIMemoryWA extends GUIComponent
+{
+       private final static String paramAddr = "addrBits", paramWordWidth = "wordWidth", paramMaxAddr = "maxAddr", paramMinAddr = "minAddr";
+       private final int addressBits, wordWidth;
+       public final long maximalAddress, minimalAddress;
+       private final Pin addrPin, dataPin, rWPin;
+       private final static int width = 100, height = 300;
+
+       public GUIMemoryWA(ViewModelModifiable model, int addressBits, int wordWidth, long maximalAddress, long minimalAddress, String name)
+       {
+               super(model, name);
+               this.addressBits = addressBits;
+               this.wordWidth = wordWidth;
+               this.maximalAddress = maximalAddress;
+               this.minimalAddress = minimalAddress;
+               setSize(width, height);
+               addPin(addrPin = new Pin(this, "A", addressBits, 0, 10));
+               addPin(dataPin = new Pin(this, "D", wordWidth, 0, 30));
+               addPin(rWPin = new Pin(this, "RW", 1, 0, 50));
+       }
+
+       public Pin getAddressPin()
+       {
+               return addrPin;
+       }
+
+       public Pin getDataPin()
+       {
+               return dataPin;
+       }
+
+       public Pin getReadWritePin()
+       {
+               return rWPin;
+       }
+
+       @Override
+       public void render(GeneralGC gc, Rectangle visibleRegion)
+       {
+               // TODO This is copied from SimpleRectangularGUIGate; do this via delegation instead
+               Color foreground = Preferences.current().getColor("net.mograsim.logic.model.color.foreground");
+               if (foreground != null)
+                       gc.setForeground(foreground);
+               gc.drawRectangle(getPosX(), getPosY(), width, height);
+               Font oldFont = gc.getFont();
+               Font labelFont = new Font(oldFont.getName(), 24, oldFont.getStyle());
+               gc.setFont(labelFont);
+               String label = "RAM";
+               Point textExtent = gc.textExtent(label);
+               Color textColor = Preferences.current().getColor("net.mograsim.logic.model.color.text");
+               if (textColor != null)
+                       gc.setForeground(textColor);
+               gc.drawText(label, getPosX() + (width - textExtent.x) / 2, getPosY() + (height - textExtent.y) / 2, true);
+               gc.setFont(oldFont);
+       }
+
+       @Override
+       public JsonElement getParamsForSerializing(IdentifierGetter idGetter)
+       {
+               JsonObject obj = new JsonObject();
+               obj.addProperty(paramAddr, addressBits);
+               obj.addProperty(paramWordWidth, wordWidth);
+               obj.addProperty(paramMaxAddr, maximalAddress);
+               obj.addProperty(paramMinAddr, minimalAddress);
+               return obj;
+       }
+
+       static
+       {
+               ViewLogicModelAdapter.addComponentAdapter(new WordAddressableMemoryAdapter());
+               IndirectGUIComponentCreator.setComponentSupplier(GUIAndGate.class.getCanonicalName(), (m, p, n) ->
+               {
+                       JsonObject obj = p.getAsJsonObject();
+                       return new GUIMemoryWA(m, obj.get(paramAddr).getAsInt(), obj.get(paramWordWidth).getAsInt(), obj.get(paramMaxAddr).getAsLong(),
+                                       obj.get(paramMinAddr).getAsLong(), n);
+               });
+       }
+}
diff --git a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java
new file mode 100644 (file)
index 0000000..719c993
--- /dev/null
@@ -0,0 +1,80 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+
+public class WordAddressableMemory
+{
+       private final int cellWidth;
+       private final long minimalAddress, maximalAddress;
+       private final int pageSize = 64;
+
+       private HashMap<Long, Page> pages;
+
+       public WordAddressableMemory(int cellWidth, long minimalAddress, long maximalAddress)
+       {
+               super();
+               this.cellWidth = cellWidth;
+               this.minimalAddress = minimalAddress;
+               this.maximalAddress = maximalAddress;
+               this.pages = new HashMap<>();
+       }
+
+       public void setCell(long address, BitVector b)
+       {
+               if (address < minimalAddress || address > maximalAddress)
+                       throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d",
+                                       minimalAddress, maximalAddress, address));
+               long page = address / pageSize;
+               int offset = (int) (address % pageSize);
+               Page p = pages.get(Long.valueOf(page));
+               if (p == null)
+                       pages.put(page, p = new Page());
+               p.setCell(offset, b);
+       }
+
+       public BitVector getCell(long address)
+       {
+               long page = address / pageSize;
+               int offset = (int) (address % pageSize);
+               Page p = pages.get(Long.valueOf(page));
+               if (p == null)
+                       return BitVector.of(Bit.U, cellWidth);
+               return p.getCell(offset);
+       }
+
+       private class Page
+       {
+               private BitVector[] memory;
+
+               public Page()
+               {
+                       memory = new BitVector[pageSize];
+               }
+
+               public BitVector getCell(int index)
+               {
+                       BitVector b = memory[index];
+                       if (b == null)
+                               return BitVector.of(Bit.U, cellWidth);
+                       return memory[index];
+               }
+
+               public void setCell(int index, BitVector bits)
+               {
+                       if (bits.length() != cellWidth)
+                               throw new IllegalArgumentException(String.format(
+                                               "BitVector to be saved in memory cell has unexpected length. Expected: %d Actual: %d", cellWidth, bits.length()));
+                       memory[index] = bits;
+               }
+
+               @Override
+               public String toString()
+               {
+                       return Arrays.deepToString(memory);
+               }
+       }
+}
diff --git a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java
new file mode 100644 (file)
index 0000000..bc979dc
--- /dev/null
@@ -0,0 +1,33 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.Map;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.wires.Wire;
+import net.mograsim.logic.core.wires.Wire.ReadEnd;
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.modeladapter.LogicModelParameters;
+import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
+
+public class WordAddressableMemoryAdapter implements ComponentAdapter<GUIMemoryWA>
+{
+
+       @Override
+       public Class<GUIMemoryWA> getSupportedClass()
+       {
+               return GUIMemoryWA.class;
+       }
+
+       @SuppressWarnings("unused")
+       @Override
+       public void createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIMemoryWA guiComponent,
+                       Map<Pin, Wire> logicWiresPerPin)
+       {
+               ReadWriteEnd data = logicWiresPerPin.get(guiComponent.getDataPin()).createReadWriteEnd();
+               ReadEnd address = logicWiresPerPin.get(guiComponent.getAddressPin()).createReadOnlyEnd();
+               ReadEnd mode = logicWiresPerPin.get(guiComponent.getReadWritePin()).createReadOnlyEnd();
+               new WordAddressableMemoryComponent(timeline, 2, guiComponent.maximalAddress, guiComponent.minimalAddress, data, mode, address);
+       }
+
+}
diff --git a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryComponent.java b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryComponent.java
new file mode 100644 (file)
index 0000000..4a3edde
--- /dev/null
@@ -0,0 +1,75 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.List;
+
+import net.mograsim.logic.core.components.BasicComponent;
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.Wire.ReadEnd;
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
+
+/**
+ * A memory component that only allows access to words of a specific length
+ */
+public class WordAddressableMemoryComponent extends BasicComponent
+{
+       private final WordAddressableMemory memory;
+       private final static Bit read = Bit.ONE;
+
+       private ReadWriteEnd data;
+       private ReadEnd rWBit, address;
+
+       /**
+        * @param data    The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
+        *                a memory word
+        * @param rWBit   The value of the 0th bit dictates the mode: 0: Write, 1: Read
+        * @param address The bits of this ReadEnd address the memory cell to read/write
+        */
+       public WordAddressableMemoryComponent(Timeline timeline, int processTime, long minimalAddress, long maximalAddress, ReadWriteEnd data,
+                       ReadEnd rWBit, ReadEnd address)
+       {
+               super(timeline, processTime);
+               this.data = data;
+               this.rWBit = rWBit;
+               this.address = address;
+               data.registerObserver(this);
+               rWBit.registerObserver(this);
+               address.registerObserver(this);
+
+               memory = new WordAddressableMemory(data.length(), minimalAddress, maximalAddress);
+       }
+
+       @Override
+       protected void compute()
+       {
+               if (!address.hasNumericValue())
+               {
+                       if (read.equals(rWBit.getValue()))
+                               data.feedSignals(BitVector.of(Bit.U, data.length()));
+                       else
+                               data.clearSignals();
+                       return;
+               }
+               long addressed = address.getUnsignedValue();
+               if (read.equals(rWBit.getValue()))
+                       data.feedSignals(memory.getCell(addressed));
+               else
+               {
+                       data.clearSignals();
+                       memory.setCell(addressed, data.getValues());
+               }
+       }
+
+       @Override
+       public List<ReadEnd> getAllInputs()
+       {
+               return List.of(data, rWBit, address);
+       }
+
+       @Override
+       public List<ReadWriteEnd> getAllOutputs()
+       {
+               return List.of(data);
+       }
+}
\ No newline at end of file
diff --git a/net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java b/net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java
new file mode 100644 (file)
index 0000000..74aeb3e
--- /dev/null
@@ -0,0 +1,61 @@
+package net.mograsim.machine.standard.memory;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.junit.jupiter.api.Test;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.Wire;
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
+
+class WordAddressableMemoryTest {
+       
+       private Timeline t = new Timeline(10);
+
+       @Test
+       public void wordAddressableMemoryLargeTest()
+       {
+               Wire rW = new Wire(t, 1, 2);
+               Wire data = new Wire(t, 16, 2);
+               Wire address = new Wire(t, 64, 2);
+               ReadWriteEnd rWI = rW.createReadWriteEnd();
+               ReadWriteEnd dataI = data.createReadWriteEnd();
+               ReadWriteEnd addressI = address.createReadWriteEnd();
+
+               WordAddressableMemoryComponent memory = new WordAddressableMemoryComponent(t, 4, 4096L, Long.MAX_VALUE, data.createReadWriteEnd(),
+                               rW.createReadOnlyEnd(), address.createReadOnlyEnd());
+
+               Random r = new Random();
+               for (long j = 1; j > 0; j *= 2)
+               {
+                       for (int i = 0; i < 50; i++)
+                       {
+                               String sAddress = String.format("%64s", BigInteger.valueOf(4096 + i + j).toString(2)).replace(' ', '0');
+                               sAddress = new StringBuilder(sAddress).reverse().toString();
+                               BitVector bAddress = BitVector.parse(sAddress);
+                               addressI.feedSignals(bAddress);
+                               t.executeAll();
+                               String random = BigInteger.valueOf(Math.abs(r.nextInt())).toString(5);
+                               random = random.substring(Integer.max(0, random.length() - 16));
+                               random = String.format("%16s", random).replace(' ', '0');
+                               random = random.replace('2', 'X').replace('3', 'Z').replace('4', 'U');
+                               BitVector vector = BitVector.parse(random);
+                               dataI.feedSignals(vector);
+                               rWI.feedSignals(Bit.ZERO);
+                               t.executeAll();
+                               rWI.feedSignals(Bit.ONE);
+                               t.executeAll();
+                               dataI.clearSignals();
+                               t.executeAll();
+
+                               assertEquals(dataI.getValues(), vector);
+                       }
+               }
+       }
+
+}