-Subproject commit fb5ecbf15881cdf9beba9d3950539eaa57053779
+Subproject commit dcf03eb10e7c01c691c8a14b79b55e0cecf142fb
public double getSimulTimeToRealTimeFactor()
{
- return 1 / 1000 / speedFactor;
+ return 1 / 1000d / speedFactor;
}
public void setSpeedFactor(double factor)
{
if (factor <= 0)
- throw new IllegalArgumentException("time factor can't be smaller than 1");
+ throw new IllegalArgumentException("time factor can't be less than or equal to 0");
if (!paused)
{
pause();
IndirectModelComponentCreator.registerResourceLoader(resourceLoader, "Am2900Loader");
IndirectModelComponentCreator.loadStandardComponentIDs(Am2900Loader.class.getResourceAsStream("standardComponentIDMapping.json"));
MachineLoader.setup();
-// System.out.println("SETUP DONE"); // TODO: Debug
}
}
import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
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.AssignableMicroInstructionMemory;
import net.mograsim.machine.mi.MicroInstruction;
import net.mograsim.machine.mi.StandardMicroInstructionMemory;
import net.mograsim.machine.mi.parameters.MicroInstructionParameter;
import net.mograsim.machine.mi.parameters.ParameterClassification;
+import net.mograsim.machine.standard.memory.AssignableMainMemory;
import net.mograsim.machine.standard.memory.WordAddressableMemory;
public class Am2900Machine implements Machine
private LogicModelModifiable logicModel;
private ModelComponent am2900;
private Timeline timeline;
- private MainMemory mainMemory;
+ private AssignableMainMemory mainMemory;
private AssignableMicroInstructionMemory instMemory;
private CoreClock clock;
CoreModelParameters params = new CoreModelParameters();
params.gateProcessTime = 50;
params.wireTravelTime = 10;
- mainMemory = new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition());
+ mainMemory = new AssignableMainMemory(new WordAddressableMemory(am2900MachineDefinition.getMainMemoryDefinition()));
instMemory = new AssignableMicroInstructionMemory(
new StandardMicroInstructionMemory(am2900MachineDefinition.getMicroInstructionMemoryDefinition()));
timeline = LogicCoreAdapter.convert(logicModel, params);
}
@Override
- public MainMemory getMainMemory()
+ public AssignableMainMemory getMainMemory()
{
return mainMemory;
}
import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
import net.mograsim.logic.model.editor.ui.EditorGUI;
+import net.mograsim.preferences.Preferences;
public class EditorUserInput
{
gui.logicCanvas.addListener(SWT.MouseDown, e ->
{
Point clicked = editor.gui.logicCanvas.canvasToWorldCoords(e.x, e.y);
- switch (e.button)
- {
- case 1:
+ if (e.button == Preferences.current().getInt("net.mograsim.logic.model.button.action"))
editor.handleManager.click(clicked, e.stateMask);
- break;
- default:
- // don't react
- }
-
});
gui.logicCanvas.addMouseMoveListener(e ->
import net.mograsim.logic.model.editor.Editor;
import net.mograsim.logic.model.editor.SaveLoadManager;
import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
+import net.mograsim.preferences.Preferences;
public class EditorGUI
{
setupBottomToolBar(innerComp);
ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(logicCanvas);
- userInput.buttonDrag = 3;
- userInput.buttonZoom = 2;
+ userInput.buttonDrag = Preferences.current().getInt("net.mograsim.logic.model.button.drag");
+ userInput.buttonZoom = Preferences.current().getInt("net.mograsim.logic.model.button.zoom");
userInput.enableUserInput();
new ZoomableCanvasOverlay(logicCanvas, null).enableScale();
}
private void mouseDown(Event e)
{
- if (e.button == 1)
+ if (e.button == Preferences.current().getInt("net.mograsim.logic.model.button.action"))
{
Point click = canvasToWorldCoords(e.x, e.y);
for (ModelComponent component : model.getComponentsByName().values())
import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasOverlay;
import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;
import net.mograsim.logic.model.model.LogicModel;
+import net.mograsim.preferences.Preferences;
/**
* Standalone simulation visualizer graphical user interface.
ui = new LogicUICanvas(shell, SWT.NONE, model);
ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(ui);
- userInput.buttonDrag = 3;
- userInput.buttonZoom = 2;
+ userInput.buttonDrag = Preferences.current().getInt("net.mograsim.logic.model.button.drag");
+ userInput.buttonZoom = Preferences.current().getInt("net.mograsim.logic.model.button.zoom");
userInput.enableUserInput();
new ZoomableCanvasOverlay(ui, null).enableScale();
}
import net.mograsim.logic.core.types.BitVector;
import net.mograsim.logic.model.model.LogicModel;
import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
+import net.mograsim.machine.standard.memory.AssignableMainMemory;
public interface Machine
{
Timeline getTimeline();
- MainMemory getMainMemory();
+ AssignableMainMemory getMainMemory();
AssignableMicroInstructionMemory getMicroInstructionMemory();
-
-}
+}
\ No newline at end of file
ClassLoaderBasedResourceLoader resourceLoader = ClassLoaderBasedResourceLoader.create(MachineLoader.class.getClassLoader());
IndirectModelComponentCreator.registerResourceLoader(resourceLoader, "MachineLoader");
IndirectModelComponentCreator.loadStandardComponentIDs(MachineLoader.class.getResourceAsStream("standardComponentIDMapping.json"));
-// System.out.println("SETUP DONE"); // TODO: Debug
}
}
package net.mograsim.machine;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
{
installedMachines.clear();
IExtensionRegistry registry = Platform.getExtensionRegistry();
- System.out.println(Arrays.toString(registry.getExtensionPoints("net.mograsim.machine")));
IConfigurationElement[] config = registry.getConfigurationElementsFor(MACHINE_EXT_ID);
try
{
for (IConfigurationElement e : config)
{
- System.out.println(e.getNamespaceIdentifier());
- System.out.println(Arrays.toString(e.getAttributeNames()));
final Object o = e.createExecutableExtension("class");
final String id = e.getAttribute("unique_id");
if (o instanceof MachineDefinition)
{
- System.out.println("Found " + id);
MachineDefinition md = (MachineDefinition) o;
if (Objects.equals(id, md.getId()))
installedMachines.put(id, md);
}
catch (CoreException ex)
{
- System.out.println(ex.getMessage());
+ System.err.println("An error occurred reloading the machines:");
+ ex.printStackTrace();
}
notifyListeners();
}
--- /dev/null
+package net.mograsim.machine.standard.memory;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
+import net.mograsim.machine.Memory.MemoryCellModifiedListener;
+
+public class AssignableMainMemory implements MainMemory, MemoryCellModifiedListener
+{
+ private Set<MemoryCellModifiedListener> observers = new HashSet<>();
+ private Set<MainMemoryReassignedListener> reassignmentListeners = new HashSet<>();
+ private MainMemory real = null;
+
+ public AssignableMainMemory(MainMemory mainMemory)
+ {
+ real = mainMemory;
+ real.registerCellModifiedListener(this);
+ }
+
+ public void bind(MainMemory real)
+ {
+ this.real.deregisterCellModifiedListener(this);
+ this.real = real;
+ real.registerCellModifiedListener(this);
+ notifyMemoryChanged(-1);
+ notifyMemoryReassigned(real);
+ }
+
+ @Override
+ public BitVector getCell(long address)
+ {
+ return real.getCell(address);
+ }
+
+ @Override
+ public BigInteger getCellAsBigInteger(long address)
+ {
+ return real.getCellAsBigInteger(address);
+ }
+
+ @Override
+ public void setCell(long address, BitVector data)
+ {
+ real.setCell(address, data);
+ }
+
+ @Override
+ public void setCellAsBigInteger(long address, BigInteger word)
+ {
+ real.setCellAsBigInteger(address, word);
+ }
+
+ @Override
+ public void registerCellModifiedListener(MemoryCellModifiedListener ob)
+ {
+ observers.add(ob);
+ }
+
+ @Override
+ public void deregisterCellModifiedListener(MemoryCellModifiedListener ob)
+ {
+ observers.remove(ob);
+ }
+
+ private void notifyMemoryChanged(long address)
+ {
+ observers.forEach(o -> o.update(address));
+ }
+
+ @Override
+ public MainMemoryDefinition getDefinition()
+ {
+ return real.getDefinition();
+ }
+
+ @Override
+ public void update(long address)
+ {
+ notifyMemoryChanged(address);
+ }
+
+ public void registerMemoryReassignedListener(MainMemoryReassignedListener listener)
+ {
+ reassignmentListeners.add(listener);
+ }
+
+ public void deregisterMemoryReassignedListener(MainMemoryReassignedListener listener)
+ {
+ reassignmentListeners.remove(listener);
+ }
+
+ private void notifyMemoryReassigned(MainMemory newAssignee)
+ {
+ reassignmentListeners.forEach(l -> l.reassigned(newAssignee));
+ }
+
+ public static interface MainMemoryReassignedListener
+ {
+ public void reassigned(MainMemory newAssignee);
+ }
+}
net.mograsim.preferences;bundle-version="0.1.0",
net.mograsim.machine,
net.mograsim.plugin.core,
- org.eclipse.core.expressions
+ org.eclipse.core.expressions,
+ SWTInput
Bundle-RequiredExecutionEnvironment: JavaSE-11
Automatic-Module-Name: net.mograsim.plugin.core
Bundle-Vendor: %Bundle-Vendor.0
name="Registers / Latches state"
priority="high">
</content-type>
+ <content-type
+ base-type="org.eclipse.core.runtime.text"
+ default-charset="UTF-8"
+ file-extensions="mem"
+ id="net.mograsim.plugin.mem"
+ name="Main Memory"
+ priority="high">
+ </content-type>
</extension>
<extension
point="org.eclipse.ui.menus">
name="Simulation View Editor">
<contentTypeBinding contentTypeId="net.mograsim.plugin.regs"/>
</editor>
+ <editor
+ class="net.mograsim.plugin.editors.MemoryEditor"
+ icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+ id="net.mograsim.plugin.editors.memoryeditor"
+ name="Memory Editor">
+ <contentTypeBinding
+ contentTypeId="net.mograsim.plugin.mem">
+ </contentTypeBinding>
+ </editor>
</extension>
<extension
point="org.eclipse.ui.genericeditor.presentationReconcilers">
inject="true"
name="%view.name">
</view>
- <view
- category="net.mograsim.plugin"
- 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>
</extension>
<extension
id="net.mograsim.plugin.nature.mograsimBuilder"
+++ /dev/null
-package net.mograsim.plugin;
-
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-import net.mograsim.machine.Machine;
-import net.mograsim.machine.MachineRegistry;
-import net.mograsim.plugin.nature.ProjectMachineContext;
-
-/**
- * @deprecated use the {@link ProjectMachineContext} instead to make the context project dependent.
- */
-@Deprecated(forRemoval = true)
-public class MachineContext
-{
- private Machine machine;
- private Set<ContextObserver> observers;
- private static MachineContext instance;
-
- private MachineContext()
- {
- observers = new HashSet<>();
- }
-
- public static MachineContext getInstance()
- {
- if (instance == null)
- {
- instance = new MachineContext();
- // TODO don't hardcode the Am2900
- instance.setMachine(MachineRegistry.getMachine("Am2900").createNew());
- }
- return instance;
- }
-
- public Machine getMachine()
- {
- return machine;
- }
-
- public void setMachine(Machine machine)
- {
- this.machine = machine;
- notifyObservers(machine);
- }
-
- public void registerObserver(ContextObserver ob)
- {
- observers.add(ob);
- ob.setMachine(Optional.ofNullable(machine));
- }
-
- public void deregisterObserver(ContextObserver ob)
- {
- observers.remove(ob);
- }
-
- private void notifyObservers(Machine machine)
- {
- observers.forEach(ob -> ob.setMachine(Optional.ofNullable(machine)));
- }
-
- @FunctionalInterface
- public static interface ContextObserver
- {
- void setMachine(Optional<Machine> machine);
- }
-}
package net.mograsim.plugin;
import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.swt.widgets.Composite;
public class MainPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{
+ private static final String[][] MOUSE_BUTTONS = { { "left", "1" }, { "middle", "2" }, { "right", "3" }, { "4th", "4" },
+ { "5th", "5" } };
+
public MainPreferencePage()
{
super(GRID);
Composite parent = getFieldEditorParent();
addField(new BooleanFieldEditor("net.mograsim.logic.model.debug.openhlsshell", "Open the debug HLS shell", parent));
addField(new IntegerFieldEditor("net.mograsim.logic.model.debug.hlsshelldepth",
- "Depth of components to list in the debug HLS shell", parent));
+ "Depth of components to list in the debug HLS shell (0: unbounded)", parent));
+ addField(new ComboFieldEditor("net.mograsim.logic.model.button.action", "Mouse button for actions", MOUSE_BUTTONS, parent));
+ addField(new ComboFieldEditor("net.mograsim.logic.model.button.drag", "Mouse button for dragging", MOUSE_BUTTONS, parent));
+ addField(new ComboFieldEditor("net.mograsim.logic.model.button.zoom", "Mouse button for zooming", MOUSE_BUTTONS, parent));
// TODO add other preferences
}
}
\ No newline at end of file
--- /dev/null
+package net.mograsim.plugin.editors;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.util.SafeRunnable;
+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.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorPart;
+
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
+import net.mograsim.machine.standard.memory.WordAddressableMemory;
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.nature.MachineContext;
+import net.mograsim.plugin.nature.ProjectMachineContext;
+import net.mograsim.plugin.tables.AddressLabelProvider;
+import net.mograsim.plugin.tables.DisplaySettings;
+import net.mograsim.plugin.tables.LazyTableViewer;
+import net.mograsim.plugin.tables.NumberColumnLabelProvider;
+import net.mograsim.plugin.tables.RadixSelector;
+import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
+import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
+import net.mograsim.plugin.tables.memory.MemoryTableRow;
+import net.mograsim.plugin.tables.memory.NumberVerifyListener;
+
+public class MemoryEditor extends EditorPart
+{
+ private MachineContext context;
+
+ private MainMemory memory;
+
+ private LazyTableViewer viewer;
+ private MemoryTableContentProvider provider;
+ private DisplaySettings displaySettings;
+
+ @Override
+ public void createPartControl(Composite parent)
+ {
+ provider = new MemoryTableContentProvider();
+ displaySettings = new DisplaySettings();
+
+ parent.setLayout(new GridLayout(7, false));
+
+ createHeader(parent);
+ createViewer(parent);
+
+ displaySettings.addObserver(() -> viewer.refresh());
+ }
+
+ @SuppressWarnings("unused") // RadixSelector and exceptions
+ private void createHeader(Composite parent)
+ {
+ Label fromLabel = new Label(parent, SWT.NONE);
+ fromLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ fromLabel.setText("Address: ");
+
+ Text fromText = new Text(parent, SWT.BORDER);
+ fromText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ NumberVerifyListener vl = new NumberVerifyListener();
+ fromText.addVerifyListener(vl);
+ fromText.setText("0");
+ fromText.addModifyListener(e ->
+ {
+ try
+ {
+ provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
+ viewer.refresh();
+ }
+ catch (NumberFormatException x)
+ {
+ // Nothing to do here
+ }
+ });
+ Label amountLabel = new Label(parent, SWT.NONE);
+ amountLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ amountLabel.setText("Number of cells: ");
+ Text amountText = new Text(parent, SWT.BORDER);
+ amountText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ amountText.addVerifyListener(vl);
+ amountText.setText("0");
+ amountText.addModifyListener(e ->
+ {
+ try
+ {
+ provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
+ viewer.refresh();
+ }
+ catch (NumberFormatException x)
+ {
+ // Nothing to do here
+ }
+ });
+ new RadixSelector(parent, displaySettings);
+
+ addActivationButton(parent);
+ }
+
+ private void addActivationButton(Composite parent)
+ {
+ Button activationButton = new Button(parent, SWT.PUSH);
+ activationButton.setText("Set Active");
+ activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m -> m.getMainMemory().bind(memory)));
+ }
+
+ private void createViewer(Composite parent)
+ {
+ viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+ createColumns();
+ Table table = viewer.getTable();
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ viewer.setUseHashlookup(true);
+ viewer.setContentProvider(provider);
+ getSite().setSelectionProvider(viewer);// TODO what does this?
+ viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 7, 1));
+ if (memory != null)
+ viewer.setInput(memory);
+ }
+
+ private void createColumns()
+ {
+ TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
+ addrCol.setLabelProvider(new AddressLabelProvider());
+
+ TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
+ dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
+ {
+ @Override
+ public BigInteger getAsBigInteger(Object element)
+ {
+ MemoryTableRow row = (MemoryTableRow) element;
+ return row.getMemory().getCellAsBigInteger(row.address);
+ }
+
+ @Override
+ public int getBitLength(Object element)
+ {
+ return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
+ }
+ });
+ dataCol.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
+ }
+
+ private TableViewerColumn createTableViewerColumn(String title, int width)
+ {
+ TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+ TableColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setWidth(width);
+ column.setResizable(true);
+ column.setMoveable(false);
+ return viewerColumn;
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException
+ {
+ if (input instanceof IFileEditorInput)
+ {
+ IFileEditorInput fileInput = (IFileEditorInput) input;
+ context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
+ context.activateMachine();
+
+ setPartName(fileInput.getName());
+ open(fileInput.getFile());
+ } else
+ throw new IllegalArgumentException("MemoryEditor can only be used with Files");
+
+ setSite(site);
+ setInput(input);
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor)
+ {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput)
+ SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
+ }
+
+ private void save(IFile file, IProgressMonitor monitor) throws CoreException
+ {
+ file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
+ }
+
+ private void open(IFile file)
+ {
+ // TODO actually parse the file
+ memory = new WordAddressableMemory(context.getMachineDefinition()
+ .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition());
+ if (viewer != null)
+ viewer.setInput(memory);
+ }
+
+ @Override
+ public void doSaveAs()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isDirty()
+ {
+ // TODO
+ return false;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed()
+ {
+ return false;
+ }
+
+ @Override
+ public void setFocus()
+ {
+ viewer.getTable().setFocus();
+ }
+
+ @Override
+ public void dispose()
+ {
+ // TODO Auto-generated method stub
+ super.dispose();
+ }
+}
\ No newline at end of file
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Slider;
+import org.eclipse.swt.widgets.Scale;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
+import net.haspamelodica.swt.helper.input.DoubleInput;
import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;
import net.mograsim.logic.core.LogicObserver;
import net.mograsim.logic.core.components.CoreClock;
import net.mograsim.logic.model.LogicExecuter;
import net.mograsim.logic.model.LogicUICanvas;
+import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
import net.mograsim.machine.Machine;
import net.mograsim.machine.Memory.MemoryCellModifiedListener;
import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
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;
//TODO what if we open multiple editors?
//TODO actually save / load register and latch states
public class SimulationViewEditor extends EditorPart
{
+ private static final int SIM_SPEED_SCALE_STEPS = 50;
+ private static final double SIM_SPEED_SCALE_STEP_FACTOR = 1.32;
+ private static final double SIM_SPEED_SCALE_STEP_FACTOR_LOG = Math.log(SIM_SPEED_SCALE_STEP_FACTOR);
+
private MachineContext context;
private LogicExecuter exec;
private Button resetButton;
private Button sbseButton;
private Button pauseButton;
- private Label speedFactorLabel;
- private Slider simSpeedSlider;
+ private Scale simSpeedScale;
+ private DoubleInput simSpeedInput;
private Composite canvasParent;
private LogicUICanvas canvas;
private InstructionTable instPreview;
private Label noMachineLabel;
- private ActiveMachineListener activeMNachineListener;
+ private ActiveMachineListener activeMachineListener;
private MemoryCellModifiedListener memCellListener;
private LogicObserver clockObserver;
public SimulationViewEditor()
{
- activeMNachineListener = m -> recreateContextDependentControls();
+ activeMachineListener = m -> recreateContextDependentControls();
memCellListener = a -> instPreview.refresh();
clockObserver = o ->
{
resetButton.setEnabled(true);
sbseButton.setEnabled(true);
pauseButton.setEnabled(true);
- simSpeedSlider.setEnabled(true);
+ simSpeedScale.setEnabled(true);
+ simSpeedInput.setEnabled(true);
machine = machineOptional.get();
canvas = new LogicUICanvas(canvasParent, SWT.NONE, machine.getModel());
+ canvas.addListener(SWT.MouseDown, e -> canvas.setFocus());
ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
- userInput.buttonDrag = 3;
- userInput.buttonZoom = 2;
+ userInput.buttonDrag = Preferences.current().getInt("net.mograsim.logic.model.button.drag");
+ userInput.buttonZoom = Preferences.current().getInt("net.mograsim.logic.model.button.zoom");
userInput.enableUserInput();
if (zoom > 0)
{
// initialize executer
exec = new LogicExecuter(machine.getTimeline());
- updateSpeedFactor();
+ updateSpeedFactorFromInput(simSpeedInput.getValue());
updatePausedState();
exec.startLiveExecution();
} else
resetButton.setEnabled(false);
sbseButton.setEnabled(false);
pauseButton.setEnabled(false);
- simSpeedSlider.setEnabled(false);
+ simSpeedScale.setEnabled(false);
+ simSpeedInput.setEnabled(false);
}
}
resetButton.setText("Reset machine");
resetButton.addListener(SWT.Selection, e -> context.getActiveMachine().get().reset());
+ // TODO do we want this button in the final product?
+ Button reloadMachineButton = new Button(c, SWT.PUSH);
+ reloadMachineButton.setText("Reload machine");
+ reloadMachineButton.addListener(SWT.Selection, e ->
+ {
+ IndirectModelComponentCreator.clearComponentCache();
+ context.setActiveMachine(context.getMachineDefinition().get().createNew());
+ });
+
sbseButton = new Button(c, SWT.CHECK);
pauseButton = new Button(c, SWT.TOGGLE);
new Label(c, SWT.NONE).setText("Simulation Speed: ");
- simSpeedSlider = new Slider(c, SWT.NONE);
- simSpeedSlider.setMinimum(0);
- simSpeedSlider.setMaximum(50 + simSpeedSlider.getThumb());
- simSpeedSlider.setIncrement(1);
- simSpeedSlider.setSelection(0);
+ simSpeedScale = new Scale(c, SWT.NONE);
+ simSpeedScale.setMinimum(0);
+ simSpeedScale.setMaximum(SIM_SPEED_SCALE_STEPS);
+ simSpeedScale.setIncrement(1);
+ simSpeedScale.setSelection(0);
+ simSpeedScale.addListener(SWT.Selection, e -> updateSpeedFactorFromScale());
- speedFactorLabel = new Label(c, SWT.NONE);
- speedFactorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ simSpeedInput = new DoubleInput(c, SWT.NONE);
+ simSpeedInput.setPrecision(Preferences.current().getInt("net.mograsim.plugin.core.simspeedprecision"));
+ simSpeedInput.addChangeListener(this::updateSpeedFactorFromInput);
- simSpeedSlider.addListener(SWT.Selection, e -> updateSpeedFactor());
- updateSpeedFactor();
+ updateSpeedFactorFromScale();
c.layout();
}
exec.pauseLiveExecution();
}
- private void updateSpeedFactor()
+ private void updateSpeedFactorFromScale()
{
- double factor = Math.pow(1.32, simSpeedSlider.getSelection() - 50);
- speedFactorLabel.setText(String.format("%f", factor));
+ double factor = Math.pow(SIM_SPEED_SCALE_STEP_FACTOR, simSpeedScale.getSelection() - SIM_SPEED_SCALE_STEPS);
+ simSpeedInput.setValue(factor);
if (exec != null)
exec.setSpeedFactor(factor);
}
+ private void updateSpeedFactorFromInput(double factor)
+ {
+ double factorCheckedFor0;
+ if (factor != 0)
+ factorCheckedFor0 = factor;
+ else
+ {
+ factorCheckedFor0 = Math.pow(10, -simSpeedInput.getPrecision());
+ simSpeedInput.setValue(factorCheckedFor0);
+ }
+ int closestScalePos = (int) Math.round(Math.log(factorCheckedFor0) / SIM_SPEED_SCALE_STEP_FACTOR_LOG + SIM_SPEED_SCALE_STEPS);
+ simSpeedScale.setSelection(Math.min(Math.max(closestScalePos, 0), SIM_SPEED_SCALE_STEPS));
+ if (exec != null)
+ exec.setSpeedFactor(factorCheckedFor0);
+ }
+
private void addInstructionPreviewControlWidgets(Composite parent)
{
instPreview = new InstructionTable(parent, new DisplaySettings());
IFileEditorInput fileInput = (IFileEditorInput) input;
context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
context.activateMachine();
- context.addActiveMachineListener(activeMNachineListener);
+ context.addActiveMachineListener(activeMachineListener);
recreateContextDependentControls();
setPartName(fileInput.getName());
public void dispose()
{
stopExecAndDeregisterContextDependentListeners();
- context.removeActiveMachineListener(activeMNachineListener);
+ context.removeActiveMachineListener(activeMachineListener);
super.dispose();
}
}
\ No newline at end of file
package net.mograsim.plugin.nature;
-import static net.mograsim.plugin.nature.MachineContextStatus.*;
+import static net.mograsim.plugin.nature.MachineContextStatus.ACTIVE;
+import static net.mograsim.plugin.nature.MachineContextStatus.ACTIVE_CHANGED;
+import static net.mograsim.plugin.nature.MachineContextStatus.BROKEN;
+import static net.mograsim.plugin.nature.MachineContextStatus.CLOSED;
+import static net.mograsim.plugin.nature.MachineContextStatus.DEAD;
+import static net.mograsim.plugin.nature.MachineContextStatus.INTACT;
+import static net.mograsim.plugin.nature.MachineContextStatus.READY;
+import static net.mograsim.plugin.nature.MachineContextStatus.UNKOWN;
import java.io.IOException;
import java.util.HashSet;
if (status == ACTIVE)
return true;
machineDefinition.ifPresent(md -> setActiveMachine(md.createNew()));
- if (activeMachine.isPresent())
- System.out.format("Created new machine %s for project %s%n", activeMachine.get().getDefinition().getId(), owner.getName());
updateStatus();
return isActive();
}
if (oldStatus == newStatus)
return;
status = newStatus;
- System.out.format("Project %s context status: %s -> %s%n", owner.getName(), oldStatus, newStatus);
doPostStatusChangedAction();
notifyMachineContextStatusListeners(oldStatus);
}
{
if ((status == DEAD || status == CLOSED) && activeMachine.isPresent())
{
- System.out.format("Removed machine %s for project %s%n", activeMachine.get().getDefinition().getId(), owner.getName());
activeMachine = Optional.empty();
notifyActiveMachineListeners();
}
private static void resourceChanged(IResourceChangeEvent event)
{
-// System.out.println(((ResourceChangeEvent) event).toDebugString());
// We try to do as many cheap tests first as possible, because this listener is not limited to plain project actions.
if (event.getResource() == null)
return;
+++ /dev/null
-package net.mograsim.plugin.tables.memory;
-
-import java.math.BigInteger;
-import java.util.Optional;
-
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.VerifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.part.ViewPart;
-
-import net.mograsim.machine.Machine;
-import net.mograsim.machine.MainMemory;
-import net.mograsim.machine.MainMemoryDefinition;
-import net.mograsim.machine.standard.memory.WordAddressableMemory;
-import net.mograsim.plugin.MachineContext;
-import net.mograsim.plugin.MachineContext.ContextObserver;
-import net.mograsim.plugin.asm.AsmNumberUtil;
-import net.mograsim.plugin.tables.AddressLabelProvider;
-import net.mograsim.plugin.tables.DisplaySettings;
-import net.mograsim.plugin.tables.LazyTableViewer;
-import net.mograsim.plugin.tables.NumberColumnLabelProvider;
-import net.mograsim.plugin.tables.RadixSelector;
-
-public class MemoryView extends ViewPart implements ContextObserver
-{
- private LazyTableViewer viewer;
- private MemoryTableContentProvider provider;
- private DisplaySettings displaySettings;
-
- @Override
- public void createPartControl(Composite parent)
- {
- provider = new MemoryTableContentProvider();
- displaySettings = new DisplaySettings();
-
- GridLayout layout = new GridLayout(6, false);
- parent.setLayout(layout);
-
- createHeader(parent);
- createViewer(parent);
-
- displaySettings.addObserver(() -> viewer.refresh());
-
- setupContextBinding();
- }
-
- @SuppressWarnings("unused")
- private void createHeader(Composite parent)
- {
- Label fromLabel = new Label(parent, SWT.NONE);
- fromLabel.setText("Address: ");
- Text fromText = new Text(parent, SWT.BORDER | SWT.SEARCH);
- fromText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
- VerifyListener vl = new NumberVerifyListener();
- fromText.addVerifyListener(vl);
- fromText.setText("0");
- fromText.addModifyListener(e ->
- {
- try
- {
- provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
- viewer.refresh();
- }
- catch (NumberFormatException ex)
- {
- // Nothing to do here
- }
- });
-
- Label amountLabel = new Label(parent, SWT.NONE);
- amountLabel.setText("Number of cells: ");
- Text amountText = new Text(parent, SWT.BORDER | SWT.SEARCH);
- amountText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
- amountText.addVerifyListener(vl);
- amountText.setText("0");
- amountText.addModifyListener(e ->
- {
- try
- {
- provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
- viewer.refresh();
- }
- catch (NumberFormatException ex)
- {
- // Nothing to do here
- }
- });
- new RadixSelector(parent, displaySettings);
- }
-
- private void createViewer(Composite parent)
- {
- viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
- createColumns();
- Table table = viewer.getTable();
- table.setHeaderVisible(true);
- table.setLinesVisible(true);
- viewer.setUseHashlookup(true);
- viewer.setContentProvider(provider);
- bindMainMemory(new WordAddressableMemory(MainMemoryDefinition.create(8, 8, 8L, Long.MAX_VALUE)));
- getSite().setSelectionProvider(viewer);
-
- GridData gd = new GridData();
- gd.verticalAlignment = GridData.FILL;
- gd.horizontalSpan = 6;
- gd.grabExcessHorizontalSpace = true;
- gd.grabExcessVerticalSpace = true;
- gd.horizontalAlignment = GridData.FILL;
- viewer.getControl().setLayoutData(gd);
- }
-
- private void createColumns()
- {
- String[] titles = { "Address", "Data" };
- int[] bounds = { 100, 100 };
-
- TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0]);
- col.setLabelProvider(new AddressLabelProvider());
-
- col = createTableViewerColumn(titles[1], bounds[1]);
- col.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
- {
- @Override
- public BigInteger getAsBigInteger(Object element)
- {
- MemoryTableRow row = (MemoryTableRow) element;
- return row.getMemory().getCellAsBigInteger(row.address);
- }
-
- @Override
- public int getBitLength(Object element)
- {
- return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
- }
-
- });
- col.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
- }
-
- 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;
- }
-
- @Override
- public void setFocus()
- {
- viewer.getControl().setFocus();
- }
-
- private void bindMainMemory(MainMemory m)
- {
- viewer.setInput(m);
- }
-
- private void setupContextBinding()
- {
- MachineContext.getInstance().registerObserver(this);
- setMachine(Optional.ofNullable(MachineContext.getInstance().getMachine()));
- }
-
- @Override
- public void setMachine(Optional<Machine> machine)
- {
- if (machine.isPresent())
- bindMainMemory(machine.get().getMainMemory());
- }
-}
{
case "net.mograsim.logic.model.debug.hlsshelldepth":
return 0;
+ case "net.mograsim.logic.model.button.action":
+ return 3;
+ case "net.mograsim.logic.model.button.drag":
+ return 1;
+ case "net.mograsim.logic.model.button.zoom":
+ return 2;
+ case "net.mograsim.plugin.core.simspeedprecision":
+ return 6;
default:
throw new IllegalArgumentException("Unknown int preference name: " + name);
}