From: Christian Femers Date: Fri, 23 Aug 2019 02:42:13 +0000 (+0200) Subject: Moved main memory to machine module X-Git-Url: https://mograsim.net/gitweb/?a=commitdiff_plain;h=7e9243a7a0be91c87090ccd44c9de07f42c221e3;hp=a5b67d41510298139bbfa54d58d48fe440757925;p=Mograsim.git Moved main memory to machine module Maybe there is some better structure possible? --- diff --git a/net.mograsim.logic.core/META-INF/MANIFEST.MF b/net.mograsim.logic.core/META-INF/MANIFEST.MF index 7312d958..2aff2ab9 100644 --- a/net.mograsim.logic.core/META-INF/MANIFEST.MF +++ b/net.mograsim.logic.core/META-INF/MANIFEST.MF @@ -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 index 3e83832c..00000000 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemory.java +++ /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 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 index 33262717..00000000 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/components/memory/WordAddressableMemoryComponent.java +++ /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 getAllInputs() - { - return List.of(data, rWBit, address); - } - - @Override - public List getAllOutputs() - { - return List.of(data); - } -} \ No newline at end of file diff --git a/net.mograsim.logic.core/test/net/mograsim/logic/core/tests/ComponentTest.java b/net.mograsim.logic.core/test/net/mograsim/logic/core/tests/ComponentTest.java index 69251d73..f3f05bb3 100644 --- a/net.mograsim.logic.core/test/net/mograsim/logic/core/tests/ComponentTest.java +++ b/net.mograsim.logic.core/test/net/mograsim/logic/core/tests/ComponentTest.java @@ -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 index 464a8b10..00000000 --- a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/GUIMemoryWA.java +++ /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 index 339c238b..00000000 --- a/net.mograsim.logic.model/src/net/mograsim/logic/model/modeladapter/componentadapters/WordAddressableMemoryAdapter.java +++ /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 -{ - - @Override - public Class getSupportedClass() - { - return GUIMemoryWA.class; - } - - @SuppressWarnings("unused") - @Override - public void createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIMemoryWA guiComponent, - Map 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/.classpath b/net.mograsim.machine/.classpath index ca3785c4..6f92f68a 100644 --- a/net.mograsim.machine/.classpath +++ b/net.mograsim.machine/.classpath @@ -1,7 +1,17 @@ - + + + + + + + + + + + - + diff --git a/net.mograsim.machine/META-INF/MANIFEST.MF b/net.mograsim.machine/META-INF/MANIFEST.MF index 3be14f8a..518b6a13 100644 --- a/net.mograsim.machine/META-INF/MANIFEST.MF +++ b/net.mograsim.machine/META-INF/MANIFEST.MF @@ -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 index 00000000..3d63b470 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java @@ -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 index 00000000..719c993e --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java @@ -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 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 index 00000000..bc979dc7 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java @@ -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 +{ + + @Override + public Class getSupportedClass() + { + return GUIMemoryWA.class; + } + + @SuppressWarnings("unused") + @Override + public void createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIMemoryWA guiComponent, + Map 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 index 00000000..4a3edde2 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryComponent.java @@ -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 getAllInputs() + { + return List.of(data, rWBit, address); + } + + @Override + public List 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 index 00000000..a32cb6fe --- /dev/null +++ b/net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java @@ -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); + } + } + } + +}