MicroInstructionMemory editor can now open and save to files
authorFabian Stemmler <stemmler@in.tum.de>
Tue, 17 Sep 2019 19:40:57 +0000 (21:40 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Tue, 17 Sep 2019 19:40:57 +0000 (21:40 +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/mi/AssignableMicroInstructionMemory.java [new file with mode: 0644]
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java

index 0a0787c..bcde112 100644 (file)
@@ -14,7 +14,7 @@ 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.MicroInstructionMemory;
+import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 import net.mograsim.machine.mi.StandardMicroInstructionMemory;
 import net.mograsim.machine.standard.memory.WordAddressableMemory;
 
@@ -24,7 +24,7 @@ public class Am2900Machine implements Machine
        private LogicModelModifiable logicModel;
        private Timeline timeline;
        private MainMemory mainMemory;
-       private MicroInstructionMemory instMemory;
+       private AssignableMicroInstructionMemory instMemory;
        private CoreClock clock;
 
        public Am2900Machine(Am2900MachineDefinition am2900MachineDefinition)
@@ -37,7 +37,8 @@ public class Am2900Machine implements Machine
                params.gateProcessTime = 50;
                params.wireTravelTime = 10;
                mainMemory = new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition());
-               instMemory = new StandardMicroInstructionMemory(am2900MachineDefinition.getMicroInstructionMemoryDefinition());
+               instMemory = new AssignableMicroInstructionMemory(
+                               new StandardMicroInstructionMemory(am2900MachineDefinition.getMicroInstructionMemoryDefinition()));
                logicModel.getComponentBySubmodelPath("Am2900.Am2900MainMemory#0", ModelAm2900MainMemory.class).setMachine(this);
                logicModel.getComponentBySubmodelPath("Am2900.Am2900MicroInstructionMemory#0", ModelAm2900MicroInstructionMemory.class)
                                .setMachine(this);
@@ -96,7 +97,7 @@ public class Am2900Machine implements Machine
        }
 
        @Override
-       public MicroInstructionMemory getMicroInstructionMemory()
+       public AssignableMicroInstructionMemory getMicroInstructionMemory()
        {
                return instMemory;
        }
index 6ff074d..f9d851d 100644 (file)
@@ -3,8 +3,8 @@ package net.mograsim.machine;
 import net.mograsim.logic.core.components.CoreClock;
 import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.machine.mi.MicroInstructionMemory;
 import net.mograsim.logic.model.model.LogicModel;
+import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
 
 public interface Machine
 {
@@ -24,6 +24,6 @@ public interface Machine
 
        MainMemory getMainMemory();
 
-       MicroInstructionMemory getMicroInstructionMemory();
+       AssignableMicroInstructionMemory getMicroInstructionMemory();
 
 }
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
new file mode 100644 (file)
index 0000000..5fe753e
--- /dev/null
@@ -0,0 +1,67 @@
+package net.mograsim.machine.mi;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import net.mograsim.machine.MemoryObserver;
+
+public class AssignableMicroInstructionMemory implements MicroInstructionMemory, MemoryObserver
+{
+       private Set<MemoryObserver> observers = new HashSet<>();
+       MicroInstructionMemory real = null;
+
+       public AssignableMicroInstructionMemory(StandardMicroInstructionMemory standardMicroInstructionMemory)
+       {
+               real = standardMicroInstructionMemory;
+               real.registerObserver(this);
+       }
+
+       public void bind(MicroInstructionMemory real)
+       {
+               this.real.deregisterObserver(this);
+               this.real = real;
+               real.registerObserver(this);
+       }
+
+       @Override
+       public MicroInstruction getCell(long address)
+       {
+               return real.getCell(address);
+       }
+
+       @Override
+       public void setCell(long address, MicroInstruction data)
+       {
+               real.setCell(address, data);
+       }
+
+       @Override
+       public void registerObserver(MemoryObserver ob)
+       {
+               observers.add(ob);
+       }
+
+       @Override
+       public void deregisterObserver(MemoryObserver ob)
+       {
+               observers.remove(ob);
+       }
+
+       @Override
+       public void notifyObservers(long address)
+       {
+               observers.forEach(o -> o.update(address));
+       }
+
+       @Override
+       public MicroInstructionMemoryDefinition getDefinition()
+       {
+               return real.getDefinition();
+       }
+
+       @Override
+       public void update(long address)
+       {
+               notifyObservers(address);
+       }
+}
index 1aa518d..3c13f67 100644 (file)
@@ -6,13 +6,17 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.util.Objects;
 
+import net.mograsim.machine.MachineRegistry;
 import net.mograsim.machine.MemoryDefinition;
 import net.mograsim.machine.mi.parameters.MicroInstructionParameter;
 import net.mograsim.machine.mi.parameters.ParameterClassification;
 
 public class MicroInstructionMemoryParser
 {
+       private final static String lineSeparator = System.getProperty("line.separator");
+
        public static void parseMemory(final MicroInstructionMemory memory, String inputPath) throws IOException
        {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputPath))))
@@ -21,6 +25,52 @@ public class MicroInstructionMemoryParser
                }
        }
 
+       public static MicroInstructionMemory parseMemory(String inputPath) throws IOException
+       {
+               try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputPath))))
+               {
+                       return parseMemory(reader);
+               }
+       }
+
+       /**
+        * First line must be the machine name, the rest must be in csv format
+        */
+       public static MicroInstructionMemory parseMemory(BufferedReader input)
+       {
+               try
+               {
+                       return parseMemory(input.readLine(), input);
+               }
+               catch (IOException e)
+               {
+                       throw new MicroInstructionMemoryParseException(e);
+               }
+       }
+
+       /**
+        * must be in csv format
+        */
+       public static MicroInstructionMemory parseMemory(String machineName, BufferedReader input)
+       {
+               try
+               {
+                       MicroInstructionMemoryDefinition def = Objects
+                                       .requireNonNull(MachineRegistry.getinstalledMachines().get(machineName), "Unknown machine: " + machineName)
+                                       .getMicroInstructionMemoryDefinition();
+                       MicroInstructionMemory memory = new StandardMicroInstructionMemory(def);
+                       parseMemory(memory, input);
+                       return memory;
+               }
+               catch (NullPointerException e)
+               {
+                       throw new MicroInstructionMemoryParseException(e);
+               }
+       }
+
+       /**
+        * must be in csv format
+        */
        public static void parseMemory(final MicroInstructionMemory memory, BufferedReader input)
        {
                MicroInstructionMemoryDefinition def = memory.getDefinition();
@@ -49,10 +99,13 @@ public class MicroInstructionMemoryParser
                }
        }
 
-       public static MicroInstruction parse(MicroInstructionDefinition definition, String toParse)
+       /**
+        * must be in csv format
+        */
+       public static MicroInstruction parse(MicroInstructionDefinition definition, String path)
        {
                int size = definition.size();
-               String[] strings = toParse.split(",");
+               String[] strings = path.split(",");
                if (size != strings.length)
                        throw new MicroInstructionMemoryParseException("String does not match definition! The number of parameters does not match.");
                MicroInstructionParameter[] params = new MicroInstructionParameter[size];
@@ -79,13 +132,32 @@ public class MicroInstructionMemoryParser
                }
        }
 
+       public static void write(MicroInstructionMemory memory, String machineName, String outputPath) throws IOException
+       {
+               try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(outputPath)))
+               {
+                       write(memory, machineName, writer);
+               }
+       }
+
        public static void write(MicroInstructionMemory memory, OutputStreamWriter output) throws IOException
        {
                MemoryDefinition def = memory.getDefinition();
                long min = def.getMinimalAddress(), max = def.getMaximalAddress() + 1;
                for (long i = min; i < max; i++)
                {
-                       output.write(toCSV(memory.getCell(i)) + "\n");
+                       output.write(toCSV(memory.getCell(i)) + lineSeparator);
+               }
+       }
+
+       public static void write(MicroInstructionMemory memory, String machineName, OutputStreamWriter output) throws IOException
+       {
+               output.write(machineName + lineSeparator);
+               MemoryDefinition def = memory.getDefinition();
+               long min = def.getMinimalAddress(), max = def.getMaximalAddress() + 1;
+               for (long i = min; i < max; i++)
+               {
+                       output.write(toCSV(memory.getCell(i)) + lineSeparator);
                }
        }
 
index b14e42d..aa1df4d 100644 (file)
@@ -1,17 +1,21 @@
 package net.mograsim.plugin.tables.mi;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileReader;
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Optional;
 
 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.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
 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.FileDialog;
 import org.eclipse.swt.widgets.Table;
@@ -22,7 +26,6 @@ import org.eclipse.ui.IPathEditorInput;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.EditorPart;
 
-import net.mograsim.machine.Machine;
 import net.mograsim.machine.MemoryObserver;
 import net.mograsim.machine.mi.MicroInstructionDefinition;
 import net.mograsim.machine.mi.MicroInstructionMemory;
@@ -31,17 +34,13 @@ 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.MachineContext.ContextObserver;
 import net.mograsim.plugin.tables.AddressLabelProvider;
 import net.mograsim.plugin.tables.DisplaySettings;
 import net.mograsim.plugin.tables.LazyTableViewer;
 import net.mograsim.plugin.tables.RadixSelector;
-import net.mograsim.plugin.util.DropDownMenu;
-import net.mograsim.plugin.util.DropDownMenu.DropDownEntry;
 
-public class InstructionView extends EditorPart implements ContextObserver, MemoryObserver
+public class InstructionView extends EditorPart implements MemoryObserver
 {
-       private String saveLoc = null;
        private LazyTableViewer viewer;
        private TableViewerColumn[] columns = new TableViewerColumn[0];
        private MicroInstructionDefinition miDef;
@@ -50,6 +49,7 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
        private InstructionTableContentProvider provider;
        private int highlighted = 0;
        private boolean dirty = false;
+       private String machineName;
 
        @SuppressWarnings("unused")
        @Override
@@ -57,12 +57,12 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
        {
                provider = new InstructionTableContentProvider();
                GridLayout layout = new GridLayout(3, false);
-               setupMenuButtons(parent);
+               parent.setLayout(layout);
 
                displaySettings = new DisplaySettings();
                new RadixSelector(parent, displaySettings);
 
-               parent.setLayout(layout);
+               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();
@@ -70,6 +70,7 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                table.setLinesVisible(true);
                viewer.setUseHashlookup(true);
                viewer.setContentProvider(provider);
+               setViewerInput(memory);
                getSite().setSelectionProvider(viewer);
 
                GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
@@ -77,60 +78,54 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                viewer.getTable().setLayoutData(viewerData);
 
                displaySettings.addObserver(() -> viewer.refresh());
-               MachineContext.getInstance().registerObserver(this);
-               setMachine(Optional.ofNullable(MachineContext.getInstance().getMachine()));
        }
 
-       public void highlight(int index)
+       private void addActivationButton(Composite parent)
        {
-               viewer.highlightRow(highlighted, false);
-               viewer.highlightRow(index, true);
-               viewer.getTable().setTopIndex(index);
-       }
-
-       @SuppressWarnings("unused")
-       private void setupMenuButtons(Composite parent)
-       {
-               DropDownEntry open = new DropDownEntry("Open", (e) ->
+               Button activationButton = new Button(parent, SWT.PUSH);
+               activationButton.setText("Set Active");
+               activationButton.addSelectionListener(new SelectionListener()
                {
-                       FileDialog d = new FileDialog(parent.getShell(), SWT.NONE);
-                       d.open();
-                       String filename = d.getFileName();
-                       if (!filename.equals(""))
-                               open(d.getFilterPath() + File.separator + filename);
-               });
 
-               DropDownEntry save = new DropDownEntry("Save", (e) ->
-               {
-                       if (saveLoc == null)
-                               openSaveAsDialog(parent);
-                       save(saveLoc);
-               });
-               DropDownEntry saveAs = new DropDownEntry("SaveAs", (e) ->
-               {
-                       openSaveAsDialog(parent);
-                       save(saveLoc);
+                       @Override
+                       public void widgetSelected(SelectionEvent e)
+                       {
+                               if (e.detail == SWT.PUSH)
+                                       MachineContext.getInstance().getMachine().getMicroInstructionMemory().bind(memory);
+                               // TODO register this in project context
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e)
+                       {
+                               widgetSelected(e);
+                       }
                });
-               new DropDownMenu(parent, "File", open, save, saveAs);
        }
 
-       private void openSaveAsDialog(Composite parent)
+       public void highlight(int index)
        {
-               FileDialog d = new FileDialog(parent.getShell(), SWT.SAVE);
-               d.open();
-               String filename = d.getFileName();
-               if (!filename.equals(""))
-                       saveLoc = d.getFilterPath() + File.separator + filename;
+               viewer.highlightRow(highlighted, false);
+               viewer.highlightRow(index, true);
+               viewer.getTable().setTopIndex(index);
        }
 
        public void bindMicroInstructionMemory(MicroInstructionMemory memory)
        {
-               deleteColumns();
                this.memory = memory;
-               viewer.setInput(memory);
                this.miDef = memory.getDefinition().getMicroInstructionDefinition();
                this.memory.registerObserver(this);
-               createColumns();
+               setViewerInput(memory);
+       }
+
+       private void setViewerInput(MicroInstructionMemory memory)
+       {
+               if (viewer != null)
+               {
+                       deleteColumns();
+                       viewer.setInput(memory);
+                       createColumns();
+               }
        }
 
        private void deleteColumns()
@@ -236,16 +231,10 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
 
        private void open(String file)
        {
-               if (miDef == null)
+               try (BufferedReader bf = new BufferedReader(new FileReader(file)))
                {
-                       System.err.println("Failed to parse MicroprogrammingMemory from File. No MicroInstructionDefinition assigned.");
-                       return;
-               }
-               try
-               {
-                       MicroInstructionMemoryParser.parseMemory(memory, file);
-                       viewer.refresh();
-                       saveLoc = file;
+                       machineName = bf.readLine();
+                       bindMicroInstructionMemory(MicroInstructionMemoryParser.parseMemory(machineName, bf));
                }
                catch (IOException | MicroInstructionMemoryParseException e)
                {
@@ -262,7 +251,7 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                }
                try
                {
-                       MicroInstructionMemoryParser.write(memory, file);
+                       MicroInstructionMemoryParser.write(memory, machineName, file);
                }
                catch (IOException e)
                {
@@ -276,16 +265,6 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                viewer.getControl().setFocus();
        }
 
-       @Override
-       public void setMachine(Optional<Machine> machine)
-       {
-               if (machine.isPresent())
-               {
-                       Machine actualMachine = machine.get();
-                       bindMicroInstructionMemory(actualMachine.getMicroInstructionMemory());
-               }
-       }
-
        @Override
        public void doSave(IProgressMonitor progressMonitor)
        {
@@ -294,15 +273,26 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                {
                        IPathEditorInput pathInput = (IPathEditorInput) input;
                        save(pathInput.getPath().toOSString());
-                       dirty = false;
-                       firePropertyChange(PROP_DIRTY);
+                       setDirty(false);
                }
        }
 
        @Override
        public void doSaveAs()
        {
-               // not allowed
+               openSaveAsDialog();
+       }
+
+       private void openSaveAsDialog()
+       {
+               FileDialog d = new FileDialog(viewer.getTable().getShell(), SWT.SAVE);
+               d.open();
+               String filename = d.getFileName();
+               if (!filename.equals(""))
+               {
+                       save(d.getFilterPath() + File.separator + filename);
+                       setDirty(false);
+               }
        }
 
        @Override
@@ -313,6 +303,7 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
                if (input instanceof IPathEditorInput)
                {
                        IPathEditorInput pathInput = (IPathEditorInput) input;
+                       setPartName(pathInput.getName());
                        open(pathInput.getPath().toOSString());
                }
        }
@@ -326,13 +317,18 @@ public class InstructionView extends EditorPart implements ContextObserver, Memo
        @Override
        public boolean isSaveAsAllowed()
        {
-               return false;
+               return true;
        }
 
        @Override
        public void update(long address)
        {
-               dirty = true;
+               setDirty(true);
+       }
+
+       private void setDirty(boolean value)
+       {
+               dirty = value;
                firePropertyChange(PROP_DIRTY);
        }
 }