Made main memory access via the Memory view work
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / launch / MachineProcess.java
1 package net.mograsim.plugin.launch;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.eclipse.core.runtime.IStatus;
7 import org.eclipse.core.runtime.PlatformObject;
8 import org.eclipse.core.runtime.Status;
9 import org.eclipse.debug.core.DebugEvent;
10 import org.eclipse.debug.core.DebugException;
11 import org.eclipse.debug.core.DebugPlugin;
12 import org.eclipse.debug.core.ILaunch;
13 import org.eclipse.debug.core.ILaunchConfiguration;
14 import org.eclipse.debug.core.model.IDebugTarget;
15 import org.eclipse.debug.core.model.IProcess;
16 import org.eclipse.debug.core.model.IStreamsProxy;
17 import org.eclipse.debug.core.model.ISuspendResume;
18
19 import net.mograsim.logic.model.LogicExecuter;
20 import net.mograsim.machine.Machine;
21 import net.mograsim.machine.MachineDefinition;
22 import net.mograsim.plugin.MograsimActivator;
23
24 public class MachineProcess extends PlatformObject implements IProcess, ISuspendResume
25 {
26         private final ILaunch launch;
27         private final Machine machine;
28         private final LogicExecuter exec;
29
30         private boolean running;
31
32         public MachineProcess(ILaunch launch, MachineDefinition machineDefinition)
33         {
34                 this.launch = launch;
35                 this.machine = machineDefinition.createNew();
36                 this.exec = new LogicExecuter(machine.getTimeline());
37
38                 exec.startLiveExecution();
39                 running = true;
40
41                 launch.addProcess(this);
42                 fireCreationEvent();
43         }
44
45         public Machine getMachine()
46         {
47                 return machine;
48         }
49
50         @Override
51         public ILaunch getLaunch()
52         {
53                 return launch;
54         }
55
56         public String getName()
57         {
58                 return "Mograsim machine \"" + machine.getDefinition().getId() + '"';
59         }
60
61         @Override
62         public String getLabel()
63         {
64                 return getName() + " (" + getStatusString() + ')';
65         }
66
67         public String getStatusString()
68         {
69                 return isTerminated() ? "terminated" : isSuspended() ? "paused" : "running";
70         }
71
72         public void setExecutionSpeed(double speed)
73         {
74                 exec.setSpeedFactor(speed);
75         }
76
77         @Override
78         public boolean isSuspended()
79         {
80                 return exec.isPaused();
81         }
82
83         @Override
84         public boolean canSuspend()
85         {
86                 return !isTerminated() && !isSuspended();
87         }
88
89         @Override
90         public void suspend() throws DebugException
91         {
92                 if (isTerminated())
93                         throwDebugException("Can't suspend a terminated MachineProcess");
94                 if (isSuspended())
95                         throwDebugException("Can't suspend a suspended MachineProcess");
96
97                 exec.pauseLiveExecution();
98                 fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
99         }
100
101         @Override
102         public boolean canResume()
103         {
104                 return !isTerminated() && isSuspended();
105         }
106
107         @Override
108         public void resume() throws DebugException
109         {
110                 if (isTerminated())
111                         throwDebugException("Can't resume a terminated MachineProcess");
112                 if (!isSuspended())
113                         throwDebugException("Can't resume a non-suspended MachineProcess");
114
115                 exec.unpauseLiveExecution();
116                 fireResumeEvent(DebugEvent.CLIENT_REQUEST);
117         }
118
119         @Override
120         public boolean isTerminated()
121         {
122                 return !running;
123         }
124
125         @Override
126         public boolean canTerminate()
127         {
128                 return !isTerminated();
129         }
130
131         @Override
132         public void terminate() throws DebugException
133         {
134                 if (isTerminated())
135                         return;
136
137                 exec.stopLiveExecution();
138                 running = false;
139                 fireTerminateEvent();
140         }
141
142         @Override
143         public int getExitValue() throws DebugException
144         {
145                 if (!isTerminated())
146                         throwDebugException("Can't get the exit value of a running process");
147
148                 return 0;
149         }
150
151         @Override
152         public IStreamsProxy getStreamsProxy()
153         {
154                 return null;
155         }
156
157         private Map<String, String> attributes;
158
159         @Override
160         public void setAttribute(String key, String value)
161         {
162                 if (attributes == null)
163                         attributes = new HashMap<>(5);
164                 Object origVal = attributes.get(key);
165                 if (origVal != null && origVal.equals(value))
166                         return;
167                 attributes.put(key, value);
168                 fireChangeEvent();
169         }
170
171         @Override
172         public String getAttribute(String key)
173         {
174                 if (attributes == null)
175                         return null;
176                 return attributes.get(key);
177         }
178
179         @SuppressWarnings("unchecked")
180         @Override
181         public <T> T getAdapter(Class<T> adapter)
182         {
183                 if (adapter.equals(IProcess.class))
184                         return (T) this;
185
186                 if (adapter.equals(IDebugTarget.class))
187                 {
188                         ILaunch launch = getLaunch();
189                         IDebugTarget[] targets = launch.getDebugTargets();
190                         for (int i = 0; i < targets.length; i++)
191                                 if (this.equals(targets[i].getProcess()))
192                                         return (T) targets[i];
193                         return null;
194                 }
195
196                 if (adapter.equals(ILaunch.class))
197                         return (T) getLaunch();
198
199                 if (adapter.equals(ILaunchConfiguration.class))
200                         return (T) getLaunch().getLaunchConfiguration();
201
202                 return super.getAdapter(adapter);
203         }
204
205         /**
206          * Fires a creation event.
207          */
208         private void fireCreationEvent()
209         {
210                 fireEvent(new DebugEvent(this, DebugEvent.CREATE));
211         }
212
213         /**
214          * Fires a change event.
215          */
216         private void fireChangeEvent()
217         {
218                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
219         }
220
221         /**
222          * Fires a resume for this debug element with the specified detail code.
223          *
224          * @param detail detail code for the resume event, such as <code>DebugEvent.STEP_OVER</code>
225          */
226         private void fireResumeEvent(int detail)
227         {
228                 fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
229         }
230
231         /**
232          * Fires a suspend event for this debug element with the specified detail code.
233          *
234          * @param detail detail code for the suspend event, such as <code>DebugEvent.BREAKPOINT</code>
235          */
236         private void fireSuspendEvent(int detail)
237         {
238                 fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
239         }
240
241         /**
242          * Fires a terminate event.
243          */
244         private void fireTerminateEvent()
245         {
246                 fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
247         }
248
249         /**
250          * Fires the given debug event.
251          *
252          * @param event debug event to fire
253          */
254         private static void fireEvent(DebugEvent event)
255         {
256                 DebugPlugin manager = DebugPlugin.getDefault();
257                 if (manager != null)
258                         manager.fireDebugEventSet(new DebugEvent[] { event });
259         }
260
261         private static void throwDebugException(String message) throws DebugException
262         {
263                 throw new DebugException(
264                                 new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED, message, null));
265         }
266 }