From 97fd4dc20d7db4f5b3d162f56910df4fc56b7871 Mon Sep 17 00:00:00 2001 From: Fabian Stemmler Date: Sat, 31 Aug 2019 16:47:18 +0200 Subject: [PATCH] Fleshed out Memory and Microprogramming interfaces --- .../machine/DefaultMainMemoryDefinition.java | 45 ------ .../net/mograsim/machine/GenericMemory.java | 119 +++++++++++++++ .../src/net/mograsim/machine/MainMemory.java | 10 +- .../machine/MainMemoryDefinition.java | 38 +---- .../src/net/mograsim/machine/Memory.java | 8 +- .../mograsim/machine/MemoryDefinition.java | 44 ++++++ .../mograsim/machine/MicroprogramMemory.java | 5 - .../machine/StandardMainMemoryDefinition.java | 17 +++ .../machine/StandardMemoryDefinition.java | 42 +++++ .../machine/{ => mi}/MicroInstruction.java | 8 +- .../{ => mi}/MicroInstructionDefinition.java | 14 +- .../machine/mi/MicroprogramMemory.java | 12 ++ .../machine/mi/MicroprogramMemoryParser.java | 94 ++++++++++++ .../machine/mi/StandardMicroInstruction.java | 38 +++++ .../StandardMicroInstructionDefinition.java | 26 ++++ .../mi/StandardMicroprogramMemory.java | 64 ++++++++ .../mi/parameters/BooleanClassification.java | 6 + .../mi/parameters/IntegerClassification.java | 8 + .../machine/mi/parameters/MnemonicFamily.java | 13 +- .../parameters/ParameterClassification.java | 2 + .../parameters/UnknownMnemonicException.java | 26 ++++ .../machine/standard/memory/GUIMemoryWA.java | 19 ++- .../memory/WordAddressableMemory.java | 143 ++---------------- .../memory/WordAddressableMemoryTest.java | 5 +- 24 files changed, 568 insertions(+), 238 deletions(-) delete mode 100644 net.mograsim.machine/src/net/mograsim/machine/DefaultMainMemoryDefinition.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java delete mode 100644 net.mograsim.machine/src/net/mograsim/machine/MicroprogramMemory.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java rename net.mograsim.machine/src/net/mograsim/machine/{ => mi}/MicroInstruction.java (57%) rename net.mograsim.machine/src/net/mograsim/machine/{ => mi}/MicroInstructionDefinition.java (64%) create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemory.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParser.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstruction.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionDefinition.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroprogramMemory.java create mode 100644 net.mograsim.machine/src/net/mograsim/machine/mi/parameters/UnknownMnemonicException.java diff --git a/net.mograsim.machine/src/net/mograsim/machine/DefaultMainMemoryDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/DefaultMainMemoryDefinition.java deleted file mode 100644 index 2431b65a..00000000 --- a/net.mograsim.machine/src/net/mograsim/machine/DefaultMainMemoryDefinition.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.mograsim.machine; - -public class DefaultMainMemoryDefinition implements MainMemoryDefinition { - private final int memoryAddressBits, cellWidth; - private final long minimalAddress, maximalAddress; - - public DefaultMainMemoryDefinition(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress) - { - super(); - this.memoryAddressBits = memoryAddressBits; - this.cellWidth = cellWidth; - this.minimalAddress = minimalAddress; - this.maximalAddress = maximalAddress; - } - - public DefaultMainMemoryDefinition(MainMemoryDefinition definition) - { - this(definition.getMemoryAddressBits(), definition.getCellWidth(), definition.getMinimalAddress(), definition.getMaximalAddress()); - } - - @Override - public int getMemoryAddressBits() - { - return memoryAddressBits; - } - - @Override - public int getCellWidth() - { - return cellWidth; - } - - @Override - public long getMinimalAddress() - { - return minimalAddress; - } - - @Override - public long getMaximalAddress() - { - return maximalAddress; - } - -} diff --git a/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java b/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java new file mode 100644 index 00000000..f01f9df8 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java @@ -0,0 +1,119 @@ +package net.mograsim.machine; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public abstract class GenericMemory implements Memory +{ + private final long minimalAddress, maximalAddress; + private final MemoryDefinition definition; + private final int pageSize = 64; + private Set observers = new HashSet<>(); + + private HashMap pages; + + public GenericMemory(MemoryDefinition definition) + { + super(); + this.definition = definition; + this.minimalAddress = definition.getMinimalAddress(); + this.maximalAddress = definition.getMaximalAddress(); + this.pages = new HashMap<>(); + } + + private void inBoundsCheck(long address) + { + if (address < minimalAddress || address > maximalAddress) + throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d", + minimalAddress, maximalAddress, address)); + } + + private long page(long address) + { + return address / pageSize; + } + + private int offset(long address) + { + return (int) (address % pageSize); + } + + @Override + public void setCell(long address, T data) + { + inBoundsCheck(address); + long page = page(address); + int offset = offset(address); + Page p = pages.get(Long.valueOf(page)); + if (p == null) + pages.put(page, p = new Page()); + p.setCell(offset, data); + notifyObservers(address); + } + + @Override + public T getCell(long address) + { + inBoundsCheck(address); + long page = page(address); + int offset = offset(address); + Page p = pages.get(Long.valueOf(page)); + if (p == null) + return null; + return p.getCell(offset); + } + + private class Page + { + private Object[] memory; + + public Page() + { + memory = new Object[pageSize]; + } + + public T getCell(int index) + { + @SuppressWarnings("unchecked") + T data = (T) memory[index]; + return data; + } + + public void setCell(int index, T data) + { + memory[index] = data; + } + + @Override + public String toString() + { + return Arrays.deepToString(memory); + } + } + + @Override + public void registerObserver(MemoryObserver ob) + { + observers.add(ob); + } + + @Override + public void deregisterObserver(MemoryObserver ob) + { + observers.remove(ob); + } + + @Override + public void notifyObservers(long address) + { + observers.forEach(ob -> ob.update(address)); + } + + @Override + public MemoryDefinition getDefinition() + { + return definition; + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java b/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java index dcd3ee21..94140b73 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java +++ b/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java @@ -4,13 +4,11 @@ import java.math.BigInteger; import net.mograsim.logic.core.types.BitVector; -public interface MainMemory extends Memory { - +public interface MainMemory extends Memory +{ public BigInteger getCellAsBigInteger(long address); + public void setCellAsBigInteger(long address, BigInteger word); + public MainMemoryDefinition getDefinition(); - public default long size() - { - return getDefinition().size(); - } } diff --git a/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java index f01d119d..4f696736 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java +++ b/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java @@ -7,17 +7,8 @@ package net.mograsim.machine; * @author Christian Femers * */ -public interface MainMemoryDefinition { - - /** - * The number of bits that the main memory uses to address cells. Note that this - * does not need to equal {@link MachineDefinition#getAddressBits()}. - * - * @return the number of bits used to address a memory cell - * @author Christian Femers - */ - int getMemoryAddressBits(); - +public interface MainMemoryDefinition extends MemoryDefinition +{ /** * The width in bits of an addressable memory cell/unit. This is often 8 (= one * byte). The actual cells/lines of the memory may be a lot larger. @@ -26,30 +17,9 @@ public interface MainMemoryDefinition { * @author Christian Femers */ int getCellWidth(); - - /** - * The minimal address possible to address/use. This is usually 0. - * - * @return the minimal possible address. - * @author Christian Femers - */ - long getMinimalAddress(); - - /** - * The maximal address possible to address/use. - * - * @return the maximal possible address as unsigned long - * @author Christian Femers - */ - long getMaximalAddress(); - /** - * The size of the MainMemory as the amount of addressable memory cells. - * - * @return the amount of addressable memory cells - */ - default long size() + public static MainMemoryDefinition create(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress) { - return getMaximalAddress() - getMinimalAddress(); + return new StandardMainMemoryDefinition(memoryAddressBits, cellWidth, minimalAddress, maximalAddress); } } diff --git a/net.mograsim.machine/src/net/mograsim/machine/Memory.java b/net.mograsim.machine/src/net/mograsim/machine/Memory.java index e421e470..58798c39 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/Memory.java +++ b/net.mograsim.machine/src/net/mograsim/machine/Memory.java @@ -16,7 +16,11 @@ public interface Memory */ public void setCell(long address, T data); - public long size(); + public default long size() + { + MemoryDefinition def = getDefinition(); + return Long.max(0, def.getMaximalAddress() - def.getMinimalAddress()); + } /** * Registers an observer to be notified when a memory cell is modified @@ -26,4 +30,6 @@ public interface Memory public void deregisterObserver(MemoryObserver ob); public void notifyObservers(long address); + + public MemoryDefinition getDefinition(); } diff --git a/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java new file mode 100644 index 00000000..5f42d10c --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java @@ -0,0 +1,44 @@ +package net.mograsim.machine; + +public interface MemoryDefinition { + + /** + * The number of bits that the main memory uses to address cells. Note that this + * does not need to equal {@link MachineDefinition#getAddressBits()}. + * + * @return the number of bits used to address a memory cell + * @author Christian Femers + */ + int getMemoryAddressBits(); + + /** + * The minimal address possible to address/use. This is usually 0. + * + * @return the minimal possible address. + * @author Christian Femers + */ + long getMinimalAddress(); + + /** + * The maximal address possible to address/use. + * + * @return the maximal possible address as unsigned long + * @author Christian Femers + */ + long getMaximalAddress(); + + /** + * The size of the MainMemory as the amount of addressable memory cells. + * + * @return the amount of addressable memory cells + */ + default long size() + { + return getMaximalAddress() - getMinimalAddress(); + } + + public static MemoryDefinition create(int memoryAddressBits, long minimalAddress, long maximalAddress) + { + return new StandardMemoryDefinition(memoryAddressBits, minimalAddress, maximalAddress); + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/MicroprogramMemory.java b/net.mograsim.machine/src/net/mograsim/machine/MicroprogramMemory.java deleted file mode 100644 index 333f8a64..00000000 --- a/net.mograsim.machine/src/net/mograsim/machine/MicroprogramMemory.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.mograsim.machine; - -public interface MicroprogramMemory extends Memory -{ -} diff --git a/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java new file mode 100644 index 00000000..1e3bd50c --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java @@ -0,0 +1,17 @@ +package net.mograsim.machine; + +class StandardMainMemoryDefinition extends StandardMemoryDefinition implements MainMemoryDefinition { + private final int cellWidth; + + StandardMainMemoryDefinition(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress) + { + super(memoryAddressBits, minimalAddress, maximalAddress); + this.cellWidth = cellWidth; + } + + @Override + public int getCellWidth() + { + return cellWidth; + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java new file mode 100644 index 00000000..7ba5fb87 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java @@ -0,0 +1,42 @@ +package net.mograsim.machine; + +class StandardMemoryDefinition implements MemoryDefinition { + private final int memoryAddressBits; + private final long minimalAddress, maximalAddress; + + StandardMemoryDefinition(int memoryAddressBits, long minimalAddress, long maximalAddress) + { + super(); + this.memoryAddressBits = memoryAddressBits; + this.minimalAddress = minimalAddress; + this.maximalAddress = maximalAddress; + } + + public StandardMemoryDefinition(MainMemoryDefinition definition) + { + this(definition.getMemoryAddressBits(), definition.getMinimalAddress(), definition.getMaximalAddress()); + } + + @Override + public int getMemoryAddressBits() + { + return memoryAddressBits; + } + + @Override + public long getMinimalAddress() + { + return minimalAddress; + } + + @Override + public long getMaximalAddress() + { + return maximalAddress; + } + + public static MemoryDefinition create(int memoryAddressBits, long minimalAddress, long maximalAddress) + { + return new StandardMemoryDefinition(memoryAddressBits, minimalAddress, maximalAddress); + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/MicroInstruction.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstruction.java similarity index 57% rename from net.mograsim.machine/src/net/mograsim/machine/MicroInstruction.java rename to net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstruction.java index 9f16320a..07a15d2c 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/MicroInstruction.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstruction.java @@ -1,4 +1,4 @@ -package net.mograsim.machine; +package net.mograsim.machine.mi; import net.mograsim.machine.mi.parameters.MicroInstructionParameter; import net.mograsim.machine.mi.parameters.Mnemonic; @@ -6,9 +6,15 @@ import net.mograsim.machine.mi.parameters.Mnemonic; public interface MicroInstruction { public MicroInstructionParameter getParameter(int index); + public void setParameter(int index, MicroInstructionParameter param); /** * @return The amount of {@link Mnemonic}s, the instruction is composed of */ public int getSize(); + + public static MicroInstruction create(MicroInstructionParameter... parameters) + { + return new StandardMicroInstruction(parameters); + } } diff --git a/net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionDefinition.java similarity index 64% rename from net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java rename to net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionDefinition.java index 63134a0e..b940e652 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionDefinition.java @@ -1,4 +1,4 @@ -package net.mograsim.machine; +package net.mograsim.machine.mi; import net.mograsim.machine.mi.parameters.MicroInstructionParameter; import net.mograsim.machine.mi.parameters.ParameterClassification; @@ -10,6 +10,12 @@ public interface MicroInstructionDefinition */ public ParameterClassification[] getParameterClassifications(); + /** + * @throws IndexOutOfBoundsException + */ + public ParameterClassification getParameterClassification(int index); + + /** * @return The amount of {@link MicroInstructionParameter}s in a {@link MicroInstruction} that follows this definition. */ @@ -18,4 +24,8 @@ public interface MicroInstructionDefinition return getParameterClassifications().length; } -} + public static MicroInstructionDefinition create(ParameterClassification... classes) + { + return new StandardMicroInstructionDefinition(classes); + } +} \ No newline at end of file diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemory.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemory.java new file mode 100644 index 00000000..e31ce771 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemory.java @@ -0,0 +1,12 @@ +package net.mograsim.machine.mi; + +import net.mograsim.machine.Memory; +import net.mograsim.machine.MemoryDefinition; + +public interface MicroprogramMemory extends Memory +{ + public static MicroprogramMemory create(MemoryDefinition def) + { + return new StandardMicroprogramMemory(def); + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParser.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParser.java new file mode 100644 index 00000000..065ba152 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParser.java @@ -0,0 +1,94 @@ +package net.mograsim.machine.mi; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.math.BigInteger; + +import net.mograsim.logic.core.types.BitVector; +import net.mograsim.machine.MemoryDefinition; +import net.mograsim.machine.mi.parameters.BooleanClassification; +import net.mograsim.machine.mi.parameters.BooleanImmediate; +import net.mograsim.machine.mi.parameters.IntegerClassification; +import net.mograsim.machine.mi.parameters.IntegerImmediate; +import net.mograsim.machine.mi.parameters.MicroInstructionParameter; +import net.mograsim.machine.mi.parameters.MnemonicFamily; +import net.mograsim.machine.mi.parameters.MnemonicFamily.MnemonicPair; +import net.mograsim.machine.mi.parameters.ParameterClassification; + +public class MicroprogramMemoryParser +{ + public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition, String input) throws IOException + { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input)))) + { + parse(memory, startAddress, definition, reader); + } + } + + public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition, + BufferedReader input) + { + MemoryDefinition def = memory.getDefinition(); + long minAddress = Long.max(startAddress, def.getMinimalAddress()), maxAddress = def.getMaximalAddress(); + try + { + String line; + for (long i = minAddress; i < maxAddress && input.ready() && !"".equals((line = input.readLine())); i++) + memory.setCell(i, parse(definition, line)); + } catch (IOException e) + { + e.printStackTrace(); + } + } + + public static MicroInstruction parse(MicroInstructionDefinition definition, String toParse) + { + int size = definition.size(); + String[] strings = toParse.split(","); + if (size != strings.length) + throw new IllegalArgumentException( + "String does not match definition! The number of parameters does not match."); + MicroInstructionParameter[] params = new MicroInstructionParameter[size]; + ParameterClassification[] classes = definition.getParameterClassifications(); + for (int i = 0; i < size; i++) + { + params[i] = classes[i].parse(strings[i]); + } + return new StandardMicroInstruction(params); + } + + public static void write(MicroprogramMemory memory, long startAddress, long endAddress, String output) throws IOException + { + try(OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(output))) + { + write(memory, startAddress, endAddress, writer); + } + } + + public static void write(MicroprogramMemory memory, long startAddress, long endAddress, OutputStreamWriter output) throws IOException + { + MemoryDefinition def = memory.getDefinition(); + long min = Long.max(def.getMinimalAddress(), startAddress), max = Long.min(def.getMaximalAddress(), endAddress) + 1; + for(long i = min; i < max; i++) + { + output.write(toCSV(memory.getCell(i)) + "\n"); + } + } + + private static String toCSV(MicroInstruction inst) + { + int max = inst.getSize() - 1; + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < max; i++) + { + sb.append(inst.getParameter(i).toString()); + sb.append(","); + } + sb.append(inst.getParameter(max).toString()); + return sb.toString(); + } +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstruction.java b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstruction.java new file mode 100644 index 00000000..e40350df --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstruction.java @@ -0,0 +1,38 @@ +package net.mograsim.machine.mi; + +import net.mograsim.machine.mi.parameters.MicroInstructionParameter; + +class StandardMicroInstruction implements MicroInstruction +{ + private MicroInstructionParameter[] parameters; + + StandardMicroInstruction(MicroInstructionParameter... parameters) + { + this.parameters = parameters; + } + + /** + * @throws IndexOutOfBoundsException + */ + @Override + public MicroInstructionParameter getParameter(int index) + { + return parameters[index]; + } + + @Override + public int getSize() + { + return parameters.length; + } + + /** + * @throws IndexOutOfBoundsException + */ + @Override + public void setParameter(int index, MicroInstructionParameter param) + { + parameters[index] = param; + } + +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionDefinition.java new file mode 100644 index 00000000..2def5e1e --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionDefinition.java @@ -0,0 +1,26 @@ +package net.mograsim.machine.mi; + +import net.mograsim.machine.mi.parameters.ParameterClassification; + +class StandardMicroInstructionDefinition implements MicroInstructionDefinition +{ + private ParameterClassification[] classes; + + public StandardMicroInstructionDefinition(ParameterClassification... classes) + { + this.classes = classes; + } + + @Override + public ParameterClassification[] getParameterClassifications() + { + return classes.clone(); + } + + @Override + public ParameterClassification getParameterClassification(int index) + { + return classes[index]; + } + +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroprogramMemory.java b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroprogramMemory.java new file mode 100644 index 00000000..a253f22d --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroprogramMemory.java @@ -0,0 +1,64 @@ +package net.mograsim.machine.mi; + +import java.util.HashSet; + +import net.mograsim.machine.MemoryDefinition; +import net.mograsim.machine.MemoryObserver; +import net.mograsim.machine.standard.memory.MemoryException; + +class StandardMicroprogramMemory implements MicroprogramMemory +{ + private MicroInstruction[] data; + private MemoryDefinition definition; + private HashSet observers; + + StandardMicroprogramMemory(MemoryDefinition definition) + { + if(definition.size() > Integer.MAX_VALUE) + throw new MemoryException("Size of MicroprogramMemory must be an int, not a long"); + this.definition = definition; + data = new MicroInstruction[(int) definition.size()]; + } + + private int translate(long address) + { + return (int) (address - definition.getMinimalAddress()); + } + + @Override + public MicroInstruction getCell(long address) + { + return data[translate(address)]; + } + + @Override + public void setCell(long address, MicroInstruction data) + { + this.data[translate(address)] = data; + } + + @Override + public void registerObserver(MemoryObserver ob) + { + observers.add(ob); + } + + @Override + public void deregisterObserver(MemoryObserver ob) + { + observers.remove(ob); + } + + @Override + public void notifyObservers(long address) + { + observers.forEach(ob -> ob.update(address)); + } + + @Override + public MemoryDefinition getDefinition() + { + return definition; + } + +} diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/BooleanClassification.java b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/BooleanClassification.java index abe552f9..1689cffb 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/BooleanClassification.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/BooleanClassification.java @@ -15,4 +15,10 @@ public class BooleanClassification implements ParameterClassification { return 1; } + + @Override + public BooleanImmediate parse(String toParse) + { + return new BooleanImmediate("H".equals(toParse)); + } } diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/IntegerClassification.java b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/IntegerClassification.java index d5ba9640..b28a4361 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/IntegerClassification.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/IntegerClassification.java @@ -1,5 +1,7 @@ package net.mograsim.machine.mi.parameters; +import java.math.BigInteger; + import net.mograsim.machine.mi.parameters.MicroInstructionParameter.ParameterType; public class IntegerClassification implements ParameterClassification @@ -22,4 +24,10 @@ public class IntegerClassification implements ParameterClassification { return bits; } + + @Override + public IntegerImmediate parse(String toParse) + { + return new IntegerImmediate(new BigInteger(toParse), bits); + } } diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/MnemonicFamily.java b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/MnemonicFamily.java index b9c13738..a513b60a 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/MnemonicFamily.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/MnemonicFamily.java @@ -104,8 +104,6 @@ public class MnemonicFamily implements ParameterClassification return stringValues.clone(); } - - @Override public int hashCode() { @@ -120,8 +118,15 @@ public class MnemonicFamily implements ParameterClassification { return this == obj; } - - + + @Override + public Mnemonic parse(String toParse) + { + Mnemonic parsed = get(toParse); + if(parsed == null) + throw new UnknownMnemonicException(toParse); + return parsed; + } public static class MnemonicPair { diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/ParameterClassification.java b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/ParameterClassification.java index 3b3f1a23..33734011 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/ParameterClassification.java +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/ParameterClassification.java @@ -22,4 +22,6 @@ public interface ParameterClassification * @return The number of bits of the parameters in this classification. */ public int getExpectedBits(); + + public MicroInstructionParameter parse(String toParse); } diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/UnknownMnemonicException.java b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/UnknownMnemonicException.java new file mode 100644 index 00000000..9b23236f --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/parameters/UnknownMnemonicException.java @@ -0,0 +1,26 @@ +package net.mograsim.machine.mi.parameters; + +import net.mograsim.machine.MachineException; + +public class UnknownMnemonicException extends MachineException +{ + /** + * + */ + private static final long serialVersionUID = 701558899889830975L; + + public UnknownMnemonicException() + { + super(); + } + + public UnknownMnemonicException(String message) + { + super(message); + } + + public UnknownMnemonicException(Throwable cause) + { + super(cause); + } +} 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 index 1632c8eb..079c7e5b 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/GUIMemoryWA.java @@ -2,8 +2,8 @@ package net.mograsim.machine.standard.memory; import org.eclipse.swt.graphics.Color; -import com.google.gson.Gson; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import net.haspamelodica.swt.helper.gcs.GeneralGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Font; @@ -16,7 +16,6 @@ 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.machine.DefaultMainMemoryDefinition; import net.mograsim.machine.MainMemoryDefinition; import net.mograsim.machine.standard.memory.WordAddressableMemoryComponent; import net.mograsim.preferences.Preferences; @@ -27,6 +26,8 @@ public class GUIMemoryWA extends GUIComponent private final Pin addrPin, dataPin, rWPin; private WordAddressableMemoryComponent memory; private final static int width = 100, height = 300; + + private final static String addrKey = "addrBits", cellWidthKey = "cellWidth", minAddrKey = "minAddr", maxAddrKey = "maxAddr"; public GUIMemoryWA(ViewModelModifiable model, MainMemoryDefinition definition, String name) { @@ -91,7 +92,12 @@ public class GUIMemoryWA extends GUIComponent @Override public JsonElement getParamsForSerializing(IdentifierGetter idGetter) { - return new Gson().toJsonTree(new DefaultMainMemoryDefinition(definition)); + JsonObject o = new JsonObject(); + o.addProperty(addrKey, definition.getMemoryAddressBits()); + o.addProperty(cellWidthKey, definition.getCellWidth()); + o.addProperty(maxAddrKey, definition.getMaximalAddress()); + o.addProperty(minAddrKey, definition.getMinimalAddress()); + return o; } static @@ -99,7 +105,12 @@ public class GUIMemoryWA extends GUIComponent ViewLogicModelAdapter.addComponentAdapter(new WordAddressableMemoryAdapter()); IndirectGUIComponentCreator.setComponentSupplier(GUIAndGate.class.getCanonicalName(), (m, p, n) -> { - return new GUIMemoryWA(m, new Gson().fromJson(p, DefaultMainMemoryDefinition.class), n); + JsonObject o = (JsonObject) p; + int addressBits = o.get(addrKey).getAsInt(); + int cellWidth = o.get(cellWidthKey).getAsInt(); + long maxAddr = o.get(maxAddrKey).getAsLong(); + long minAddr = o.get(minAddrKey).getAsLong(); + return new GUIMemoryWA(m, MainMemoryDefinition.create(addressBits, cellWidth, minAddr, maxAddr), 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 index 516b01ff..3dddc2ed 100644 --- a/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java +++ b/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java @@ -1,150 +1,43 @@ package net.mograsim.machine.standard.memory; import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; import net.mograsim.logic.core.types.Bit; import net.mograsim.logic.core.types.BitVector; +import net.mograsim.machine.GenericMemory; import net.mograsim.machine.MainMemory; import net.mograsim.machine.MainMemoryDefinition; -import net.mograsim.machine.MemoryObserver; -public class WordAddressableMemory implements MainMemory +public class WordAddressableMemory extends GenericMemory implements MainMemory { private final int cellWidth; - private final long minimalAddress, maximalAddress; private final MainMemoryDefinition definition; - private final int pageSize = 64; - private Set observers = new HashSet<>(); - - private HashMap pages; public WordAddressableMemory(MainMemoryDefinition definition) { - super(); + super(definition); this.cellWidth = definition.getCellWidth(); - this.minimalAddress = definition.getMinimalAddress(); - this.maximalAddress = definition.getMaximalAddress(); this.definition = definition; - this.pages = new HashMap<>(); - } - - private void inBoundsCheck(long address) - { - if (address < minimalAddress || address > maximalAddress) - throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d", - minimalAddress, maximalAddress, address)); - } - - private long page(long address) - { - return address / pageSize; - } - - private int offset(long address) - { - return (int) (address % pageSize); - } - - @Override - public void setCell(long address, BitVector b) - { - inBoundsCheck(address); - long page = page(address); - int offset = offset(address); - Page p = pages.get(Long.valueOf(page)); - if (p == null) - pages.put(page, p = new Page()); - p.setCell(offset, b); - notifyObservers(address); } @Override public BitVector getCell(long address) { - inBoundsCheck(address); - long page = page(address); - int offset = offset(address); - Page p = pages.get(Long.valueOf(page)); - if (p == null) - return BitVector.of(Bit.ZERO, cellWidth); - return p.getCell(offset); + BitVector data = super.getCell(address); + return data == null ? BitVector.of(Bit.ZERO, cellWidth) : data; } @Override public BigInteger getCellAsBigInteger(long address) { - inBoundsCheck(address); - long page = page(address); - int offset = offset(address); - Page p = pages.get(Long.valueOf(page)); - if (p == null) - return BigInteger.valueOf(0L); - return p.getCellAsBigInteger(offset); + BitVector data = getCell(address); + return data == null ? BigInteger.valueOf(0) : data.getUnsignedValue(); } @Override - public void setCellAsBigInteger(long address, BigInteger word) - { - inBoundsCheck(address); - long page = page(address); - int offset = offset(address); - Page p = pages.get(Long.valueOf(page)); - if (p == null) - pages.put(page, p = new Page()); - p.setCellAsBigInteger(offset, word); - notifyObservers(address); - } - - private class Page + public void setCellAsBigInteger(long address, BigInteger data) { - 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.ZERO, 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 width. Expected: %d Actual: %d", cellWidth, bits.length())); - memory[index] = bits; - } - - public void setCellAsBigInteger(int index, BigInteger bits) - { - setCell(index, BitVector.from(bits, cellWidth)); - } - - public BigInteger getCellAsBigInteger(int index) - { - try { - return getCell(index).getUnsignedValue(); - } - catch(NumberFormatException e) - { - throw new MemoryException(e); - } - } - - @Override - public String toString() - { - return Arrays.deepToString(memory); - } + setCell(address, BitVector.from(data, cellWidth)); } @Override @@ -152,22 +45,4 @@ public class WordAddressableMemory implements MainMemory { return definition; } - - @Override - public void registerObserver(MemoryObserver ob) - { - observers.add(ob); - } - - @Override - public void deregisterObserver(MemoryObserver ob) - { - observers.remove(ob); - } - - @Override - public void notifyObservers(long address) - { - observers.forEach(ob -> ob.update(address)); - } } 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 index 1fb59d0e..5f50dbc9 100644 --- a/net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java +++ b/net.mograsim.machine/test/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java @@ -12,7 +12,7 @@ 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; -import net.mograsim.machine.DefaultMainMemoryDefinition; +import net.mograsim.machine.MainMemoryDefinition; class WordAddressableMemoryTest { @@ -28,7 +28,8 @@ class WordAddressableMemoryTest { ReadWriteEnd dataI = data.createReadWriteEnd(); ReadWriteEnd addressI = address.createReadWriteEnd(); - WordAddressableMemoryComponent memory = new WordAddressableMemoryComponent(t, 4, new DefaultMainMemoryDefinition(64, 16, 4096L, Long.MAX_VALUE), data.createReadWriteEnd(), + @SuppressWarnings("unused") + WordAddressableMemoryComponent memory = new WordAddressableMemoryComponent(t, 4, MainMemoryDefinition.create(64, 16, 4096L, Long.MAX_VALUE), data.createReadWriteEnd(), rW.createReadOnlyEnd(), address.createReadOnlyEnd()); Random r = new Random(); -- 2.17.1