59e22f83dae8fa92cacd4b5cc15ad1aa50893574
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / launch / MachineRegister.java
1 package net.mograsim.plugin.launch;
2
3 import java.math.BigInteger;
4 import java.util.Arrays;
5 import java.util.function.Consumer;
6
7 import org.eclipse.core.runtime.IStatus;
8 import org.eclipse.core.runtime.PlatformObject;
9 import org.eclipse.core.runtime.Status;
10 import org.eclipse.debug.core.DebugEvent;
11 import org.eclipse.debug.core.DebugException;
12 import org.eclipse.debug.core.DebugPlugin;
13 import org.eclipse.debug.core.ILaunch;
14 import org.eclipse.debug.core.model.IDebugElement;
15 import org.eclipse.debug.core.model.IDebugTarget;
16 import org.eclipse.debug.core.model.IRegister;
17 import org.eclipse.debug.core.model.IRegisterGroup;
18 import org.eclipse.debug.core.model.IValue;
19 import org.eclipse.swt.SWT;
20
21 import net.mograsim.logic.core.types.BitVector;
22 import net.mograsim.machine.Machine;
23 import net.mograsim.machine.registers.Register;
24 import net.mograsim.plugin.MograsimActivator;
25
26 public class MachineRegister extends PlatformObject implements IRegister
27 {
28         private final MachineRegisterGroup registerGroup;
29         private final Register machineRegister;
30
31         private final Consumer<BitVector> registerListener;
32
33         public MachineRegister(MachineRegisterGroup registerGroup, Register machineRegister)
34         {
35                 this.registerGroup = registerGroup;
36                 this.machineRegister = machineRegister;
37
38                 this.registerListener = v -> fireChangeEvent();
39                 getMachine().addRegisterListener(machineRegister, registerListener);
40
41                 DebugPlugin.getDefault().addDebugEventListener(es -> Arrays.stream(es).filter(e -> e.getKind() == DebugEvent.TERMINATE).filter(e ->
42                 {
43                         Object source = e.getSource();
44                         if (!(source instanceof IDebugElement))
45                                 return false;
46                         return ((IDebugElement) source).getDebugTarget() == getDebugTarget();
47                 }).forEach(e -> getMachine().removeRegisterListener(machineRegister, registerListener)));
48         }
49
50         public Machine getMachine()
51         {
52                 return registerGroup.getMachine();
53         }
54
55         @Override
56         public IValue getValue() throws DebugException
57         {
58                 return new MachineValue(this);
59         }
60
61         @Override
62         public String getName() throws DebugException
63         {
64                 return machineRegister.id();// TODO name
65         }
66
67         @Override
68         public String getReferenceTypeName() throws DebugException
69         {
70                 return "BitVector";
71         }
72
73         @Override
74         public boolean hasValueChanged() throws DebugException
75         {
76                 // TODO
77                 return false;
78         }
79
80         @Override
81         public String getModelIdentifier()
82         {
83                 return MograsimActivator.PLUGIN_ID;
84         }
85
86         @Override
87         public IDebugTarget getDebugTarget()
88         {
89                 return registerGroup.getDebugTarget();
90         }
91
92         @Override
93         public ILaunch getLaunch()
94         {
95                 return registerGroup.getLaunch();
96         }
97
98         public String getValueString()
99         {
100                 BitVector bitvector = getMachine().getRegister(machineRegister);
101                 if (bitvector.isBinary())
102                 {
103                         String hexdigits = bitvector.getUnsignedValue().toString(16);
104                         StringBuilder sb = new StringBuilder();
105                         sb.append("0x");
106                         sb.append("0".repeat((machineRegister.getWidth() + 3) / 4 - hexdigits.length()));
107                         sb.append(hexdigits);
108                         return sb.toString();
109                 }
110                 return bitvector.toString();
111         }
112
113         @Override
114         public void setValue(String expression) throws DebugException
115         {
116                 BitVector bitvector = parseValue(expression);
117                 if (bitvector == null)
118                         throw new DebugException(
119                                         new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "Couldn't parse value string: " + expression, null));
120                 getMachine().setRegister(machineRegister, bitvector);
121         }
122
123         private BitVector parseValue(String expression)
124         {
125                 BitVector bitvector = null;
126                 if (expression.matches("0x[0-9a-fA-F]+"))
127                         // TODO should we check for overflows?
128                         bitvector = BitVector.from(new BigInteger(expression.substring(2), 16), machineRegister.getWidth());
129                 else if (expression.length() == machineRegister.getWidth())
130                         // TODO do this without exceptions
131                         try
132                         {
133                                 bitvector = BitVector.parse(expression);
134                         }
135                         catch (@SuppressWarnings("unused") NullPointerException x)
136                         {
137                                 // ignore
138                         }
139                 if (bitvector == null)
140                         try
141                         {
142                                 // TODO should we check for overflows?
143                                 bitvector = BitVector.from(new BigInteger(expression), machineRegister.getWidth());
144                         }
145                         catch (@SuppressWarnings("unused") NumberFormatException x)
146                         {
147                                 // ignore
148                         }
149                 return bitvector;
150         }
151
152         @Override
153         public void setValue(IValue value) throws DebugException
154         {
155                 if (!"Bitvector".equals(value.getReferenceTypeName()))
156                         throw new DebugException(new Status(SWT.ERROR, MograsimActivator.PLUGIN_ID, ""));
157                 setValue(value.getValueString());
158         }
159
160         @Override
161         public boolean supportsValueModification()
162         {
163                 return true;
164         }
165
166         @Override
167         public boolean verifyValue(String expression) throws DebugException
168         {
169                 return parseValue(expression) != null;
170         }
171
172         @Override
173         public boolean verifyValue(IValue value) throws DebugException
174         {
175                 return verifyValue(value.getValueString());
176         }
177
178         @Override
179         public IRegisterGroup getRegisterGroup() throws DebugException
180         {
181                 return registerGroup;
182         }
183
184         /**
185          * Fires a change event for this debug element.
186          */
187         private void fireChangeEvent()
188         {
189                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
190         }
191
192         /**
193          * Fires a debug event.
194          *
195          * @param event debug event to fire
196          */
197         private static void fireEvent(DebugEvent event)
198         {
199                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { event });
200         }
201 }