From 6c32f347005a369359a68c09b7e9ac2f4a1eab0f Mon Sep 17 00:00:00 2001 From: Fabian Stemmler Date: Tue, 17 Sep 2019 21:40:57 +0200 Subject: [PATCH] MicroInstructionMemory editor can now open and save to files --- .../model/am2900/machine/Am2900Machine.java | 9 +- .../src/net/mograsim/machine/Machine.java | 4 +- .../mi/AssignableMicroInstructionMemory.java | 67 +++++++++ .../mi/MicroInstructionMemoryParser.java | 78 +++++++++- .../plugin/tables/mi/InstructionView.java | 140 +++++++++--------- 5 files changed, 217 insertions(+), 81 deletions(-) create mode 100644 plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java diff --git a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java index 0a0787cc..bcde112d 100644 --- a/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java +++ b/plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java @@ -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; } diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java index 6ff074d0..f9d851dc 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java @@ -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 index 00000000..5fe753eb --- /dev/null +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java @@ -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 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); + } +} diff --git a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java index 1aa518dc..3c13f67b 100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java @@ -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); } } 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 b14e42db..aa1df4d2 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 @@ -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) - { - 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); } } -- 2.17.1