Made MemoryView to an Editor
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Thu, 26 Sep 2019 16:16:11 +0000 (18:16 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Thu, 26 Sep 2019 16:16:32 +0000 (18:16 +0200)
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/plugin.xml
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java [deleted file]

index f0bbb22..ac1b237 100644 (file)
@@ -12,7 +12,6 @@ import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
 import net.mograsim.machine.Machine;
 import net.mograsim.machine.MachineDefinition;
-import net.mograsim.machine.MainMemory;
 import net.mograsim.machine.Register;
 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 import net.mograsim.machine.mi.MicroInstruction;
@@ -20,6 +19,7 @@ import net.mograsim.machine.mi.MicroInstructionDefinition;
 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.AssignableMainMemory;
 import net.mograsim.machine.standard.memory.WordAddressableMemory;
 
 public class Am2900Machine implements Machine
@@ -28,7 +28,7 @@ public class Am2900Machine implements Machine
        private LogicModelModifiable logicModel;
        private ModelComponent am2900;
        private Timeline timeline;
-       private MainMemory mainMemory;
+       private AssignableMainMemory mainMemory;
        private AssignableMicroInstructionMemory instMemory;
        private CoreClock clock;
 
@@ -41,7 +41,7 @@ public class Am2900Machine implements Machine
                CoreModelParameters params = new CoreModelParameters();
                params.gateProcessTime = 50;
                params.wireTravelTime = 10;
-               mainMemory = new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition());
+               mainMemory = new AssignableMainMemory(new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition()));
                instMemory = new AssignableMicroInstructionMemory(
                                new StandardMicroInstructionMemory(am2900MachineDefinition.getMicroInstructionMemoryDefinition()));
                timeline = LogicCoreAdapter.convert(logicModel, params);
@@ -105,7 +105,7 @@ public class Am2900Machine implements Machine
        }
 
        @Override
-       public MainMemory getMainMemory()
+       public AssignableMainMemory getMainMemory()
        {
                return mainMemory;
        }
index f9d851d..df99984 100644 (file)
@@ -5,6 +5,7 @@ import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.logic.model.model.LogicModel;
 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
+import net.mograsim.machine.standard.memory.AssignableMainMemory;
 
 public interface Machine
 {
@@ -22,8 +23,7 @@ public interface Machine
 
        Timeline getTimeline();
 
-       MainMemory getMainMemory();
+       AssignableMainMemory getMainMemory();
 
        AssignableMicroInstructionMemory getMicroInstructionMemory();
-
-}
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/AssignableMainMemory.java
new file mode 100644 (file)
index 0000000..38b17ab
--- /dev/null
@@ -0,0 +1,105 @@
+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);
+       }
+}
index 965c260..79cd428 100644 (file)
             name="Registers / Latches state"
             priority="high">
       </content-type>
+      <content-type
+            base-type="org.eclipse.core.runtime.text"
+            default-charset="UTF-8"
+            file-extensions="mem"
+            id="net.mograsim.plugin.mem"
+            name="Main Memory"
+            priority="high">
+      </content-type>
    </extension>
    <extension
          point="org.eclipse.ui.menus">
             name="Simulation View Editor">
                <contentTypeBinding contentTypeId="net.mograsim.plugin.regs"/>
       </editor>
+      <editor
+            class="net.mograsim.plugin.editors.MemoryEditor"
+            icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+            id="net.mograsim.plugin.editors.memoryeditor"
+            name="Memory Editor">
+         <contentTypeBinding
+               contentTypeId="net.mograsim.plugin.mem">
+         </contentTypeBinding>
+      </editor>
    </extension>
    <extension
          point="org.eclipse.ui.genericeditor.presentationReconcilers">
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java
new file mode 100644 (file)
index 0000000..2b02852
--- /dev/null
@@ -0,0 +1,242 @@
+package net.mograsim.plugin.editors;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+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.Label;
+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 net.mograsim.machine.MainMemory;
+import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
+import net.mograsim.machine.standard.memory.WordAddressableMemory;
+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;
+
+       @Override
+       public void createPartControl(Composite parent)
+       {
+               provider = new MemoryTableContentProvider();
+               displaySettings = new DisplaySettings();
+
+               parent.setLayout(new GridLayout(7, false));
+
+               createHeader(parent);
+               createViewer(parent);
+
+               displaySettings.addObserver(() -> viewer.refresh());
+       }
+
+       @SuppressWarnings("unused") // RadixSelector and exceptions
+       private void createHeader(Composite parent)
+       {
+               Label fromLabel = new Label(parent, SWT.NONE);
+               fromLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+               fromLabel.setText("Address: ");
+
+               Text fromText = new Text(parent, SWT.BORDER);
+               fromText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               NumberVerifyListener vl = new NumberVerifyListener();
+               fromText.addVerifyListener(vl);
+               fromText.setText("0");
+               fromText.addModifyListener(e ->
+               {
+                       try
+                       {
+                               provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
+                               viewer.refresh();
+                       }
+                       catch (NumberFormatException x)
+                       {
+                               // Nothing to do here
+                       }
+               });
+               Label amountLabel = new Label(parent, SWT.NONE);
+               amountLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+               amountLabel.setText("Number of cells: ");
+               Text amountText = new Text(parent, SWT.BORDER);
+               amountText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               amountText.addVerifyListener(vl);
+               amountText.setText("0");
+               amountText.addModifyListener(e ->
+               {
+                       try
+                       {
+                               provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
+                               viewer.refresh();
+                       }
+                       catch (NumberFormatException x)
+                       {
+                               // Nothing to do here
+                       }
+               });
+               new RadixSelector(parent, displaySettings);
+
+               addActivationButton(parent);
+       }
+
+       private void addActivationButton(Composite parent)
+       {
+               Button activationButton = new Button(parent, SWT.PUSH);
+               activationButton.setText("Set Active");
+               activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m -> m.getMainMemory().bind(memory)));
+       }
+
+       private void createViewer(Composite parent)
+       {
+               viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+               createColumns();
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+               viewer.setUseHashlookup(true);
+               viewer.setContentProvider(provider);
+               getSite().setSelectionProvider(viewer);// TODO what does this?
+               viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 7, 1));
+               if (memory != null)
+                       viewer.setInput(memory);
+       }
+
+       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();
+                       }
+               });
+               dataCol.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
+       }
+
+       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());
+                       context.activateMachine();
+
+                       setPartName(fileInput.getName());
+                       open(fileInput.getFile());
+               } 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
+       {
+               file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
+       }
+
+       private void open(IFile file)
+       {
+               // TODO actually parse the file
+               memory = new WordAddressableMemory(context.getMachineDefinition()
+                               .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition());
+               if (viewer != null)
+                       viewer.setInput(memory);
+       }
+
+       @Override
+       public void doSaveAs()
+       {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public boolean isDirty()
+       {
+               // TODO
+               return false;
+       }
+
+       @Override
+       public boolean isSaveAsAllowed()
+       {
+               return false;
+       }
+
+       @Override
+       public void setFocus()
+       {
+               viewer.getTable().setFocus();
+       }
+
+       @Override
+       public void dispose()
+       {
+               // TODO Auto-generated method stub
+               super.dispose();
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryView.java
deleted file mode 100644 (file)
index e490bd0..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-package net.mograsim.plugin.tables.memory;
-
-import java.math.BigInteger;
-import java.util.Optional;
-
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.VerifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.part.ViewPart;
-
-import net.mograsim.machine.Machine;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.standard.memory.WordAddressableMemory;
-import net.mograsim.plugin.MachineContext;
-import net.mograsim.plugin.MachineContext.ContextObserver;
-import net.mograsim.plugin.asm.AsmNumberUtil;
-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;
-
-public class MemoryView extends ViewPart implements ContextObserver
-{
-       private LazyTableViewer viewer;
-       private MemoryTableContentProvider provider;
-       private DisplaySettings displaySettings;
-
-       @Override
-       public void createPartControl(Composite parent)
-       {
-               provider = new MemoryTableContentProvider();
-               displaySettings = new DisplaySettings();
-
-               GridLayout layout = new GridLayout(6, false);
-               parent.setLayout(layout);
-
-               createHeader(parent);
-               createViewer(parent);
-
-               displaySettings.addObserver(() -> viewer.refresh());
-
-               setupContextBinding();
-       }
-
-       @SuppressWarnings("unused")
-       private void createHeader(Composite parent)
-       {
-               Label fromLabel = new Label(parent, SWT.NONE);
-               fromLabel.setText("Address: ");
-               Text fromText = new Text(parent, SWT.BORDER | SWT.SEARCH);
-               fromText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
-               VerifyListener vl = new NumberVerifyListener();
-               fromText.addVerifyListener(vl);
-               fromText.setText("0");
-               fromText.addModifyListener(e ->
-               {
-                       try
-                       {
-                               provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
-                               viewer.refresh();
-                       }
-                       catch (NumberFormatException ex)
-                       {
-                               // Nothing to do here
-                       }
-               });
-
-               Label amountLabel = new Label(parent, SWT.NONE);
-               amountLabel.setText("Number of cells: ");
-               Text amountText = new Text(parent, SWT.BORDER | SWT.SEARCH);
-               amountText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
-               amountText.addVerifyListener(vl);
-               amountText.setText("0");
-               amountText.addModifyListener(e ->
-               {
-                       try
-                       {
-                               provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
-                               viewer.refresh();
-                       }
-                       catch (NumberFormatException ex)
-                       {
-                               // Nothing to do here
-                       }
-               });
-               new RadixSelector(parent, displaySettings);
-       }
-
-       private void createViewer(Composite parent)
-       {
-               viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
-               createColumns();
-               Table table = viewer.getTable();
-               table.setHeaderVisible(true);
-               table.setLinesVisible(true);
-               viewer.setUseHashlookup(true);
-               viewer.setContentProvider(provider);
-               bindMainMemory(new WordAddressableMemory(MainMemoryDefinition.create(8, 8, 8L, Long.MAX_VALUE)));
-               getSite().setSelectionProvider(viewer);
-
-               GridData gd = new GridData();
-               gd.verticalAlignment = GridData.FILL;
-               gd.horizontalSpan = 6;
-               gd.grabExcessHorizontalSpace = true;
-               gd.grabExcessVerticalSpace = true;
-               gd.horizontalAlignment = GridData.FILL;
-               viewer.getControl().setLayoutData(gd);
-       }
-
-       private void createColumns()
-       {
-               String[] titles = { "Address", "Data" };
-               int[] bounds = { 100, 100 };
-
-               TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0]);
-               col.setLabelProvider(new AddressLabelProvider());
-
-               col = createTableViewerColumn(titles[1], bounds[1]);
-               col.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
-               {
-                       @Override
-                       public BigInteger getAsBigInteger(Object element)
-                       {
-                               MemoryTableRow row = (MemoryTableRow) element;
-                               return row.getMemory().getCellAsBigInteger(row.address);
-                       }
-
-                       @Override
-                       public int getBitLength(Object element)
-                       {
-                               return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
-                       }
-
-               });
-               col.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
-       }
-
-       private TableViewerColumn createTableViewerColumn(String title, int bound)
-       {
-               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
-               TableColumn column = viewerColumn.getColumn();
-               column.setText(title);
-               column.setWidth(bound);
-               column.setResizable(true);
-               column.setMoveable(false);
-               return viewerColumn;
-       }
-
-       @Override
-       public void setFocus()
-       {
-               viewer.getControl().setFocus();
-       }
-
-       private void bindMainMemory(MainMemory m)
-       {
-               viewer.setInput(m);
-       }
-
-       private void setupContextBinding()
-       {
-               MachineContext.getInstance().registerObserver(this);
-               setMachine(Optional.ofNullable(MachineContext.getInstance().getMachine()));
-       }
-
-       @Override
-       public void setMachine(Optional<Machine> machine)
-       {
-               if (machine.isPresent())
-                       bindMainMemory(machine.get().getMainMemory());
-       }
-}