From: Fabian Stemmler Date: Wed, 18 Sep 2019 20:15:02 +0000 (+0200) Subject: Added active instruction preview to LogicUIPart X-Git-Url: https://mograsim.net/gitweb/?p=Mograsim.git;a=commitdiff_plain;h=41292b984ee229deb329c83b525006fd2840becb Added active instruction preview to LogicUIPart --- diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java index 80520140..40873f00 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/GenericMemory.java @@ -10,7 +10,7 @@ public abstract class GenericMemory implements Memory private final long minimalAddress, maximalAddress; private final MemoryDefinition definition; private final int pageSize = 64; - private Set observers = new HashSet<>(); + private Set observers = new HashSet<>(); private HashMap pages; @@ -94,19 +94,18 @@ public abstract class GenericMemory implements Memory } @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)); } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/Memory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/Memory.java index 0ff9bb41..4f0e58f7 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/Memory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/Memory.java @@ -26,11 +26,15 @@ public interface Memory /** * 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 index 1d7fc4dd..00000000 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/MemoryObserver.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.mograsim.machine; - -public interface MemoryObserver -{ - public void update(long address); -} diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java index b0ab5a4e..a366ae0a 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java @@ -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 observers = new HashSet<>(); - MicroInstructionMemory real = null; + + private Set observers = new HashSet<>(); + private Set activeInstructionListeners = new HashSet<>(); + private Set 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); } } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java index 6409f78d..abfed465 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java @@ -6,4 +6,15 @@ public interface MicroInstructionMemory extends Memory { @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); + } } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java index 7ef53d90..94905a5b 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java @@ -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 observers = new HashSet<>(); + private HashSet observers = new HashSet<>(); + private Set 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); + } + } + } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java index aacc243e..b01802c0 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java @@ -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 diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java index e7249b9a..801895be 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java @@ -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(); } diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/LazyTableViewer.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/LazyTableViewer.java index 1b371e28..c4488138 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/LazyTableViewer.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/LazyTableViewer.java @@ -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); } diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java index 95d18358..90ad7885 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java @@ -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 index 00000000..604c2859 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ActiveInstructionPreviewContentProvider.java @@ -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 index 00000000..93179c08 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTable.java @@ -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()); + } +} diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java index 6519b628..c82fbc7d 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java @@ -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 index 00000000..94de0aed --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableLazyContentProvider.java @@ -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)); + } +} diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java index 76d4a693..b21c848d 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java @@ -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())); + } } diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/views/LogicUIPart.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/views/LogicUIPart.java index 9916bf4d..49c6fa43 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/views/LogicUIPart.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/views/LogicUIPart.java @@ -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());