From: Fabian Stemmler Date: Sat, 31 Aug 2019 14:52:37 +0000 (+0200) Subject: Merge branch 'development' of https://gitlab.lrz.de/lrr-tum/students/eragp-misim... X-Git-Url: https://mograsim.net/gitweb/?a=commitdiff_plain;h=976f7f2be00457b5cda2489545635ccd076c9afd;hp=571344ae28e5003822604d7fd93b8ac3de8e3950;p=Mograsim.git Merge branch 'development' of https://gitlab.lrz.de/lrr-tum/students/eragp-misim-2019.git into development --- 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/MicroInstruction.java b/net.mograsim.machine/src/net/mograsim/machine/MicroInstruction.java deleted file mode 100644 index 9f16320a..00000000 --- a/net.mograsim.machine/src/net/mograsim/machine/MicroInstruction.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.mograsim.machine; - -import net.mograsim.machine.mi.parameters.MicroInstructionParameter; -import net.mograsim.machine.mi.parameters.Mnemonic; - -public interface MicroInstruction { - - public MicroInstructionParameter getParameter(int index); - - /** - * @return The amount of {@link Mnemonic}s, the instruction is composed of - */ - public int getSize(); -} diff --git a/net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java deleted file mode 100644 index 63134a0e..00000000 --- a/net.mograsim.machine/src/net/mograsim/machine/MicroInstructionDefinition.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.mograsim.machine; - -import net.mograsim.machine.mi.parameters.MicroInstructionParameter; -import net.mograsim.machine.mi.parameters.ParameterClassification; - -public interface MicroInstructionDefinition -{ - /** - * @return The {@link ParameterClassification}s of which a MicroInstruction is composed. - */ - public ParameterClassification[] getParameterClassifications(); - - /** - * @return The amount of {@link MicroInstructionParameter}s in a {@link MicroInstruction} that follows this definition. - */ - public default int size() - { - return getParameterClassifications().length; - } - -} 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/mi/MicroInstruction.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstruction.java new file mode 100644 index 00000000..07a15d2c --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstruction.java @@ -0,0 +1,20 @@ +package net.mograsim.machine.mi; + +import net.mograsim.machine.mi.parameters.MicroInstructionParameter; +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/mi/MicroInstructionDefinition.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionDefinition.java new file mode 100644 index 00000000..b940e652 --- /dev/null +++ b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionDefinition.java @@ -0,0 +1,31 @@ +package net.mograsim.machine.mi; + +import net.mograsim.machine.mi.parameters.MicroInstructionParameter; +import net.mograsim.machine.mi.parameters.ParameterClassification; + +public interface MicroInstructionDefinition +{ + /** + * @return The {@link ParameterClassification}s of which a MicroInstruction is composed. + */ + 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. + */ + public default int size() + { + 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(); diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java deleted file mode 100644 index 10498f65..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.mograsim.plugin.memory; - -import java.math.BigInteger; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.jface.viewers.EditingSupport; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TextCellEditor; - -import net.mograsim.plugin.asm.AsmNumberUtil; -import net.mograsim.plugin.memory.MemoryView.DisplaySettings; - -public class MemoryCellEditingSupport extends EditingSupport -{ - private final TableViewer viewer; - private final CellEditor editor; - private final DisplaySettings displaySettings; - - public MemoryCellEditingSupport(TableViewer viewer, DisplaySettings displaySettings) - { - super(viewer); - this.viewer = viewer; - this.displaySettings = displaySettings; - editor = new TextCellEditor(viewer.getTable()); - editor.setValidator(new NumberCellEditorValidator()); - } - - @Override - protected boolean canEdit(Object element) - { - return true; - } - - @Override - protected CellEditor getCellEditor(Object element) - { - return editor; - } - - @Override - protected Object getValue(Object element) - { - MemoryTableRow row = (MemoryTableRow) element; - return AsmNumberUtil.toString(row.getMemory().getCellAsBigInteger(row.address), displaySettings.getDataNumberType()); - } - - @Override - protected void setValue(Object element, Object userInput) - { - MemoryTableRow row = (MemoryTableRow) element; - try - { - row.getMemory().setCellAsBigInteger(row.address, AsmNumberUtil.valueOf((String) userInput)); - } - catch (@SuppressWarnings("unused") NumberFormatException e) - { - row.getMemory().setCellAsBigInteger(row.address, BigInteger.valueOf(0)); - } - viewer.update(element, null); - } -} \ No newline at end of file diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java deleted file mode 100644 index 9f2a9e13..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.mograsim.plugin.memory; - -import org.eclipse.jface.viewers.ILazyContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.widgets.Display; - -import net.mograsim.machine.MainMemory; -import net.mograsim.machine.MemoryObserver; - -public class MemoryTableContentProvider implements ILazyContentProvider, MemoryObserver -{ - private long lower; - private TableViewer viewer; - private final static int limit = 10_000; - private int amount = 0; - private MainMemory memory; - - public void setLowerBound(long lower) - { - if (memory != null) - this.lower = Long.min(memory.getDefinition().getMaximalAddress(), Long.max(memory.getDefinition().getMinimalAddress(), lower)); - else - this.lower = lower; - updateItemCount(); - } - - public void updateItemCount() - { - if (memory != null) - { - long size = memory.getDefinition().getMaximalAddress() - lower; - viewer.setItemCount(size > amount ? amount : (int) size); - } else - viewer.setItemCount(0); - } - - public long getLowerBound() - { - return lower; - } - - public void setAmount(int amount) - { - this.amount = Integer.min(amount, limit); - updateItemCount(); - } - - public int getAmount() - { - return amount; - } - - @Override - public void updateElement(int index) - { - long address = lower + index; - if (address <= memory.getDefinition().getMaximalAddress()) - viewer.replace(new MemoryTableRow(address, memory), index); - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) - { - this.viewer = (TableViewer) viewer; - this.memory = (MainMemory) newInput; - if (oldInput != null) - ((MainMemory) oldInput).deregisterObserver(this); - if (memory != null) - memory.registerObserver(this); - setLowerBound(0L); - } - - @Override - public void update(long address) - { - Display.getDefault().asyncExec(() -> updateElement((int) (address - lower))); - } -} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java deleted file mode 100644 index fa5b6264..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.mograsim.plugin.memory; - -import net.mograsim.machine.MainMemory; - -public class MemoryTableRow -{ - public final long address; - private final MainMemory memory; - - public MemoryTableRow(long address, MainMemory memory) - { - this.address = address; - this.memory = memory; - } - - public MainMemory getMemory() - { - return memory; - } -} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java deleted file mode 100644 index 52547453..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java +++ /dev/null @@ -1,206 +0,0 @@ -package net.mograsim.plugin.memory; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.part.ViewPart; - -import net.mograsim.machine.DefaultMainMemoryDefinition; -import net.mograsim.machine.MainMemory; -import net.mograsim.machine.standard.memory.WordAddressableMemory; -import net.mograsim.plugin.asm.AsmNumberUtil; -import net.mograsim.plugin.asm.AsmNumberUtil.NumberType; - -public class MemoryView extends ViewPart -{ - private TableViewer viewer; - private MemoryTableContentProvider provider; - private DisplaySettings displaySettings; - private String addressFormat; - - @Override - public void createPartControl(Composite parent) - { - provider = new MemoryTableContentProvider(); - displaySettings = new DisplaySettings(); - displaySettings.setDataNumberType(NumberType.HEXADECIMAL); - - GridLayout layout = new GridLayout(6, false); - parent.setLayout(layout); - Label fromLabel = new Label(parent, SWT.NONE); - fromLabel.setText("Address: "); - Text fromText = new Text(parent, SWT.BORDER | SWT.SEARCH); - fromText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL)); - VerifyListener vl = new NumberVerifyListener(); - fromText.addVerifyListener(vl); - fromText.setText("0"); - fromText.addModifyListener(e -> - { - try - { - provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue()); - viewer.refresh(); - } - catch (@SuppressWarnings("unused") NumberFormatException ex) - { - // Nothing to do here - } - }); - - Label amountLabel = new Label(parent, SWT.NONE); - amountLabel.setText("Number of cells: "); - Text amountText = new Text(parent, SWT.BORDER | SWT.SEARCH); - amountText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL)); - amountText.addVerifyListener(vl); - amountText.setText("0"); - amountText.addModifyListener(e -> - { - try - { - provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue()); - viewer.refresh(); - } - catch (@SuppressWarnings("unused") NumberFormatException ex) - { - // Nothing to do here - } - }); - - setupRadixSelector(parent); - - createViewer(parent); - } - - private void setupRadixSelector(Composite parent) - { - Label radixLabel = new Label(parent, SWT.NONE); - radixLabel.setText("Radix: "); - Combo selectRadix = new Combo(parent, SWT.READ_ONLY); - - String entries[] = new String[] { "Binary", "Octal", "Decimal", "Hexadecimal" }; - NumberType corTypes[] = new NumberType[] { NumberType.BINARY, NumberType.OCTAL, NumberType.DECIMAL, NumberType.HEXADECIMAL }; - selectRadix.setItems(entries); - selectRadix.addSelectionListener(new SelectionListener() - { - @Override - public void widgetSelected(SelectionEvent e) - { - int index = selectRadix.getSelectionIndex(); - if (index == -1) - displaySettings.setDataNumberType(NumberType.HEXADECIMAL); - else - { - displaySettings.setDataNumberType(corTypes[index]); - } - viewer.refresh(); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) - { - widgetSelected(e); - } - }); - } - - private void createViewer(Composite parent) - { - viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL); - createColumns(); - Table table = viewer.getTable(); - table.setHeaderVisible(true); - table.setLinesVisible(true); - viewer.setUseHashlookup(true); - viewer.setContentProvider(provider); - setMemoryBinding(new WordAddressableMemory(new DefaultMainMemoryDefinition(8, 8, 8L, Long.MAX_VALUE))); - getSite().setSelectionProvider(viewer); - - GridData gd = new GridData(); - gd.verticalAlignment = GridData.FILL; - gd.horizontalSpan = 6; - gd.grabExcessHorizontalSpace = true; - gd.grabExcessVerticalSpace = true; - gd.horizontalAlignment = GridData.FILL; - viewer.getControl().setLayoutData(gd); - } - - private void createColumns() - { - String[] titles = { "Address", "Data" }; - int[] bounds = { 100, 100 }; - - TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0]); - col.setLabelProvider(new ColumnLabelProvider() - { - @Override - public String getText(Object element) - { - MemoryTableRow row = (MemoryTableRow) element; - return String.format(addressFormat, row.address);// TODO: make the string length dependent on memory address length - } - }); - - col = createTableViewerColumn(titles[1], bounds[1]); - col.setLabelProvider(new ColumnLabelProvider() - { - @Override - public String getText(Object element) - { - MemoryTableRow row = (MemoryTableRow) element; - return AsmNumberUtil.toString(row.getMemory().getCellAsBigInteger(row.address), displaySettings.getDataNumberType()); - } - }); - col.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings)); - } - - private TableViewerColumn createTableViewerColumn(String title, int bound) - { - TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE); - TableColumn column = viewerColumn.getColumn(); - column.setText(title); - column.setWidth(bound); - column.setResizable(true); - column.setMoveable(false); - return viewerColumn; - } - - @Override - public void setFocus() - { - viewer.getControl().setFocus(); - } - - public void setMemoryBinding(MainMemory m) - { - int hexAddressLength = Long.toUnsignedString(m.getDefinition().getMaximalAddress(), 16).length(); - addressFormat = "0x%0" + hexAddressLength + "X"; - viewer.setInput(m); - } - - public static class DisplaySettings - { - private AsmNumberUtil.NumberType dataNumberType; - - public AsmNumberUtil.NumberType getDataNumberType() - { - return dataNumberType; - } - - public void setDataNumberType(AsmNumberUtil.NumberType dataNumberType) - { - this.dataNumberType = dataNumberType; - } - } -} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java deleted file mode 100644 index 236eaa06..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.mograsim.plugin.memory; - -import org.eclipse.jface.viewers.ICellEditorValidator; - -import net.mograsim.plugin.asm.AsmNumberUtil; - -public class NumberCellEditorValidator implements ICellEditorValidator -{ - - @Override - public String isValid(Object value) - { - return AsmNumberUtil.NumberType.NONE.equals(AsmNumberUtil.getType((String) value)) ? (String) value + "is not a valid number" - : null; - } - -} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java deleted file mode 100644 index 4e5d11c8..00000000 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.mograsim.plugin.memory; - -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.widgets.Text; - -import net.mograsim.plugin.asm.AsmNumberUtil; -import net.mograsim.plugin.asm.AsmNumberUtil.NumberType; - -public class NumberVerifyListener implements VerifyListener -{ - - @Override - public void verifyText(VerifyEvent e) - { - String text = computeModifiedText(e); - e.doit = !NumberType.NONE.equals(AsmNumberUtil.prefixOfType(text)); - } - - private static String computeModifiedText(VerifyEvent e) - { - String modifiedText = ((Text) e.getSource()).getText(); - modifiedText = modifiedText.substring(0, e.start).concat(e.text).concat(modifiedText.substring(e.end)); - return modifiedText; - } -} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditingSupport.java new file mode 100644 index 00000000..7bba426d --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditingSupport.java @@ -0,0 +1,63 @@ +package net.mograsim.plugin.tables; + +import java.math.BigInteger; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; + +import net.mograsim.plugin.asm.AsmNumberUtil; +import net.mograsim.plugin.tables.memory.DisplaySettings; + +public abstract class NumberCellEditingSupport extends EditingSupport +{ + private final TableViewer viewer; + private final CellEditor editor; + private final DisplaySettings displaySettings; + + public NumberCellEditingSupport(TableViewer viewer, DisplaySettings displaySettings) + { + super(viewer); + this.viewer = viewer; + this.displaySettings = displaySettings; + editor = new TextCellEditor(viewer.getTable()); + editor.setValidator(new NumberCellEditorValidator()); + } + + @Override + final protected boolean canEdit(Object element) + { + return true; + } + + @Override + final protected CellEditor getCellEditor(Object element) + { + return editor; + } + + @Override + final protected Object getValue(Object element) + { + return AsmNumberUtil.toString(getAsBigInteger(element), displaySettings.getDataNumberType()); + } + + @Override + final protected void setValue(Object element, Object userInput) + { + try + { + setAsBigInteger(element, AsmNumberUtil.valueOf((String) userInput)); + } + catch (@SuppressWarnings("unused") NumberFormatException e) + { + setAsBigInteger(element, BigInteger.valueOf(0)); + } + viewer.update(element, null); + } + + protected abstract void setAsBigInteger(Object element, BigInteger value); + + protected abstract BigInteger getAsBigInteger(Object element); +} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditorValidator.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditorValidator.java new file mode 100644 index 00000000..e0b445dd --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberCellEditorValidator.java @@ -0,0 +1,17 @@ +package net.mograsim.plugin.tables; + +import org.eclipse.jface.viewers.ICellEditorValidator; + +import net.mograsim.plugin.asm.AsmNumberUtil; + +public class NumberCellEditorValidator implements ICellEditorValidator +{ + + @Override + public String isValid(Object value) + { + return AsmNumberUtil.NumberType.NONE.equals(AsmNumberUtil.getType((String) value)) ? (String) value + "is not a valid number" + : null; + } + +} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberColumnLabelProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberColumnLabelProvider.java new file mode 100644 index 00000000..35f032ac --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/NumberColumnLabelProvider.java @@ -0,0 +1,26 @@ +package net.mograsim.plugin.tables; + +import java.math.BigInteger; + +import org.eclipse.jface.viewers.ColumnLabelProvider; + +import net.mograsim.plugin.asm.AsmNumberUtil; +import net.mograsim.plugin.tables.memory.DisplaySettings; + +public abstract class NumberColumnLabelProvider extends ColumnLabelProvider +{ + private DisplaySettings displaySettings; + + public NumberColumnLabelProvider(DisplaySettings displaySettings) + { + this.displaySettings = displaySettings; + } + + @Override + public String getText(Object element) + { + return AsmNumberUtil.toString(getAsBigInteger(element), displaySettings.getDataNumberType()); + } + + public abstract BigInteger getAsBigInteger(Object element); +} \ No newline at end of file diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/DisplaySettings.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/DisplaySettings.java new file mode 100644 index 00000000..8816a526 --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/DisplaySettings.java @@ -0,0 +1,23 @@ +package net.mograsim.plugin.tables.memory; + +import net.mograsim.plugin.asm.AsmNumberUtil.NumberType; + +public class DisplaySettings +{ + private NumberType dataNumberType; + + public DisplaySettings(NumberType dataNumberType) + { + this.dataNumberType = dataNumberType; + } + + public NumberType getDataNumberType() + { + return dataNumberType; + } + + public void setDataNumberType(NumberType dataNumberType) + { + this.dataNumberType = dataNumberType; + } +} \ No newline at end of file diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryCellEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryCellEditingSupport.java new file mode 100644 index 00000000..94f1821e --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryCellEditingSupport.java @@ -0,0 +1,29 @@ +package net.mograsim.plugin.tables.memory; + +import java.math.BigInteger; + +import org.eclipse.jface.viewers.TableViewer; + +import net.mograsim.plugin.tables.NumberCellEditingSupport; + +public class MemoryCellEditingSupport extends NumberCellEditingSupport +{ + public MemoryCellEditingSupport(TableViewer viewer, DisplaySettings displaySettings) + { + super(viewer, displaySettings); + } + + @Override + protected void setAsBigInteger(Object element, BigInteger value) + { + MemoryTableRow row = (MemoryTableRow) element; + row.getMemory().setCellAsBigInteger(row.address, value); + } + + @Override + protected BigInteger getAsBigInteger(Object element) + { + MemoryTableRow row = (MemoryTableRow) element; + return row.getMemory().getCellAsBigInteger(row.address); + } +} \ No newline at end of file diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java new file mode 100644 index 00000000..aaecc754 --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java @@ -0,0 +1,79 @@ +package net.mograsim.plugin.tables.memory; + +import org.eclipse.jface.viewers.ILazyContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Display; + +import net.mograsim.machine.MainMemory; +import net.mograsim.machine.MemoryObserver; + +public class MemoryTableContentProvider implements ILazyContentProvider, MemoryObserver +{ + private long lower; + private TableViewer viewer; + private final static int limit = 10_000; + private int amount = 0; + private MainMemory memory; + + public void setLowerBound(long lower) + { + if (memory != null) + this.lower = Long.min(memory.getDefinition().getMaximalAddress(), Long.max(memory.getDefinition().getMinimalAddress(), lower)); + else + this.lower = lower; + updateItemCount(); + } + + public void updateItemCount() + { + if (memory != null) + { + long size = memory.getDefinition().getMaximalAddress() - lower; + viewer.setItemCount(size > amount ? amount : (int) size); + } else + viewer.setItemCount(0); + } + + public long getLowerBound() + { + return lower; + } + + public void setAmount(int amount) + { + this.amount = Integer.min(amount, limit); + updateItemCount(); + } + + public int getAmount() + { + return amount; + } + + @Override + public void updateElement(int index) + { + long address = lower + index; + if (address <= memory.getDefinition().getMaximalAddress()) + viewer.replace(new MemoryTableRow(address, memory), index); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) + { + this.viewer = (TableViewer) viewer; + this.memory = (MainMemory) newInput; + if (oldInput != null) + ((MainMemory) oldInput).deregisterObserver(this); + if (memory != null) + memory.registerObserver(this); + setLowerBound(0L); + } + + @Override + public void update(long address) + { + Display.getDefault().asyncExec(() -> updateElement((int) (address - lower))); + } +} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java new file mode 100644 index 00000000..6f1c3530 --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java @@ -0,0 +1,20 @@ +package net.mograsim.plugin.tables.memory; + +import net.mograsim.machine.MainMemory; + +public class MemoryTableRow +{ + public final long address; + private final MainMemory memory; + + public MemoryTableRow(long address, MainMemory memory) + { + this.address = address; + this.memory = memory; + } + + public MainMemory getMemory() + { + return memory; + } +} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java new file mode 100644 index 00000000..98983a66 --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java @@ -0,0 +1,194 @@ +package net.mograsim.plugin.tables.memory; + +import java.math.BigInteger; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.part.ViewPart; + +import net.mograsim.machine.MainMemory; +import net.mograsim.machine.MainMemoryDefinition; +import net.mograsim.machine.standard.memory.WordAddressableMemory; +import net.mograsim.plugin.asm.AsmNumberUtil; +import net.mograsim.plugin.asm.AsmNumberUtil.NumberType; +import net.mograsim.plugin.tables.NumberColumnLabelProvider; + +public class MemoryView extends ViewPart +{ + private TableViewer viewer; + private MemoryTableContentProvider provider; + private DisplaySettings displaySettings; + private String addressFormat; + + @Override + public void createPartControl(Composite parent) + { + provider = new MemoryTableContentProvider(); + displaySettings = new DisplaySettings(NumberType.HEXADECIMAL); + + GridLayout layout = new GridLayout(6, false); + parent.setLayout(layout); + Label fromLabel = new Label(parent, SWT.NONE); + fromLabel.setText("Address: "); + Text fromText = new Text(parent, SWT.BORDER | SWT.SEARCH); + fromText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL)); + VerifyListener vl = new NumberVerifyListener(); + fromText.addVerifyListener(vl); + fromText.setText("0"); + fromText.addModifyListener(e -> + { + try + { + provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue()); + viewer.refresh(); + } + catch (@SuppressWarnings("unused") NumberFormatException ex) + { + // Nothing to do here + } + }); + + Label amountLabel = new Label(parent, SWT.NONE); + amountLabel.setText("Number of cells: "); + Text amountText = new Text(parent, SWT.BORDER | SWT.SEARCH); + amountText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL)); + amountText.addVerifyListener(vl); + amountText.setText("0"); + amountText.addModifyListener(e -> + { + try + { + provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue()); + viewer.refresh(); + } + catch (@SuppressWarnings("unused") NumberFormatException ex) + { + // Nothing to do here + } + }); + + setupRadixSelector(parent); + + createViewer(parent); + } + + private void setupRadixSelector(Composite parent) + { + Label radixLabel = new Label(parent, SWT.NONE); + radixLabel.setText("Radix: "); + Combo selectRadix = new Combo(parent, SWT.READ_ONLY); + + String entries[] = new String[] { "Binary", "Octal", "Decimal", "Hexadecimal" }; + NumberType corTypes[] = new NumberType[] { NumberType.BINARY, NumberType.OCTAL, NumberType.DECIMAL, NumberType.HEXADECIMAL }; + selectRadix.setItems(entries); + selectRadix.addSelectionListener(new SelectionListener() + { + @Override + public void widgetSelected(SelectionEvent e) + { + int index = selectRadix.getSelectionIndex(); + if (index == -1) + displaySettings.setDataNumberType(NumberType.HEXADECIMAL); + else + { + displaySettings.setDataNumberType(corTypes[index]); + } + viewer.refresh(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) + { + widgetSelected(e); + } + }); + } + + private void createViewer(Composite parent) + { + viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL); + createColumns(); + Table table = viewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + viewer.setUseHashlookup(true); + viewer.setContentProvider(provider); + setMemoryBinding(new WordAddressableMemory(MainMemoryDefinition.create(8, 8, 8L, Long.MAX_VALUE))); + getSite().setSelectionProvider(viewer); + + GridData gd = new GridData(); + gd.verticalAlignment = GridData.FILL; + gd.horizontalSpan = 6; + gd.grabExcessHorizontalSpace = true; + gd.grabExcessVerticalSpace = true; + gd.horizontalAlignment = GridData.FILL; + viewer.getControl().setLayoutData(gd); + } + + private void createColumns() + { + String[] titles = { "Address", "Data" }; + int[] bounds = { 100, 100 }; + + TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0]); + col.setLabelProvider(new ColumnLabelProvider() + { + @Override + public String getText(Object element) + { + MemoryTableRow row = (MemoryTableRow) element; + return String.format(addressFormat, row.address); + } + }); + + col = createTableViewerColumn(titles[1], bounds[1]); + col.setLabelProvider(new NumberColumnLabelProvider(displaySettings) + { + @Override + public BigInteger getAsBigInteger(Object element) + { + MemoryTableRow row = (MemoryTableRow) element; + return row.getMemory().getCellAsBigInteger(row.address); + } + + }); + col.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings)); + } + + private TableViewerColumn createTableViewerColumn(String title, int bound) + { + TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE); + TableColumn column = viewerColumn.getColumn(); + column.setText(title); + column.setWidth(bound); + column.setResizable(true); + column.setMoveable(false); + return viewerColumn; + } + + @Override + public void setFocus() + { + viewer.getControl().setFocus(); + } + + public void setMemoryBinding(MainMemory m) + { + int hexAddressLength = Long.toUnsignedString(m.getDefinition().getMaximalAddress(), 16).length(); + addressFormat = "0x%0" + hexAddressLength + "X"; + viewer.setInput(m); + } +} diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/NumberVerifyListener.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/NumberVerifyListener.java new file mode 100644 index 00000000..54d71762 --- /dev/null +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/NumberVerifyListener.java @@ -0,0 +1,26 @@ +package net.mograsim.plugin.tables.memory; + +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.widgets.Text; + +import net.mograsim.plugin.asm.AsmNumberUtil; +import net.mograsim.plugin.asm.AsmNumberUtil.NumberType; + +public class NumberVerifyListener implements VerifyListener +{ + + @Override + public void verifyText(VerifyEvent e) + { + String text = computeModifiedText(e); + e.doit = !NumberType.NONE.equals(AsmNumberUtil.prefixOfType(text)); + } + + private static String computeModifiedText(VerifyEvent e) + { + String modifiedText = ((Text) e.getSource()).getText(); + modifiedText = modifiedText.substring(0, e.start).concat(e.text).concat(modifiedText.substring(e.end)); + return modifiedText; + } +}