1 package net.mograsim.plugin.views;
3 import java.util.HashSet;
5 import java.util.function.Consumer;
7 import org.eclipse.core.runtime.SafeRunner;
8 import org.eclipse.debug.core.ILaunch;
9 import org.eclipse.debug.core.model.IDebugTarget;
10 import org.eclipse.debug.ui.DebugUITools;
11 import org.eclipse.debug.ui.contexts.IDebugContextListener;
12 import org.eclipse.debug.ui.contexts.IDebugContextManager;
13 import org.eclipse.debug.ui.contexts.IDebugContextService;
14 import org.eclipse.jface.viewers.ISelection;
15 import org.eclipse.jface.viewers.TreeSelection;
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.layout.FillLayout;
18 import org.eclipse.swt.layout.GridData;
19 import org.eclipse.swt.layout.GridLayout;
20 import org.eclipse.swt.widgets.Button;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Label;
24 import org.eclipse.swt.widgets.Scale;
25 import org.eclipse.ui.PlatformUI;
26 import org.eclipse.ui.part.ViewPart;
28 import net.haspamelodica.swt.helper.input.DoubleInput;
29 import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;
30 import net.mograsim.logic.core.LogicObserver;
31 import net.mograsim.logic.core.components.CoreClock;
32 import net.mograsim.logic.model.LogicUICanvas;
33 import net.mograsim.machine.Machine;
34 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
35 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
36 import net.mograsim.plugin.launch.MachineDebugTarget;
37 import net.mograsim.plugin.tables.DisplaySettings;
38 import net.mograsim.plugin.tables.mi.ActiveInstructionPreviewContentProvider;
39 import net.mograsim.plugin.tables.mi.InstructionTable;
40 import net.mograsim.plugin.util.OverlappingFillLayout;
41 import net.mograsim.preferences.Preferences;
43 public class SimulationView extends ViewPart
45 private static final int SIM_SPEED_SCALE_STEPS = 50;
46 private static final double SIM_SPEED_SCALE_STEP_FACTOR = 1.32;
47 private static final double SIM_SPEED_SCALE_STEP_FACTOR_LOG = Math.log(SIM_SPEED_SCALE_STEP_FACTOR);
49 private final Set<Control> controlsToDisableWhenNoMachinePresent;
50 private Button sbseButton;
51 private Scale simSpeedScale;
52 private DoubleInput simSpeedInput;
53 private Composite contextDependentControlsParent;
54 private Composite canvasParent;
55 private InstructionTable instPreview;
56 private ActiveInstructionPreviewContentProvider contentProvider;
57 private Label noRunningMachineLabel;
59 private MachineDebugTarget debugTarget;
60 private LogicUICanvas canvas;
62 private final MemoryCellModifiedListener memCellListener;
63 private final LogicObserver clockObserver;
64 private final IDebugContextListener debugContextListener;
65 private final Consumer<Double> executionSpeedListener;
67 public SimulationView()
69 controlsToDisableWhenNoMachinePresent = new HashSet<>();
70 memCellListener = a -> instPreview.refresh();
71 // TODO could this be a breakpoint?
74 if (((CoreClock) o).isOn())
75 SafeRunner.run(() -> debugTarget.suspend());
77 debugContextListener = e -> debugContextChanged(e.getContext());
78 executionSpeedListener = this::speedFactorChanged;
82 public void createPartControl(Composite parent)
85 parent.setLayout(new GridLayout());
87 addSimulationControlWidgets(parent);
89 Composite contextDependentControlsParentParent = new Composite(parent, SWT.NONE);
90 contextDependentControlsParentParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
91 contextDependentControlsParentParent.setLayout(new OverlappingFillLayout());
93 noRunningMachineLabel = new Label(contextDependentControlsParentParent, SWT.NONE);
94 noRunningMachineLabel.setText("No machine running && selected in the Debug view...");
96 contextDependentControlsParent = new Composite(contextDependentControlsParentParent, SWT.NONE);
97 GridLayout contexDependentControlsLayout = new GridLayout();
98 contexDependentControlsLayout.marginWidth = 0;
99 contexDependentControlsLayout.marginHeight = 0;
100 contextDependentControlsParent.setLayout(contexDependentControlsLayout);
102 canvasParent = new Composite(contextDependentControlsParent, SWT.NONE);
103 canvasParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
104 canvasParent.setLayout(new FillLayout());
106 addInstructionPreviewControlWidgets(contextDependentControlsParent);
108 IDebugContextManager debugCManager = DebugUITools.getDebugContextManager();
109 IDebugContextService contextService = debugCManager.getContextService(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
110 contextService.addDebugContextListener(debugContextListener);
111 debugContextChanged(contextService.getActiveContext());
114 private void addSimulationControlWidgets(Composite parent)
116 Composite c = new Composite(parent, SWT.NONE);
117 c.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
118 c.setLayout(new GridLayout(7, false));
120 sbseButton = new Button(c, SWT.CHECK);
121 controlsToDisableWhenNoMachinePresent.add(sbseButton);
123 sbseButton.setText("Step by step execution");
124 sbseButton.addListener(SWT.Selection, e ->
126 CoreClock cl = debugTarget.getMachine().getClock();
127 if (sbseButton.getSelection())
128 cl.registerObserver(clockObserver);
130 cl.deregisterObserver(clockObserver);
132 sbseButton.setSelection(false);
134 Label simSpeedLabel = new Label(c, SWT.NONE);
135 controlsToDisableWhenNoMachinePresent.add(simSpeedLabel);
136 simSpeedLabel.setText("Simulation Speed: ");
138 simSpeedScale = new Scale(c, SWT.NONE);
139 controlsToDisableWhenNoMachinePresent.add(simSpeedScale);
140 simSpeedScale.setMinimum(0);
141 simSpeedScale.setMaximum(SIM_SPEED_SCALE_STEPS);
142 simSpeedScale.setIncrement(1);
143 simSpeedScale.setSelection(0);
144 simSpeedScale.addListener(SWT.Selection, e ->
146 double speed = Math.pow(SIM_SPEED_SCALE_STEP_FACTOR, simSpeedScale.getSelection() - SIM_SPEED_SCALE_STEPS);
147 debugTarget.setExecutionSpeed(speed);
150 simSpeedInput = new DoubleInput(c, SWT.NONE);
151 controlsToDisableWhenNoMachinePresent.add(simSpeedInput);
152 simSpeedInput.setPrecision(Preferences.current().getInt("net.mograsim.plugin.core.simspeedprecision"));
153 simSpeedInput.addChangeListener(speed ->
156 debugTarget.setExecutionSpeed(speed);
158 debugTarget.setExecutionSpeed(Math.pow(10, -simSpeedInput.getPrecision()));
164 private void speedFactorChanged(double speed)
166 simSpeedInput.setValue(speed);
167 int closestScalePos = (int) Math.round(Math.log(speed) / SIM_SPEED_SCALE_STEP_FACTOR_LOG + SIM_SPEED_SCALE_STEPS);
168 simSpeedScale.setSelection(Math.min(Math.max(closestScalePos, 0), SIM_SPEED_SCALE_STEPS));
171 private void addInstructionPreviewControlWidgets(Composite parent)
173 instPreview = new InstructionTable(parent, new DisplaySettings(), getSite().getWorkbenchWindow().getWorkbench().getThemeManager());
174 instPreview.getTableViewer().getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
175 contentProvider = new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer());
176 instPreview.setContentProvider(contentProvider);
179 private void debugContextChanged(ISelection selection)
181 if (selection != null && selection instanceof TreeSelection)
183 TreeSelection treeSelection = (TreeSelection) selection;
184 Object[] selectedElements = treeSelection.toArray();
185 for (Object selectedElement : selectedElements)
187 MachineDebugTarget debugTarget;
188 if (selectedElement instanceof MachineDebugTarget)
189 debugTarget = (MachineDebugTarget) selectedElement;
190 else if (selectedElement instanceof ILaunch)
192 ILaunch launch = (ILaunch) selectedElement;
193 IDebugTarget genericDebugTarget = launch.getDebugTarget();
194 if (genericDebugTarget instanceof MachineDebugTarget)
195 debugTarget = (MachineDebugTarget) genericDebugTarget;
200 if (debugTarget.isTerminated())
202 // we found a selected MachineDebugTarget
203 if (this.debugTarget != debugTarget)
204 bindToDebugTarget(debugTarget);
208 // we didn't find a selected MachineDebugTarget
209 // call binToDebugTarget even if this.debugTarget==null
210 bindToDebugTarget(null);
213 private void bindToDebugTarget(MachineDebugTarget debugTarget)
215 this.debugTarget = debugTarget;
217 if (canvasParent == null)
218 // createPartControls has not been called yet
224 deregisterMachineDependentListeners();
227 offX = canvas.getOffX();
228 offY = canvas.getOffY();
229 zoom = canvas.getZoom();
238 if (debugTarget != null)
240 noRunningMachineLabel.setVisible(false);
241 contextDependentControlsParent.setVisible(true);
242 controlsToDisableWhenNoMachinePresent.forEach(c -> c.setEnabled(true));
244 Machine machine = debugTarget.getMachine();
246 canvas = new LogicUICanvas(canvasParent, SWT.NONE, machine.getModel());
247 canvas.addListener(SWT.MouseDown, e -> canvas.setFocus());
248 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
249 userInput.buttonDrag = Preferences.current().getInt("net.mograsim.logic.model.button.drag");
250 userInput.buttonZoom = Preferences.current().getInt("net.mograsim.logic.model.button.zoom");
251 userInput.enableUserInput();
254 canvas.moveTo(offX, offY, zoom);
255 canvas.commitTransform();
258 AssignableMicroInstructionMemory mIMemory = machine.getMicroInstructionMemory();
259 instPreview.bindMicroInstructionMemory(mIMemory);
260 mIMemory.registerCellModifiedListener(memCellListener);
262 canvasParent.layout();
265 contentProvider.setMachine(machine);
267 // initialize executer
268 debugTarget.addExecutionSpeedListener(executionSpeedListener);
269 speedFactorChanged(debugTarget.getExecutionSpeed());
272 noRunningMachineLabel.setVisible(true);
273 contextDependentControlsParent.setVisible(false);
274 controlsToDisableWhenNoMachinePresent.forEach(c -> c.setEnabled(false));
275 contentProvider.setMachine(null);
279 private void deregisterMachineDependentListeners()
281 if (debugTarget != null)
283 debugTarget.removeExecutionSpeedListener(executionSpeedListener);
284 debugTarget.getMachine().getMicroInstructionMemory().deregisterCellModifiedListener(memCellListener);
285 debugTarget.getMachine().getClock().deregisterObserver(clockObserver);
286 if (sbseButton != null && !sbseButton.isDisposed())
287 sbseButton.setSelection(false);
292 public void setFocus()
294 if (canvas != null && !canvas.isDisposed())
299 public void dispose()
301 deregisterMachineDependentListeners();
302 contentProvider.setMachine(null);
303 DebugUITools.getDebugContextManager().removeDebugContextListener(debugContextListener);