Finished MPROM support. Fixes #10
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Sat, 3 Oct 2020 20:21:34 +0000 (22:21 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Sat, 3 Oct 2020 20:49:21 +0000 (22:49 +0200)
54 files changed:
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MPROM.java
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MainMemory.java
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900MPROMDefinition.java
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/AssignableMainMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemoryDefinition.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMPROM.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROM.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROMDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROM.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROMDefinition.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMPROM.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/MPROMAdapter.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/ModelMPROM.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractAssignableBitVectorMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractModelBitVectorMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorBasedMemoryParser.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryAdapter.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryParseException.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreBitVectorMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParseException.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParser.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/ModelWordAddressableMemory.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemoryDefinition.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java [deleted file]
plugins/net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties
plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties
plugins/net.mograsim.plugin.core/plugin.xml
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/AbstractMemoryEditor.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MPROMEditor.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MainMemoryEditor.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java [deleted file]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineDebugTarget.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java
tests/net.mograsim.logic.model.am2900.tests/src/net/mograsim/logic/model/am2900/TestGCD.java
tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/MainMemoryTest.java [new file with mode: 0644]
tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java [deleted file]

index fbfc44d..1370774 100644 (file)
@@ -4,13 +4,15 @@ import net.mograsim.logic.model.am2900.machine.Am2900MPROMDefinition;
 import net.mograsim.logic.model.model.LogicModelModifiable;
 import net.mograsim.logic.model.serializing.IdentifyParams;
 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
-import net.mograsim.machine.mi.components.ModelMPROM;
+import net.mograsim.machine.mi.MPROM;
+import net.mograsim.machine.mi.MPROMDefinition;
+import net.mograsim.machine.standard.memory.AbstractModelBitVectorMemory;
 
-public class ModelAm2900MPROM extends ModelMPROM
+public class ModelAm2900MPROM extends AbstractModelBitVectorMemory<MPROM, MPROMDefinition>
 {
        public ModelAm2900MPROM(LogicModelModifiable model, String name)
        {
-               super(model, Am2900MPROMDefinition.instance, name);
+               super(model, 30, 80, 30, 50, -1, true, "MPROM", Am2900MPROMDefinition.instance, name);
        }
 
        @Override
index c065598..f60fd54 100644 (file)
@@ -4,13 +4,15 @@ import net.mograsim.logic.model.am2900.machine.Am2900MainMemoryDefinition;
 import net.mograsim.logic.model.model.LogicModelModifiable;
 import net.mograsim.logic.model.serializing.IdentifyParams;
 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
-import net.mograsim.machine.standard.memory.ModelWordAddressableMemory;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.standard.memory.AbstractModelBitVectorMemory;
 
-public class ModelAm2900MainMemory extends ModelWordAddressableMemory
+public class ModelAm2900MainMemory extends AbstractModelBitVectorMemory<MainMemory, MainMemoryDefinition>
 {
        public ModelAm2900MainMemory(LogicModelModifiable model, String name)
        {
-               super(model, Am2900MainMemoryDefinition.instance, name);
+               super(model, 120, 150, 30, 50, 70, false, "RAM", Am2900MainMemoryDefinition.instance, name);
        }
 
        @Override
index e8f4afc..0af200f 100644 (file)
@@ -25,7 +25,7 @@ public class Am2900MPROMDefinition implements MPROMDefinition
        }
 
        @Override
-       public int getMicroInstructionMemoryAddressBits()
+       public int getCellWidth()
        {
                return 12;
        }
index 00c4d6d..a7f7379 100644 (file)
@@ -18,8 +18,10 @@ import net.mograsim.logic.model.model.components.atomic.ModelClock;
 import net.mograsim.logic.model.modeladapter.CoreModelParameters;
 import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
+import net.mograsim.machine.AssignableMainMemory;
 import net.mograsim.machine.Machine;
 import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.StandardMainMemory;
 import net.mograsim.machine.mi.AssignableMPROM;
 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 import net.mograsim.machine.mi.MicroInstruction;
@@ -30,8 +32,6 @@ import net.mograsim.machine.mi.parameters.MicroInstructionParameter;
 import net.mograsim.machine.mi.parameters.ParameterClassification;
 import net.mograsim.machine.registers.Register;
 import net.mograsim.machine.registers.RegisterGroup;
-import net.mograsim.machine.standard.memory.AssignableMainMemory;
-import net.mograsim.machine.standard.memory.WordAddressableMemory;
 
 public class Am2900Machine implements Machine
 {
@@ -59,7 +59,7 @@ public class Am2900Machine implements Machine
                params.gateProcessTime = 50;
                params.hardcodedComponentProcessTime = params.gateProcessTime * 5;
                params.wireTravelTime = 10;
-               mainMemory = new AssignableMainMemory(new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition()));
+               mainMemory = new AssignableMainMemory(new StandardMainMemory(am2900MachineDefinition.getMainMemoryDefinition()));
                instMemory = new AssignableMicroInstructionMemory(
                                new StandardMicroInstructionMemory(am2900MachineDefinition.getMicroInstructionMemoryDefinition()));
                mprom = new AssignableMPROM(new StandardMPROM(am2900MachineDefinition.getMPROMDefinition()));
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/AssignableMainMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/AssignableMainMemory.java
new file mode 100644 (file)
index 0000000..20a6c6e
--- /dev/null
@@ -0,0 +1,17 @@
+package net.mograsim.machine;
+
+import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory;
+
+public class AssignableMainMemory extends AbstractAssignableBitVectorMemory<MainMemory> implements MainMemory
+{
+       public AssignableMainMemory(MainMemory memory)
+       {
+               super(memory);
+       }
+
+       @Override
+       public MainMemoryDefinition getDefinition()
+       {
+               return getReal().getDefinition();
+       }
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemory.java
new file mode 100644 (file)
index 0000000..ef0b79a
--- /dev/null
@@ -0,0 +1,15 @@
+package net.mograsim.machine;
+
+import java.math.BigInteger;
+
+import net.mograsim.logic.core.types.BitVector;
+
+public interface BitVectorMemory extends Memory<BitVector>
+{
+       BigInteger getCellAsBigInteger(long address);
+
+       public void setCellAsBigInteger(long address, BigInteger word);
+
+       @Override
+       BitVectorMemoryDefinition getDefinition();
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemoryDefinition.java
new file mode 100644 (file)
index 0000000..7cc8fea
--- /dev/null
@@ -0,0 +1,14 @@
+package net.mograsim.machine;
+
+public interface BitVectorMemoryDefinition 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.
+        * 
+        * @return the addressable unit width in bits
+        * @author Christian Femers
+        */
+       int getCellWidth();
+}
index 40873f0..314a748 100644 (file)
@@ -5,16 +5,16 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
 
-public abstract class GenericMemory<T> implements Memory<T>
+public abstract class GenericMemory<T, D extends MemoryDefinition> implements Memory<T>
 {
        private final long minimalAddress, maximalAddress;
-       private final MemoryDefinition definition;
+       private final D definition;
        private final int pageSize = 64;
        private Set<MemoryCellModifiedListener> observers = new HashSet<>();
 
        private HashMap<Long, Page> pages;
 
-       public GenericMemory(MemoryDefinition definition)
+       public GenericMemory(D definition)
        {
                super();
                this.definition = definition;
@@ -67,18 +67,17 @@ public abstract class GenericMemory<T> implements Memory<T>
 
        private class Page
        {
-               private Object[] memory;
+               private T[] memory;
 
+               @SuppressWarnings("unchecked")
                public Page()
                {
-                       memory = new Object[pageSize];
+                       memory = (T[]) new Object[pageSize];
                }
 
                public T getCell(int index)
                {
-                       @SuppressWarnings("unchecked")
-                       T data = (T) memory[index];
-                       return data;
+                       return memory[index];
                }
 
                public void setCell(int index, T data)
@@ -111,7 +110,7 @@ public abstract class GenericMemory<T> implements Memory<T>
        }
 
        @Override
-       public MemoryDefinition getDefinition()
+       public D getDefinition()
        {
                return definition;
        }
index 0f713b2..115973f 100644 (file)
@@ -9,7 +9,6 @@ import net.mograsim.logic.model.model.LogicModel;
 import net.mograsim.machine.mi.AssignableMPROM;
 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 import net.mograsim.machine.registers.Register;
-import net.mograsim.machine.standard.memory.AssignableMainMemory;
 
 public interface Machine
 {
index 33ad260..9a0b898 100644 (file)
@@ -1,15 +1,7 @@
 package net.mograsim.machine;
 
-import java.math.BigInteger;
-
-import net.mograsim.logic.core.types.BitVector;
-
-public interface MainMemory extends Memory<BitVector>
+public interface MainMemory extends BitVectorMemory
 {
-       public BigInteger getCellAsBigInteger(long address);
-
-       public void setCellAsBigInteger(long address, BigInteger word);
-
        @Override
        public MainMemoryDefinition getDefinition();
 }
\ No newline at end of file
index 72153d6..fecbbaf 100644 (file)
@@ -6,17 +6,8 @@ package net.mograsim.machine;
  * @author Christian Femers
  *
  */
-public interface MainMemoryDefinition extends MemoryDefinition
+public interface MainMemoryDefinition extends BitVectorMemoryDefinition
 {
-       /**
-        * 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.
-        * 
-        * @return the addressable unit width in bits
-        * @author Christian Femers
-        */
-       int getCellWidth();
-
        public static MainMemoryDefinition create(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress)
        {
                return new StandardMainMemoryDefinition(memoryAddressBits, cellWidth, minimalAddress, maximalAddress);
index 39d12c4..2487308 100644 (file)
@@ -29,7 +29,7 @@ public interface MemoryDefinition
        long getMaximalAddress();
 
        /**
-        * The size of the MainMemory as the amount of addressable memory cells.
+        * The size of the memory as the amount of addressable memory cells.
         * 
         * @return the amount of addressable memory cells
         */
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemory.java
new file mode 100644 (file)
index 0000000..a3630a6
--- /dev/null
@@ -0,0 +1,19 @@
+package net.mograsim.machine;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemory;
+
+public class StandardMainMemory extends StandardBitVectorMemory<MainMemoryDefinition> implements MainMemory
+{
+       public StandardMainMemory(MainMemoryDefinition definition)
+       {
+               super(definition);
+       }
+
+       @Override
+       protected BitVector getDefaultValue(long address)
+       {
+               return BitVector.of(Bit.ZERO, getDefinition().getCellWidth());
+       }
+}
index 22be93e..235dea1 100644 (file)
@@ -1,18 +1,11 @@
 package net.mograsim.machine;
 
-class StandardMainMemoryDefinition extends StandardMemoryDefinition implements MainMemoryDefinition
-{
-       private final int cellWidth;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemoryDefinition;
 
+class StandardMainMemoryDefinition extends StandardBitVectorMemoryDefinition implements MainMemoryDefinition
+{
        StandardMainMemoryDefinition(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress)
        {
-               super(memoryAddressBits, minimalAddress, maximalAddress);
-               this.cellWidth = cellWidth;
-       }
-
-       @Override
-       public int getCellWidth()
-       {
-               return cellWidth;
+               super(memoryAddressBits, cellWidth, minimalAddress, maximalAddress);
        }
 }
index 8f1904d..b8f5a81 100644 (file)
@@ -13,11 +13,6 @@ public class StandardMemoryDefinition implements MemoryDefinition
                this.maximalAddress = maximalAddress;
        }
 
-       public StandardMemoryDefinition(MainMemoryDefinition definition)
-       {
-               this(definition.getMemoryAddressBits(), definition.getMinimalAddress(), definition.getMaximalAddress());
-       }
-
        @Override
        public int getMemoryAddressBits()
        {
index 0405013..39cd679 100644 (file)
@@ -1,99 +1,17 @@
 package net.mograsim.machine.mi;
 
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Set;
+import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory;
 
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-public class AssignableMPROM implements MPROM, MemoryCellModifiedListener
+public class AssignableMPROM extends AbstractAssignableBitVectorMemory<MPROM> implements MPROM
 {
-
-       private Set<MemoryCellModifiedListener> observers = new HashSet<>();
-
-       private Set<MPROMReassignedListener> reassignmentListeners = new HashSet<>();
-       private MPROM real = null;
-
-       public AssignableMPROM(MPROM standardMPROM)
-       {
-               real = standardMPROM;
-               real.registerCellModifiedListener(this);
-       }
-
-       public void bind(MPROM real)
-       {
-               this.real.deregisterCellModifiedListener(this);
-               this.real = real;
-               real.registerCellModifiedListener(this);
-               notifyMemoryChanged(-1);
-               notifyMemoryReassigned(real);
-       }
-
-       @Override
-       public BitVector getCell(long address)
-       {
-               return real.getCell(address);
-       }
-
-       @Override
-       public void setCell(long address, BitVector data)
-       {
-               real.setCell(address, data);
-       }
-
-       @Override
-       public BigInteger getCellAsBigInteger(long address)
-       {
-               return real.getCellAsBigInteger(address);
-       }
-
-       @Override
-       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
+       public AssignableMPROM(MPROM memory)
        {
-               observers.add(ob);
-       }
-
-       @Override
-       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
-       {
-               observers.remove(ob);
-       }
-
-       private void notifyMemoryChanged(long address)
-       {
-               observers.forEach(o -> o.update(address));
+               super(memory);
        }
 
        @Override
        public MPROMDefinition getDefinition()
        {
-               return real.getDefinition();
-       }
-
-       @Override
-       public void update(long address)
-       {
-               notifyMemoryChanged(address);
-       }
-
-       public void registerMemoryReassignedListener(MPROMReassignedListener listener)
-       {
-               reassignmentListeners.add(listener);
-       }
-
-       public void deregisterMemoryReassignedListener(MPROMReassignedListener listener)
-       {
-               reassignmentListeners.remove(listener);
-       }
-
-       private void notifyMemoryReassigned(MPROM newAssignee)
-       {
-               reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
-       }
-
-       public static interface MPROMReassignedListener
-       {
-               public void reassigned(MPROM newAssignee);
+               return getReal().getDefinition();
        }
 }
index 0d8be38..a0b87ca 100644 (file)
@@ -1,14 +1,9 @@
 package net.mograsim.machine.mi;
 
-import java.math.BigInteger;
+import net.mograsim.machine.BitVectorMemory;
 
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.Memory;
-
-public interface MPROM extends Memory<BitVector>
+public interface MPROM extends BitVectorMemory
 {
-       public BigInteger getCellAsBigInteger(long address);
-
        @Override
        public MPROMDefinition getDefinition();
 }
\ No newline at end of file
index 680a1fa..1fec8bb 100644 (file)
@@ -1,6 +1,6 @@
 package net.mograsim.machine.mi;
 
-import net.mograsim.machine.MemoryDefinition;
+import net.mograsim.machine.BitVectorMemoryDefinition;
 
 /**
  * This interface provides a means to get information about the machines memory architecture. It is not bound to any actual memory.
@@ -8,17 +8,8 @@ import net.mograsim.machine.MemoryDefinition;
  * @author Christian Femers
  *
  */
-public interface MPROMDefinition extends MemoryDefinition
+public interface MPROMDefinition extends BitVectorMemoryDefinition
 {
-       /**
-        * 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.
-        * 
-        * @return the addressable unit width in bits
-        * @author Christian Femers
-        */
-       int getMicroInstructionMemoryAddressBits();
-
        public static MPROMDefinition create(int opcodeBits, int microInstructionMemoryAddressBits)
        {
                return new StandardMPROMDefinition(opcodeBits, microInstructionMemoryAddressBits);
index 48df165..3d8a8cb 100644 (file)
@@ -1,73 +1,18 @@
 package net.mograsim.machine.mi;
 
-import java.math.BigInteger;
-import java.util.HashSet;
-
 import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.standard.memory.MemoryException;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemory;
 
-public class StandardMPROM implements MPROM
+public class StandardMPROM extends StandardBitVectorMemory<MPROMDefinition> implements MPROM
 {
-       private BitVector[] data;
-       private MPROMDefinition definition;
-       private HashSet<MemoryCellModifiedListener> observers = new HashSet<>();
-
        public StandardMPROM(MPROMDefinition definition)
        {
-               if (definition.size() > Integer.MAX_VALUE)
-                       throw new MemoryException("Size of MPROM must be an int, not a long");
-               this.definition = definition;
-               data = new BitVector[(int) definition.size()];
-       }
-
-       private int translate(long address)
-       {
-               return (int) (address - definition.getMinimalAddress());
-       }
-
-       @Override
-       public BitVector getCell(long address)
-       {
-               int translatedAddress = translate(address);
-               BitVector cell = data[translatedAddress];
-               if (cell == null)
-                       cell = data[translatedAddress] = BitVector.from(address * 16, definition.getMicroInstructionMemoryAddressBits());
-               return cell;
-       }
-
-       @Override
-       public BigInteger getCellAsBigInteger(long address)
-       {
-               return getCell(address).getUnsignedValue();
-       }
-
-       @Override
-       public void setCell(long address, BitVector data)
-       {
-               this.data[translate(address)] = data;
-               notifyMemoryChanged(address);
-       }
-
-       @Override
-       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
-       {
-               observers.add(ob);
-       }
-
-       @Override
-       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
-       {
-               observers.remove(ob);
-       }
-
-       private void notifyMemoryChanged(long address)
-       {
-               observers.forEach(ob -> ob.update(address));
+               super(definition);
        }
 
        @Override
-       public MPROMDefinition getDefinition()
+       protected BitVector getDefaultValue(long address)
        {
-               return definition;
+               return BitVector.from(address * 16, getDefinition().getCellWidth());
        }
 }
index cbc9790..6e1ce13 100644 (file)
@@ -1,20 +1,11 @@
 package net.mograsim.machine.mi;
 
-import net.mograsim.machine.StandardMemoryDefinition;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemoryDefinition;
 
-class StandardMPROMDefinition extends StandardMemoryDefinition implements MPROMDefinition
+class StandardMPROMDefinition extends StandardBitVectorMemoryDefinition implements MPROMDefinition
 {
-       private final int microInstructionMemoryAddressBits;
-
        StandardMPROMDefinition(int opcodeBits, int microInstructionMemoryAddressBits)
        {
-               super(opcodeBits, 0, 1 << opcodeBits);
-               this.microInstructionMemoryAddressBits = microInstructionMemoryAddressBits;
-       }
-
-       @Override
-       public int getMicroInstructionMemoryAddressBits()
-       {
-               return microInstructionMemoryAddressBits;
+               super(opcodeBits, microInstructionMemoryAddressBits, 0, 1 << opcodeBits);
        }
 }
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMPROM.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMPROM.java
deleted file mode 100644 (file)
index e2d66df..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-package net.mograsim.machine.mi.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicCoreComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.timeline.TimelineEventHandler;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-import net.mograsim.machine.mi.MPROM;
-import net.mograsim.machine.mi.MPROMDefinition;
-
-public class CoreMPROM extends BasicCoreComponent
-{
-       private final ReadWriteEnd data;
-       private final ReadEnd address;
-       private final MPROMDefinition definition;
-       private final MemoryCellModifiedListener memObs;
-       private MPROM memory;
-
-       public CoreMPROM(Timeline timeline, int processTime, MPROMDefinition definition, ReadWriteEnd data, ReadEnd address)
-       {
-               super(timeline, processTime);
-               if (data.width() != definition.getMicroInstructionMemoryAddressBits())
-                       throw new IllegalArgumentException(
-                                       String.format("Bit width of data wire does not match MPROM definition. Expected: %d Actual: %d",
-                                                       definition.getMicroInstructionMemoryAddressBits(), data.width()));
-               if (address.width() != definition.getMemoryAddressBits())
-                       throw new IllegalArgumentException(
-                                       String.format("Bit width of address wire does not match MPROM definition. Expected: %d Actual: %d",
-                                                       definition.getMemoryAddressBits(), address.width()));
-
-               this.data = data;
-               this.address = address;
-               this.definition = definition;
-               this.memObs = a -> update();
-               address.registerObserver(this);
-       }
-
-       public void setMemory(MPROM memory)
-       {
-               if (memory != null && !memory.getDefinition().equals(definition))
-                       throw new IllegalArgumentException("Memory of incorrect memory definition given");
-               if (this.memory != null)
-                       this.memory.registerCellModifiedListener(memObs);
-               this.memory = memory;
-               if (memory != null)
-                       memory.registerCellModifiedListener(memObs);
-               update();
-       }
-
-       public MPROM getMemory()
-       {
-               return memory;
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(address);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(data);
-       }
-
-       @Override
-       protected TimelineEventHandler compute()
-       {
-               if (memory == null || !address.getValues().isBinary())
-                       return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
-               long addressed = address.getValues().getUnsignedValueLong();
-               BitVector storedData = memory.getCell(addressed);
-               return e -> data.feedSignals(storedData);
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/MPROMAdapter.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/MPROMAdapter.java
deleted file mode 100644 (file)
index 9eab2b4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-package net.mograsim.machine.mi.components;
-
-import java.util.Map;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.CoreWire;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.CoreModelParameters;
-import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
-
-public class MPROMAdapter implements ComponentAdapter<ModelMPROM>
-{
-       @Override
-       public Class<ModelMPROM> getSupportedClass()
-       {
-               return ModelMPROM.class;
-       }
-
-       @Override
-       public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelMPROM modelComponent,
-                       Map<Pin, CoreWire> logicWiresPerPin)
-       {
-               ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
-               ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
-               CoreMPROM mem = new CoreMPROM(timeline, 2, modelComponent.getDefinition(), data, address);
-               modelComponent.setCoreModelBinding(mem);
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/ModelMPROM.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/ModelMPROM.java
deleted file mode 100644 (file)
index b1f791c..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-package net.mograsim.machine.mi.components;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import net.mograsim.logic.model.model.LogicModelModifiable;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.model.wires.PinUsage;
-import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
-import net.mograsim.logic.model.serializing.IdentifyParams;
-import net.mograsim.logic.model.snippets.HighLevelStateHandler;
-import net.mograsim.machine.ModelMemory;
-import net.mograsim.machine.mi.MPROM;
-import net.mograsim.machine.mi.MPROMDefinition;
-
-public abstract class ModelMPROM extends ModelMemory
-{
-       private final Pin addrPin, dataPin;
-       private CoreMPROM memory;
-       private final MPROMDefinition definition;
-
-       private final List<Consumer<Object>> memoryBindingListeners;
-
-       public ModelMPROM(LogicModelModifiable model, MPROMDefinition definition, String name)
-       {
-               super(model, 30, 80, name, "MPROM", false);
-               this.definition = definition;
-               addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, getWidth(), 30));
-               addPin(dataPin = new Pin(model, this, "D", definition.getMicroInstructionMemoryAddressBits(), PinUsage.OUTPUT, getWidth(), 50));
-
-               memoryBindingListeners = new ArrayList<>();
-
-               setHighLevelStateHandler(new HighLevelStateHandler()
-               {
-                       @Override
-                       public Object get(String stateID)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       return memory.getMemory();
-                               throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void set(String stateID, Object newState)
-                       {
-                               if (stateID.equals("memory_binding"))
-                               {
-                                       memory.setMemory((MPROM) newState);
-                                       memoryBindingListeners.forEach(l -> l.accept(newState));
-                               } else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void addListener(String stateID, Consumer<Object> stateChanged)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       memoryBindingListeners.add(stateChanged);
-                               else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void removeListener(String stateID, Consumer<Object> stateChanged)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       memoryBindingListeners.remove(stateChanged);
-                               else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public String getIDForSerializing(IdentifyParams idParams)
-                       {
-                               return null;
-                       }
-
-                       @Override
-                       public Object getParamsForSerializing(IdentifyParams idParams)
-                       {
-                               return null;
-                       }
-               });
-
-               init();
-       }
-
-       public MPROMDefinition getDefinition()
-       {
-               return definition;
-       }
-
-       public Pin getAddressPin()
-       {
-               return addrPin;
-       }
-
-       public Pin getDataPin()
-       {
-               return dataPin;
-       }
-
-       public CoreMPROM getCoreMemory()
-       {
-               return memory;
-       }
-
-       public void setCoreModelBinding(CoreMPROM memory)
-       {
-               this.memory = memory;
-       }
-
-       static
-       {
-               LogicCoreAdapter.addComponentAdapter(new MPROMAdapter());
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractAssignableBitVectorMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractAssignableBitVectorMemory.java
new file mode 100644 (file)
index 0000000..782a5b6
--- /dev/null
@@ -0,0 +1,110 @@
+package net.mograsim.machine.standard.memory;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+
+public class AbstractAssignableBitVectorMemory<M extends BitVectorMemory> implements BitVectorMemory, MemoryCellModifiedListener
+{
+       private Set<MemoryCellModifiedListener> observers = new HashSet<>();
+       private Set<BitVectorMemoryReassignedListener<M>> reassignmentListeners = new HashSet<>();
+       private M real = null;
+
+       public AbstractAssignableBitVectorMemory(M memory)
+       {
+               real = memory;
+               real.registerCellModifiedListener(this);
+       }
+
+       public void bind(M real)
+       {
+               this.real.deregisterCellModifiedListener(this);
+               this.real = real;
+               real.registerCellModifiedListener(this);
+               notifyMemoryChanged(-1);
+               notifyMemoryReassigned(real);
+       }
+
+       @Override
+       public BitVector getCell(long address)
+       {
+               return real.getCell(address);
+       }
+
+       @Override
+       public BigInteger getCellAsBigInteger(long address)
+       {
+               return real.getCellAsBigInteger(address);
+       }
+
+       @Override
+       public void setCell(long address, BitVector data)
+       {
+               real.setCell(address, data);
+       }
+
+       @Override
+       public void setCellAsBigInteger(long address, BigInteger word)
+       {
+               real.setCellAsBigInteger(address, word);
+       }
+
+       @Override
+       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
+       {
+               observers.add(ob);
+       }
+
+       protected M getReal()
+       {
+               return real;
+       }
+
+       @Override
+       public BitVectorMemoryDefinition getDefinition()
+       {
+               return real.getDefinition();
+       }
+
+       @Override
+       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
+       {
+               observers.remove(ob);
+       }
+
+       private void notifyMemoryChanged(long address)
+       {
+               observers.forEach(o -> o.update(address));
+       }
+
+       @Override
+       public void update(long address)
+       {
+               notifyMemoryChanged(address);
+       }
+
+       public void registerMemoryReassignedListener(BitVectorMemoryReassignedListener<M> listener)
+       {
+               reassignmentListeners.add(listener);
+       }
+
+       public void deregisterMemoryReassignedListener(BitVectorMemoryReassignedListener<M> listener)
+       {
+               reassignmentListeners.remove(listener);
+       }
+
+       private void notifyMemoryReassigned(M newAssignee)
+       {
+               reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
+       }
+
+       public interface BitVectorMemoryReassignedListener<M extends BitVectorMemory>
+       {
+               public void reassigned(M newAssignee);
+       }
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractModelBitVectorMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractModelBitVectorMemory.java
new file mode 100644 (file)
index 0000000..055fb4f
--- /dev/null
@@ -0,0 +1,141 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+import net.mograsim.logic.model.model.LogicModelModifiable;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.model.wires.PinUsage;
+import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
+import net.mograsim.logic.model.serializing.IdentifyParams;
+import net.mograsim.logic.model.snippets.HighLevelStateHandler;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.ModelMemory;
+
+public abstract class AbstractModelBitVectorMemory<M extends BitVectorMemory, D extends BitVectorMemoryDefinition> extends ModelMemory
+{
+       private final Pin addrPin, dataPin, rWPin;
+       private final D definition;
+       private final boolean readonly;
+
+       private CoreBitVectorMemory<M> memory;
+
+       private final List<Consumer<Object>> memoryBindingListeners;
+
+       public AbstractModelBitVectorMemory(LogicModelModifiable model, int width, int height, int aPinX, int dPinX, int rwPinX,
+                       boolean readonly, String centerText, D definition, String name)
+       {
+               super(model, width, height, name, centerText, false);
+               this.definition = definition;
+               this.readonly = readonly;
+
+               addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, width, aPinX));
+               addPin(dataPin = new Pin(model, this, "D", definition.getCellWidth(), PinUsage.TRISTATE, width, dPinX));
+               if (readonly)
+                       rWPin = null;
+               else
+                       addPin(rWPin = new Pin(model, this, "RW", 1, PinUsage.INPUT, width, rwPinX));
+
+               memoryBindingListeners = new ArrayList<>();
+
+               setHighLevelStateHandler(new HighLevelStateHandler()
+               {
+                       @Override
+                       public Object get(String stateID)
+                       {
+                               if (stateID.equals("memory_binding"))
+                                       return memory.getMemory();
+                               throw new IllegalArgumentException("No high level state with ID " + stateID);
+                       }
+
+                       @Override
+                       public void set(String stateID, Object newState)
+                       {
+                               if (stateID.equals("memory_binding"))
+                               {
+                                       @SuppressWarnings("unchecked")
+                                       M mem = (M) newState;
+                                       memory.setMemory(mem);
+                                       memoryBindingListeners.forEach(l -> l.accept(newState));
+                               } else
+                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
+                       }
+
+                       @Override
+                       public void addListener(String stateID, Consumer<Object> stateChanged)
+                       {
+                               if (stateID.equals("memory_binding"))
+                                       memoryBindingListeners.add(stateChanged);
+                               else
+                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
+                       }
+
+                       @Override
+                       public void removeListener(String stateID, Consumer<Object> stateChanged)
+                       {
+                               if (stateID.equals("memory_binding"))
+                                       memoryBindingListeners.remove(stateChanged);
+                               else
+                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
+                       }
+
+                       @Override
+                       public String getIDForSerializing(IdentifyParams idParams)
+                       {
+                               return null;
+                       }
+
+                       @Override
+                       public Object getParamsForSerializing(IdentifyParams idParams)
+                       {
+                               return null;
+                       }
+               });
+
+               init();
+       }
+
+       public D getDefinition()
+       {
+               return definition;
+       }
+
+       public Pin getAddressPin()
+       {
+               return addrPin;
+       }
+
+       public Pin getDataPin()
+       {
+               return dataPin;
+       }
+
+       public Pin getReadWritePin()
+       {
+               if (isReadonly())
+                       throw new IllegalArgumentException("This AbstractModelBitVectorMemory has no RW pin; it is readonly");
+               return rWPin;
+       }
+
+       public boolean isReadonly()
+       {
+               return readonly;
+       }
+
+       public void setCoreModelBinding(CoreBitVectorMemory<M> memory)
+       {
+               this.memory = memory;
+       }
+
+       public CoreBitVectorMemory<M> getCoreMemory()
+       {
+               return memory;
+       }
+
+       static
+       {
+               LogicCoreAdapter.addComponentAdapter(new BitVectorMemoryAdapter());
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java
deleted file mode 100644 (file)
index 38b17ab..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Set;
-
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-public class AssignableMainMemory implements MainMemory, MemoryCellModifiedListener
-{
-       private Set<MemoryCellModifiedListener> observers = new HashSet<>();
-       private Set<MainMemoryReassignedListener> reassignmentListeners = new HashSet<>();
-       private MainMemory real = null;
-
-       public AssignableMainMemory(MainMemory mainMemory)
-       {
-               real = mainMemory;
-               real.registerCellModifiedListener(this);
-       }
-
-       public void bind(MainMemory real)
-       {
-               this.real.deregisterCellModifiedListener(this);
-               this.real = real;
-               real.registerCellModifiedListener(this);
-               notifyMemoryChanged(-1);
-               notifyMemoryReassigned(real);
-       }
-
-       @Override
-       public BitVector getCell(long address)
-       {
-               return real.getCell(address);
-       }
-
-       @Override
-       public BigInteger getCellAsBigInteger(long address)
-       {
-               return real.getCellAsBigInteger(address);
-       }
-
-       @Override
-       public void setCell(long address, BitVector data)
-       {
-               real.setCell(address, data);
-       }
-
-       @Override
-       public void setCellAsBigInteger(long address, BigInteger word)
-       {
-               real.setCellAsBigInteger(address, word);
-       }
-
-       @Override
-       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
-       {
-               observers.add(ob);
-       }
-
-       @Override
-       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
-       {
-               observers.remove(ob);
-       }
-
-       private void notifyMemoryChanged(long address)
-       {
-               observers.forEach(o -> o.update(address));
-       }
-
-       @Override
-       public MainMemoryDefinition getDefinition()
-       {
-               return real.getDefinition();
-       }
-
-       @Override
-       public void update(long address)
-       {
-               notifyMemoryChanged(address);
-       }
-
-       public void registerMemoryReassignedListener(MainMemoryReassignedListener listener)
-       {
-               reassignmentListeners.add(listener);
-       }
-
-       public void deregisterMemoryReassignedListener(MainMemoryReassignedListener listener)
-       {
-               reassignmentListeners.remove(listener);
-       }
-
-       private void notifyMemoryReassigned(MainMemory newAssignee)
-       {
-               reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
-       }
-
-       public static interface MainMemoryReassignedListener
-       {
-               public void reassigned(MainMemory newAssignee);
-       }
-}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorBasedMemoryParser.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorBasedMemoryParser.java
new file mode 100644 (file)
index 0000000..f2a7ac3
--- /dev/null
@@ -0,0 +1,123 @@
+package net.mograsim.machine.standard.memory;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.MemoryDefinition;
+import net.mograsim.machine.StandardMainMemory;
+import net.mograsim.machine.mi.MPROM;
+import net.mograsim.machine.mi.MPROMDefinition;
+import net.mograsim.machine.mi.StandardMPROM;
+
+public class BitVectorBasedMemoryParser
+{
+       private final static String lineSeparator = System.getProperty("line.separator");
+
+       public static void parseMemory(final BitVectorMemory memory, String inputPath) throws IOException
+       {
+               try (InputStream input = new FileInputStream(inputPath))
+               {
+                       parseMemory(memory, input);
+               }
+       }
+
+       /**
+        * @param input The input to parse must be in csv format; The stream is closed after being consumed.
+        * 
+        * @throws IOException
+        */
+       public static MainMemory parseMainMemory(MainMemoryDefinition memDef, InputStream input) throws IOException
+       {
+               try
+               {
+                       MainMemory memory = new StandardMainMemory(memDef);
+                       parseMemory(memory, input);
+                       return memory;
+               }
+               catch (NullPointerException e)
+               {
+                       throw new BitVectorMemoryParseException(e);
+               }
+       }
+
+       /**
+        * @param input The input to parse must be in csv format; The stream is closed after being consumed.
+        * 
+        * @throws IOException
+        */
+       public static MPROM parseMPROM(MPROMDefinition memDef, InputStream input) throws IOException
+       {
+               try
+               {
+                       MPROM memory = new StandardMPROM(memDef);
+                       parseMemory(memory, input);
+                       return memory;
+               }
+               catch (NullPointerException e)
+               {
+                       throw new BitVectorMemoryParseException(e);
+               }
+       }
+
+       /**
+        *
+        * @param input The input to parse must be in csv format; The stream is closed after being consumed.
+        * 
+        * @throws IOException
+        */
+       public static void parseMemory(final BitVectorMemory memory, InputStream input) throws IOException
+       {
+               try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)))
+               {
+                       MemoryDefinition def = memory.getDefinition();
+
+                       long minAddr = def.getMinimalAddress();
+                       long maxAddr = def.getMaximalAddress();
+
+                       String line;
+                       long i = minAddr;
+                       try
+                       {
+                               for (; i <= maxAddr && reader.ready() && !"".equals((line = reader.readLine())); i++)
+                               {
+                                       memory.setCell(i, BitVector.parseBitstring(line));
+                               }
+                       }
+                       catch (IOException e)
+                       {
+                               e.printStackTrace();
+                       }
+               }
+       }
+
+       public static InputStream write(BitVectorMemory memory)
+       {
+               return new InputStream()
+               {
+                       long instIndex = memory.getDefinition().getMinimalAddress(), maxAddress = memory.getDefinition().getMaximalAddress();
+                       InputStream instStream = new ByteArrayInputStream(new byte[0]);
+
+                       @Override
+                       public int read() throws IOException
+                       {
+                               int val = instStream.read();
+                               if (val == -1 && instIndex <= maxAddress)
+                               {
+                                       instStream = new ByteArrayInputStream(
+                                                       (memory.getCell(instIndex++).toBitstring() + lineSeparator).getBytes(StandardCharsets.UTF_8));
+                                       val = instStream.read();
+                               }
+                               return val;
+                       }
+               };
+       }
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryAdapter.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryAdapter.java
new file mode 100644 (file)
index 0000000..777a6bc
--- /dev/null
@@ -0,0 +1,42 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.Map;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.wires.CoreWire;
+import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.modeladapter.CoreModelParameters;
+import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+
+public class BitVectorMemoryAdapter implements ComponentAdapter<AbstractModelBitVectorMemory<?, ?>>
+{
+       @SuppressWarnings({ "cast", "unchecked", "rawtypes" })
+       @Override
+       public Class<AbstractModelBitVectorMemory<?, ?>> getSupportedClass()
+       {
+               return (Class<AbstractModelBitVectorMemory<?, ?>>) (Class) AbstractModelBitVectorMemory.class;
+       }
+
+       @Override
+       public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, AbstractModelBitVectorMemory<?, ?> modelComponent,
+                       Map<Pin, CoreWire> logicWiresPerPin)
+       {
+               createAndLinkComponentCasted(timeline, params, modelComponent, logicWiresPerPin);
+       }
+
+       private static <M extends BitVectorMemory, D extends BitVectorMemoryDefinition> void createAndLinkComponentCasted(Timeline timeline,
+                       CoreModelParameters params, AbstractModelBitVectorMemory<M, D> modelComponent, Map<Pin, CoreWire> logicWiresPerPin)
+       {
+               ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
+               ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
+               ReadEnd rwBit = modelComponent.isReadonly() ? null : logicWiresPerPin.get(modelComponent.getReadWritePin()).createReadOnlyEnd();
+               // TODO introduce memoryProcessTime
+               CoreBitVectorMemory<M> mem = new CoreBitVectorMemory<>(timeline, 2, modelComponent.getDefinition(), data, rwBit, address,
+                               modelComponent.isReadonly());
+               modelComponent.setCoreModelBinding(mem);
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryParseException.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryParseException.java
new file mode 100644 (file)
index 0000000..a807e09
--- /dev/null
@@ -0,0 +1,28 @@
+package net.mograsim.machine.standard.memory;
+
+import net.mograsim.machine.MachineException;
+
+public class BitVectorMemoryParseException extends MachineException
+{
+
+       /**
+        * 
+        */
+       private static final long serialVersionUID = 6820101808901789906L;
+
+       public BitVectorMemoryParseException()
+       {
+               super();
+       }
+
+       public BitVectorMemoryParseException(String message)
+       {
+               super(message);
+       }
+
+       public BitVectorMemoryParseException(Throwable cause)
+       {
+               super(cause);
+       }
+
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreBitVectorMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreBitVectorMemory.java
new file mode 100644 (file)
index 0000000..e3e20ce
--- /dev/null
@@ -0,0 +1,119 @@
+package net.mograsim.machine.standard.memory;
+
+import java.util.List;
+
+import net.mograsim.logic.core.components.BasicCoreComponent;
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.timeline.TimelineEventHandler;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+
+/**
+ * A memory component that only allows access to words of a specific width
+ */
+public class CoreBitVectorMemory<M extends BitVectorMemory> extends BasicCoreComponent
+{
+       private final static Bit read = Bit.ONE;
+
+       private final ReadWriteEnd data;
+       private final ReadEnd rWBit, address;
+       private final boolean readonly;
+       private final MemoryCellModifiedListener memObs;
+       private final BitVectorMemoryDefinition definition;
+       private M memory;
+
+       /**
+        * @param data    The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
+        *                a memory word
+        * @param rWBit   The value of the 0th bit dictates the mode: 0: Write, 1: Read
+        * @param address The bits of this ReadEnd address the memory cell to read/write
+        */
+       public CoreBitVectorMemory(Timeline timeline, int processTime, BitVectorMemoryDefinition definition, ReadWriteEnd data, ReadEnd rWBit,
+                       ReadEnd address, boolean readonly)
+       {
+               super(timeline, processTime);
+               if (data.width() != definition.getCellWidth())
+                       throw new IllegalArgumentException(
+                                       String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d",
+                                                       definition.getCellWidth(), data.width()));
+               if (!readonly && rWBit.width() != 1)
+                       throw new IllegalArgumentException(
+                                       String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width()));
+               if (address.width() != definition.getMemoryAddressBits())
+                       throw new IllegalArgumentException(
+                                       String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d",
+                                                       definition.getMemoryAddressBits(), address.width()));
+               this.data = data;
+               this.rWBit = rWBit;
+               this.address = address;
+               this.readonly = readonly;
+               this.definition = definition;
+               this.memObs = a -> update();
+               data.registerObserver(this);
+               if (!readonly)
+                       rWBit.registerObserver(this);
+               address.registerObserver(this);
+       }
+
+       public void setMemory(M memory)
+       {
+               if (memory != null && !memory.getDefinition().equals(definition))
+                       throw new IllegalArgumentException("Memory of incorrect memory definition given");
+               if (this.memory != null)
+                       this.memory.registerCellModifiedListener(memObs);
+               this.memory = memory;
+               if (memory != null)
+                       memory.registerCellModifiedListener(memObs);
+               update();
+       }
+
+       public M getMemory()
+       {
+               return memory;
+       }
+
+       @Override
+       protected TimelineEventHandler compute()
+       {
+               if (memory == null)
+                       return e -> data.feedSignals(Bit.U.toVector(data.width()));
+               boolean isReading = readonly || read.equals(rWBit.getValue());
+               if (!address.getValues().isBinary())
+               {
+                       if (isReading)
+                               return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
+                       return e -> data.clearSignals();
+               }
+               long addressed = address.getValues().getUnsignedValueLong();
+               if (isReading)
+               {
+                       BitVector storedData = memory.getCell(addressed);
+                       return e -> data.feedSignals(storedData);
+               }
+               BitVector transData = data.getValues();
+               boolean isNewData = !transData.equals(memory.getCell(addressed));
+               return e ->
+               {
+                       data.clearSignals();
+                       if (isNewData)
+                               memory.setCell(addressed, transData);
+               };
+       }
+
+       @Override
+       public List<ReadEnd> getAllInputs()
+       {
+               return readonly ? List.of(data, address) : List.of(data, rWBit, address);
+       }
+
+       @Override
+       public List<ReadWriteEnd> getAllOutputs()
+       {
+               return List.of(data);
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java
deleted file mode 100644 (file)
index 801895b..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicCoreComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.timeline.TimelineEventHandler;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-/**
- * A memory component that only allows access to words of a specific width
- */
-public class CoreWordAddressableMemory extends BasicCoreComponent
-{
-       private final static Bit read = Bit.ONE;
-
-       private ReadWriteEnd data;
-       private ReadEnd rWBit, address;
-       private final MemoryCellModifiedListener memObs;
-       private final MainMemoryDefinition definition;
-       private MainMemory memory;
-
-       /**
-        * @param data    The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
-        *                a memory word
-        * @param rWBit   The value of the 0th bit dictates the mode: 0: Write, 1: Read
-        * @param address The bits of this ReadEnd address the memory cell to read/write
-        */
-       public CoreWordAddressableMemory(Timeline timeline, int processTime, MainMemoryDefinition definition, ReadWriteEnd data, ReadEnd rWBit,
-                       ReadEnd address)
-       {
-               super(timeline, processTime);
-               if (data.width() != definition.getCellWidth())
-                       throw new IllegalArgumentException(
-                                       String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d",
-                                                       definition.getCellWidth(), data.width()));
-               if (rWBit.width() != 1)
-                       throw new IllegalArgumentException(
-                                       String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width()));
-               if (address.width() != definition.getMemoryAddressBits())
-                       throw new IllegalArgumentException(
-                                       String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d",
-                                                       definition.getMemoryAddressBits(), address.width()));
-               this.data = data;
-               this.rWBit = rWBit;
-               this.address = address;
-               this.definition = definition;
-               this.memObs = a -> update();
-               data.registerObserver(this);
-               rWBit.registerObserver(this);
-               address.registerObserver(this);
-       }
-
-       public void setMemory(MainMemory memory)
-       {
-               if (memory != null && !memory.getDefinition().equals(definition))
-                       throw new IllegalArgumentException("Memory of incorrect memory definition given");
-               if (this.memory != null)
-                       this.memory.registerCellModifiedListener(memObs);
-               this.memory = memory;
-               if (memory != null)
-                       memory.registerCellModifiedListener(memObs);
-               update();
-       }
-
-       public MainMemory getMemory()
-       {
-               return memory;
-       }
-
-       @Override
-       protected TimelineEventHandler compute()
-       {
-               if (memory == null)
-                       return e -> data.feedSignals(Bit.U.toVector(data.width()));
-               if (!address.getValues().isBinary())
-               {
-                       if (read.equals(rWBit.getValue()))
-                               return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
-                       return e -> data.clearSignals();
-               }
-               long addressed = address.getValues().getUnsignedValueLong();
-               if (read.equals(rWBit.getValue()))
-               {
-                       BitVector storedData = memory.getCell(addressed);
-                       return e -> data.feedSignals(storedData);
-               }
-               BitVector transData = data.getValues();
-               boolean isNewData = !transData.equals(memory.getCell(addressed));
-               return e ->
-               {
-                       data.clearSignals();
-                       if (isNewData)
-                               memory.setCell(addressed, transData);
-               };
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(data, rWBit, address);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(data);
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParseException.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParseException.java
deleted file mode 100644 (file)
index 5c6297e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import net.mograsim.machine.MachineException;
-
-public class MainMemoryParseException extends MachineException
-{
-
-       /**
-        * 
-        */
-       private static final long serialVersionUID = 6820101808901789906L;
-
-       public MainMemoryParseException()
-       {
-               super();
-       }
-
-       public MainMemoryParseException(String message)
-       {
-               super(message);
-       }
-
-       public MainMemoryParseException(Throwable cause)
-       {
-               super(cause);
-       }
-
-}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParser.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParser.java
deleted file mode 100644 (file)
index c3b0d68..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-
-public class MainMemoryParser
-{
-       private final static String lineSeparator = System.getProperty("line.separator");
-
-       public static void parseMemory(final MainMemory memory, String inputPath) throws IOException
-       {
-               try (InputStream input = new FileInputStream(inputPath))
-               {
-                       parseMemory(memory, input);
-               }
-       }
-
-       /**
-        * @param input The input to parse must be in csv format; The stream is closed after being consumed.
-        * 
-        * @throws IOException
-        */
-       public static MainMemory parseMemory(MainMemoryDefinition memDef, InputStream input) throws IOException
-       {
-               try
-               {
-                       MainMemory memory = new WordAddressableMemory(memDef);
-                       parseMemory(memory, input);
-                       return memory;
-               }
-               catch (NullPointerException e)
-               {
-                       throw new MainMemoryParseException(e);
-               }
-       }
-
-       /**
-        *
-        * @param input The input to parse must be in csv format; The stream is closed after being consumed.
-        * 
-        * @throws IOException
-        */
-       public static void parseMemory(final MainMemory memory, InputStream input) throws IOException
-       {
-               try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)))
-               {
-                       MainMemoryDefinition def = memory.getDefinition();
-
-                       long minAddr = def.getMinimalAddress();
-                       long maxAddr = def.getMaximalAddress();
-
-                       String line;
-                       long i = minAddr;
-                       try
-                       {
-                               for (; i <= maxAddr && reader.ready() && !"".equals((line = reader.readLine())); i++)
-                               {
-                                       memory.setCell(i, BitVector.parseBitstring(line));
-                               }
-                       }
-                       catch (IOException e)
-                       {
-                               e.printStackTrace();
-                       }
-               }
-       }
-
-       public static InputStream write(MainMemory memory)
-       {
-               return new InputStream()
-               {
-                       long instIndex = memory.getDefinition().getMinimalAddress(), maxAddress = memory.getDefinition().getMaximalAddress();
-                       InputStream instStream = new ByteArrayInputStream(new byte[0]);
-
-                       @Override
-                       public int read() throws IOException
-                       {
-                               int val = instStream.read();
-                               if (val == -1 && instIndex <= maxAddress)
-                               {
-                                       instStream = new ByteArrayInputStream(
-                                                       (memory.getCell(instIndex++).toBitstring() + lineSeparator).getBytes(StandardCharsets.UTF_8));
-                                       val = instStream.read();
-                               }
-                               return val;
-                       }
-               };
-       }
-}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/ModelWordAddressableMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/ModelWordAddressableMemory.java
deleted file mode 100644 (file)
index a1112e6..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import net.mograsim.logic.model.model.LogicModelModifiable;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.model.wires.PinUsage;
-import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
-import net.mograsim.logic.model.serializing.IdentifyParams;
-import net.mograsim.logic.model.snippets.HighLevelStateHandler;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.ModelMemory;
-
-public abstract class ModelWordAddressableMemory extends ModelMemory
-{
-       private final Pin addrPin, dataPin, rWPin;
-       private CoreWordAddressableMemory memory;
-       private MainMemoryDefinition definition;
-
-       private final List<Consumer<Object>> memoryBindingListeners;
-
-       public ModelWordAddressableMemory(LogicModelModifiable model, MainMemoryDefinition definition, String name)
-       {
-               super(model, 120, 150, name, "RAM", false);
-               this.definition = definition;
-
-               addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, getWidth(), 30));
-               addPin(dataPin = new Pin(model, this, "D", definition.getCellWidth(), PinUsage.TRISTATE, getWidth(), 50));
-               addPin(rWPin = new Pin(model, this, "RW", 1, PinUsage.INPUT, getWidth(), 70));
-
-               memoryBindingListeners = new ArrayList<>();
-
-               setHighLevelStateHandler(new HighLevelStateHandler()
-               {
-                       @Override
-                       public Object get(String stateID)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       return memory.getMemory();
-                               throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void set(String stateID, Object newState)
-                       {
-                               if (stateID.equals("memory_binding"))
-                               {
-                                       memory.setMemory((MainMemory) newState);
-                                       memoryBindingListeners.forEach(l -> l.accept(newState));
-                               } else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void addListener(String stateID, Consumer<Object> stateChanged)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       memoryBindingListeners.add(stateChanged);
-                               else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public void removeListener(String stateID, Consumer<Object> stateChanged)
-                       {
-                               if (stateID.equals("memory_binding"))
-                                       memoryBindingListeners.remove(stateChanged);
-                               else
-                                       throw new IllegalArgumentException("No high level state with ID " + stateID);
-                       }
-
-                       @Override
-                       public String getIDForSerializing(IdentifyParams idParams)
-                       {
-                               return null;
-                       }
-
-                       @Override
-                       public Object getParamsForSerializing(IdentifyParams idParams)
-                       {
-                               return null;
-                       }
-               });
-
-               init();
-       }
-
-       public MainMemoryDefinition getDefinition()
-       {
-               return definition;
-       }
-
-       public Pin getAddressPin()
-       {
-               return addrPin;
-       }
-
-       public Pin getDataPin()
-       {
-               return dataPin;
-       }
-
-       public Pin getReadWritePin()
-       {
-               return rWPin;
-       }
-
-       public void setCoreModelBinding(CoreWordAddressableMemory memory)
-       {
-               this.memory = memory;
-       }
-
-       public CoreWordAddressableMemory getCoreMemory()
-       {
-               return memory;
-       }
-
-       static
-       {
-               LogicCoreAdapter.addComponentAdapter(new WordAddressableMemoryAdapter());
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemory.java
new file mode 100644 (file)
index 0000000..01f7cf6
--- /dev/null
@@ -0,0 +1,50 @@
+package net.mograsim.machine.standard.memory;
+
+import java.math.BigInteger;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.GenericMemory;
+
+public class StandardBitVectorMemory<D extends BitVectorMemoryDefinition> extends GenericMemory<BitVector, D> implements BitVectorMemory
+{
+       public StandardBitVectorMemory(D definition)
+       {
+               super(definition);
+       }
+
+       @Override
+       public BitVector getCell(long address)
+       {
+               BitVector cell = super.getCell(address);
+               if (cell == null)
+                       setCell(address, cell = getDefaultValue(address));
+               return cell;
+       }
+
+       @Override
+       public BigInteger getCellAsBigInteger(long address)
+       {
+               return getCell(address).getUnsignedValue();
+       }
+
+       @Override
+       public void setCell(long address, BitVector data)
+       {
+               if (data.isBinary())
+                       super.setCell(address, data);
+       }
+
+       @Override
+       public void setCellAsBigInteger(long address, BigInteger data)
+       {
+               setCell(address, BitVector.from(data, getDefinition().getCellWidth()));
+       }
+
+       protected BitVector getDefaultValue(@SuppressWarnings("unused") /* this method is inteded to be overridden */ long address)
+       {
+               return BitVector.of(Bit.U, getDefinition().getCellWidth());
+       }
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemoryDefinition.java
new file mode 100644 (file)
index 0000000..5d088d3
--- /dev/null
@@ -0,0 +1,21 @@
+package net.mograsim.machine.standard.memory;
+
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.StandardMemoryDefinition;
+
+public class StandardBitVectorMemoryDefinition extends StandardMemoryDefinition implements BitVectorMemoryDefinition
+{
+       private final int cellWidth;
+
+       public StandardBitVectorMemoryDefinition(int memoryAddressBits, int cellWidth, long minimalAddress, long maximalAddress)
+       {
+               super(memoryAddressBits, minimalAddress, maximalAddress);
+               this.cellWidth = cellWidth;
+       }
+
+       @Override
+       public int getCellWidth()
+       {
+               return cellWidth;
+       }
+}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java
deleted file mode 100644 (file)
index e8ce245..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.math.BigInteger;
-
-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;
-
-public class WordAddressableMemory extends GenericMemory<BitVector> implements MainMemory
-{
-       private final int cellWidth;
-       private final MainMemoryDefinition definition;
-
-       public WordAddressableMemory(MainMemoryDefinition definition)
-       {
-               super(definition);
-               this.cellWidth = definition.getCellWidth();
-               this.definition = definition;
-       }
-
-       @Override
-       public void setCell(long address, BitVector data)
-       {
-               if (data.isBinary())
-                       super.setCell(address, data);
-       }
-
-       @Override
-       public BitVector getCell(long address)
-       {
-               BitVector data = super.getCell(address);
-               return data == null ? BitVector.of(Bit.ZERO, cellWidth) : data;
-       }
-
-       @Override
-       public BigInteger getCellAsBigInteger(long address)
-       {
-               BitVector data = getCell(address);
-               return data == null ? BigInteger.valueOf(0) : data.getUnsignedValue();
-       }
-
-       @Override
-       public void setCellAsBigInteger(long address, BigInteger data)
-       {
-               setCell(address, BitVector.from(data, cellWidth));
-       }
-
-       @Override
-       public MainMemoryDefinition getDefinition()
-       {
-               return definition;
-       }
-}
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java
deleted file mode 100644 (file)
index d7fbbaa..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import java.util.Map;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.CoreWire;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.CoreModelParameters;
-import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
-
-public class WordAddressableMemoryAdapter implements ComponentAdapter<ModelWordAddressableMemory>
-{
-       @Override
-       public Class<ModelWordAddressableMemory> getSupportedClass()
-       {
-               return ModelWordAddressableMemory.class;
-       }
-
-       @Override
-       public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelWordAddressableMemory modelComponent,
-                       Map<Pin, CoreWire> logicWiresPerPin)
-       {
-               ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
-               ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
-               ReadEnd mode = logicWiresPerPin.get(modelComponent.getReadWritePin()).createReadOnlyEnd();
-               CoreWordAddressableMemory mem = new CoreWordAddressableMemory(timeline, 2, modelComponent.getDefinition(), data, mode, address);
-               modelComponent.setCoreModelBinding(mem);
-       }
-}
\ No newline at end of file
index 707d67b..e69d3c4 100644 (file)
@@ -3,6 +3,7 @@ Bundle-Vendor = Mograsim Team
 Bundle-Name = Mograsim core
 content-type.name = Assembler
 content-type.mpm.name = Mikroprogrammspeicher
+content-type.mprom.name = MPROM
 editor.name.0 = Mikroinstruktionseditor
 category.name = Mograsim
 view.name = Beispiel AsmOpsEdit
index 7ab33c1..3628250 100644 (file)
@@ -3,6 +3,7 @@ Bundle-Vendor = Mograsim Team
 Bundle-Name = Mograsim core
 content-type.name = Assembler
 content-type.mpm.name = Microprogram Memory
+content-type.mprom.name = MPROM
 editor.name.0 = Instruction Editor
 category.name = Mograsim
 view.name = Sample AsmOpsEdit
index 959e6a8..9e8b8cf 100644 (file)
             name="Main Memory"
             priority="high">
       </content-type>
+      <content-type
+            base-type="org.eclipse.core.runtime.text"
+            default-charset="UTF-8"
+            file-extensions="mprom"
+            id="net.mograsim.plugin.mprom"
+            name="%content-type.mprom.name"
+            priority="high">
+      </content-type>
    </extension>
    <extension
          point="org.eclipse.ui.menus">
                <contentTypeBinding contentTypeId="net.mograsim.plugin.mpm"/>
       </editor>
       <editor
-            class="net.mograsim.plugin.editors.MemoryEditor"
+            class="net.mograsim.plugin.editors.MPROMEditor"
+            icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+            id="net.mograsim.plugin.editors.mpromeditor"
+            name="MPROM Editor">xcdys
+         <contentTypeBinding
+               contentTypeId="net.mograsim.plugin.mprom">
+         </contentTypeBinding>
+      </editor>
+      <editor
+            class="net.mograsim.plugin.editors.MainMemoryEditor"
             icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
-            id="net.mograsim.plugin.editors.memoryeditor"
-            name="Memory Editor">
+            id="net.mograsim.plugin.editors.mainmemoryeditor"
+            name="Main Memory Editor">
+         xcdys
          <contentTypeBinding
                contentTypeId="net.mograsim.plugin.mem">
          </contentTypeBinding>
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/AbstractMemoryEditor.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/AbstractMemoryEditor.java
new file mode 100644 (file)
index 0000000..e306cff
--- /dev/null
@@ -0,0 +1,336 @@
+package net.mograsim.plugin.editors;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.themes.ITheme;
+import org.eclipse.ui.themes.IThemeManager;
+
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
+import net.mograsim.machine.standard.memory.BitVectorBasedMemoryParser;
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.nature.MachineContext;
+import net.mograsim.plugin.nature.ProjectMachineContext;
+import net.mograsim.plugin.tables.AddressLabelProvider;
+import net.mograsim.plugin.tables.DisplaySettings;
+import net.mograsim.plugin.tables.LazyTableViewer;
+import net.mograsim.plugin.tables.NumberColumnLabelProvider;
+import net.mograsim.plugin.tables.RadixSelector;
+import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
+import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
+import net.mograsim.plugin.tables.memory.MemoryTableRow;
+import net.mograsim.plugin.tables.memory.NumberVerifyListener;
+
+public abstract class AbstractMemoryEditor extends EditorPart
+{
+       private MachineContext context;
+
+       private BitVectorMemory memory;
+
+       private LazyTableViewer viewer;
+       private MemoryTableContentProvider provider;
+       private DisplaySettings displaySettings;
+
+       private Collection<Control> fontDependent = new HashSet<>();
+
+       private boolean dirty;
+
+       private final MemoryCellModifiedListener memListener;
+
+       private final static String font = "net.mograsim.plugin.memory.table_font";
+       private IPropertyChangeListener fontChangeListener;
+
+       public AbstractMemoryEditor()
+       {
+               memListener = this::cellModified;
+       }
+
+       @Override
+       public void createPartControl(Composite parent)
+       {
+               provider = new MemoryTableContentProvider();
+               displaySettings = new DisplaySettings();
+
+               parent.setLayout(new GridLayout(8, false));
+               createHeader(parent);
+               createViewer(parent);
+
+               displaySettings.addObserver(() -> viewer.refresh());
+       }
+
+       @SuppressWarnings("unused") // RadixSelector and exceptions
+       private void createHeader(Composite parent)
+       {
+               Text gotoText = new Text(parent, SWT.BORDER);
+               gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               NumberVerifyListener vl = new NumberVerifyListener();
+               gotoText.addVerifyListener(vl);
+               gotoText.setText("0");
+
+               Runnable gotoAction = () ->
+               {
+                       try
+                       {
+                               loadAround((int) (AsmNumberUtil.valueOf(gotoText.getText()).longValue() - provider.getLowerBound()));
+                               viewer.getTable().deselectAll();
+                       }
+                       catch (NumberFormatException x)
+                       {
+                               // Nothing to do here
+                       }
+               };
+
+               gotoText.addTraverseListener((e) ->
+               {
+                       if (e.detail == SWT.TRAVERSE_RETURN)
+                               gotoAction.run();
+               });
+
+               Button gotoButton = new Button(parent, SWT.PUSH);
+               gotoButton.setText("Go to");
+               gotoButton.addListener(SWT.Selection, e ->
+               {
+                       gotoAction.run();
+               });
+
+               new Label(parent, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+               new RadixSelector(parent, displaySettings);
+       }
+
+       private void createViewer(Composite parent)
+       {
+               viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+               fontDependent.add(viewer.getTable());
+               createColumns();
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+               viewer.setUseHashlookup(true);
+               viewer.setContentProvider(provider);
+               getSite().setSelectionProvider(viewer);
+               viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 8, 1));
+
+               // TODO: Also support keyboard inputs for flexible scrolling
+               ScrollBar vBar = table.getVerticalBar();
+               vBar.addListener(SWT.Selection, (e) ->
+               {
+                       int sel;
+                       if ((sel = vBar.getSelection()) < vBar.getMinimum() + vBar.getThumb() * 2 || sel > vBar.getMaximum() - vBar.getThumb() * 2)
+                       {
+                               loadAround(table.getTopIndex());
+                               table.deselectAll();
+                       }
+               });
+
+               IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
+               themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
+               {
+                       if (IThemeManager.CHANGE_CURRENT_THEME.equals(e.getProperty()) || font.equals(e.getProperty()))
+                       {
+                               updateFont(themeManager.getCurrentTheme());
+                               viewer.refresh();
+                       }
+               });
+               updateFont(themeManager.getCurrentTheme());
+
+               if (memory != null)
+                       viewer.setInput(memory);
+       }
+
+       private void updateFont(ITheme theme)
+       {
+               Font newFont = theme.getFontRegistry().get(font);
+               // TODO: This is a quick fix! Still have to figure out why the CellEditors do not get the appropriate Font on their own
+               fontDependent.forEach(c -> c.setFont(newFont));
+       }
+
+       private void loadAround(int row)
+       {
+               long prevLb = provider.getLowerBound();
+               long address = prevLb + row;
+               long actualLb = Long.max(address - MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMinimalAddress());
+
+               long prevHb = provider.getUpperBound();
+               // +- 1 row is not really important
+               long actualHb = Long.min(address + MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMaximalAddress());
+
+               if (actualLb != prevLb || actualHb != prevHb)
+               {
+                       Table table = viewer.getTable();
+                       provider.setBounds(actualLb, actualHb);
+                       int rowIndex = (int) (address - actualLb);
+                       if (rowIndex >= 0 && rowIndex < table.getItemCount())
+                               table.showItem(table.getItem(rowIndex));
+                       viewer.refresh();
+               }
+       }
+
+       private void createColumns()
+       {
+               TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
+               addrCol.setLabelProvider(new AddressLabelProvider());
+
+               TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
+               dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
+               {
+                       @Override
+                       public BigInteger getAsBigInteger(Object element)
+                       {
+                               MemoryTableRow row = (MemoryTableRow) element;
+                               return row.getMemory().getCellAsBigInteger(row.address);
+                       }
+
+                       @Override
+                       public int getBitLength(Object element)
+                       {
+                               return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
+                       }
+               });
+               MemoryCellEditingSupport eSup;
+               dataCol.setEditingSupport(eSup = new MemoryCellEditingSupport(viewer, displaySettings));
+               fontDependent.add(eSup.getCellEditorControl());
+       }
+
+       private TableViewerColumn createTableViewerColumn(String title, int width)
+       {
+               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+               TableColumn column = viewerColumn.getColumn();
+               column.setText(title);
+               column.setWidth(width);
+               column.setResizable(true);
+               column.setMoveable(false);
+               return viewerColumn;
+       }
+
+       @Override
+       public void init(IEditorSite site, IEditorInput input) throws PartInitException
+       {
+               if (input instanceof IFileEditorInput)
+               {
+                       IFileEditorInput fileInput = (IFileEditorInput) input;
+                       context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
+
+                       setPartName(fileInput.getName());
+                       try
+                       {
+                               open(fileInput.getFile());
+                       }
+                       catch (Exception e)
+                       {
+                               throw new PartInitException("Failed to read input!", e);
+                       }
+               } else
+                       throw new IllegalArgumentException("MemoryEditor can only be used with Files");
+
+               setSite(site);
+               setInput(input);
+       }
+
+       @Override
+       public void doSave(IProgressMonitor monitor)
+       {
+               IEditorInput input = getEditorInput();
+               if (input instanceof IFileEditorInput)
+                       SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
+       }
+
+       private void save(IFile file, IProgressMonitor monitor) throws CoreException, IOException
+       {
+               if (memory == null)
+               {
+                       throw new MicroInstructionMemoryParseException("Failed to write the memory to File. No memory assigned.");
+               }
+               try (InputStream toWrite = BitVectorBasedMemoryParser.write(memory))
+               {
+                       file.setContents(toWrite, 0, monitor);
+                       setDirty(false);
+               }
+       }
+
+       private void open(IFile file) throws IOException, CoreException
+       {
+               MachineDefinition machDef = context.getMachineDefinition()
+                               .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!"));
+               memory = createEmptyMemory(machDef);
+               BitVectorBasedMemoryParser.parseMemory(memory, file.getContents());
+               memory.registerCellModifiedListener(memListener);
+               if (viewer != null)
+                       viewer.setInput(memory);
+       }
+
+       protected abstract BitVectorMemory createEmptyMemory(MachineDefinition activeMachineDefinition);
+
+       private void cellModified(@SuppressWarnings("unused") long address)
+       {
+               setDirty(true);
+       }
+
+       private void setDirty(boolean newDirty)
+       {
+               dirty = newDirty;
+               firePropertyChange(PROP_DIRTY);
+       }
+
+       @Override
+       public void doSaveAs()
+       {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public boolean isDirty()
+       {
+               return dirty;
+       }
+
+       @Override
+       public boolean isSaveAsAllowed()
+       {
+               return false;
+       }
+
+       @Override
+       public void setFocus()
+       {
+               viewer.getTable().setFocus();
+       }
+
+       @Override
+       public void dispose()
+       {
+               getSite().getWorkbenchWindow().getWorkbench().getThemeManager().removePropertyChangeListener(fontChangeListener);
+               if (memory != null)
+                       memory.deregisterCellModifiedListener(memListener);
+               super.dispose();
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MPROMEditor.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MPROMEditor.java
new file mode 100644 (file)
index 0000000..9c6ce81
--- /dev/null
@@ -0,0 +1,14 @@
+package net.mograsim.plugin.editors;
+
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.mi.StandardMPROM;
+
+public class MPROMEditor extends AbstractMemoryEditor
+{
+       @Override
+       protected BitVectorMemory createEmptyMemory(MachineDefinition activeMachineDefinition)
+       {
+               return new StandardMPROM(activeMachineDefinition.getMPROMDefinition());
+       }
+}
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MainMemoryEditor.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MainMemoryEditor.java
new file mode 100644 (file)
index 0000000..6d0d7b5
--- /dev/null
@@ -0,0 +1,14 @@
+package net.mograsim.plugin.editors;
+
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.StandardMainMemory;
+
+public class MainMemoryEditor extends AbstractMemoryEditor
+{
+       @Override
+       protected BitVectorMemory createEmptyMemory(MachineDefinition activeMachineDefinition)
+       {
+               return new StandardMainMemory(activeMachineDefinition.getMainMemoryDefinition());
+       }
+}
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java
deleted file mode 100644 (file)
index 0186780..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-package net.mograsim.plugin.editors;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.util.Collection;
-import java.util.HashSet;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.util.IPropertyChangeListener;
-import org.eclipse.jface.util.SafeRunnable;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.ScrollBar;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IFileEditorInput;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.part.EditorPart;
-import org.eclipse.ui.themes.ITheme;
-import org.eclipse.ui.themes.IThemeManager;
-
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
-import net.mograsim.machine.standard.memory.MainMemoryParser;
-import net.mograsim.plugin.asm.AsmNumberUtil;
-import net.mograsim.plugin.nature.MachineContext;
-import net.mograsim.plugin.nature.ProjectMachineContext;
-import net.mograsim.plugin.tables.AddressLabelProvider;
-import net.mograsim.plugin.tables.DisplaySettings;
-import net.mograsim.plugin.tables.LazyTableViewer;
-import net.mograsim.plugin.tables.NumberColumnLabelProvider;
-import net.mograsim.plugin.tables.RadixSelector;
-import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
-import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
-import net.mograsim.plugin.tables.memory.MemoryTableRow;
-import net.mograsim.plugin.tables.memory.NumberVerifyListener;
-
-public class MemoryEditor extends EditorPart
-{
-       private MachineContext context;
-
-       private MainMemory memory;
-
-       private LazyTableViewer viewer;
-       private MemoryTableContentProvider provider;
-       private DisplaySettings displaySettings;
-
-       private Collection<Control> fontDependent = new HashSet<>();
-
-       private boolean dirty;
-
-       private final MemoryCellModifiedListener memListener;
-
-       private final static String font = "net.mograsim.plugin.memory.table_font";
-       private IPropertyChangeListener fontChangeListener;
-
-       public MemoryEditor()
-       {
-               memListener = this::cellModified;
-       }
-
-       @Override
-       public void createPartControl(Composite parent)
-       {
-               provider = new MemoryTableContentProvider();
-               displaySettings = new DisplaySettings();
-
-               parent.setLayout(new GridLayout(8, false));
-               createHeader(parent);
-               createViewer(parent);
-
-               displaySettings.addObserver(() -> viewer.refresh());
-       }
-
-       @SuppressWarnings("unused") // RadixSelector and exceptions
-       private void createHeader(Composite parent)
-       {
-               Text gotoText = new Text(parent, SWT.BORDER);
-               gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               NumberVerifyListener vl = new NumberVerifyListener();
-               gotoText.addVerifyListener(vl);
-               gotoText.setText("0");
-
-               Runnable gotoAction = () ->
-               {
-                       try
-                       {
-                               loadAround((int) (AsmNumberUtil.valueOf(gotoText.getText()).longValue() - provider.getLowerBound()));
-                               viewer.getTable().deselectAll();
-                       }
-                       catch (NumberFormatException x)
-                       {
-                               // Nothing to do here
-                       }
-               };
-
-               gotoText.addTraverseListener((e) ->
-               {
-                       if (e.detail == SWT.TRAVERSE_RETURN)
-                               gotoAction.run();
-               });
-
-               Button gotoButton = new Button(parent, SWT.PUSH);
-               gotoButton.setText("Go to");
-               gotoButton.addListener(SWT.Selection, e ->
-               {
-                       gotoAction.run();
-               });
-
-               new Label(parent, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-
-               new RadixSelector(parent, displaySettings);
-       }
-
-       private void createViewer(Composite parent)
-       {
-               viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
-               fontDependent.add(viewer.getTable());
-               createColumns();
-               Table table = viewer.getTable();
-               table.setHeaderVisible(true);
-               table.setLinesVisible(true);
-               viewer.setUseHashlookup(true);
-               viewer.setContentProvider(provider);
-               getSite().setSelectionProvider(viewer);
-               viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 8, 1));
-
-               // TODO: Also support keyboard inputs for flexible scrolling
-               ScrollBar vBar = table.getVerticalBar();
-               vBar.addListener(SWT.Selection, (e) ->
-               {
-                       int sel;
-                       if ((sel = vBar.getSelection()) < vBar.getMinimum() + vBar.getThumb() * 2 || sel > vBar.getMaximum() - vBar.getThumb() * 2)
-                       {
-                               loadAround(table.getTopIndex());
-                               table.deselectAll();
-                       }
-               });
-
-               IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
-               themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
-               {
-                       if (IThemeManager.CHANGE_CURRENT_THEME.equals(e.getProperty()) || font.equals(e.getProperty()))
-                       {
-                               updateFont(themeManager.getCurrentTheme());
-                               viewer.refresh();
-                       }
-               });
-               updateFont(themeManager.getCurrentTheme());
-
-               if (memory != null)
-                       viewer.setInput(memory);
-       }
-
-       private void updateFont(ITheme theme)
-       {
-               Font newFont = theme.getFontRegistry().get(font);
-               // TODO: This is a quick fix! Still have to figure out why the CellEditors do not get the appropriate Font on their own
-               fontDependent.forEach(c -> c.setFont(newFont));
-       }
-
-       private void loadAround(int row)
-       {
-               long prevLb = provider.getLowerBound();
-               long address = prevLb + row;
-               long actualLb = Long.max(address - MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMinimalAddress());
-
-               long prevHb = provider.getUpperBound();
-               // +- 1 row is not really important
-               long actualHb = Long.min(address + MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMaximalAddress());
-
-               if (actualLb != prevLb || actualHb != prevHb)
-               {
-                       Table table = viewer.getTable();
-                       provider.setBounds(actualLb, actualHb);
-                       int rowIndex = (int) (address - actualLb);
-                       if (rowIndex >= 0 && rowIndex < table.getItemCount())
-                               table.showItem(table.getItem(rowIndex));
-                       viewer.refresh();
-               }
-       }
-
-       private void createColumns()
-       {
-               TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
-               addrCol.setLabelProvider(new AddressLabelProvider());
-
-               TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
-               dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
-               {
-                       @Override
-                       public BigInteger getAsBigInteger(Object element)
-                       {
-                               MemoryTableRow row = (MemoryTableRow) element;
-                               return row.getMemory().getCellAsBigInteger(row.address);
-                       }
-
-                       @Override
-                       public int getBitLength(Object element)
-                       {
-                               return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
-                       }
-               });
-               MemoryCellEditingSupport eSup;
-               dataCol.setEditingSupport(eSup = new MemoryCellEditingSupport(viewer, displaySettings));
-               fontDependent.add(eSup.getCellEditorControl());
-       }
-
-       private TableViewerColumn createTableViewerColumn(String title, int width)
-       {
-               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
-               TableColumn column = viewerColumn.getColumn();
-               column.setText(title);
-               column.setWidth(width);
-               column.setResizable(true);
-               column.setMoveable(false);
-               return viewerColumn;
-       }
-
-       @Override
-       public void init(IEditorSite site, IEditorInput input) throws PartInitException
-       {
-               if (input instanceof IFileEditorInput)
-               {
-                       IFileEditorInput fileInput = (IFileEditorInput) input;
-                       context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
-
-                       setPartName(fileInput.getName());
-                       try
-                       {
-                               open(fileInput.getFile());
-                       }
-                       catch (Exception e)
-                       {
-                               throw new PartInitException("Failed to read input!", e);
-                       }
-               } else
-                       throw new IllegalArgumentException("MemoryEditor can only be used with Files");
-
-               setSite(site);
-               setInput(input);
-       }
-
-       @Override
-       public void doSave(IProgressMonitor monitor)
-       {
-               IEditorInput input = getEditorInput();
-               if (input instanceof IFileEditorInput)
-                       SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
-       }
-
-       private void save(IFile file, IProgressMonitor monitor) throws CoreException, IOException
-       {
-               if (memory == null)
-               {
-                       throw new MicroInstructionMemoryParseException("Failed to write MainMemory to File. No MainMemory assigned.");
-               }
-               try (InputStream toWrite = MainMemoryParser.write(memory))
-               {
-                       file.setContents(toWrite, 0, monitor);
-                       setDirty(false);
-               }
-       }
-
-       private void open(IFile file) throws IOException, CoreException
-       {
-               MainMemoryDefinition memDef = context.getMachineDefinition()
-                               .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition();
-               memory = MainMemoryParser.parseMemory(memDef, file.getContents());
-               memory.registerCellModifiedListener(memListener);
-               if (viewer != null)
-                       viewer.setInput(memory);
-       }
-
-       private void cellModified(@SuppressWarnings("unused") long address)
-       {
-               setDirty(true);
-       }
-
-       private void setDirty(boolean newDirty)
-       {
-               dirty = newDirty;
-               firePropertyChange(PROP_DIRTY);
-       }
-
-       @Override
-       public void doSaveAs()
-       {
-               throw new UnsupportedOperationException();
-       }
-
-       @Override
-       public boolean isDirty()
-       {
-               return dirty;
-       }
-
-       @Override
-       public boolean isSaveAsAllowed()
-       {
-               return false;
-       }
-
-       @Override
-       public void setFocus()
-       {
-               viewer.getTable().setFocus();
-       }
-
-       @Override
-       public void dispose()
-       {
-               getSite().getWorkbenchWindow().getWorkbench().getThemeManager().removePropertyChangeListener(fontChangeListener);
-               if (memory != null)
-                       memory.deregisterCellModifiedListener(memListener);
-               super.dispose();
-       }
-}
\ No newline at end of file
index ca74804..5bb87a8 100644 (file)
@@ -9,6 +9,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarkerDelta;
@@ -38,10 +39,15 @@ import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.ui.PlatformUI;
 
 import net.mograsim.logic.model.LogicExecuter;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
 import net.mograsim.machine.Machine;
 import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.StandardMainMemory;
 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
-import net.mograsim.machine.standard.memory.MainMemoryParser;
+import net.mograsim.machine.mi.StandardMPROM;
+import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory;
+import net.mograsim.machine.standard.memory.BitVectorBasedMemoryParser;
 import net.mograsim.plugin.MograsimActivator;
 
 public class MachineDebugTarget extends PlatformObject implements IDebugTarget, IMemoryBlockRetrievalExtension
@@ -53,6 +59,7 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
        private final LogicExecuter exec;
        private final MachineThread thread;
        private final IFile mpmFile;
+       private final Optional<IFile> mpromFile;
        private final Optional<IFile> memFile;
 
        private boolean running;
@@ -61,8 +68,8 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
 
        private final IResourceChangeListener resChangedListener;
 
-       public MachineDebugTarget(ILaunch launch, IFile mpmFile, Optional<IFile> memFile, MachineDefinition machineDefinition)
-                       throws CoreException
+       public MachineDebugTarget(ILaunch launch, IFile mpmFile, Optional<IFile> mpromFile, Optional<IFile> memFile,
+                       MachineDefinition machineDefinition) throws CoreException
        {
                this.launch = launch;
                this.machine = machineDefinition.createNew();
@@ -70,9 +77,11 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
 
                this.executionSpeedListeners = new ArrayList<>();
                this.mpmFile = mpmFile;
+               this.mpromFile = mpromFile;
                this.memFile = memFile;
 
                assignMicroInstructionMemory();
+               assignMPROM();
                assignMainMemory();
 
                exec.startLiveExecution();
@@ -371,35 +380,53 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
 
        private void resourceChanged(IResourceChangeEvent event)
        {
-               IResourceDelta mpmDelta;
-               if (event.getType() == IResourceChangeEvent.POST_CHANGE && (mpmDelta = event.getDelta().findMember(mpmFile.getFullPath())) != null
-                               && (mpmDelta.getKind() & CHANGED) == CHANGED && mpmFile.exists())
+               if (event.getType() == IResourceChangeEvent.POST_CHANGE)
                {
-                       AtomicBoolean doHotReplace = new AtomicBoolean();
-                       PlatformUI.getWorkbench().getDisplay().syncExec(() ->
+                       tryHotReplaceIfChanged(event, mpmFile, this::assignMicroInstructionMemory, "MPM");
+
+                       if (mpromFile.isPresent())
+                               tryHotReplaceIfChanged(event, mpromFile.get(), this::assignMPROM, "MPROM");
+               }
+       }
+
+       private static void tryHotReplaceIfChanged(IResourceChangeEvent event, IFile memFile, RunnableThrowingCoreException assign, String type)
+       {
+               IResourceDelta mpmDelta = event.getDelta().findMember(memFile.getFullPath());
+               if (mpmDelta != null && (mpmDelta.getKind() & CHANGED) == CHANGED && memFile.exists())
+                       tryHotReplace(memFile, assign, type);
+       }
+
+       private static void tryHotReplace(IFile memFile, RunnableThrowingCoreException assign, String type)
+       {
+               AtomicBoolean doHotReplace = new AtomicBoolean();
+               PlatformUI.getWorkbench().getDisplay().syncExec(() ->
+               {
+                       if (MessageDialog.openConfirm(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Hot Replace " + type + "?",
+                                       String.format("The " + type + " %s has been modified on the file system. Replace simulated " + type
+                                                       + " with modified contents?", memFile.getName())))
+                               doHotReplace.set(true);
+               });
+               if (doHotReplace.get())
+               {
+                       try
                        {
-                               if (MessageDialog.openConfirm(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Hot Replace MPM?",
-                                               String.format("The MPM %s has been modified on the file system. Replace simulated MPM with modified contents?",
-                                                               mpmFile.getName())))
-                                       doHotReplace.set(true);
-                       });
-                       if (doHotReplace.get())
+                               assign.run();
+                       }
+                       catch (CoreException e)
                        {
-                               try
-                               {
-                                       assignMicroInstructionMemory();
-                               }
-                               catch (CoreException e)
-                               {
-                                       PlatformUI.getWorkbench().getDisplay()
-                                                       .asyncExec(() -> MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
-                                                                       "Failed Hot Replace!",
-                                                                       "An error occurred trying to read the modified MPM from the file system: " + e.getMessage()));
-                               }
+                               PlatformUI.getWorkbench().getDisplay()
+                                               .asyncExec(() -> MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                                                               "Failed Hot Replace!",
+                                                               "An error occurred trying to read the modified " + type + " from the file system: " + e.getMessage()));
                        }
                }
        }
 
+       private static interface RunnableThrowingCoreException
+       {
+               public void run() throws CoreException;
+       }
+
        private void assignMicroInstructionMemory() throws CoreException
        {
                try (InputStream mpmStream = mpmFile.getContents())
@@ -413,19 +440,32 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
                }
        }
 
+       private void assignMPROM() throws CoreException
+       {
+               assignMemory(mpromFile, machine.getMPROM(), machine.getDefinition().getMPROMDefinition(), StandardMPROM::new, "MPROM");
+       }
+
        private void assignMainMemory() throws CoreException
+       {
+               assignMemory(memFile, machine.getMainMemory(), machine.getDefinition().getMainMemoryDefinition(), StandardMainMemory::new,
+                               "initial RAM");
+       }
+
+       private static <D extends BitVectorMemoryDefinition, M extends BitVectorMemory> void assignMemory(Optional<IFile> memFile,
+                       AbstractAssignableBitVectorMemory<M> memoryToAssign, D definition, Function<D, M> newMemory, String type) throws CoreException
        {
                if (memFile.isPresent())
                {
                        try (InputStream initialRAMStream = memFile.get().getContents())
                        {
-                               machine.getMainMemory()
-                                               .bind(MainMemoryParser.parseMemory(machine.getDefinition().getMainMemoryDefinition(), initialRAMStream));
+                               M mem = newMemory.apply(definition);
+                               BitVectorBasedMemoryParser.parseMemory(mem, initialRAMStream);
+                               memoryToAssign.bind(mem);
                        }
                        catch (IOException e)
                        {
                                throw new CoreException(
-                                               new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading initial RAM file", e));
+                                               new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading " + type + " file", e));
                        }
                }
        }
@@ -435,6 +475,11 @@ public class MachineDebugTarget extends PlatformObject implements IDebugTarget,
                return mpmFile;
        }
 
+       public Optional<IFile> getMPROMFile()
+       {
+               return mpromFile;
+       }
+
        public Optional<IFile> getMEMFile()
        {
                return memFile;
index 5622ca6..a09ff23 100644 (file)
@@ -18,12 +18,15 @@ import org.eclipse.debug.core.model.IMemoryBlock;
 import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
 import org.eclipse.ui.statushandlers.StatusManager;
 
+import net.mograsim.machine.BitVectorMemoryDefinition;
 import net.mograsim.machine.Machine;
 import net.mograsim.machine.MachineDefinition;
 import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.mi.MPROMDefinition;
 import net.mograsim.machine.mi.MicroInstructionMemoryDefinition;
 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
-import net.mograsim.machine.standard.memory.MainMemoryParser;
+import net.mograsim.machine.standard.memory.BitVectorBasedMemoryParser;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemory;
 import net.mograsim.plugin.MograsimActivator;
 import net.mograsim.plugin.nature.MachineContext;
 import net.mograsim.plugin.nature.MograsimNature;
@@ -33,11 +36,9 @@ public class MachineLaunchConfigType extends LaunchConfigurationDelegate
 {
        public static final String PROJECT_ATTR = MograsimActivator.PLUGIN_ID + ".project";
        public static final String MPM_FILE_ATTR = MograsimActivator.PLUGIN_ID + ".mpm";
+       public static final String MPROM_FILE_ATTR = MograsimActivator.PLUGIN_ID + ".mprom";
        public static final String INITIAL_RAM_FILE_ATTR = MograsimActivator.PLUGIN_ID + ".initialram";
 
-       private IFile mpmFile;
-       private Machine machine;
-
        @Override
        public boolean preLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException
        {
@@ -59,6 +60,7 @@ public class MachineLaunchConfigType extends LaunchConfigurationDelegate
                MachineDefinition machineDefinition = machDefOptional.orElseThrow();
                MicroInstructionMemoryDefinition miMemDef = machineDefinition.getMicroInstructionMemoryDefinition();
                MainMemoryDefinition mainMemDef = machineDefinition.getMainMemoryDefinition();
+               MPROMDefinition mpromDef = machineDefinition.getMPROMDefinition();
 
                String mpmFileName = configuration.getAttribute(MPM_FILE_ATTR, "");
                if ("".equals(mpmFileName))
@@ -77,25 +79,37 @@ public class MachineLaunchConfigType extends LaunchConfigurationDelegate
                        throw new CoreException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading MPM file", e));
                }
 
+               String mpromFileName = configuration.getAttribute(MPROM_FILE_ATTR, "");
+               if (!checkMemoryFileReadable(project, mpromDef, mpromFileName, "MPROM"))
+                       return false;
+
                String initialRAMFileName = configuration.getAttribute(INITIAL_RAM_FILE_ATTR, "");
-               if (!"".equals(initialRAMFileName))
+               if (!checkMemoryFileReadable(project, mainMemDef, initialRAMFileName, "initial RAM"))
+                       return false;
+
+               return super.preLaunchCheck(configuration, mode, monitor);
+       }
+
+       private static boolean checkMemoryFileReadable(IProject project, BitVectorMemoryDefinition mainMemDef, String fileName, String fileType)
+                       throws CoreException
+       {
+               if (!"".equals(fileName))
                {
-                       IFile initialRAMFile = project.getFile(initialRAMFileName);
+                       IFile initialRAMFile = project.getFile(fileName);
                        if (initialRAMFile == null || !initialRAMFile.isAccessible())
-                               return showErrorAndReturnFalse("Initial RAM file not accessible");
+                               return showErrorAndReturnFalse(fileType + " file not accessible");
 
                        try (InputStream initialRAMStream = initialRAMFile.getContents())
                        {
-                               MainMemoryParser.parseMemory(mainMemDef, initialRAMStream);
+                               BitVectorBasedMemoryParser.parseMemory(new StandardBitVectorMemory<>(mainMemDef), initialRAMStream);
                        }
                        catch (IOException e)
                        {
                                throw new CoreException(
-                                               new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading initial RAM file", e));
+                                               new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading " + fileType + " file", e));
                        }
                }
-
-               return super.preLaunchCheck(configuration, mode, monitor);
+               return true;
        }
 
        private static boolean showErrorAndReturnFalse(String message)
@@ -113,19 +127,14 @@ public class MachineLaunchConfigType extends LaunchConfigurationDelegate
                MachineContext machineContext = ProjectMachineContext.getMachineContextOf(project);
                MachineDefinition machineDefinition = machineContext.getMachineDefinition().orElseThrow();
 
-               mpmFile = project.getFile(configuration.getAttribute(MPM_FILE_ATTR, ""));
-
-               String initialRAMFileName = configuration.getAttribute(INITIAL_RAM_FILE_ATTR, "");
-               Optional<IFile> memFile = Optional.empty();
-               if (!"".equals(initialRAMFileName))
-               {
-                       memFile = Optional.of(project.getFile(initialRAMFileName));
-               }
-               MachineDebugTarget debugTarget = new MachineDebugTarget(launch, mpmFile, memFile, machineDefinition);
+               IFile mpmFile = project.getFile(configuration.getAttribute(MPM_FILE_ATTR, ""));
+               Optional<IFile> mpromFile = fileOptional(project, configuration.getAttribute(MPROM_FILE_ATTR, ""));
+               Optional<IFile> memFile = fileOptional(project, configuration.getAttribute(INITIAL_RAM_FILE_ATTR, ""));
+               MachineDebugTarget debugTarget = new MachineDebugTarget(launch, mpmFile, mpromFile, memFile, machineDefinition);
                // TODO make selectable whether the machine starts paused or not
                debugTarget.suspend();
                debugTarget.setExecutionSpeed(1);
-               machine = debugTarget.getMachine();
+               Machine machine = debugTarget.getMachine();
                machine.reset();
 
                // Add the default Mograsim memory block to make it less confusing and more comfortable.
@@ -133,4 +142,11 @@ public class MachineLaunchConfigType extends LaunchConfigurationDelegate
                                .addMemoryBlocks(new IMemoryBlock[] { new MainMemoryBlockExtension(debugTarget, "0", null) });
        }
 
+       private static Optional<IFile> fileOptional(IProject project, String filename)
+       {
+               if ("".equals(filename))
+                       return Optional.empty();
+               return Optional.of(project.getFile(filename));
+       }
+
 }
\ No newline at end of file
index 843789a..fbbe264 100644 (file)
@@ -44,6 +44,7 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
 {
        private Text projSelText;
        private Text mpmFileSelText;
+       private Text mpromFileSelText;
        private Text initialRAMFileSelText;
 
        @Override
@@ -55,10 +56,12 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
 
                innerParent.setLayout(new GridLayout(3, false));
 
-               this.projSelText = addResourceSelector(innerParent, "&Project:", this::chooseMograsimProject);
+               this.projSelText = addResourceSelector(innerParent, "P&roject:", this::chooseMograsimProject);
 
                this.mpmFileSelText = addResourceSelector(innerParent, "&MPM:", this::chooseMPMFile);
 
+               this.mpromFileSelText = addResourceSelector(innerParent, "M&PROM:", this::chooseMPROMFile);
+
                this.initialRAMFileSelText = addResourceSelector(innerParent, "Initial &RAM (optional):", this::chooseInitialRAMFile);
        }
 
@@ -97,6 +100,7 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
 
        private String chooseMograsimProject()
        {
+               // TODO this seems very ugly, especially hardcoded width/height
                WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
                {
                        @Override
@@ -116,27 +120,27 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
 
        private String chooseMPMFile()
        {
-               ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(),
-                               new WorkbenchContentProvider());
-               dialog.setTitle("MPM Selection");
-               dialog.setMessage("Select a MPM file");
-               dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
-               dialog.addFilter(new FileExtensionViewerFilter("mpm"));
-               dialog.addFilter(new ProjectViewerFilter(getSelectedProject()));
+               return chooseFile("MPM", "mpm");
+       }
 
-               if (dialog.open() == Window.OK)
-                       return ((IResource) dialog.getResult()[0]).getProjectRelativePath().toPortableString();
-               return null;
+       private String chooseMPROMFile()
+       {
+               return chooseFile("MPROM", "mprom");
        }
 
        private String chooseInitialRAMFile()
+       {
+               return chooseFile("Initial RAM", "mem");
+       }
+
+       private String chooseFile(String type, String fileext)
        {
                ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(),
                                new WorkbenchContentProvider());
-               dialog.setTitle("Initial RAM Selection");
-               dialog.setMessage("Select a RAM file");
+               dialog.setTitle(type + " Selection");
+               dialog.setMessage("Select a ." + fileext + " file");
                dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
-               dialog.addFilter(new FileExtensionViewerFilter("mem"));
+               dialog.addFilter(new FileExtensionViewerFilter(fileext));
                dialog.addFilter(new ProjectViewerFilter(getSelectedProject()));
 
                if (dialog.open() == Window.OK)
@@ -179,6 +183,7 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
        {
                projSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.PROJECT_ATTR, ""));
                mpmFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.MPM_FILE_ATTR, ""));
+               mpromFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.MPROM_FILE_ATTR, ""));
                initialRAMFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, ""));
        }
 
@@ -200,6 +205,7 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
        {
                String projName = projSelText.getText().trim();
                String mpmFileName = mpmFileSelText.getText().trim();
+               String mpromFileName = mpromFileSelText.getText().trim();
                String initialRAMFileName = initialRAMFileSelText.getText().trim();
 
                Set<IResource> associatedResources = new HashSet<>();
@@ -217,6 +223,10 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
                                        if (mpmFile != null && mpmFile.exists() && mpmFile.getType() == IResource.FILE)
                                                associatedResources.add(mpmFile);
 
+                                       IResource mpromFile = project.findMember(mpromFileName);
+                                       if (mpromFile != null && mpromFile.exists() && mpromFile.getType() == IResource.FILE)
+                                               associatedResources.add(mpromFile);
+
                                        IResource ramFile = project.findMember(initialRAMFileName);
                                        if (ramFile != null && ramFile.exists() && ramFile.getType() == IResource.FILE)
                                                associatedResources.add(ramFile);
@@ -230,6 +240,7 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
                configuration.setMappedResources(associatedResources.toArray(IResource[]::new));
                configuration.setAttribute(MachineLaunchConfigType.PROJECT_ATTR, projName);
                configuration.setAttribute(MachineLaunchConfigType.MPM_FILE_ATTR, mpmFileName);
+               configuration.setAttribute(MachineLaunchConfigType.MPROM_FILE_ATTR, mpromFileName);
                configuration.setAttribute(MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, initialRAMFileName);
        }
 
@@ -271,6 +282,16 @@ public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
                if (mpmResource.getType() != IResource.FILE)
                        return setErrorAndReturnFalse("MPM file {0} is not a file", mpmFileName);
 
+               String mpromFileName = mpromFileSelText.getText().trim();
+               if (mpromFileName.length() > 0)
+               {
+                       IResource mpromResource = project.findMember(mpromFileName);
+                       if (mpromResource == null || !mpromResource.exists())
+                               return setErrorAndReturnFalse("MPROM file {0} does not exist", mpromFileName);
+                       if (mpromResource.getType() != IResource.FILE)
+                               return setErrorAndReturnFalse("MPROM file {0} is not a file", mpromFileName);
+               }
+
                String initialRAMFileName = initialRAMFileSelText.getText().trim();
                if (initialRAMFileName.length() > 0)
                {
index 147b244..f3965f2 100644 (file)
@@ -245,6 +245,11 @@ public class MachineContext
                        return;
                machineId = newMachineDefinitionId;
                machineDefinition = machineId.map(MachineRegistry::getMachine);
+               if (machineDefinition.isEmpty() && newMachineDefinitionId.isPresent())
+               {
+                       // TODO open a dialog
+                       System.err.println("Machine definition for ID " + newMachineDefinitionId.get() + " not found");
+               }
                updateStatus();
                ProjectMachineContext.notifyListeners(new ProjectContextEvent(this, ProjectContextEventType.MACHINE_DEFINITION_CHANGE));
        }
index 983e822..03619e4 100644 (file)
@@ -5,8 +5,8 @@ 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.MainMemoryDefinition;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 
 public class MemoryTableContentProvider implements ILazyContentProvider, MemoryCellModifiedListener
@@ -14,13 +14,13 @@ public class MemoryTableContentProvider implements ILazyContentProvider, MemoryC
        private long lower, upper;
        private TableViewer viewer;
        public final static int MAX_VISIBLE_ROWS = 1_000;
-       private MainMemory memory;
+       private BitVectorMemory memory;
 
        public void setBounds(long lower, long upper)
        {
                if (memory != null)
                {
-                       MainMemoryDefinition definition = memory.getDefinition();
+                       BitVectorMemoryDefinition definition = memory.getDefinition();
                        this.lower = Long.min(definition.getMaximalAddress(), Long.max(definition.getMinimalAddress(), lower));
                        this.upper = Long.max(this.lower, Long.min(definition.getMaximalAddress(), upper));
                } else
@@ -67,9 +67,9 @@ public class MemoryTableContentProvider implements ILazyContentProvider, MemoryC
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
        {
                this.viewer = (TableViewer) viewer;
-               this.memory = (MainMemory) newInput;
+               this.memory = (BitVectorMemory) newInput;
                if (oldInput != null)
-                       ((MainMemory) oldInput).deregisterCellModifiedListener(this);
+                       ((BitVectorMemory) oldInput).deregisterCellModifiedListener(this);
                if (memory != null)
                        memory.registerCellModifiedListener(this);
                setBounds(0, MAX_VISIBLE_ROWS);
index 81ee6e6..27af63c 100644 (file)
@@ -1,16 +1,16 @@
 package net.mograsim.plugin.tables.memory;
 
-import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.BitVectorMemory;
 import net.mograsim.plugin.tables.TableRow;
 
-public class MemoryTableRow extends TableRow<MainMemory>
+public class MemoryTableRow extends TableRow<BitVectorMemory>
 {
-       public MemoryTableRow(long address, MainMemory memory)
+       public MemoryTableRow(long address, BitVectorMemory memory)
        {
                super(address, memory);
        }
 
-       public MainMemory getMemory()
+       public BitVectorMemory getMemory()
        {
                return getData();
        }
index a616c11..df4c92a 100644 (file)
@@ -18,14 +18,15 @@ import org.junit.jupiter.params.provider.MethodSource;
 
 import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.logic.model.LogicUIStandaloneGUI;
+import net.mograsim.logic.model.am2900.machine.Am2900ExpertMachineDefinition;
 import net.mograsim.logic.model.am2900.machine.Am2900Machine;
 import net.mograsim.logic.model.am2900.machine.Am2900MainMemoryDefinition;
 import net.mograsim.logic.model.am2900.machine.Am2900MicroInstructionDefinition;
 import net.mograsim.logic.model.am2900.machine.Am2900MicroInstructionMemoryDefinition;
-import net.mograsim.logic.model.am2900.machine.Am2900ExpertMachineDefinition;
 import net.mograsim.logic.model.am2900.machine.registers.am2901.NumberedRegister;
 import net.mograsim.logic.model.preferences.DefaultRenderPreferences;
 import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.StandardMainMemory;
 import net.mograsim.machine.mi.MicroInstruction;
 import net.mograsim.machine.mi.MicroInstructionDefinition;
 import net.mograsim.machine.mi.MicroInstructionMemory;
@@ -33,7 +34,6 @@ import net.mograsim.machine.mi.MicroInstructionMemoryParser;
 import net.mograsim.machine.mi.StandardMicroInstructionMemory;
 import net.mograsim.machine.mi.parameters.MicroInstructionParameter;
 import net.mograsim.machine.mi.parameters.ParameterClassification;
-import net.mograsim.machine.standard.memory.WordAddressableMemory;
 
 @TestInstance(Lifecycle.PER_CLASS)
 public class TestGCD
@@ -54,7 +54,7 @@ public class TestGCD
                mach = new Am2900ExpertMachineDefinition().createNew();
                mpm = MicroInstructionMemoryParser.parseMemory(Am2900MicroInstructionMemoryDefinition.instance,
                                TestGCD.class.getResourceAsStream("gcd.mpm"));
-               ram = new WordAddressableMemory(Am2900MainMemoryDefinition.instance);
+               ram = new StandardMainMemory(Am2900MainMemoryDefinition.instance);
                mach.getMainMemory().bind(ram);
 
                if (startGUI)
diff --git a/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/MainMemoryTest.java b/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/MainMemoryTest.java
new file mode 100644 (file)
index 0000000..220aa9d
--- /dev/null
@@ -0,0 +1,69 @@
+package net.mograsim.machine.standard.memory;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigInteger;
+import java.util.Random;
+import java.util.stream.LongStream;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.CoreWire;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.StandardMainMemory;
+
+class MainMemoryTest
+{
+
+       private Timeline t = new Timeline(10);
+
+       @ParameterizedTest(name = "seed = {0}")
+       @MethodSource("seedsForRandom")
+       public void wordAddressableMemoryLargeTest(long seed)
+       {
+               CoreWire rW = new CoreWire(t, 1, 2);
+               CoreWire data = new CoreWire(t, 16, 2);
+               CoreWire address = new CoreWire(t, 64, 2);
+               ReadWriteEnd rWI = rW.createReadWriteEnd();
+               ReadWriteEnd dataI = data.createReadWriteEnd();
+               ReadWriteEnd addressI = address.createReadWriteEnd();
+
+               MainMemoryDefinition definition = MainMemoryDefinition.create(64, 16, 4096L, Long.MAX_VALUE);
+               CoreBitVectorMemory<MainMemory> memory = new CoreBitVectorMemory<>(t, 4, definition, data.createReadWriteEnd(),
+                               rW.createReadOnlyEnd(), address.createReadOnlyEnd(), false);
+               memory.setMemory(new StandardMainMemory(definition));
+
+               Random r = new Random(seed);
+               for (long j = 1; j > 0; j *= 2)
+               {
+                       for (int i = 0; i < 100; i++)
+                       {
+                               BitVector bAddress = BitVector.from(4096 + i + j, 64);
+                               addressI.feedSignals(bAddress);
+                               t.executeAll();
+                               BigInteger random = BigInteger.valueOf(Math.abs(r.nextInt()));
+                               BitVector vector = BitVector.from(random, 16);
+                               dataI.feedSignals(vector);
+                               rWI.feedSignals(Bit.ZERO);
+                               t.executeAll();
+                               rWI.feedSignals(Bit.ONE);
+                               t.executeAll();
+                               dataI.clearSignals();
+                               t.executeAll();
+
+                               assertEquals(vector, dataI.getValues(), "seed=" + seed + ", j=" + j + ", i=" + i);
+                       }
+               }
+       }
+
+       public static LongStream seedsForRandom()
+       {
+               return LongStream.range(0, 20);
+       }
+}
diff --git a/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java b/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java
deleted file mode 100644 (file)
index e3f32e1..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.mograsim.machine.standard.memory;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.math.BigInteger;
-import java.util.Random;
-import java.util.stream.LongStream;
-
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.CoreWire;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.machine.MainMemoryDefinition;
-
-class WordAddressableMemoryTest
-{
-
-       private Timeline t = new Timeline(10);
-
-       @ParameterizedTest(name = "seed = {0}")
-       @MethodSource("seedsForRandom")
-       public void wordAddressableMemoryLargeTest(long seed)
-       {
-               CoreWire rW = new CoreWire(t, 1, 2);
-               CoreWire data = new CoreWire(t, 16, 2);
-               CoreWire address = new CoreWire(t, 64, 2);
-               ReadWriteEnd rWI = rW.createReadWriteEnd();
-               ReadWriteEnd dataI = data.createReadWriteEnd();
-               ReadWriteEnd addressI = address.createReadWriteEnd();
-
-               MainMemoryDefinition definition = MainMemoryDefinition.create(64, 16, 4096L, Long.MAX_VALUE);
-               CoreWordAddressableMemory memory = new CoreWordAddressableMemory(t, 4, definition, data.createReadWriteEnd(),
-                               rW.createReadOnlyEnd(), address.createReadOnlyEnd());
-               memory.setMemory(new WordAddressableMemory(definition));
-
-               Random r = new Random(seed);
-               for (long j = 1; j > 0; j *= 2)
-               {
-                       for (int i = 0; i < 100; i++)
-                       {
-                               BitVector bAddress = BitVector.from(4096 + i + j, 64);
-                               addressI.feedSignals(bAddress);
-                               t.executeAll();
-                               BigInteger random = BigInteger.valueOf(Math.abs(r.nextInt()));
-                               BitVector vector = BitVector.from(random, 16);
-                               dataI.feedSignals(vector);
-                               rWI.feedSignals(Bit.ZERO);
-                               t.executeAll();
-                               rWI.feedSignals(Bit.ONE);
-                               t.executeAll();
-                               dataI.clearSignals();
-                               t.executeAll();
-
-                               assertEquals(vector, dataI.getValues(), "seed=" + seed + ", j=" + j + ", i=" + i);
-                       }
-               }
-       }
-
-       public static LongStream seedsForRandom()
-       {
-               return LongStream.range(0, 20);
-       }
-}