Export-Package: net.mograsim.machine,
net.mograsim.machine.isa,
net.mograsim.machine.isa.types,
+ net.mograsim.machine.mi,
+ net.mograsim.machine.mi.parameters,
net.mograsim.machine.standard.memory
*/
default long size()
{
- return getMaximalAddress() - getMinimalAddress();
+ return getMaximalAddress() - getMinimalAddress() + 1;
}
public static MemoryDefinition create(int memoryAddressBits, long minimalAddress, long maximalAddress)
--- /dev/null
+package net.mograsim.machine.mi;
+
+import net.mograsim.machine.MachineException;
+
+public class MicroprogramMemoryParseException extends MachineException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6820101808901789906L;
+
+ public MicroprogramMemoryParseException()
+ {
+ super();
+ }
+
+ public MicroprogramMemoryParseException(String message)
+ {
+ super(message);
+ }
+
+ public MicroprogramMemoryParseException(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
import net.mograsim.logic.core.types.BitVector;
import net.mograsim.machine.MemoryDefinition;
public class MicroprogramMemoryParser
{
- public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition, String input) throws IOException
+ public static MicroprogramMemory parseMemory(MicroInstructionDefinition definition, String input) throws IOException
{
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input))))
{
- parse(memory, startAddress, definition, reader);
+ return parseMemory(definition, reader);
}
}
- public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition,
- BufferedReader input)
+ public static MicroprogramMemory parseMemory(MicroInstructionDefinition definition, BufferedReader input)
{
- MemoryDefinition def = memory.getDefinition();
- long minAddress = Long.max(startAddress, def.getMinimalAddress()), maxAddress = def.getMaximalAddress();
+ List<MicroInstruction> instructions = new ArrayList<>();
try
{
String line;
- for (long i = minAddress; i < maxAddress && input.ready() && !"".equals((line = input.readLine())); i++)
- memory.setCell(i, parse(definition, line));
+ while (input.ready() && !"".equals((line = input.readLine())))
+ instructions.add(parse(definition, line));
} catch (IOException e)
{
e.printStackTrace();
}
+
+ int maxAddress = instructions.size() - 1;
+ MicroprogramMemory memory = MicroprogramMemory
+ .create(MemoryDefinition.create((int) Math.ceil(Math.log(maxAddress)), 0, maxAddress));
+ int i = 0;
+ for (MicroInstruction inst : instructions)
+ memory.setCell(i++, inst);
+ return memory;
}
public static MicroInstruction parse(MicroInstructionDefinition definition, String toParse)
int size = definition.size();
String[] strings = toParse.split(",");
if (size != strings.length)
- throw new IllegalArgumentException(
+ throw new MicroprogramMemoryParseException(
"String does not match definition! The number of parameters does not match.");
MicroInstructionParameter[] params = new MicroInstructionParameter[size];
ParameterClassification[] classes = definition.getParameterClassifications();
- for (int i = 0; i < size; i++)
+ try
{
- params[i] = classes[i].parse(strings[i]);
+ for (int i = 0; i < size; i++)
+ {
+ params[i] = classes[i].parse(strings[i]);
+ }
+ return new StandardMicroInstruction(params);
+ } catch (Exception e)
+ {
+ throw new MicroprogramMemoryParseException(e.getCause());
}
- return new StandardMicroInstruction(params);
}
-
- public static void write(MicroprogramMemory memory, long startAddress, long endAddress, String output) throws IOException
+
+ public static void write(MicroprogramMemory memory, String output) throws IOException
{
- try(OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(output)))
+ try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(output)))
{
- write(memory, startAddress, endAddress, writer);
+ write(memory, writer);
}
}
-
- public static void write(MicroprogramMemory memory, long startAddress, long endAddress, OutputStreamWriter output) throws IOException
+
+ public static void write(MicroprogramMemory memory, OutputStreamWriter output) throws IOException
{
MemoryDefinition def = memory.getDefinition();
- long min = Long.max(def.getMinimalAddress(), startAddress), max = Long.min(def.getMaximalAddress(), endAddress) + 1;
- for(long i = min; i < max; i++)
+ long min = def.getMinimalAddress(), max = def.getMaximalAddress() + 1;
+ for (long i = min; i < max; i++)
{
output.write(toCSV(memory.getCell(i)) + "\n");
}
}
-
+
private static String toCSV(MicroInstruction inst)
{
int max = inst.getSize() - 1;
StringBuilder sb = new StringBuilder();
- for(int i = 0; i < max; i++)
+ for (int i = 0; i < max; i++)
{
sb.append(inst.getParameter(i).toString());
sb.append(",");
sb.append(inst.getParameter(max).toString());
return sb.toString();
}
+
+ public static void main(String[] args)
+ {
+ MnemonicFamily family = new MnemonicFamily(new MnemonicPair("ZERO", BitVector.SINGLE_0),
+ new MnemonicPair("ONE", BitVector.SINGLE_1));
+ MicroInstructionDefinition def = MicroInstructionDefinition.create(new BooleanClassification(),
+ new IntegerClassification(8), family);
+ MicroprogramMemory memory = new StandardMicroprogramMemory(MemoryDefinition.create(4, 0, 16));
+ for (int i = 0; i < 17; i++)
+ memory.setCell(i, new StandardMicroInstruction(new BooleanImmediate(false),
+ new IntegerImmediate(BigInteger.valueOf(i), 8), family.get(i % 2)));
+ try
+ {
+ write(memory, "test.txt");
+ MicroprogramMemory newMemory = parseMemory(def, "test.txt");
+ write(newMemory, "test2.txt");
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ }
}
{
private MicroInstruction[] data;
private MemoryDefinition definition;
- private HashSet<MemoryObserver> observers;
+ private HashSet<MemoryObserver> observers = new HashSet<>();
StandardMicroprogramMemory(MemoryDefinition definition)
{
fontDefinition.label = Assembler Operation Textstil
view.name.0 = Simulation View
view.name.1 = Speicher
+view.name.2 = Instruktionseditor
themeElementCategory.label.0 = Simulation
\ No newline at end of file
fontDefinition.label = Assembler Operation Style
view.name.0 = Simulation View
view.name.1 = Memory
+view.name.1 = Instruction Editor
themeElementCategory.label.0 = Simulation
Bundle-Vendor.0 = Mograsim Team
\ No newline at end of file
</view>
<view
category="net.mograsim.plugin"
- id="net.mograsim.plugin.memory.MemoryView"
- class="net.mograsim.plugin.memory.MemoryView"
+ id="net.mograsim.plugin.tables.memory.MemoryView"
+ class="net.mograsim.plugin.tables.memory.MemoryView"
icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
name="%view.name.1">
+ </view>
+ <view
+ category="net.mograsim.plugin"
+ id="net.mograsim.plugin.tables.mi.InstructionView"
+ class="net.mograsim.plugin.tables.mi.InstructionView"
+ icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+ name="%view.name.2">
</view>
</extension>
<extension
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckboxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.parameters.BooleanImmediate;
+
+public class BooleanEditingSupport extends EditingSupport
+{
+ private final CheckboxCellEditor editor;
+ private final TableViewer viewer;
+ private final int index;
+
+ public BooleanEditingSupport(TableViewer viewer, int index)
+ {
+ super(viewer);
+ this.viewer = viewer;
+ editor = new CheckboxCellEditor(viewer.getTable());
+ this.index = index;
+ }
+
+ @Override
+ protected boolean canEdit(Object element)
+ {
+ return true;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element)
+ {
+ return editor;
+ }
+
+ @Override
+ protected Object getValue(Object element)
+ {
+ return ((BooleanImmediate) ((MicroInstruction) element).getParameter(index)).getBooleanValue();
+ }
+
+ @Override
+ protected void setValue(Object element, Object value)
+ {
+ ((MicroInstruction) element).setParameter(index, new BooleanImmediate((Boolean) value));
+ viewer.update(element, null);
+ }
+
+}
--- /dev/null
+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.MicroprogramMemory;
+
+public class InstructionTableContentProvider implements ILazyContentProvider
+{
+ private TableViewer viewer;
+ private MicroprogramMemory memory;
+
+ @Override
+ public void updateElement(int index)
+ {
+ viewer.replace(memory.getCell(index), index);
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+ {
+ this.viewer = (TableViewer) viewer;
+ this.memory = (MicroprogramMemory) newInput;
+ if (this.memory != null)
+ this.viewer.setItemCount((int) memory.size());
+ }
+}
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.part.ViewPart;
+
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.MicroprogramMemory;
+import net.mograsim.machine.mi.MicroprogramMemoryParseException;
+import net.mograsim.machine.mi.MicroprogramMemoryParser;
+import net.mograsim.machine.mi.parameters.ParameterClassification;
+import net.mograsim.plugin.asm.AsmNumberUtil.NumberType;
+import net.mograsim.plugin.tables.memory.DisplaySettings;
+import net.mograsim.plugin.util.DropDownMenu;
+import net.mograsim.plugin.util.DropDownMenu.DropDownEntry;
+
+public class InstructionView extends ViewPart
+{
+ private String saveLoc = null;
+ private TableViewer viewer;
+ private TableViewerColumn[] columns = new TableViewerColumn[0];
+ private MicroInstructionDefinition miDef;
+ private MicroprogramMemory memory;
+
+ @Override
+ public void createPartControl(Composite parent)
+ {
+ InstructionTableContentProvider provider = new InstructionTableContentProvider();
+ GridLayout layout = new GridLayout(1, false);
+ setupMenuButtons(parent);
+ parent.setLayout(layout);
+ viewer = new TableViewer(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);
+
+ viewer.getTable().setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
+ }
+
+ @SuppressWarnings("unused")
+ private void setupMenuButtons(Composite parent)
+ {
+ DropDownEntry open = new DropDownEntry("Open", (e) ->
+ {
+ 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);
+ });
+ new DropDownMenu(parent, "File", open, save, saveAs);
+ }
+
+ private void openSaveAsDialog(Composite parent)
+ {
+ FileDialog d = new FileDialog(parent.getShell(), SWT.SAVE);
+ d.open();
+ String filename = d.getFileName();
+ if (!filename.equals(""))
+ saveLoc = d.getFilterPath() + File.separator + filename;
+ }
+
+ public void bindMicroprogramMemory(MicroprogramMemory memory)
+ {
+ this.memory = memory;
+ viewer.setInput(memory);
+ }
+
+ public void bindMicroInstructionDef(MicroInstructionDefinition miDef)
+ {
+ this.miDef = miDef;
+ createColumns();
+ }
+
+ private void createColumns()
+ {
+ for (TableViewerColumn col : columns)
+ col.getColumn().dispose();
+ int size = miDef.size();
+ int bit = 0;
+ columns = new TableViewerColumn[size];
+ ParameterClassification[] classes = miDef.getParameterClassifications();
+
+ for (int i = 0; i < size; i++)
+ {
+ int startBit = bit;
+ int endBit = (bit = bit + classes[i].getExpectedBits()) - 1;
+ String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
+ int bounds = 20 + 20 * classes[i].getExpectedBits();
+
+ TableViewerColumn col = createTableViewerColumn(name, bounds);
+ col.setLabelProvider(new ParameterLabelProvider(i));
+ col.setEditingSupport(createEditingSupport(miDef, i));
+ }
+
+ }
+
+ private EditingSupport createEditingSupport(MicroInstructionDefinition miDef, int index)
+ {
+ ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
+ switch (parameterClassification.getExpectedType())
+ {
+ case BOOLEAN_IMMEDIATE:
+ return new BooleanEditingSupport(viewer, index);
+ case INTEGER_IMMEDIATE:
+ return new IntegerEditingSupport(viewer, miDef, index, new DisplaySettings(NumberType.DECIMAL));
+ case MNEMONIC:
+ return new MnemonicEditingSupport(viewer, miDef, index);
+ default:
+ throw new IllegalStateException(
+ "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
+ }
+ }
+
+ private TableViewerColumn createTableViewerColumn(String title, int bound)
+ {
+ TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+ TableColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setWidth(bound);
+ column.setResizable(true);
+ column.setMoveable(false);
+ return viewerColumn;
+ }
+
+ private void open(String file)
+ {
+ if (miDef == null)
+ {
+ System.err.println("Failed to parse MicroprogrammingMemory from File. No MicroInstructionDefinition assigned.");
+ return;
+ }
+ try
+ {
+ MicroprogramMemory newMemory = MicroprogramMemoryParser.parseMemory(miDef, file);
+ bindMicroprogramMemory(newMemory);
+ saveLoc = file;
+ }
+ catch (IOException | MicroprogramMemoryParseException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void save(String file)
+ {
+ if (memory == null)
+ {
+ System.err.println("Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
+ }
+ if (saveLoc != null)
+ {
+ try
+ {
+ MicroprogramMemoryParser.write(memory, file);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void setFocus()
+ {
+ viewer.getControl().setFocus();
+ }
+}
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import java.math.BigInteger;
+
+import org.eclipse.jface.viewers.TableViewer;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.parameters.IntegerClassification;
+import net.mograsim.machine.mi.parameters.IntegerImmediate;
+import net.mograsim.plugin.tables.NumberCellEditingSupport;
+import net.mograsim.plugin.tables.memory.DisplaySettings;
+
+public class IntegerEditingSupport extends NumberCellEditingSupport
+{
+ private IntegerClassification classification;
+ private int index;
+
+ public IntegerEditingSupport(TableViewer viewer, MicroInstructionDefinition miDef, int index, DisplaySettings displaySettings)
+ {
+ super(viewer, displaySettings);
+ classification = (IntegerClassification) miDef.getParameterClassifications()[index];
+ this.index = index;
+ }
+
+ @Override
+ protected void setAsBigInteger(Object element, BigInteger value)
+ {
+ ((MicroInstruction) element).setParameter(index, new IntegerImmediate(value, classification.getExpectedBits()));
+ }
+
+ @Override
+ protected BigInteger getAsBigInteger(Object element)
+ {
+ return ((IntegerImmediate) ((MicroInstruction) element).getParameter(index)).getValueAsBigInteger();
+ }
+
+}
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.ICellEditorValidator;
+
+import net.mograsim.machine.mi.parameters.MnemonicFamily;
+
+public class MnemonicCellEditorValidator implements ICellEditorValidator
+{
+ private MnemonicFamily family;
+
+ public MnemonicCellEditorValidator(MnemonicFamily family)
+ {
+ this.family = family;
+ }
+
+ @Override
+ public String isValid(Object value)
+ {
+ int index = (Integer) value;
+ return index >= 0 && index < family.size() ? null
+ : String.format("MnemonicFamily has %s elements, index %s is out of bounds", family.size(), value.toString());
+ }
+
+}
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.parameters.Mnemonic;
+import net.mograsim.machine.mi.parameters.MnemonicFamily;
+
+public class MnemonicEditingSupport extends EditingSupport
+{
+ private final ComboBoxCellEditor editor;
+ private final MnemonicFamily family;
+ private final TableViewer viewer;
+ private final int index;
+
+ public MnemonicEditingSupport(TableViewer viewer, MicroInstructionDefinition definition, int index)
+ {
+ super(viewer);
+ this.viewer = viewer;
+ family = (MnemonicFamily) definition.getParameterClassifications()[index];
+ editor = new ComboBoxCellEditor(viewer.getTable(), family.getStringValues(), SWT.READ_ONLY);
+ this.index = index;
+ editor.setValidator(new MnemonicCellEditorValidator(family));
+ }
+
+ @Override
+ protected boolean canEdit(Object element)
+ {
+ return true;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element)
+ {
+ return editor;
+ }
+
+ @Override
+ protected Object getValue(Object element)
+ {
+ return ((Mnemonic) ((MicroInstruction) element).getParameter(index)).ordinal();
+ }
+
+ @Override
+ protected void setValue(Object element, Object value)
+ {
+ ((MicroInstruction) element).setParameter(index, family.get((Integer) value));
+ viewer.update(element, null);
+ }
+
+}
--- /dev/null
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+
+import net.mograsim.machine.mi.MicroInstruction;
+
+public class ParameterLabelProvider extends ColumnLabelProvider
+{
+ private final int index;
+
+ public ParameterLabelProvider(int index)
+ {
+ super();
+ this.index = index;
+ }
+
+ @Override
+ public String getText(Object element)
+ {
+ return ((MicroInstruction) element).getParameter(index).toString();
+ }
+}
--- /dev/null
+package net.mograsim.plugin.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+public class DropDownMenu
+{
+ private Button button;
+
+ public DropDownMenu(Composite parent, String label, DropDownEntry... entries)
+ {
+ button = new Button(parent, SWT.PUSH);
+ button.setText(label);
+ setupDrowpDownMenu(entries);
+ }
+
+ private void setupDrowpDownMenu(DropDownEntry[] entries)
+ {
+ Menu menu = new Menu(button);
+ for (DropDownEntry entry : entries)
+ {
+ MenuItem item = new MenuItem(menu, SWT.PUSH);
+ item.addSelectionListener(new SelectionListener()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ entry.listener.widgetSelected(e);
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e)
+ {
+ widgetSelected(e);
+ }
+ });
+ item.setText(entry.title);
+ }
+
+ button.addListener(SWT.Selection, new Listener()
+ {
+ @Override
+ public void handleEvent(Event event)
+ {
+ Rectangle rect = button.getBounds();
+ Point pt = new Point(rect.x, rect.y + rect.height);
+ pt = button.getParent().toDisplay(pt);
+ menu.setLocation(pt.x, pt.y);
+ menu.setVisible(true);
+ }
+ });
+ }
+
+ public Button getButton()
+ {
+ return button;
+ }
+
+ public static class DropDownEntry
+ {
+ public final String title;
+ public final EntrySelectedListener listener;
+
+ public DropDownEntry(String title, EntrySelectedListener listener)
+ {
+ super();
+ this.title = title;
+ this.listener = listener;
+ }
+ }
+
+ @FunctionalInterface
+ public static interface EntrySelectedListener
+ {
+ public void widgetSelected(SelectionEvent e);
+ }
+}