import net.mograsim.logic.model.model.LogicModelModifiable;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
-import net.mograsim.machine.mi.components.ModelMPROM;
+import net.mograsim.machine.mi.MPROM;
+import net.mograsim.machine.mi.MPROMDefinition;
+import net.mograsim.machine.standard.memory.AbstractModelBitVectorMemory;
-public class ModelAm2900MPROM extends ModelMPROM
+public class ModelAm2900MPROM extends AbstractModelBitVectorMemory<MPROM, MPROMDefinition>
{
public ModelAm2900MPROM(LogicModelModifiable model, String name)
{
- super(model, Am2900MPROMDefinition.instance, name);
+ super(model, 30, 80, 30, 50, -1, true, "MPROM", Am2900MPROMDefinition.instance, name);
}
@Override
import net.mograsim.logic.model.model.LogicModelModifiable;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
-import net.mograsim.machine.standard.memory.ModelWordAddressableMemory;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.standard.memory.AbstractModelBitVectorMemory;
-public class ModelAm2900MainMemory extends ModelWordAddressableMemory
+public class ModelAm2900MainMemory extends AbstractModelBitVectorMemory<MainMemory, MainMemoryDefinition>
{
public ModelAm2900MainMemory(LogicModelModifiable model, String name)
{
- super(model, Am2900MainMemoryDefinition.instance, name);
+ super(model, 120, 150, 30, 50, 70, false, "RAM", Am2900MainMemoryDefinition.instance, name);
}
@Override
}
@Override
- public int getMicroInstructionMemoryAddressBits()
+ public int getCellWidth()
{
return 12;
}
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;
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
{
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()));
--- /dev/null
+package net.mograsim.machine;
+
+import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory;
+
+public class AssignableMainMemory extends AbstractAssignableBitVectorMemory<MainMemory> implements MainMemory
+{
+ public AssignableMainMemory(MainMemory memory)
+ {
+ super(memory);
+ }
+
+ @Override
+ public MainMemoryDefinition getDefinition()
+ {
+ return getReal().getDefinition();
+ }
+}
--- /dev/null
+package net.mograsim.machine;
+
+import java.math.BigInteger;
+
+import net.mograsim.logic.core.types.BitVector;
+
+public interface BitVectorMemory extends Memory<BitVector>
+{
+ BigInteger getCellAsBigInteger(long address);
+
+ public void setCellAsBigInteger(long address, BigInteger word);
+
+ @Override
+ BitVectorMemoryDefinition getDefinition();
+}
--- /dev/null
+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();
+}
import java.util.HashSet;
import java.util.Set;
-public abstract class GenericMemory<T> implements Memory<T>
+public abstract class GenericMemory<T, D extends MemoryDefinition> implements Memory<T>
{
private final long minimalAddress, maximalAddress;
- private final MemoryDefinition definition;
+ private final D definition;
private final int pageSize = 64;
private Set<MemoryCellModifiedListener> observers = new HashSet<>();
private HashMap<Long, Page> pages;
- public GenericMemory(MemoryDefinition definition)
+ public GenericMemory(D definition)
{
super();
this.definition = definition;
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)
}
@Override
- public MemoryDefinition getDefinition()
+ public D getDefinition()
{
return definition;
}
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
{
package net.mograsim.machine;
-import java.math.BigInteger;
-
-import net.mograsim.logic.core.types.BitVector;
-
-public interface MainMemory extends Memory<BitVector>
+public interface MainMemory extends BitVectorMemory
{
- public BigInteger getCellAsBigInteger(long address);
-
- public void setCellAsBigInteger(long address, BigInteger word);
-
@Override
public MainMemoryDefinition getDefinition();
}
\ No newline at end of file
* @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);
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
*/
--- /dev/null
+package net.mograsim.machine;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemory;
+
+public class StandardMainMemory extends StandardBitVectorMemory<MainMemoryDefinition> implements MainMemory
+{
+ public StandardMainMemory(MainMemoryDefinition definition)
+ {
+ super(definition);
+ }
+
+ @Override
+ protected BitVector getDefaultValue(long address)
+ {
+ return BitVector.of(Bit.ZERO, getDefinition().getCellWidth());
+ }
+}
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);
}
}
this.maximalAddress = maximalAddress;
}
- public StandardMemoryDefinition(MainMemoryDefinition definition)
- {
- this(definition.getMemoryAddressBits(), definition.getMinimalAddress(), definition.getMaximalAddress());
- }
-
@Override
public int getMemoryAddressBits()
{
package net.mograsim.machine.mi;
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Set;
+import net.mograsim.machine.standard.memory.AbstractAssignableBitVectorMemory;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-public class AssignableMPROM implements MPROM, MemoryCellModifiedListener
+public class AssignableMPROM extends AbstractAssignableBitVectorMemory<MPROM> implements MPROM
{
-
- private Set<MemoryCellModifiedListener> observers = new HashSet<>();
-
- private Set<MPROMReassignedListener> reassignmentListeners = new HashSet<>();
- private MPROM real = null;
-
- public AssignableMPROM(MPROM standardMPROM)
- {
- real = standardMPROM;
- real.registerCellModifiedListener(this);
- }
-
- public void bind(MPROM real)
- {
- this.real.deregisterCellModifiedListener(this);
- this.real = real;
- real.registerCellModifiedListener(this);
- notifyMemoryChanged(-1);
- notifyMemoryReassigned(real);
- }
-
- @Override
- public BitVector getCell(long address)
- {
- return real.getCell(address);
- }
-
- @Override
- public void setCell(long address, BitVector data)
- {
- real.setCell(address, data);
- }
-
- @Override
- public BigInteger getCellAsBigInteger(long address)
- {
- return real.getCellAsBigInteger(address);
- }
-
- @Override
- public void registerCellModifiedListener(MemoryCellModifiedListener ob)
+ public AssignableMPROM(MPROM memory)
{
- observers.add(ob);
- }
-
- @Override
- public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
- {
- observers.remove(ob);
- }
-
- private void notifyMemoryChanged(long address)
- {
- observers.forEach(o -> o.update(address));
+ super(memory);
}
@Override
public MPROMDefinition getDefinition()
{
- return real.getDefinition();
- }
-
- @Override
- public void update(long address)
- {
- notifyMemoryChanged(address);
- }
-
- public void registerMemoryReassignedListener(MPROMReassignedListener listener)
- {
- reassignmentListeners.add(listener);
- }
-
- public void deregisterMemoryReassignedListener(MPROMReassignedListener listener)
- {
- reassignmentListeners.remove(listener);
- }
-
- private void notifyMemoryReassigned(MPROM newAssignee)
- {
- reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
- }
-
- public static interface MPROMReassignedListener
- {
- public void reassigned(MPROM newAssignee);
+ return getReal().getDefinition();
}
}
package net.mograsim.machine.mi;
-import java.math.BigInteger;
+import net.mograsim.machine.BitVectorMemory;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.Memory;
-
-public interface MPROM extends Memory<BitVector>
+public interface MPROM extends BitVectorMemory
{
- public BigInteger getCellAsBigInteger(long address);
-
@Override
public MPROMDefinition getDefinition();
}
\ No newline at end of file
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.
* @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);
package net.mograsim.machine.mi;
-import java.math.BigInteger;
-import java.util.HashSet;
-
import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.standard.memory.MemoryException;
+import net.mograsim.machine.standard.memory.StandardBitVectorMemory;
-public class StandardMPROM implements MPROM
+public class StandardMPROM extends StandardBitVectorMemory<MPROMDefinition> implements MPROM
{
- private BitVector[] data;
- private MPROMDefinition definition;
- private HashSet<MemoryCellModifiedListener> observers = new HashSet<>();
-
public StandardMPROM(MPROMDefinition definition)
{
- if (definition.size() > Integer.MAX_VALUE)
- throw new MemoryException("Size of MPROM must be an int, not a long");
- this.definition = definition;
- data = new BitVector[(int) definition.size()];
- }
-
- private int translate(long address)
- {
- return (int) (address - definition.getMinimalAddress());
- }
-
- @Override
- public BitVector getCell(long address)
- {
- int translatedAddress = translate(address);
- BitVector cell = data[translatedAddress];
- if (cell == null)
- cell = data[translatedAddress] = BitVector.from(address * 16, definition.getMicroInstructionMemoryAddressBits());
- return cell;
- }
-
- @Override
- public BigInteger getCellAsBigInteger(long address)
- {
- return getCell(address).getUnsignedValue();
- }
-
- @Override
- public void setCell(long address, BitVector data)
- {
- this.data[translate(address)] = data;
- notifyMemoryChanged(address);
- }
-
- @Override
- public void registerCellModifiedListener(MemoryCellModifiedListener ob)
- {
- observers.add(ob);
- }
-
- @Override
- public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
- {
- observers.remove(ob);
- }
-
- private void notifyMemoryChanged(long address)
- {
- observers.forEach(ob -> ob.update(address));
+ super(definition);
}
@Override
- public MPROMDefinition getDefinition()
+ protected BitVector getDefaultValue(long address)
{
- return definition;
+ return BitVector.from(address * 16, getDefinition().getCellWidth());
}
}
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);
}
}
+++ /dev/null
-package net.mograsim.machine.mi.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicCoreComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.timeline.TimelineEventHandler;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-import net.mograsim.machine.mi.MPROM;
-import net.mograsim.machine.mi.MPROMDefinition;
-
-public class CoreMPROM extends BasicCoreComponent
-{
- private final ReadWriteEnd data;
- private final ReadEnd address;
- private final MPROMDefinition definition;
- private final MemoryCellModifiedListener memObs;
- private MPROM memory;
-
- public CoreMPROM(Timeline timeline, int processTime, MPROMDefinition definition, ReadWriteEnd data, ReadEnd address)
- {
- super(timeline, processTime);
- if (data.width() != definition.getMicroInstructionMemoryAddressBits())
- throw new IllegalArgumentException(
- String.format("Bit width of data wire does not match MPROM definition. Expected: %d Actual: %d",
- definition.getMicroInstructionMemoryAddressBits(), data.width()));
- if (address.width() != definition.getMemoryAddressBits())
- throw new IllegalArgumentException(
- String.format("Bit width of address wire does not match MPROM definition. Expected: %d Actual: %d",
- definition.getMemoryAddressBits(), address.width()));
-
- this.data = data;
- this.address = address;
- this.definition = definition;
- this.memObs = a -> update();
- address.registerObserver(this);
- }
-
- public void setMemory(MPROM memory)
- {
- if (memory != null && !memory.getDefinition().equals(definition))
- throw new IllegalArgumentException("Memory of incorrect memory definition given");
- if (this.memory != null)
- this.memory.registerCellModifiedListener(memObs);
- this.memory = memory;
- if (memory != null)
- memory.registerCellModifiedListener(memObs);
- update();
- }
-
- public MPROM getMemory()
- {
- return memory;
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(address);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(data);
- }
-
- @Override
- protected TimelineEventHandler compute()
- {
- if (memory == null || !address.getValues().isBinary())
- return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
- long addressed = address.getValues().getUnsignedValueLong();
- BitVector storedData = memory.getCell(addressed);
- return e -> data.feedSignals(storedData);
- }
-}
\ No newline at end of file
+++ /dev/null
-package net.mograsim.machine.mi.components;
-
-import java.util.Map;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.CoreWire;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.CoreModelParameters;
-import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
-
-public class MPROMAdapter implements ComponentAdapter<ModelMPROM>
-{
- @Override
- public Class<ModelMPROM> getSupportedClass()
- {
- return ModelMPROM.class;
- }
-
- @Override
- public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelMPROM modelComponent,
- Map<Pin, CoreWire> logicWiresPerPin)
- {
- ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
- ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
- CoreMPROM mem = new CoreMPROM(timeline, 2, modelComponent.getDefinition(), data, address);
- modelComponent.setCoreModelBinding(mem);
- }
-}
\ No newline at end of file
+++ /dev/null
-package net.mograsim.machine.mi.components;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import net.mograsim.logic.model.model.LogicModelModifiable;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.model.wires.PinUsage;
-import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
-import net.mograsim.logic.model.serializing.IdentifyParams;
-import net.mograsim.logic.model.snippets.HighLevelStateHandler;
-import net.mograsim.machine.ModelMemory;
-import net.mograsim.machine.mi.MPROM;
-import net.mograsim.machine.mi.MPROMDefinition;
-
-public abstract class ModelMPROM extends ModelMemory
-{
- private final Pin addrPin, dataPin;
- private CoreMPROM memory;
- private final MPROMDefinition definition;
-
- private final List<Consumer<Object>> memoryBindingListeners;
-
- public ModelMPROM(LogicModelModifiable model, MPROMDefinition definition, String name)
- {
- super(model, 30, 80, name, "MPROM", false);
- this.definition = definition;
- addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, getWidth(), 30));
- addPin(dataPin = new Pin(model, this, "D", definition.getMicroInstructionMemoryAddressBits(), PinUsage.OUTPUT, getWidth(), 50));
-
- memoryBindingListeners = new ArrayList<>();
-
- setHighLevelStateHandler(new HighLevelStateHandler()
- {
- @Override
- public Object get(String stateID)
- {
- if (stateID.equals("memory_binding"))
- return memory.getMemory();
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void set(String stateID, Object newState)
- {
- if (stateID.equals("memory_binding"))
- {
- memory.setMemory((MPROM) newState);
- memoryBindingListeners.forEach(l -> l.accept(newState));
- } else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void addListener(String stateID, Consumer<Object> stateChanged)
- {
- if (stateID.equals("memory_binding"))
- memoryBindingListeners.add(stateChanged);
- else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void removeListener(String stateID, Consumer<Object> stateChanged)
- {
- if (stateID.equals("memory_binding"))
- memoryBindingListeners.remove(stateChanged);
- else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public String getIDForSerializing(IdentifyParams idParams)
- {
- return null;
- }
-
- @Override
- public Object getParamsForSerializing(IdentifyParams idParams)
- {
- return null;
- }
- });
-
- init();
- }
-
- public MPROMDefinition getDefinition()
- {
- return definition;
- }
-
- public Pin getAddressPin()
- {
- return addrPin;
- }
-
- public Pin getDataPin()
- {
- return dataPin;
- }
-
- public CoreMPROM getCoreMemory()
- {
- return memory;
- }
-
- public void setCoreModelBinding(CoreMPROM memory)
- {
- this.memory = memory;
- }
-
- static
- {
- LogicCoreAdapter.addComponentAdapter(new MPROMAdapter());
- }
-}
\ No newline at end of file
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+
+public class AbstractAssignableBitVectorMemory<M extends BitVectorMemory> implements BitVectorMemory, MemoryCellModifiedListener
+{
+ private Set<MemoryCellModifiedListener> observers = new HashSet<>();
+ private Set<BitVectorMemoryReassignedListener<M>> reassignmentListeners = new HashSet<>();
+ private M real = null;
+
+ public AbstractAssignableBitVectorMemory(M memory)
+ {
+ real = memory;
+ real.registerCellModifiedListener(this);
+ }
+
+ public void bind(M real)
+ {
+ this.real.deregisterCellModifiedListener(this);
+ this.real = real;
+ real.registerCellModifiedListener(this);
+ notifyMemoryChanged(-1);
+ notifyMemoryReassigned(real);
+ }
+
+ @Override
+ public BitVector getCell(long address)
+ {
+ return real.getCell(address);
+ }
+
+ @Override
+ public BigInteger getCellAsBigInteger(long address)
+ {
+ return real.getCellAsBigInteger(address);
+ }
+
+ @Override
+ public void setCell(long address, BitVector data)
+ {
+ real.setCell(address, data);
+ }
+
+ @Override
+ public void setCellAsBigInteger(long address, BigInteger word)
+ {
+ real.setCellAsBigInteger(address, word);
+ }
+
+ @Override
+ public void registerCellModifiedListener(MemoryCellModifiedListener ob)
+ {
+ observers.add(ob);
+ }
+
+ protected M getReal()
+ {
+ return real;
+ }
+
+ @Override
+ public BitVectorMemoryDefinition getDefinition()
+ {
+ return real.getDefinition();
+ }
+
+ @Override
+ public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
+ {
+ observers.remove(ob);
+ }
+
+ private void notifyMemoryChanged(long address)
+ {
+ observers.forEach(o -> o.update(address));
+ }
+
+ @Override
+ public void update(long address)
+ {
+ notifyMemoryChanged(address);
+ }
+
+ public void registerMemoryReassignedListener(BitVectorMemoryReassignedListener<M> listener)
+ {
+ reassignmentListeners.add(listener);
+ }
+
+ public void deregisterMemoryReassignedListener(BitVectorMemoryReassignedListener<M> listener)
+ {
+ reassignmentListeners.remove(listener);
+ }
+
+ private void notifyMemoryReassigned(M newAssignee)
+ {
+ reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
+ }
+
+ public interface BitVectorMemoryReassignedListener<M extends BitVectorMemory>
+ {
+ public void reassigned(M newAssignee);
+ }
+}
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+import net.mograsim.logic.model.model.LogicModelModifiable;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.model.wires.PinUsage;
+import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
+import net.mograsim.logic.model.serializing.IdentifyParams;
+import net.mograsim.logic.model.snippets.HighLevelStateHandler;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.ModelMemory;
+
+public abstract class AbstractModelBitVectorMemory<M extends BitVectorMemory, D extends BitVectorMemoryDefinition> extends ModelMemory
+{
+ private final Pin addrPin, dataPin, rWPin;
+ private final D definition;
+ private final boolean readonly;
+
+ private CoreBitVectorMemory<M> memory;
+
+ private final List<Consumer<Object>> memoryBindingListeners;
+
+ public AbstractModelBitVectorMemory(LogicModelModifiable model, int width, int height, int aPinX, int dPinX, int rwPinX,
+ boolean readonly, String centerText, D definition, String name)
+ {
+ super(model, width, height, name, centerText, false);
+ this.definition = definition;
+ this.readonly = readonly;
+
+ addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, width, aPinX));
+ addPin(dataPin = new Pin(model, this, "D", definition.getCellWidth(), PinUsage.TRISTATE, width, dPinX));
+ if (readonly)
+ rWPin = null;
+ else
+ addPin(rWPin = new Pin(model, this, "RW", 1, PinUsage.INPUT, width, rwPinX));
+
+ memoryBindingListeners = new ArrayList<>();
+
+ setHighLevelStateHandler(new HighLevelStateHandler()
+ {
+ @Override
+ public Object get(String stateID)
+ {
+ if (stateID.equals("memory_binding"))
+ return memory.getMemory();
+ throw new IllegalArgumentException("No high level state with ID " + stateID);
+ }
+
+ @Override
+ public void set(String stateID, Object newState)
+ {
+ if (stateID.equals("memory_binding"))
+ {
+ @SuppressWarnings("unchecked")
+ M mem = (M) newState;
+ memory.setMemory(mem);
+ memoryBindingListeners.forEach(l -> l.accept(newState));
+ } else
+ throw new IllegalArgumentException("No high level state with ID " + stateID);
+ }
+
+ @Override
+ public void addListener(String stateID, Consumer<Object> stateChanged)
+ {
+ if (stateID.equals("memory_binding"))
+ memoryBindingListeners.add(stateChanged);
+ else
+ throw new IllegalArgumentException("No high level state with ID " + stateID);
+ }
+
+ @Override
+ public void removeListener(String stateID, Consumer<Object> stateChanged)
+ {
+ if (stateID.equals("memory_binding"))
+ memoryBindingListeners.remove(stateChanged);
+ else
+ throw new IllegalArgumentException("No high level state with ID " + stateID);
+ }
+
+ @Override
+ public String getIDForSerializing(IdentifyParams idParams)
+ {
+ return null;
+ }
+
+ @Override
+ public Object getParamsForSerializing(IdentifyParams idParams)
+ {
+ return null;
+ }
+ });
+
+ init();
+ }
+
+ public D getDefinition()
+ {
+ return definition;
+ }
+
+ public Pin getAddressPin()
+ {
+ return addrPin;
+ }
+
+ public Pin getDataPin()
+ {
+ return dataPin;
+ }
+
+ public Pin getReadWritePin()
+ {
+ if (isReadonly())
+ throw new IllegalArgumentException("This AbstractModelBitVectorMemory has no RW pin; it is readonly");
+ return rWPin;
+ }
+
+ public boolean isReadonly()
+ {
+ return readonly;
+ }
+
+ public void setCoreModelBinding(CoreBitVectorMemory<M> memory)
+ {
+ this.memory = memory;
+ }
+
+ public CoreBitVectorMemory<M> getCoreMemory()
+ {
+ return memory;
+ }
+
+ static
+ {
+ LogicCoreAdapter.addComponentAdapter(new BitVectorMemoryAdapter());
+ }
+}
\ No newline at end of file
+++ /dev/null
-package net.mograsim.machine.standard.memory;
-
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Set;
-
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-public class AssignableMainMemory implements MainMemory, MemoryCellModifiedListener
-{
- private Set<MemoryCellModifiedListener> observers = new HashSet<>();
- private Set<MainMemoryReassignedListener> reassignmentListeners = new HashSet<>();
- private MainMemory real = null;
-
- public AssignableMainMemory(MainMemory mainMemory)
- {
- real = mainMemory;
- real.registerCellModifiedListener(this);
- }
-
- public void bind(MainMemory real)
- {
- this.real.deregisterCellModifiedListener(this);
- this.real = real;
- real.registerCellModifiedListener(this);
- notifyMemoryChanged(-1);
- notifyMemoryReassigned(real);
- }
-
- @Override
- public BitVector getCell(long address)
- {
- return real.getCell(address);
- }
-
- @Override
- public BigInteger getCellAsBigInteger(long address)
- {
- return real.getCellAsBigInteger(address);
- }
-
- @Override
- public void setCell(long address, BitVector data)
- {
- real.setCell(address, data);
- }
-
- @Override
- public void setCellAsBigInteger(long address, BigInteger word)
- {
- real.setCellAsBigInteger(address, word);
- }
-
- @Override
- public void registerCellModifiedListener(MemoryCellModifiedListener ob)
- {
- observers.add(ob);
- }
-
- @Override
- public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
- {
- observers.remove(ob);
- }
-
- private void notifyMemoryChanged(long address)
- {
- observers.forEach(o -> o.update(address));
- }
-
- @Override
- public MainMemoryDefinition getDefinition()
- {
- return real.getDefinition();
- }
-
- @Override
- public void update(long address)
- {
- notifyMemoryChanged(address);
- }
-
- public void registerMemoryReassignedListener(MainMemoryReassignedListener listener)
- {
- reassignmentListeners.add(listener);
- }
-
- public void deregisterMemoryReassignedListener(MainMemoryReassignedListener listener)
- {
- reassignmentListeners.remove(listener);
- }
-
- private void notifyMemoryReassigned(MainMemory newAssignee)
- {
- reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
- }
-
- public static interface MainMemoryReassignedListener
- {
- public void reassigned(MainMemory newAssignee);
- }
-}
--- /dev/null
+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;
+ }
+ };
+ }
+}
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.util.Map;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.wires.CoreWire;
+import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.modeladapter.CoreModelParameters;
+import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+
+public class BitVectorMemoryAdapter implements ComponentAdapter<AbstractModelBitVectorMemory<?, ?>>
+{
+ @SuppressWarnings({ "cast", "unchecked", "rawtypes" })
+ @Override
+ public Class<AbstractModelBitVectorMemory<?, ?>> getSupportedClass()
+ {
+ return (Class<AbstractModelBitVectorMemory<?, ?>>) (Class) AbstractModelBitVectorMemory.class;
+ }
+
+ @Override
+ public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, AbstractModelBitVectorMemory<?, ?> modelComponent,
+ Map<Pin, CoreWire> logicWiresPerPin)
+ {
+ createAndLinkComponentCasted(timeline, params, modelComponent, logicWiresPerPin);
+ }
+
+ private static <M extends BitVectorMemory, D extends BitVectorMemoryDefinition> void createAndLinkComponentCasted(Timeline timeline,
+ CoreModelParameters params, AbstractModelBitVectorMemory<M, D> modelComponent, Map<Pin, CoreWire> logicWiresPerPin)
+ {
+ ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
+ ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
+ ReadEnd rwBit = modelComponent.isReadonly() ? null : logicWiresPerPin.get(modelComponent.getReadWritePin()).createReadOnlyEnd();
+ // TODO introduce memoryProcessTime
+ CoreBitVectorMemory<M> mem = new CoreBitVectorMemory<>(timeline, 2, modelComponent.getDefinition(), data, rwBit, address,
+ modelComponent.isReadonly());
+ modelComponent.setCoreModelBinding(mem);
+ }
+}
\ No newline at end of file
--- /dev/null
+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);
+ }
+
+}
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.util.List;
+
+import net.mograsim.logic.core.components.BasicCoreComponent;
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.timeline.TimelineEventHandler;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+
+/**
+ * A memory component that only allows access to words of a specific width
+ */
+public class CoreBitVectorMemory<M extends BitVectorMemory> extends BasicCoreComponent
+{
+ private final static Bit read = Bit.ONE;
+
+ private final ReadWriteEnd data;
+ private final ReadEnd rWBit, address;
+ private final boolean readonly;
+ private final MemoryCellModifiedListener memObs;
+ private final BitVectorMemoryDefinition definition;
+ private M memory;
+
+ /**
+ * @param data The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
+ * a memory word
+ * @param rWBit The value of the 0th bit dictates the mode: 0: Write, 1: Read
+ * @param address The bits of this ReadEnd address the memory cell to read/write
+ */
+ public CoreBitVectorMemory(Timeline timeline, int processTime, BitVectorMemoryDefinition definition, ReadWriteEnd data, ReadEnd rWBit,
+ ReadEnd address, boolean readonly)
+ {
+ super(timeline, processTime);
+ if (data.width() != definition.getCellWidth())
+ throw new IllegalArgumentException(
+ String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d",
+ definition.getCellWidth(), data.width()));
+ if (!readonly && rWBit.width() != 1)
+ throw new IllegalArgumentException(
+ String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width()));
+ if (address.width() != definition.getMemoryAddressBits())
+ throw new IllegalArgumentException(
+ String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d",
+ definition.getMemoryAddressBits(), address.width()));
+ this.data = data;
+ this.rWBit = rWBit;
+ this.address = address;
+ this.readonly = readonly;
+ this.definition = definition;
+ this.memObs = a -> update();
+ data.registerObserver(this);
+ if (!readonly)
+ rWBit.registerObserver(this);
+ address.registerObserver(this);
+ }
+
+ public void setMemory(M memory)
+ {
+ if (memory != null && !memory.getDefinition().equals(definition))
+ throw new IllegalArgumentException("Memory of incorrect memory definition given");
+ if (this.memory != null)
+ this.memory.registerCellModifiedListener(memObs);
+ this.memory = memory;
+ if (memory != null)
+ memory.registerCellModifiedListener(memObs);
+ update();
+ }
+
+ public M getMemory()
+ {
+ return memory;
+ }
+
+ @Override
+ protected TimelineEventHandler compute()
+ {
+ if (memory == null)
+ return e -> data.feedSignals(Bit.U.toVector(data.width()));
+ boolean isReading = readonly || read.equals(rWBit.getValue());
+ if (!address.getValues().isBinary())
+ {
+ if (isReading)
+ return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
+ return e -> data.clearSignals();
+ }
+ long addressed = address.getValues().getUnsignedValueLong();
+ if (isReading)
+ {
+ BitVector storedData = memory.getCell(addressed);
+ return e -> data.feedSignals(storedData);
+ }
+ BitVector transData = data.getValues();
+ boolean isNewData = !transData.equals(memory.getCell(addressed));
+ return e ->
+ {
+ data.clearSignals();
+ if (isNewData)
+ memory.setCell(addressed, transData);
+ };
+ }
+
+ @Override
+ public List<ReadEnd> getAllInputs()
+ {
+ return readonly ? List.of(data, address) : List.of(data, rWBit, address);
+ }
+
+ @Override
+ public List<ReadWriteEnd> getAllOutputs()
+ {
+ return List.of(data);
+ }
+}
\ No newline at end of file
+++ /dev/null
-package net.mograsim.machine.standard.memory;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicCoreComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.timeline.TimelineEventHandler;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-
-/**
- * A memory component that only allows access to words of a specific width
- */
-public class CoreWordAddressableMemory extends BasicCoreComponent
-{
- private final static Bit read = Bit.ONE;
-
- private ReadWriteEnd data;
- private ReadEnd rWBit, address;
- private final MemoryCellModifiedListener memObs;
- private final MainMemoryDefinition definition;
- private MainMemory memory;
-
- /**
- * @param data The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
- * a memory word
- * @param rWBit The value of the 0th bit dictates the mode: 0: Write, 1: Read
- * @param address The bits of this ReadEnd address the memory cell to read/write
- */
- public CoreWordAddressableMemory(Timeline timeline, int processTime, MainMemoryDefinition definition, ReadWriteEnd data, ReadEnd rWBit,
- ReadEnd address)
- {
- super(timeline, processTime);
- if (data.width() != definition.getCellWidth())
- throw new IllegalArgumentException(
- String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d",
- definition.getCellWidth(), data.width()));
- if (rWBit.width() != 1)
- throw new IllegalArgumentException(
- String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width()));
- if (address.width() != definition.getMemoryAddressBits())
- throw new IllegalArgumentException(
- String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d",
- definition.getMemoryAddressBits(), address.width()));
- this.data = data;
- this.rWBit = rWBit;
- this.address = address;
- this.definition = definition;
- this.memObs = a -> update();
- data.registerObserver(this);
- rWBit.registerObserver(this);
- address.registerObserver(this);
- }
-
- public void setMemory(MainMemory memory)
- {
- if (memory != null && !memory.getDefinition().equals(definition))
- throw new IllegalArgumentException("Memory of incorrect memory definition given");
- if (this.memory != null)
- this.memory.registerCellModifiedListener(memObs);
- this.memory = memory;
- if (memory != null)
- memory.registerCellModifiedListener(memObs);
- update();
- }
-
- public MainMemory getMemory()
- {
- return memory;
- }
-
- @Override
- protected TimelineEventHandler compute()
- {
- if (memory == null)
- return e -> data.feedSignals(Bit.U.toVector(data.width()));
- if (!address.getValues().isBinary())
- {
- if (read.equals(rWBit.getValue()))
- return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
- return e -> data.clearSignals();
- }
- long addressed = address.getValues().getUnsignedValueLong();
- if (read.equals(rWBit.getValue()))
- {
- BitVector storedData = memory.getCell(addressed);
- return e -> data.feedSignals(storedData);
- }
- BitVector transData = data.getValues();
- boolean isNewData = !transData.equals(memory.getCell(addressed));
- return e ->
- {
- data.clearSignals();
- if (isNewData)
- memory.setCell(addressed, transData);
- };
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(data, rWBit, address);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(data);
- }
-}
\ No newline at end of file
+++ /dev/null
-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);
- }
-
-}
+++ /dev/null
-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;
- }
- };
- }
-}
+++ /dev/null
-package net.mograsim.machine.standard.memory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import net.mograsim.logic.model.model.LogicModelModifiable;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.model.wires.PinUsage;
-import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
-import net.mograsim.logic.model.serializing.IdentifyParams;
-import net.mograsim.logic.model.snippets.HighLevelStateHandler;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.ModelMemory;
-
-public abstract class ModelWordAddressableMemory extends ModelMemory
-{
- private final Pin addrPin, dataPin, rWPin;
- private CoreWordAddressableMemory memory;
- private MainMemoryDefinition definition;
-
- private final List<Consumer<Object>> memoryBindingListeners;
-
- public ModelWordAddressableMemory(LogicModelModifiable model, MainMemoryDefinition definition, String name)
- {
- super(model, 120, 150, name, "RAM", false);
- this.definition = definition;
-
- addPin(addrPin = new Pin(model, this, "A", definition.getMemoryAddressBits(), PinUsage.INPUT, getWidth(), 30));
- addPin(dataPin = new Pin(model, this, "D", definition.getCellWidth(), PinUsage.TRISTATE, getWidth(), 50));
- addPin(rWPin = new Pin(model, this, "RW", 1, PinUsage.INPUT, getWidth(), 70));
-
- memoryBindingListeners = new ArrayList<>();
-
- setHighLevelStateHandler(new HighLevelStateHandler()
- {
- @Override
- public Object get(String stateID)
- {
- if (stateID.equals("memory_binding"))
- return memory.getMemory();
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void set(String stateID, Object newState)
- {
- if (stateID.equals("memory_binding"))
- {
- memory.setMemory((MainMemory) newState);
- memoryBindingListeners.forEach(l -> l.accept(newState));
- } else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void addListener(String stateID, Consumer<Object> stateChanged)
- {
- if (stateID.equals("memory_binding"))
- memoryBindingListeners.add(stateChanged);
- else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public void removeListener(String stateID, Consumer<Object> stateChanged)
- {
- if (stateID.equals("memory_binding"))
- memoryBindingListeners.remove(stateChanged);
- else
- throw new IllegalArgumentException("No high level state with ID " + stateID);
- }
-
- @Override
- public String getIDForSerializing(IdentifyParams idParams)
- {
- return null;
- }
-
- @Override
- public Object getParamsForSerializing(IdentifyParams idParams)
- {
- return null;
- }
- });
-
- init();
- }
-
- public MainMemoryDefinition getDefinition()
- {
- return definition;
- }
-
- public Pin getAddressPin()
- {
- return addrPin;
- }
-
- public Pin getDataPin()
- {
- return dataPin;
- }
-
- public Pin getReadWritePin()
- {
- return rWPin;
- }
-
- public void setCoreModelBinding(CoreWordAddressableMemory memory)
- {
- this.memory = memory;
- }
-
- public CoreWordAddressableMemory getCoreMemory()
- {
- return memory;
- }
-
- static
- {
- LogicCoreAdapter.addComponentAdapter(new WordAddressableMemoryAdapter());
- }
-}
\ No newline at end of file
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.math.BigInteger;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.BitVectorMemoryDefinition;
+import net.mograsim.machine.GenericMemory;
+
+public class StandardBitVectorMemory<D extends BitVectorMemoryDefinition> extends GenericMemory<BitVector, D> implements BitVectorMemory
+{
+ public StandardBitVectorMemory(D definition)
+ {
+ super(definition);
+ }
+
+ @Override
+ public BitVector getCell(long address)
+ {
+ BitVector cell = super.getCell(address);
+ if (cell == null)
+ setCell(address, cell = getDefaultValue(address));
+ return cell;
+ }
+
+ @Override
+ public BigInteger getCellAsBigInteger(long address)
+ {
+ return getCell(address).getUnsignedValue();
+ }
+
+ @Override
+ public void setCell(long address, BitVector data)
+ {
+ if (data.isBinary())
+ super.setCell(address, data);
+ }
+
+ @Override
+ public void setCellAsBigInteger(long address, BigInteger data)
+ {
+ setCell(address, BitVector.from(data, getDefinition().getCellWidth()));
+ }
+
+ protected BitVector getDefaultValue(@SuppressWarnings("unused") /* this method is inteded to be overridden */ long address)
+ {
+ return BitVector.of(Bit.U, getDefinition().getCellWidth());
+ }
+}
--- /dev/null
+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;
+ }
+}
+++ /dev/null
-package net.mograsim.machine.standard.memory;
-
-import java.math.BigInteger;
-
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.GenericMemory;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-
-public class WordAddressableMemory extends GenericMemory<BitVector> implements MainMemory
-{
- private final int cellWidth;
- private final MainMemoryDefinition definition;
-
- public WordAddressableMemory(MainMemoryDefinition definition)
- {
- super(definition);
- this.cellWidth = definition.getCellWidth();
- this.definition = definition;
- }
-
- @Override
- public void setCell(long address, BitVector data)
- {
- if (data.isBinary())
- super.setCell(address, data);
- }
-
- @Override
- public BitVector getCell(long address)
- {
- BitVector data = super.getCell(address);
- return data == null ? BitVector.of(Bit.ZERO, cellWidth) : data;
- }
-
- @Override
- public BigInteger getCellAsBigInteger(long address)
- {
- BitVector data = getCell(address);
- return data == null ? BigInteger.valueOf(0) : data.getUnsignedValue();
- }
-
- @Override
- public void setCellAsBigInteger(long address, BigInteger data)
- {
- setCell(address, BitVector.from(data, cellWidth));
- }
-
- @Override
- public MainMemoryDefinition getDefinition()
- {
- return definition;
- }
-}
+++ /dev/null
-package net.mograsim.machine.standard.memory;
-
-import java.util.Map;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.CoreWire;
-import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
-import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.CoreModelParameters;
-import net.mograsim.logic.model.modeladapter.componentadapters.ComponentAdapter;
-
-public class WordAddressableMemoryAdapter implements ComponentAdapter<ModelWordAddressableMemory>
-{
- @Override
- public Class<ModelWordAddressableMemory> getSupportedClass()
- {
- return ModelWordAddressableMemory.class;
- }
-
- @Override
- public void createAndLinkComponent(Timeline timeline, CoreModelParameters params, ModelWordAddressableMemory modelComponent,
- Map<Pin, CoreWire> logicWiresPerPin)
- {
- ReadWriteEnd data = logicWiresPerPin.get(modelComponent.getDataPin()).createReadWriteEnd();
- ReadEnd address = logicWiresPerPin.get(modelComponent.getAddressPin()).createReadOnlyEnd();
- ReadEnd mode = logicWiresPerPin.get(modelComponent.getReadWritePin()).createReadOnlyEnd();
- CoreWordAddressableMemory mem = new CoreWordAddressableMemory(timeline, 2, modelComponent.getDefinition(), data, mode, address);
- modelComponent.setCoreModelBinding(mem);
- }
-}
\ No newline at end of file
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
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
name="Main Memory"
priority="high">
</content-type>
+ <content-type
+ base-type="org.eclipse.core.runtime.text"
+ default-charset="UTF-8"
+ file-extensions="mprom"
+ id="net.mograsim.plugin.mprom"
+ name="%content-type.mprom.name"
+ priority="high">
+ </content-type>
</extension>
<extension
point="org.eclipse.ui.menus">
<contentTypeBinding contentTypeId="net.mograsim.plugin.mpm"/>
</editor>
<editor
- class="net.mograsim.plugin.editors.MemoryEditor"
+ class="net.mograsim.plugin.editors.MPROMEditor"
+ icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+ id="net.mograsim.plugin.editors.mpromeditor"
+ name="MPROM Editor">xcdys
+ <contentTypeBinding
+ contentTypeId="net.mograsim.plugin.mprom">
+ </contentTypeBinding>
+ </editor>
+ <editor
+ class="net.mograsim.plugin.editors.MainMemoryEditor"
icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
- id="net.mograsim.plugin.editors.memoryeditor"
- name="Memory Editor">
+ id="net.mograsim.plugin.editors.mainmemoryeditor"
+ name="Main Memory Editor">
+ xcdys
<contentTypeBinding
contentTypeId="net.mograsim.plugin.mem">
</contentTypeBinding>
--- /dev/null
+package net.mograsim.plugin.editors;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.themes.ITheme;
+import org.eclipse.ui.themes.IThemeManager;
+
+import net.mograsim.machine.BitVectorMemory;
+import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
+import net.mograsim.machine.standard.memory.BitVectorBasedMemoryParser;
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.nature.MachineContext;
+import net.mograsim.plugin.nature.ProjectMachineContext;
+import net.mograsim.plugin.tables.AddressLabelProvider;
+import net.mograsim.plugin.tables.DisplaySettings;
+import net.mograsim.plugin.tables.LazyTableViewer;
+import net.mograsim.plugin.tables.NumberColumnLabelProvider;
+import net.mograsim.plugin.tables.RadixSelector;
+import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
+import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
+import net.mograsim.plugin.tables.memory.MemoryTableRow;
+import net.mograsim.plugin.tables.memory.NumberVerifyListener;
+
+public abstract class AbstractMemoryEditor extends EditorPart
+{
+ private MachineContext context;
+
+ private BitVectorMemory memory;
+
+ private LazyTableViewer viewer;
+ private MemoryTableContentProvider provider;
+ private DisplaySettings displaySettings;
+
+ private Collection<Control> fontDependent = new HashSet<>();
+
+ private boolean dirty;
+
+ private final MemoryCellModifiedListener memListener;
+
+ private final static String font = "net.mograsim.plugin.memory.table_font";
+ private IPropertyChangeListener fontChangeListener;
+
+ public AbstractMemoryEditor()
+ {
+ memListener = this::cellModified;
+ }
+
+ @Override
+ public void createPartControl(Composite parent)
+ {
+ provider = new MemoryTableContentProvider();
+ displaySettings = new DisplaySettings();
+
+ parent.setLayout(new GridLayout(8, false));
+ createHeader(parent);
+ createViewer(parent);
+
+ displaySettings.addObserver(() -> viewer.refresh());
+ }
+
+ @SuppressWarnings("unused") // RadixSelector and exceptions
+ private void createHeader(Composite parent)
+ {
+ Text gotoText = new Text(parent, SWT.BORDER);
+ gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ NumberVerifyListener vl = new NumberVerifyListener();
+ gotoText.addVerifyListener(vl);
+ gotoText.setText("0");
+
+ Runnable gotoAction = () ->
+ {
+ try
+ {
+ loadAround((int) (AsmNumberUtil.valueOf(gotoText.getText()).longValue() - provider.getLowerBound()));
+ viewer.getTable().deselectAll();
+ }
+ catch (NumberFormatException x)
+ {
+ // Nothing to do here
+ }
+ };
+
+ gotoText.addTraverseListener((e) ->
+ {
+ if (e.detail == SWT.TRAVERSE_RETURN)
+ gotoAction.run();
+ });
+
+ Button gotoButton = new Button(parent, SWT.PUSH);
+ gotoButton.setText("Go to");
+ gotoButton.addListener(SWT.Selection, e ->
+ {
+ gotoAction.run();
+ });
+
+ new Label(parent, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+ new RadixSelector(parent, displaySettings);
+ }
+
+ private void createViewer(Composite parent)
+ {
+ viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+ fontDependent.add(viewer.getTable());
+ createColumns();
+ Table table = viewer.getTable();
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ viewer.setUseHashlookup(true);
+ viewer.setContentProvider(provider);
+ getSite().setSelectionProvider(viewer);
+ viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 8, 1));
+
+ // TODO: Also support keyboard inputs for flexible scrolling
+ ScrollBar vBar = table.getVerticalBar();
+ vBar.addListener(SWT.Selection, (e) ->
+ {
+ int sel;
+ if ((sel = vBar.getSelection()) < vBar.getMinimum() + vBar.getThumb() * 2 || sel > vBar.getMaximum() - vBar.getThumb() * 2)
+ {
+ loadAround(table.getTopIndex());
+ table.deselectAll();
+ }
+ });
+
+ IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
+ themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
+ {
+ if (IThemeManager.CHANGE_CURRENT_THEME.equals(e.getProperty()) || font.equals(e.getProperty()))
+ {
+ updateFont(themeManager.getCurrentTheme());
+ viewer.refresh();
+ }
+ });
+ updateFont(themeManager.getCurrentTheme());
+
+ if (memory != null)
+ viewer.setInput(memory);
+ }
+
+ private void updateFont(ITheme theme)
+ {
+ Font newFont = theme.getFontRegistry().get(font);
+ // TODO: This is a quick fix! Still have to figure out why the CellEditors do not get the appropriate Font on their own
+ fontDependent.forEach(c -> c.setFont(newFont));
+ }
+
+ private void loadAround(int row)
+ {
+ long prevLb = provider.getLowerBound();
+ long address = prevLb + row;
+ long actualLb = Long.max(address - MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMinimalAddress());
+
+ long prevHb = provider.getUpperBound();
+ // +- 1 row is not really important
+ long actualHb = Long.min(address + MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMaximalAddress());
+
+ if (actualLb != prevLb || actualHb != prevHb)
+ {
+ Table table = viewer.getTable();
+ provider.setBounds(actualLb, actualHb);
+ int rowIndex = (int) (address - actualLb);
+ if (rowIndex >= 0 && rowIndex < table.getItemCount())
+ table.showItem(table.getItem(rowIndex));
+ viewer.refresh();
+ }
+ }
+
+ private void createColumns()
+ {
+ TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
+ addrCol.setLabelProvider(new AddressLabelProvider());
+
+ TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
+ dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
+ {
+ @Override
+ public BigInteger getAsBigInteger(Object element)
+ {
+ MemoryTableRow row = (MemoryTableRow) element;
+ return row.getMemory().getCellAsBigInteger(row.address);
+ }
+
+ @Override
+ public int getBitLength(Object element)
+ {
+ return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
+ }
+ });
+ MemoryCellEditingSupport eSup;
+ dataCol.setEditingSupport(eSup = new MemoryCellEditingSupport(viewer, displaySettings));
+ fontDependent.add(eSup.getCellEditorControl());
+ }
+
+ private TableViewerColumn createTableViewerColumn(String title, int width)
+ {
+ TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+ TableColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setWidth(width);
+ column.setResizable(true);
+ column.setMoveable(false);
+ return viewerColumn;
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException
+ {
+ if (input instanceof IFileEditorInput)
+ {
+ IFileEditorInput fileInput = (IFileEditorInput) input;
+ context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
+
+ setPartName(fileInput.getName());
+ try
+ {
+ open(fileInput.getFile());
+ }
+ catch (Exception e)
+ {
+ throw new PartInitException("Failed to read input!", e);
+ }
+ } else
+ throw new IllegalArgumentException("MemoryEditor can only be used with Files");
+
+ setSite(site);
+ setInput(input);
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor)
+ {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput)
+ SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
+ }
+
+ private void save(IFile file, IProgressMonitor monitor) throws CoreException, IOException
+ {
+ if (memory == null)
+ {
+ throw new MicroInstructionMemoryParseException("Failed to write the memory to File. No memory assigned.");
+ }
+ try (InputStream toWrite = BitVectorBasedMemoryParser.write(memory))
+ {
+ file.setContents(toWrite, 0, monitor);
+ setDirty(false);
+ }
+ }
+
+ private void open(IFile file) throws IOException, CoreException
+ {
+ MachineDefinition machDef = context.getMachineDefinition()
+ .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!"));
+ memory = createEmptyMemory(machDef);
+ BitVectorBasedMemoryParser.parseMemory(memory, file.getContents());
+ memory.registerCellModifiedListener(memListener);
+ if (viewer != null)
+ viewer.setInput(memory);
+ }
+
+ protected abstract BitVectorMemory createEmptyMemory(MachineDefinition activeMachineDefinition);
+
+ private void cellModified(@SuppressWarnings("unused") long address)
+ {
+ setDirty(true);
+ }
+
+ private void setDirty(boolean newDirty)
+ {
+ dirty = newDirty;
+ firePropertyChange(PROP_DIRTY);
+ }
+
+ @Override
+ public void doSaveAs()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isDirty()
+ {
+ return dirty;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed()
+ {
+ return false;
+ }
+
+ @Override
+ public void setFocus()
+ {
+ viewer.getTable().setFocus();
+ }
+
+ @Override
+ public void dispose()
+ {
+ getSite().getWorkbenchWindow().getWorkbench().getThemeManager().removePropertyChangeListener(fontChangeListener);
+ if (memory != null)
+ memory.deregisterCellModifiedListener(memListener);
+ super.dispose();
+ }
+}
\ No newline at end of file
--- /dev/null
+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());
+ }
+}
--- /dev/null
+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());
+ }
+}
+++ /dev/null
-package net.mograsim.plugin.editors;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.util.Collection;
-import java.util.HashSet;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.util.IPropertyChangeListener;
-import org.eclipse.jface.util.SafeRunnable;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.ScrollBar;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IFileEditorInput;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.part.EditorPart;
-import org.eclipse.ui.themes.ITheme;
-import org.eclipse.ui.themes.IThemeManager;
-
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
-import net.mograsim.machine.standard.memory.MainMemoryParser;
-import net.mograsim.plugin.asm.AsmNumberUtil;
-import net.mograsim.plugin.nature.MachineContext;
-import net.mograsim.plugin.nature.ProjectMachineContext;
-import net.mograsim.plugin.tables.AddressLabelProvider;
-import net.mograsim.plugin.tables.DisplaySettings;
-import net.mograsim.plugin.tables.LazyTableViewer;
-import net.mograsim.plugin.tables.NumberColumnLabelProvider;
-import net.mograsim.plugin.tables.RadixSelector;
-import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
-import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
-import net.mograsim.plugin.tables.memory.MemoryTableRow;
-import net.mograsim.plugin.tables.memory.NumberVerifyListener;
-
-public class MemoryEditor extends EditorPart
-{
- private MachineContext context;
-
- private MainMemory memory;
-
- private LazyTableViewer viewer;
- private MemoryTableContentProvider provider;
- private DisplaySettings displaySettings;
-
- private Collection<Control> fontDependent = new HashSet<>();
-
- private boolean dirty;
-
- private final MemoryCellModifiedListener memListener;
-
- private final static String font = "net.mograsim.plugin.memory.table_font";
- private IPropertyChangeListener fontChangeListener;
-
- public MemoryEditor()
- {
- memListener = this::cellModified;
- }
-
- @Override
- public void createPartControl(Composite parent)
- {
- provider = new MemoryTableContentProvider();
- displaySettings = new DisplaySettings();
-
- parent.setLayout(new GridLayout(8, false));
- createHeader(parent);
- createViewer(parent);
-
- displaySettings.addObserver(() -> viewer.refresh());
- }
-
- @SuppressWarnings("unused") // RadixSelector and exceptions
- private void createHeader(Composite parent)
- {
- Text gotoText = new Text(parent, SWT.BORDER);
- gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
- NumberVerifyListener vl = new NumberVerifyListener();
- gotoText.addVerifyListener(vl);
- gotoText.setText("0");
-
- Runnable gotoAction = () ->
- {
- try
- {
- loadAround((int) (AsmNumberUtil.valueOf(gotoText.getText()).longValue() - provider.getLowerBound()));
- viewer.getTable().deselectAll();
- }
- catch (NumberFormatException x)
- {
- // Nothing to do here
- }
- };
-
- gotoText.addTraverseListener((e) ->
- {
- if (e.detail == SWT.TRAVERSE_RETURN)
- gotoAction.run();
- });
-
- Button gotoButton = new Button(parent, SWT.PUSH);
- gotoButton.setText("Go to");
- gotoButton.addListener(SWT.Selection, e ->
- {
- gotoAction.run();
- });
-
- new Label(parent, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-
- new RadixSelector(parent, displaySettings);
- }
-
- private void createViewer(Composite parent)
- {
- viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
- fontDependent.add(viewer.getTable());
- createColumns();
- Table table = viewer.getTable();
- table.setHeaderVisible(true);
- table.setLinesVisible(true);
- viewer.setUseHashlookup(true);
- viewer.setContentProvider(provider);
- getSite().setSelectionProvider(viewer);
- viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 8, 1));
-
- // TODO: Also support keyboard inputs for flexible scrolling
- ScrollBar vBar = table.getVerticalBar();
- vBar.addListener(SWT.Selection, (e) ->
- {
- int sel;
- if ((sel = vBar.getSelection()) < vBar.getMinimum() + vBar.getThumb() * 2 || sel > vBar.getMaximum() - vBar.getThumb() * 2)
- {
- loadAround(table.getTopIndex());
- table.deselectAll();
- }
- });
-
- IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
- themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
- {
- if (IThemeManager.CHANGE_CURRENT_THEME.equals(e.getProperty()) || font.equals(e.getProperty()))
- {
- updateFont(themeManager.getCurrentTheme());
- viewer.refresh();
- }
- });
- updateFont(themeManager.getCurrentTheme());
-
- if (memory != null)
- viewer.setInput(memory);
- }
-
- private void updateFont(ITheme theme)
- {
- Font newFont = theme.getFontRegistry().get(font);
- // TODO: This is a quick fix! Still have to figure out why the CellEditors do not get the appropriate Font on their own
- fontDependent.forEach(c -> c.setFont(newFont));
- }
-
- private void loadAround(int row)
- {
- long prevLb = provider.getLowerBound();
- long address = prevLb + row;
- long actualLb = Long.max(address - MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMinimalAddress());
-
- long prevHb = provider.getUpperBound();
- // +- 1 row is not really important
- long actualHb = Long.min(address + MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMaximalAddress());
-
- if (actualLb != prevLb || actualHb != prevHb)
- {
- Table table = viewer.getTable();
- provider.setBounds(actualLb, actualHb);
- int rowIndex = (int) (address - actualLb);
- if (rowIndex >= 0 && rowIndex < table.getItemCount())
- table.showItem(table.getItem(rowIndex));
- viewer.refresh();
- }
- }
-
- private void createColumns()
- {
- TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
- addrCol.setLabelProvider(new AddressLabelProvider());
-
- TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
- dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
- {
- @Override
- public BigInteger getAsBigInteger(Object element)
- {
- MemoryTableRow row = (MemoryTableRow) element;
- return row.getMemory().getCellAsBigInteger(row.address);
- }
-
- @Override
- public int getBitLength(Object element)
- {
- return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
- }
- });
- MemoryCellEditingSupport eSup;
- dataCol.setEditingSupport(eSup = new MemoryCellEditingSupport(viewer, displaySettings));
- fontDependent.add(eSup.getCellEditorControl());
- }
-
- private TableViewerColumn createTableViewerColumn(String title, int width)
- {
- TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
- TableColumn column = viewerColumn.getColumn();
- column.setText(title);
- column.setWidth(width);
- column.setResizable(true);
- column.setMoveable(false);
- return viewerColumn;
- }
-
- @Override
- public void init(IEditorSite site, IEditorInput input) throws PartInitException
- {
- if (input instanceof IFileEditorInput)
- {
- IFileEditorInput fileInput = (IFileEditorInput) input;
- context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
-
- setPartName(fileInput.getName());
- try
- {
- open(fileInput.getFile());
- }
- catch (Exception e)
- {
- throw new PartInitException("Failed to read input!", e);
- }
- } else
- throw new IllegalArgumentException("MemoryEditor can only be used with Files");
-
- setSite(site);
- setInput(input);
- }
-
- @Override
- public void doSave(IProgressMonitor monitor)
- {
- IEditorInput input = getEditorInput();
- if (input instanceof IFileEditorInput)
- SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
- }
-
- private void save(IFile file, IProgressMonitor monitor) throws CoreException, IOException
- {
- if (memory == null)
- {
- throw new MicroInstructionMemoryParseException("Failed to write MainMemory to File. No MainMemory assigned.");
- }
- try (InputStream toWrite = MainMemoryParser.write(memory))
- {
- file.setContents(toWrite, 0, monitor);
- setDirty(false);
- }
- }
-
- private void open(IFile file) throws IOException, CoreException
- {
- MainMemoryDefinition memDef = context.getMachineDefinition()
- .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition();
- memory = MainMemoryParser.parseMemory(memDef, file.getContents());
- memory.registerCellModifiedListener(memListener);
- if (viewer != null)
- viewer.setInput(memory);
- }
-
- private void cellModified(@SuppressWarnings("unused") long address)
- {
- setDirty(true);
- }
-
- private void setDirty(boolean newDirty)
- {
- dirty = newDirty;
- firePropertyChange(PROP_DIRTY);
- }
-
- @Override
- public void doSaveAs()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isDirty()
- {
- return dirty;
- }
-
- @Override
- public boolean isSaveAsAllowed()
- {
- return false;
- }
-
- @Override
- public void setFocus()
- {
- viewer.getTable().setFocus();
- }
-
- @Override
- public void dispose()
- {
- getSite().getWorkbenchWindow().getWorkbench().getThemeManager().removePropertyChangeListener(fontChangeListener);
- if (memory != null)
- memory.deregisterCellModifiedListener(memListener);
- super.dispose();
- }
-}
\ No newline at end of file
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;
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
private final LogicExecuter exec;
private final MachineThread thread;
private final IFile mpmFile;
+ private final Optional<IFile> mpromFile;
private final Optional<IFile> memFile;
private boolean running;
private final IResourceChangeListener resChangedListener;
- public MachineDebugTarget(ILaunch launch, IFile mpmFile, Optional<IFile> memFile, MachineDefinition machineDefinition)
- throws CoreException
+ public MachineDebugTarget(ILaunch launch, IFile mpmFile, Optional<IFile> mpromFile, Optional<IFile> memFile,
+ MachineDefinition machineDefinition) throws CoreException
{
this.launch = launch;
this.machine = machineDefinition.createNew();
this.executionSpeedListeners = new ArrayList<>();
this.mpmFile = mpmFile;
+ this.mpromFile = mpromFile;
this.memFile = memFile;
assignMicroInstructionMemory();
+ assignMPROM();
assignMainMemory();
exec.startLiveExecution();
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())
}
}
+ private void assignMPROM() throws CoreException
+ {
+ assignMemory(mpromFile, machine.getMPROM(), machine.getDefinition().getMPROMDefinition(), StandardMPROM::new, "MPROM");
+ }
+
private void assignMainMemory() throws CoreException
+ {
+ assignMemory(memFile, machine.getMainMemory(), machine.getDefinition().getMainMemoryDefinition(), StandardMainMemory::new,
+ "initial RAM");
+ }
+
+ private static <D extends BitVectorMemoryDefinition, M extends BitVectorMemory> void assignMemory(Optional<IFile> memFile,
+ AbstractAssignableBitVectorMemory<M> memoryToAssign, D definition, Function<D, M> newMemory, String type) throws CoreException
{
if (memFile.isPresent())
{
try (InputStream initialRAMStream = memFile.get().getContents())
{
- machine.getMainMemory()
- .bind(MainMemoryParser.parseMemory(machine.getDefinition().getMainMemoryDefinition(), initialRAMStream));
+ M mem = newMemory.apply(definition);
+ BitVectorBasedMemoryParser.parseMemory(mem, initialRAMStream);
+ memoryToAssign.bind(mem);
}
catch (IOException e)
{
throw new CoreException(
- new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading initial RAM file", e));
+ new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Unexpected IO exception reading " + type + " file", e));
}
}
}
return mpmFile;
}
+ public Optional<IFile> getMPROMFile()
+ {
+ return mpromFile;
+ }
+
public Optional<IFile> getMEMFile()
{
return memFile;
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;
{
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
{
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))
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)
MachineContext machineContext = ProjectMachineContext.getMachineContextOf(project);
MachineDefinition machineDefinition = machineContext.getMachineDefinition().orElseThrow();
- mpmFile = project.getFile(configuration.getAttribute(MPM_FILE_ATTR, ""));
-
- String initialRAMFileName = configuration.getAttribute(INITIAL_RAM_FILE_ATTR, "");
- Optional<IFile> memFile = Optional.empty();
- if (!"".equals(initialRAMFileName))
- {
- memFile = Optional.of(project.getFile(initialRAMFileName));
- }
- MachineDebugTarget debugTarget = new MachineDebugTarget(launch, mpmFile, memFile, machineDefinition);
+ IFile mpmFile = project.getFile(configuration.getAttribute(MPM_FILE_ATTR, ""));
+ Optional<IFile> mpromFile = fileOptional(project, configuration.getAttribute(MPROM_FILE_ATTR, ""));
+ Optional<IFile> memFile = fileOptional(project, configuration.getAttribute(INITIAL_RAM_FILE_ATTR, ""));
+ MachineDebugTarget debugTarget = new MachineDebugTarget(launch, mpmFile, mpromFile, memFile, machineDefinition);
// TODO make selectable whether the machine starts paused or not
debugTarget.suspend();
debugTarget.setExecutionSpeed(1);
- machine = debugTarget.getMachine();
+ Machine machine = debugTarget.getMachine();
machine.reset();
// Add the default Mograsim memory block to make it less confusing and more comfortable.
.addMemoryBlocks(new IMemoryBlock[] { new MainMemoryBlockExtension(debugTarget, "0", null) });
}
+ private static Optional<IFile> fileOptional(IProject project, String filename)
+ {
+ if ("".equals(filename))
+ return Optional.empty();
+ return Optional.of(project.getFile(filename));
+ }
+
}
\ No newline at end of file
{
private Text projSelText;
private Text mpmFileSelText;
+ private Text mpromFileSelText;
private Text initialRAMFileSelText;
@Override
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);
}
private String chooseMograsimProject()
{
+ // TODO this seems very ugly, especially hardcoded width/height
WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
{
@Override
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)
{
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, ""));
}
{
String projName = projSelText.getText().trim();
String mpmFileName = mpmFileSelText.getText().trim();
+ String mpromFileName = mpromFileSelText.getText().trim();
String initialRAMFileName = initialRAMFileSelText.getText().trim();
Set<IResource> associatedResources = new HashSet<>();
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);
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);
}
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)
{
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));
}
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
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
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);
package net.mograsim.plugin.tables.memory;
-import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.BitVectorMemory;
import net.mograsim.plugin.tables.TableRow;
-public class MemoryTableRow extends TableRow<MainMemory>
+public class MemoryTableRow extends TableRow<BitVectorMemory>
{
- public MemoryTableRow(long address, MainMemory memory)
+ public MemoryTableRow(long address, BitVectorMemory memory)
{
super(address, memory);
}
- public MainMemory getMemory()
+ public BitVectorMemory getMemory()
{
return getData();
}
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;
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
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)
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigInteger;
+import java.util.Random;
+import java.util.stream.LongStream;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import net.mograsim.logic.core.timeline.Timeline;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.wires.CoreWire;
+import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.StandardMainMemory;
+
+class MainMemoryTest
+{
+
+ private Timeline t = new Timeline(10);
+
+ @ParameterizedTest(name = "seed = {0}")
+ @MethodSource("seedsForRandom")
+ public void wordAddressableMemoryLargeTest(long seed)
+ {
+ CoreWire rW = new CoreWire(t, 1, 2);
+ CoreWire data = new CoreWire(t, 16, 2);
+ CoreWire address = new CoreWire(t, 64, 2);
+ ReadWriteEnd rWI = rW.createReadWriteEnd();
+ ReadWriteEnd dataI = data.createReadWriteEnd();
+ ReadWriteEnd addressI = address.createReadWriteEnd();
+
+ MainMemoryDefinition definition = MainMemoryDefinition.create(64, 16, 4096L, Long.MAX_VALUE);
+ CoreBitVectorMemory<MainMemory> memory = new CoreBitVectorMemory<>(t, 4, definition, data.createReadWriteEnd(),
+ rW.createReadOnlyEnd(), address.createReadOnlyEnd(), false);
+ memory.setMemory(new StandardMainMemory(definition));
+
+ Random r = new Random(seed);
+ for (long j = 1; j > 0; j *= 2)
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ BitVector bAddress = BitVector.from(4096 + i + j, 64);
+ addressI.feedSignals(bAddress);
+ t.executeAll();
+ BigInteger random = BigInteger.valueOf(Math.abs(r.nextInt()));
+ BitVector vector = BitVector.from(random, 16);
+ dataI.feedSignals(vector);
+ rWI.feedSignals(Bit.ZERO);
+ t.executeAll();
+ rWI.feedSignals(Bit.ONE);
+ t.executeAll();
+ dataI.clearSignals();
+ t.executeAll();
+
+ assertEquals(vector, dataI.getValues(), "seed=" + seed + ", j=" + j + ", i=" + i);
+ }
+ }
+ }
+
+ public static LongStream seedsForRandom()
+ {
+ return LongStream.range(0, 20);
+ }
+}
+++ /dev/null
-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);
- }
-}