Added active instruction preview to LogicUIPart
authorFabian Stemmler <stemmler@in.tum.de>
Wed, 18 Sep 2019 20:15:02 +0000 (22:15 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Wed, 18 Sep 2019 20:15:02 +0000 (22:15 +0200)
16 files changed:
plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/Memory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryObserver.java [deleted file]
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/LazyTableViewer.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ActiveInstructionPreviewContentProvider.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTable.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableLazyContentProvider.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/views/LogicUIPart.java

index 8052014..40873f0 100644 (file)
@@ -10,7 +10,7 @@ public abstract class GenericMemory<T> implements Memory<T>
        private final long minimalAddress, maximalAddress;
        private final MemoryDefinition definition;
        private final int pageSize = 64;
-       private Set<MemoryObserver> observers = new HashSet<>();
+       private Set<MemoryCellModifiedListener> observers = new HashSet<>();
 
        private HashMap<Long, Page> pages;
 
@@ -94,19 +94,18 @@ public abstract class GenericMemory<T> implements Memory<T>
        }
 
        @Override
-       public void registerObserver(MemoryObserver ob)
+       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.add(ob);
        }
 
        @Override
-       public void deregisterObserver(MemoryObserver ob)
+       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.remove(ob);
        }
 
-       @Override
-       public void notifyObservers(long address)
+       protected void notifyObservers(long address)
        {
                observers.forEach(ob -> ob.update(address));
        }
index 0ff9bb4..4f0e58f 100644 (file)
@@ -26,11 +26,15 @@ public interface Memory<T>
        /**
         * Registers an observer to be notified when a memory cell is modified
         */
-       public void registerObserver(MemoryObserver ob);
+       public void registerCellModifiedListener(MemoryCellModifiedListener ob);
 
-       public void deregisterObserver(MemoryObserver ob);
-
-       public void notifyObservers(long address);
+       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob);
 
        public MemoryDefinition getDefinition();
+
+       public static interface MemoryCellModifiedListener
+       {
+               public void update(long address);
+       }
+
 }
diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryObserver.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryObserver.java
deleted file mode 100644 (file)
index 1d7fc4d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package net.mograsim.machine;
-
-public interface MemoryObserver
-{
-       public void update(long address);
-}
index b0ab5a4..a366ae0 100644 (file)
@@ -3,25 +3,31 @@ package net.mograsim.machine.mi;
 import java.util.HashSet;
 import java.util.Set;
 
-import net.mograsim.machine.MemoryObserver;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
 
-public class AssignableMicroInstructionMemory implements MicroInstructionMemory, MemoryObserver
+public class AssignableMicroInstructionMemory
+               implements MicroInstructionMemory, MemoryCellModifiedListener, ActiveMicroInstructionChangedListener
 {
-       private Set<MemoryObserver> observers = new HashSet<>();
-       MicroInstructionMemory real = null;
+
+       private Set<MemoryCellModifiedListener> observers = new HashSet<>();
+       private Set<ActiveMicroInstructionChangedListener> activeInstructionListeners = new HashSet<>();
+       private Set<MIMemoryReassignedListener> reassignmentListeners = new HashSet<>();
+       private MicroInstructionMemory real = null;
 
        public AssignableMicroInstructionMemory(StandardMicroInstructionMemory standardMicroInstructionMemory)
        {
                real = standardMicroInstructionMemory;
-               real.registerObserver(this);
+               real.registerCellModifiedListener(this);
        }
 
        public void bind(MicroInstructionMemory real)
        {
-               this.real.deregisterObserver(this);
+               this.real.deregisterCellModifiedListener(this);
                this.real = real;
-               real.registerObserver(this);
-               notifyObservers(-1);
+               real.registerCellModifiedListener(this);
+               notifyMemoryChanged(-1);
+               notifyMemoryReassigned(real);
        }
 
        @Override
@@ -37,23 +43,39 @@ public class AssignableMicroInstructionMemory implements MicroInstructionMemory,
        }
 
        @Override
-       public void registerObserver(MemoryObserver ob)
+       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.add(ob);
        }
 
        @Override
-       public void deregisterObserver(MemoryObserver ob)
+       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.remove(ob);
        }
 
        @Override
-       public void notifyObservers(long address)
+       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
+       {
+               activeInstructionListeners.add(ob);
+       }
+
+       @Override
+       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
+       {
+               activeInstructionListeners.remove(ob);
+       }
+
+       private void notifyMemoryChanged(long address)
        {
                observers.forEach(o -> o.update(address));
        }
 
+       private void notifyActiveInstructionChanged(long address)
+       {
+               activeInstructionListeners.forEach(o -> o.activeMicroInstructionChanged(address));
+       }
+
        @Override
        public MicroInstructionMemoryDefinition getDefinition()
        {
@@ -63,6 +85,38 @@ public class AssignableMicroInstructionMemory implements MicroInstructionMemory,
        @Override
        public void update(long address)
        {
-               notifyObservers(address);
+               notifyMemoryChanged(address);
+       }
+
+       @Override
+       public void setActiveInstruction(long address)
+       {
+               real.setActiveInstruction(address);
+       }
+
+       @Override
+       public void activeMicroInstructionChanged(long address)
+       {
+               notifyActiveInstructionChanged(address);
+       }
+
+       public void registerMemoryReassignedListener(MIMemoryReassignedListener listener)
+       {
+               reassignmentListeners.add(listener);
+       }
+
+       public void deregisterMemoryReassignedListener(MIMemoryReassignedListener listener)
+       {
+               reassignmentListeners.remove(listener);
+       }
+
+       private void notifyMemoryReassigned(MicroInstructionMemory newAssignee)
+       {
+               reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
+       }
+
+       public static interface MIMemoryReassignedListener
+       {
+               public void reassigned(MicroInstructionMemory newAssignee);
        }
 }
index 6409f78..abfed46 100644 (file)
@@ -6,4 +6,15 @@ public interface MicroInstructionMemory extends Memory<MicroInstruction>
 {
        @Override
        public MicroInstructionMemoryDefinition getDefinition();
+
+       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob);
+
+       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob);
+
+       public void setActiveInstruction(long address);
+
+       public static interface ActiveMicroInstructionChangedListener
+       {
+               public void activeMicroInstructionChanged(long address);
+       }
 }
index 7ef53d9..94905a5 100644 (file)
@@ -1,15 +1,17 @@
 package net.mograsim.machine.mi;
 
 import java.util.HashSet;
+import java.util.Set;
 
-import net.mograsim.machine.MemoryObserver;
 import net.mograsim.machine.standard.memory.MemoryException;
 
 public class StandardMicroInstructionMemory implements MicroInstructionMemory
 {
        private MicroInstruction[] data;
        private MicroInstructionMemoryDefinition definition;
-       private HashSet<MemoryObserver> observers = new HashSet<>();
+       private HashSet<MemoryCellModifiedListener> observers = new HashSet<>();
+       private Set<ActiveMicroInstructionChangedListener> activeInstructionListeners = new HashSet<>();
+       private long activeInstruction = -1;
 
        public StandardMicroInstructionMemory(MicroInstructionMemoryDefinition definition)
        {
@@ -38,31 +40,57 @@ public class StandardMicroInstructionMemory implements MicroInstructionMemory
        public void setCell(long address, MicroInstruction data)
        {
                this.data[translate(address)] = data;
-               notifyObservers(address);
+               notifyMemoryChanged(address);
        }
 
        @Override
-       public void registerObserver(MemoryObserver ob)
+       public void registerCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.add(ob);
        }
 
        @Override
-       public void deregisterObserver(MemoryObserver ob)
+       public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
        {
                observers.remove(ob);
        }
 
        @Override
-       public void notifyObservers(long address)
+       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
+       {
+               activeInstructionListeners.add(ob);
+       }
+
+       @Override
+       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
+       {
+               activeInstructionListeners.remove(ob);
+       }
+
+       private void notifyMemoryChanged(long address)
        {
                observers.forEach(ob -> ob.update(address));
        }
 
+       private void notifyActiveInstructionChanged(long address)
+       {
+               activeInstructionListeners.forEach(o -> o.activeMicroInstructionChanged(address));
+       }
+
        @Override
        public MicroInstructionMemoryDefinition getDefinition()
        {
                return definition;
        }
 
+       @Override
+       public void setActiveInstruction(long address)
+       {
+               if (address != activeInstruction)
+               {
+                       activeInstruction = address;
+                       notifyActiveInstructionChanged(address);
+               }
+       }
+
 }
index aacc243..b01802c 100644 (file)
@@ -9,7 +9,7 @@ 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.MemoryObserver;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 import net.mograsim.machine.mi.MicroInstructionMemory;
 import net.mograsim.machine.mi.MicroInstructionMemoryDefinition;
 
@@ -18,7 +18,7 @@ public class CoreMicroInstructionMemory extends BasicCoreComponent
        private final ReadWriteEnd data;
        private final ReadEnd address;
        private final MicroInstructionMemoryDefinition definition;
-       private final MemoryObserver memObs;
+       private final MemoryCellModifiedListener memObs;
        private MicroInstructionMemory memory;
 
        public CoreMicroInstructionMemory(Timeline timeline, int processTime, MicroInstructionMemoryDefinition definition, ReadWriteEnd data,
@@ -46,10 +46,10 @@ public class CoreMicroInstructionMemory extends BasicCoreComponent
                if (memory != null && !memory.getDefinition().equals(definition))
                        throw new IllegalArgumentException("Memory of incorrect memory definition given");
                if (this.memory != null)
-                       this.memory.registerObserver(memObs);
+                       this.memory.registerCellModifiedListener(memObs);
                this.memory = memory;
                if (memory != null)
-                       memory.registerObserver(memObs);
+                       memory.registerCellModifiedListener(memObs);
                update();
        }
 
@@ -77,6 +77,7 @@ public class CoreMicroInstructionMemory extends BasicCoreComponent
                        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).toBitVector();
+               memory.setActiveInstruction(addressed);
                return e -> data.feedSignals(storedData);
        }
 }
\ No newline at end of file
index e7249b9..801895b 100644 (file)
@@ -11,7 +11,7 @@ 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.MemoryObserver;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 
 /**
  * A memory component that only allows access to words of a specific width
@@ -22,7 +22,7 @@ public class CoreWordAddressableMemory extends BasicCoreComponent
 
        private ReadWriteEnd data;
        private ReadEnd rWBit, address;
-       private final MemoryObserver memObs;
+       private final MemoryCellModifiedListener memObs;
        private final MainMemoryDefinition definition;
        private MainMemory memory;
 
@@ -62,10 +62,10 @@ public class CoreWordAddressableMemory extends BasicCoreComponent
                if (memory != null && !memory.getDefinition().equals(definition))
                        throw new IllegalArgumentException("Memory of incorrect memory definition given");
                if (this.memory != null)
-                       this.memory.registerObserver(memObs);
+                       this.memory.registerCellModifiedListener(memObs);
                this.memory = memory;
                if (memory != null)
-                       memory.registerObserver(memObs);
+                       memory.registerCellModifiedListener(memObs);
                update();
        }
 
index 1b371e2..c448813 100644 (file)
@@ -34,7 +34,6 @@ public class LazyTableViewer extends TableViewer
                if (index < 0 || index >= table.getItemCount())
                        return;
                table.getItem(index).setBackground(highlight ? highlightColor : table.getBackground());
-               System.out.println("Infinite loop!!!");
                ((ILazyContentProvider) getContentProvider()).updateElement(index);
        }
 
index 95d1835..90ad788 100644 (file)
@@ -6,9 +6,9 @@ import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.swt.widgets.Display;
 
 import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MemoryObserver;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 
-public class MemoryTableContentProvider implements ILazyContentProvider, MemoryObserver
+public class MemoryTableContentProvider implements ILazyContentProvider, MemoryCellModifiedListener
 {
        private long lower;
        private TableViewer viewer;
@@ -65,9 +65,9 @@ public class MemoryTableContentProvider implements ILazyContentProvider, MemoryO
                this.viewer = (TableViewer) viewer;
                this.memory = (MainMemory) newInput;
                if (oldInput != null)
-                       ((MainMemory) oldInput).deregisterObserver(this);
+                       ((MainMemory) oldInput).deregisterCellModifiedListener(this);
                if (memory != null)
-                       memory.registerObserver(this);
+                       memory.registerCellModifiedListener(this);
                setLowerBound(0L);
        }
 
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ActiveInstructionPreviewContentProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ActiveInstructionPreviewContentProvider.java
new file mode 100644 (file)
index 0000000..604c285
--- /dev/null
@@ -0,0 +1,53 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+
+import net.mograsim.machine.mi.MicroInstructionMemory;
+import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
+
+public class ActiveInstructionPreviewContentProvider implements InstructionTableContentProvider, ActiveMicroInstructionChangedListener
+{
+       private TableViewer viewer;
+       private MicroInstructionMemory memory;
+       private InstructionTableRow activeRow;
+
+       public ActiveInstructionPreviewContentProvider(TableViewer viewer)
+       {
+               this.viewer = viewer;
+               viewer.setItemCount(1);
+       }
+
+       @Override
+       public void activeMicroInstructionChanged(long address)
+       {
+               this.activeRow = new InstructionTableRow(address, memory);
+               viewer.refresh();
+       }
+
+       @Override
+       public void update(long address)
+       {
+               // Nothing to do here
+       }
+
+       @Override
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+       {
+               if (oldInput != null)
+                       ((MicroInstructionMemory) oldInput).deregisterActiveMicroInstructionChangedListener(this);
+
+               memory = (MicroInstructionMemory) newInput;
+               if (memory != null)
+               {
+                       activeMicroInstructionChanged(0);
+                       memory.registerActiveMicroInstructionChangedListener(this);
+               }
+       }
+
+       @Override
+       public void updateElement(int index)
+       {
+               viewer.replace(activeRow, index);
+       }
+}
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTable.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTable.java
new file mode 100644 (file)
index 0000000..93179c0
--- /dev/null
@@ -0,0 +1,184 @@
+package net.mograsim.plugin.tables.mi;
+
+import java.util.Arrays;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.MicroInstructionMemory;
+import net.mograsim.machine.mi.parameters.MnemonicFamily;
+import net.mograsim.machine.mi.parameters.ParameterClassification;
+import net.mograsim.plugin.tables.AddressLabelProvider;
+import net.mograsim.plugin.tables.DisplaySettings;
+import net.mograsim.plugin.tables.LazyTableViewer;
+
+public class InstructionTable
+{
+       protected DisplaySettings displaySettings;
+       protected LazyTableViewer viewer;
+       private TableViewerColumn[] columns = new TableViewerColumn[0];
+       private MicroInstructionDefinition miDef;
+       private MicroInstructionMemory memory;
+       private InstructionTableContentProvider provider;
+
+       public InstructionTable(Composite parent, DisplaySettings displaySettings)
+       {
+               viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+               this.displaySettings = displaySettings;
+
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+               viewer.setUseHashlookup(true);
+
+               GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
+               viewerData.horizontalSpan = 3;
+               viewer.getTable().setLayoutData(viewerData);
+
+               displaySettings.addObserver(() -> viewer.refresh());
+       }
+
+       private void deleteColumns()
+       {
+               for (TableViewerColumn col : columns)
+                       col.getColumn().dispose();
+       }
+
+       private void createColumns()
+       {
+               int size = miDef.size();
+               columns = new TableViewerColumn[size + 1];
+
+               TableViewerColumn col = createTableViewerColumn("Address", generateLongestHexStrings(12));
+               columns[0] = col;
+               col.setLabelProvider(new AddressLabelProvider());
+
+               int bit = miDef.sizeInBits();
+               ParameterClassification[] classes = miDef.getParameterClassifications();
+
+               for (int i = 0; i < size; i++)
+               {
+                       int startBit = bit - 1;
+                       int endBit = bit = bit - classes[i].getExpectedBits();
+                       String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
+
+                       String[] longestPossibleContents;
+                       switch (classes[i].getExpectedType())
+                       {
+                       case INTEGER_IMMEDIATE:
+                               longestPossibleContents = generateLongestHexStrings(classes[i].getExpectedBits());
+                               break;
+                       case BOOLEAN_IMMEDIATE:
+                       case MNEMONIC:
+                               longestPossibleContents = ((MnemonicFamily) classes[i]).getStringValues();
+                               break;
+                       default:
+                               longestPossibleContents = new String[0];
+                               break;
+                       }
+
+                       col = createTableViewerColumn(name, longestPossibleContents);
+                       columns[i + 1] = col;
+                       createEditingAndLabel(col, miDef, i);
+               }
+       }
+
+       public void bindMicroInstructionMemory(MicroInstructionMemory memory)
+       {
+               this.memory = memory;
+               this.miDef = memory.getDefinition().getMicroInstructionDefinition();
+               setViewerInput(memory);
+       }
+
+       private static final String[] HEX_DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
+
+       private static String[] generateLongestHexStrings(int bitWidth)
+       {
+               return Arrays.stream(HEX_DIGITS).map(s -> "0x" + s.repeat((bitWidth + 3) / 4)).toArray(String[]::new);
+       }
+
+       private void createEditingAndLabel(TableViewerColumn col, MicroInstructionDefinition miDef, int index)
+       {
+               ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
+               EditingSupport support;
+               ColumnLabelProvider provider;
+               switch (parameterClassification.getExpectedType())
+               {
+               case BOOLEAN_IMMEDIATE:
+                       support = new BooleanEditingSupport(viewer, miDef, index);
+                       provider = new ParameterLabelProvider(index);
+                       break;
+               case INTEGER_IMMEDIATE:
+                       support = new IntegerEditingSupport(viewer, miDef, index, displaySettings, this.provider);
+                       provider = new IntegerColumnLabelProvider(displaySettings, index);
+                       break;
+               case MNEMONIC:
+                       support = new MnemonicEditingSupport(viewer, miDef, index, this.provider);
+                       provider = new ParameterLabelProvider(index);
+                       break;
+               default:
+                       throw new IllegalStateException(
+                                       "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
+               }
+               col.setEditingSupport(support);
+               col.setLabelProvider(provider);
+               col.getColumn().setToolTipText(miDef.getParameterDescription(index).orElse(""));
+       }
+
+       private TableViewerColumn createTableViewerColumn(String title, String... longestPossibleContents)
+       {
+               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+               TableColumn column = viewerColumn.getColumn();
+               int maxWidth = 0;
+               for (String s : longestPossibleContents)
+               {
+                       column.setText(s);
+                       column.pack();
+                       if (column.getWidth() > maxWidth)
+                               maxWidth = column.getWidth();
+               }
+               column.setText(title);
+               column.pack();
+               if (column.getWidth() < maxWidth)
+                       column.setWidth(maxWidth);
+               column.setResizable(true);
+               column.setMoveable(false);
+               return viewerColumn;
+       }
+
+       public LazyTableViewer getTableViewer()
+       {
+               return viewer;
+       }
+
+       public MicroInstructionMemory getMicroInstructionMemory()
+       {
+               return memory;
+       }
+
+       public void setContentProvider(InstructionTableContentProvider provider)
+       {
+               this.provider = provider;
+               viewer.setContentProvider(provider);
+       }
+
+       private void setViewerInput(MicroInstructionMemory memory)
+       {
+               deleteColumns();
+               viewer.setInput(memory);
+               createColumns();
+       }
+
+       public void refresh()
+       {
+               Display.getDefault().asyncExec(() -> viewer.refresh());
+       }
+}
index 6519b62..c82fbc7 100644 (file)
@@ -1,38 +1,8 @@
 package net.mograsim.plugin.tables.mi;
 
 import org.eclipse.jface.viewers.ILazyContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
 
-import net.mograsim.machine.mi.MicroInstructionMemory;
-
-public class InstructionTableContentProvider implements ILazyContentProvider
+public interface InstructionTableContentProvider extends ILazyContentProvider
 {
-       private TableViewer viewer;
-       private MicroInstructionMemory memory;
-       private long minAddr = 0;
-
-       @Override
-       public void updateElement(int index)
-       {
-               long address = memory.getDefinition().getMinimalAddress() + index;
-               viewer.replace(new InstructionTableRow(address, memory), index);
-       }
-
-       @Override
-       public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
-       {
-               this.viewer = (TableViewer) viewer;
-               this.memory = (MicroInstructionMemory) newInput;
-               if (this.memory != null)
-               {
-                       this.viewer.setItemCount((int) memory.size());
-                       this.minAddr = memory.getDefinition().getMinimalAddress();
-               }
-       }
-
-       public void update(long address)
-       {
-               updateElement((int) (address - minAddr));
-       }
+       public void update(long address);
 }
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableLazyContentProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableLazyContentProvider.java
new file mode 100644 (file)
index 0000000..94de0ae
--- /dev/null
@@ -0,0 +1,38 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+
+import net.mograsim.machine.mi.MicroInstructionMemory;
+
+public class InstructionTableLazyContentProvider implements InstructionTableContentProvider
+{
+       private TableViewer viewer;
+       private MicroInstructionMemory memory;
+       private long minAddr = 0;
+
+       @Override
+       public void updateElement(int index)
+       {
+               long address = memory.getDefinition().getMinimalAddress() + index;
+               viewer.replace(new InstructionTableRow(address, memory), index);
+       }
+
+       @Override
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+       {
+               this.viewer = (TableViewer) viewer;
+               this.memory = (MicroInstructionMemory) newInput;
+               if (this.memory != null)
+               {
+                       this.viewer.setItemCount((int) memory.size());
+                       this.minAddr = memory.getDefinition().getMinimalAddress();
+               }
+       }
+
+       @Override
+       public void update(long address)
+       {
+               updateElement((int) (address - minAddr));
+       }
+}
index 76d4a69..b21c848 100644 (file)
@@ -4,78 +4,72 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.EditingSupport;
-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.Display;
 import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.IPathEditorInput;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.EditorPart;
 
-import net.mograsim.machine.MemoryObserver;
-import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 import net.mograsim.machine.mi.MicroInstructionMemory;
+import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
-import net.mograsim.machine.mi.parameters.MnemonicFamily;
-import net.mograsim.machine.mi.parameters.ParameterClassification;
 import net.mograsim.plugin.MachineContext;
-import net.mograsim.plugin.tables.AddressLabelProvider;
 import net.mograsim.plugin.tables.DisplaySettings;
 import net.mograsim.plugin.tables.LazyTableViewer;
 import net.mograsim.plugin.tables.RadixSelector;
 
-public class InstructionView extends EditorPart implements MemoryObserver
+public class InstructionView extends EditorPart implements MemoryCellModifiedListener, ActiveMicroInstructionChangedListener
 {
-       private LazyTableViewer viewer;
-       private TableViewerColumn[] columns = new TableViewerColumn[0];
-       private MicroInstructionDefinition miDef;
-       private MicroInstructionMemory memory;
-       private DisplaySettings displaySettings;
        private InstructionTableContentProvider provider;
        private int highlighted = 0;
        private boolean dirty = false;
        private String machineName;
+       private MicroInstructionMemory memory;
+       private InstructionTable table;
 
        @SuppressWarnings("unused")
        @Override
        public void createPartControl(Composite parent)
        {
-               provider = new InstructionTableContentProvider();
+               provider = new InstructionTableLazyContentProvider();
                GridLayout layout = new GridLayout(3, false);
                parent.setLayout(layout);
 
-               displaySettings = new DisplaySettings();
+               DisplaySettings displaySettings = new DisplaySettings();
                new RadixSelector(parent, displaySettings);
 
                addActivationButton(parent);
-               viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
 
-               Table table = viewer.getTable();
-               table.setHeaderVisible(true);
-               table.setLinesVisible(true);
-               viewer.setUseHashlookup(true);
-               viewer.setContentProvider(provider);
-               setViewerInput(memory);
-               getSite().setSelectionProvider(viewer);
+               table = new InstructionTable(parent, displaySettings);
+               table.setContentProvider(provider);
+               table.bindMicroInstructionMemory(memory);
 
                GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
                viewerData.horizontalSpan = 3;
-               viewer.getTable().setLayoutData(viewerData);
+               table.getTableViewer().getTable().setLayoutData(viewerData);
+       }
 
-               displaySettings.addObserver(() -> viewer.refresh());
+       public void highlight(int index)
+       {
+               Display.getDefault().asyncExec(() ->
+               {
+                       LazyTableViewer viewer = table.getTableViewer();
+                       viewer.highlightRow(highlighted, false);
+                       highlighted = index;
+                       viewer.highlightRow(index, true);
+                       viewer.getTable().setTopIndex(index);
+               });
        }
 
        private void addActivationButton(Composite parent)
@@ -86,130 +80,13 @@ public class InstructionView extends EditorPart implements MemoryObserver
                                e -> MachineContext.getInstance().getMachine().getMicroInstructionMemory().bind(memory));
        }
 
-       public void highlight(int index)
-       {
-               viewer.highlightRow(highlighted, false);
-               viewer.highlightRow(index, true);
-               viewer.getTable().setTopIndex(index);
-       }
-
        public void bindMicroInstructionMemory(MicroInstructionMemory memory)
        {
                this.memory = memory;
-               this.miDef = memory.getDefinition().getMicroInstructionDefinition();
-               this.memory.registerObserver(this);
-               setViewerInput(memory);
-       }
-
-       private void setViewerInput(MicroInstructionMemory memory)
-       {
-               if (viewer != null)
-               {
-                       deleteColumns();
-                       viewer.setInput(memory);
-                       createColumns();
-               }
-       }
-
-       private void deleteColumns()
-       {
-               for (TableViewerColumn col : columns)
-                       col.getColumn().dispose();
-       }
-
-       private void createColumns()
-       {
-               int size = miDef.size();
-               columns = new TableViewerColumn[size + 1];
-
-               TableViewerColumn col = createTableViewerColumn("Address", generateLongestHexStrings(12));
-               columns[0] = col;
-               col.setLabelProvider(new AddressLabelProvider());
-
-               int bit = miDef.sizeInBits();
-               ParameterClassification[] classes = miDef.getParameterClassifications();
-
-               for (int i = 0; i < size; i++)
-               {
-                       int startBit = bit - 1;
-                       int endBit = bit = bit - classes[i].getExpectedBits();
-                       String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
-
-                       String[] longestPossibleContents;
-                       switch (classes[i].getExpectedType())
-                       {
-                       case INTEGER_IMMEDIATE:
-                               longestPossibleContents = generateLongestHexStrings(classes[i].getExpectedBits());
-                               break;
-                       case BOOLEAN_IMMEDIATE:
-                       case MNEMONIC:
-                               longestPossibleContents = ((MnemonicFamily) classes[i]).getStringValues();
-                               break;
-                       default:
-                               longestPossibleContents = new String[0];
-                               break;
-                       }
-
-                       col = createTableViewerColumn(name, longestPossibleContents);
-                       columns[i + 1] = col;
-                       createEditingAndLabel(col, miDef, i);
-               }
-       }
-
-       private static final String[] HEX_DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
-
-       private static String[] generateLongestHexStrings(int bitWidth)
-       {
-               return Arrays.stream(HEX_DIGITS).map(s -> "0x" + s.repeat((bitWidth + 3) / 4)).toArray(String[]::new);
-       }
-
-       private void createEditingAndLabel(TableViewerColumn col, MicroInstructionDefinition miDef, int index)
-       {
-               ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
-               EditingSupport support;
-               ColumnLabelProvider provider;
-               switch (parameterClassification.getExpectedType())
-               {
-               case BOOLEAN_IMMEDIATE:
-                       support = new BooleanEditingSupport(viewer, miDef, index);
-                       provider = new ParameterLabelProvider(index);
-                       break;
-               case INTEGER_IMMEDIATE:
-                       support = new IntegerEditingSupport(viewer, miDef, index, displaySettings, this.provider);
-                       provider = new IntegerColumnLabelProvider(displaySettings, index);
-                       break;
-               case MNEMONIC:
-                       support = new MnemonicEditingSupport(viewer, miDef, index, this.provider);
-                       provider = new ParameterLabelProvider(index);
-                       break;
-               default:
-                       throw new IllegalStateException(
-                                       "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
-               }
-               col.setEditingSupport(support);
-               col.setLabelProvider(provider);
-               col.getColumn().setToolTipText(miDef.getParameterDescription(index).orElse(""));
-       }
-
-       private TableViewerColumn createTableViewerColumn(String title, String... longestPossibleContents)
-       {
-               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
-               TableColumn column = viewerColumn.getColumn();
-               int maxWidth = 0;
-               for (String s : longestPossibleContents)
-               {
-                       column.setText(s);
-                       column.pack();
-                       if (column.getWidth() > maxWidth)
-                               maxWidth = column.getWidth();
-               }
-               column.setText(title);
-               column.pack();
-               if (column.getWidth() < maxWidth)
-                       column.setWidth(maxWidth);
-               column.setResizable(true);
-               column.setMoveable(false);
-               return viewerColumn;
+               this.memory.registerCellModifiedListener(this);
+               this.memory.registerActiveMicroInstructionChangedListener(this);
+               if (table != null)
+                       table.bindMicroInstructionMemory(memory);
        }
 
        private void open(String file)
@@ -245,7 +122,7 @@ public class InstructionView extends EditorPart implements MemoryObserver
        @Override
        public void setFocus()
        {
-               viewer.getControl().setFocus();
+               table.getTableViewer().getControl().setFocus();
        }
 
        @Override
@@ -268,7 +145,7 @@ public class InstructionView extends EditorPart implements MemoryObserver
 
        private void openSaveAsDialog()
        {
-               FileDialog d = new FileDialog(viewer.getTable().getShell(), SWT.SAVE);
+               FileDialog d = new FileDialog(table.getTableViewer().getTable().getShell(), SWT.SAVE);
                d.open();
                String filename = d.getFileName();
                if (!filename.equals(""))
@@ -307,6 +184,7 @@ public class InstructionView extends EditorPart implements MemoryObserver
        public void update(long address)
        {
                setDirty(true);
+               table.refresh();
        }
 
        private void setDirty(boolean value)
@@ -314,4 +192,10 @@ public class InstructionView extends EditorPart implements MemoryObserver
                dirty = value;
                firePropertyChange(PROP_DIRTY);
        }
+
+       @Override
+       public void activeMicroInstructionChanged(long address)
+       {
+               highlight((int) (address - memory.getDefinition().getMinimalAddress()));
+       }
 }
index 9916bf4..49c6fa4 100644 (file)
@@ -4,6 +4,8 @@ import javax.inject.Inject;
 
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.part.ViewPart;
@@ -12,9 +14,13 @@ import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInpu
 import net.mograsim.logic.model.LogicExecuter;
 import net.mograsim.logic.model.LogicUICanvas;
 import net.mograsim.machine.Machine;
+import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 import net.mograsim.plugin.EclipsePreferences;
 import net.mograsim.plugin.MachineContext;
 import net.mograsim.plugin.MograsimActivator;
+import net.mograsim.plugin.tables.DisplaySettings;
+import net.mograsim.plugin.tables.mi.ActiveInstructionPreviewContentProvider;
+import net.mograsim.plugin.tables.mi.InstructionTable;
 import net.mograsim.preferences.Preferences;
 
 public class LogicUIPart extends ViewPart
@@ -42,6 +48,9 @@ public class LogicUIPart extends ViewPart
                Machine m = MachineContext.getInstance().getMachine();
 
                // initialize UI
+               GridLayout layout = new GridLayout(1, true);
+               parent.setLayout(layout);
+
                ui = new LogicUICanvas(parent, SWT.NONE, m.getModel());
                ui.addTransformListener((x, y, z) -> part.setDirty(z < 1));
                ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(ui);
@@ -49,6 +58,20 @@ public class LogicUIPart extends ViewPart
                userInput.buttonZoom = 2;
                userInput.enableUserInput();
 
+               GridData uiData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
+               ui.setLayoutData(uiData);
+
+               // initialize Instruction preview
+               InstructionTable instPreview = new InstructionTable(parent, new DisplaySettings());
+               instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
+               AssignableMicroInstructionMemory mIMemory = m.getMicroInstructionMemory();
+               instPreview.bindMicroInstructionMemory(mIMemory);
+               mIMemory.registerCellModifiedListener(a -> instPreview.refresh());
+               mIMemory.registerMemoryReassignedListener(n -> instPreview.refresh());
+
+               GridData previewData = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
+               instPreview.getTableViewer().getTable().setLayoutData(previewData);
+
                // initialize executer
                exec = new LogicExecuter(m.getTimeline());