From: Daniel Kirschten Date: Sat, 3 Oct 2020 20:21:34 +0000 (+0200) Subject: Finished MPROM support. Fixes #10 X-Git-Url: https://mograsim.net/gitweb/?p=Mograsim.git;a=commitdiff_plain;h=b5d55c59d7069171bd928e4a945d9185ee4bc2b0 Finished MPROM support. Fixes #10 --- diff --git a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MPROM.java b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MPROM.java index fbfc44d0..1370774b 100644 --- a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MPROM.java +++ b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MPROM.java @@ -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 { public ModelAm2900MPROM(LogicModelModifiable model, String name) { - super(model, Am2900MPROMDefinition.instance, name); + super(model, 30, 80, 30, 50, -1, true, "MPROM", Am2900MPROMDefinition.instance, name); } @Override diff --git a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MainMemory.java b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MainMemory.java index c0655985..f60fd547 100644 --- a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MainMemory.java +++ b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/components/ModelAm2900MainMemory.java @@ -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 { public ModelAm2900MainMemory(LogicModelModifiable model, String name) { - super(model, Am2900MainMemoryDefinition.instance, name); + super(model, 120, 150, 30, 50, 70, false, "RAM", Am2900MainMemoryDefinition.instance, name); } @Override diff --git a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900MPROMDefinition.java b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900MPROMDefinition.java index e8f4afc2..0af200f7 100644 --- a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900MPROMDefinition.java +++ b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900MPROMDefinition.java @@ -25,7 +25,7 @@ public class Am2900MPROMDefinition implements MPROMDefinition } @Override - public int getMicroInstructionMemoryAddressBits() + public int getCellWidth() { return 12; } diff --git a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java index 00c4d6da..a7f7379e 100644 --- a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java +++ b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java @@ -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 index 00000000..20a6c6e5 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/AssignableMainMemory.java @@ -0,0 +1,17 @@ +package net.mograsim.machine; + +import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory; + +public class AssignableMainMemory extends AbstractAssignableBitVectorMemory 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 index 00000000..ef0b79ae --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemory.java @@ -0,0 +1,15 @@ +package net.mograsim.machine; + +import java.math.BigInteger; + +import net.mograsim.logic.core.types.BitVector; + +public interface BitVectorMemory extends Memory +{ + 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 index 00000000..7cc8fea2 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/BitVectorMemoryDefinition.java @@ -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(); +} diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java index 40873f00..314a748f 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java @@ -5,16 +5,16 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Set; -public abstract class GenericMemory implements Memory +public abstract class GenericMemory implements Memory { private final long minimalAddress, maximalAddress; - private final MemoryDefinition definition; + private final D definition; private final int pageSize = 64; private Set observers = new HashSet<>(); private HashMap pages; - public GenericMemory(MemoryDefinition definition) + public GenericMemory(D definition) { super(); this.definition = definition; @@ -67,18 +67,17 @@ public abstract class GenericMemory implements Memory 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 implements Memory } @Override - public MemoryDefinition getDefinition() + public D getDefinition() { return definition; } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java index 0f713b28..115973f9 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java @@ -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 { diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java index 33ad2608..9a0b8988 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemory.java @@ -1,15 +1,7 @@ package net.mograsim.machine; -import java.math.BigInteger; - -import net.mograsim.logic.core.types.BitVector; - -public interface MainMemory extends Memory +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 diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java index 72153d6d..fecbbafd 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/MainMemoryDefinition.java @@ -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); diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java index 39d12c44..2487308b 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java @@ -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 index 00000000..a3630a66 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemory.java @@ -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 implements MainMemory +{ + public StandardMainMemory(MainMemoryDefinition definition) + { + super(definition); + } + + @Override + protected BitVector getDefaultValue(long address) + { + return BitVector.of(Bit.ZERO, getDefinition().getCellWidth()); + } +} diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java index 22be93ee..235dea1b 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMainMemoryDefinition.java @@ -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); } } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java index 8f1904d1..b8f5a814 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/StandardMemoryDefinition.java @@ -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() { diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMPROM.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMPROM.java index 04050130..39cd679f 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMPROM.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMPROM.java @@ -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 implements MPROM { - - private Set observers = new HashSet<>(); - - private Set 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(); } } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROM.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROM.java index 0d8be38d..a0b87cae 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROM.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROM.java @@ -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 +public interface MPROM extends BitVectorMemory { - public BigInteger getCellAsBigInteger(long address); - @Override public MPROMDefinition getDefinition(); } \ No newline at end of file diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROMDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROMDefinition.java index 680a1fa2..1fec8bb2 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROMDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MPROMDefinition.java @@ -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); diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROM.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROM.java index 48df1656..3d8a8cb1 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROM.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROM.java @@ -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 implements MPROM { - private BitVector[] data; - private MPROMDefinition definition; - private HashSet 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()); } } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROMDefinition.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROMDefinition.java index cbc97901..6e1ce13f 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROMDefinition.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMPROMDefinition.java @@ -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 index e2d66dfd..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMPROM.java +++ /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 getAllInputs() - { - return List.of(address); - } - - @Override - public List 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 index 9eab2b49..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/MPROMAdapter.java +++ /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 -{ - @Override - public Class getSupportedClass() - { - return ModelMPROM.class; - } - - @Override - public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelMPROM modelComponent, - Map 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 index b1f791c2..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/ModelMPROM.java +++ /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> 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 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 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 index 00000000..782a5b69 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractAssignableBitVectorMemory.java @@ -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 implements BitVectorMemory, MemoryCellModifiedListener +{ + private Set observers = new HashSet<>(); + private Set> 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 listener) + { + reassignmentListeners.add(listener); + } + + public void deregisterMemoryReassignedListener(BitVectorMemoryReassignedListener listener) + { + reassignmentListeners.remove(listener); + } + + private void notifyMemoryReassigned(M newAssignee) + { + reassignmentListeners.forEach(l -> l.reassigned(newAssignee)); + } + + public interface BitVectorMemoryReassignedListener + { + 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 index 00000000..055fb4ff --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AbstractModelBitVectorMemory.java @@ -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 extends ModelMemory +{ + private final Pin addrPin, dataPin, rWPin; + private final D definition; + private final boolean readonly; + + private CoreBitVectorMemory memory; + + private final List> 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 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 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 memory) + { + this.memory = memory; + } + + public CoreBitVectorMemory 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 index 38b17abc..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java +++ /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 observers = new HashSet<>(); - private Set 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 index 00000000..f2a7ac39 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorBasedMemoryParser.java @@ -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 index 00000000..777a6bcb --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryAdapter.java @@ -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> +{ + @SuppressWarnings({ "cast", "unchecked", "rawtypes" }) + @Override + public Class> getSupportedClass() + { + return (Class>) (Class) AbstractModelBitVectorMemory.class; + } + + @Override + public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, AbstractModelBitVectorMemory modelComponent, + Map logicWiresPerPin) + { + createAndLinkComponentCasted(timeline, params, modelComponent, logicWiresPerPin); + } + + private static void createAndLinkComponentCasted(Timeline timeline, + CoreModelParameters params, AbstractModelBitVectorMemory modelComponent, Map 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 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 index 00000000..a807e091 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/BitVectorMemoryParseException.java @@ -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 index 00000000..e3e20cef --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreBitVectorMemory.java @@ -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 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 getAllInputs() + { + return readonly ? List.of(data, address) : List.of(data, rWBit, address); + } + + @Override + public List 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 index 801895be..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java +++ /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 getAllInputs() - { - return List.of(data, rWBit, address); - } - - @Override - public List 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 index 5c6297e2..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParseException.java +++ /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 index c3b0d689..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/MainMemoryParser.java +++ /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 index a1112e68..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/ModelWordAddressableMemory.java +++ /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> 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 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 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 index 00000000..01f7cf68 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemory.java @@ -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 extends GenericMemory 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 index 00000000..5d088d39 --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/StandardBitVectorMemoryDefinition.java @@ -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 index e8ce2452..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemory.java +++ /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 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 index d7fbbaa6..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/WordAddressableMemoryAdapter.java +++ /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 -{ - @Override - public Class getSupportedClass() - { - return ModelWordAddressableMemory.class; - } - - @Override - public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelWordAddressableMemory modelComponent, - Map 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 diff --git a/plugins/net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties b/plugins/net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties index 707d67b5..e69d3c45 100644 --- a/plugins/net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties +++ b/plugins/net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties @@ -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 diff --git a/plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties b/plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties index 7ab33c1b..3628250b 100644 --- a/plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties +++ b/plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties @@ -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 diff --git a/plugins/net.mograsim.plugin.core/plugin.xml b/plugins/net.mograsim.plugin.core/plugin.xml index 959e6a84..9e8b8cf7 100644 --- a/plugins/net.mograsim.plugin.core/plugin.xml +++ b/plugins/net.mograsim.plugin.core/plugin.xml @@ -49,6 +49,14 @@ name="Main Memory" priority="high"> + + @@ -96,10 +104,20 @@ xcdys + + + + + id="net.mograsim.plugin.editors.mainmemoryeditor" + name="Main Memory Editor"> + xcdys 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 index 00000000..e306cff6 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/AbstractMemoryEditor.java @@ -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 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 index 00000000..9c6ce817 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MPROMEditor.java @@ -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 index 00000000..6d0d7b52 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MainMemoryEditor.java @@ -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 index 0186780e..00000000 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java +++ /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 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 diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineDebugTarget.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineDebugTarget.java index ca748043..5bb87a8d 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineDebugTarget.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineDebugTarget.java @@ -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 mpromFile; private final Optional 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 memFile, MachineDefinition machineDefinition) - throws CoreException + public MachineDebugTarget(ILaunch launch, IFile mpmFile, Optional mpromFile, Optional 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 void assignMemory(Optional memFile, + AbstractAssignableBitVectorMemory memoryToAssign, D definition, Function 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 getMPROMFile() + { + return mpromFile; + } + public Optional getMEMFile() { return memFile; diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java index 5622ca6d..a09ff23f 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java @@ -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 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 mpromFile = fileOptional(project, configuration.getAttribute(MPROM_FILE_ATTR, "")); + Optional 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 fileOptional(IProject project, String filename) + { + if ("".equals(filename)) + return Optional.empty(); + return Optional.of(project.getFile(filename)); + } + } \ No newline at end of file diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java index 843789a3..fbbe2640 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java @@ -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 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) { diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java index 147b2441..f3965f2a 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java @@ -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)); } diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java index 983e822c..03619e46 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java @@ -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); diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java index 81ee6e65..27af63c3 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableRow.java @@ -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 +public class MemoryTableRow extends TableRow { - public MemoryTableRow(long address, MainMemory memory) + public MemoryTableRow(long address, BitVectorMemory memory) { super(address, memory); } - public MainMemory getMemory() + public BitVectorMemory getMemory() { return getData(); } diff --git a/tests/net.mograsim.logic.model.am2900.tests/src/net/mograsim/logic/model/am2900/TestGCD.java b/tests/net.mograsim.logic.model.am2900.tests/src/net/mograsim/logic/model/am2900/TestGCD.java index a616c114..df4c92a8 100644 --- a/tests/net.mograsim.logic.model.am2900.tests/src/net/mograsim/logic/model/am2900/TestGCD.java +++ b/tests/net.mograsim.logic.model.am2900.tests/src/net/mograsim/logic/model/am2900/TestGCD.java @@ -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 index 00000000..220aa9dd --- /dev/null +++ b/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/MainMemoryTest.java @@ -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 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 index e3f32e10..00000000 --- a/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java +++ /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); - } -}