Completely changed the structure and switched to Eclipse Plugin.
[Mograsim.git] / net.mograsim.logic.ui.am2900 / test / net / mograsim / logic / ui / am2900 / TestableAm2901Impl.java
1 package net.mograsim.logic.ui.am2900;\r
2 \r
3 import static org.junit.jupiter.api.Assertions.fail;\r
4 \r
5 import java.lang.reflect.Field;\r
6 import java.util.HashMap;\r
7 import java.util.HashSet;\r
8 import java.util.Objects;\r
9 import java.util.Set;\r
10 import java.util.TreeSet;\r
11 \r
12 import net.mograsim.logic.core.components.BitDisplay;\r
13 import net.mograsim.logic.core.components.ManualSwitch;\r
14 import net.mograsim.logic.core.timeline.Timeline;\r
15 import net.mograsim.logic.core.types.Bit;\r
16 import net.mograsim.logic.core.types.BitVector;\r
17 import net.mograsim.logic.core.types.BitVector.BitVectorMutator;\r
18 import net.mograsim.logic.ui.model.ModelVisitor;\r
19 import net.mograsim.logic.ui.model.ViewModel;\r
20 import net.mograsim.logic.ui.model.ViewModelModifiable;\r
21 import net.mograsim.logic.ui.model.components.GUIBitDisplay;\r
22 import net.mograsim.logic.ui.model.components.GUIComponent;\r
23 import net.mograsim.logic.ui.model.components.GUIManualSwitch;\r
24 import net.mograsim.logic.ui.model.components.SimpleRectangularGUIGate;\r
25 import net.mograsim.logic.ui.model.components.SimpleRectangularSubmodelComponent;\r
26 import net.mograsim.logic.ui.model.components.SubmodelInterface;\r
27 import net.mograsim.logic.ui.model.components.mi.nandbased.am2901.GUIAm2901;\r
28 import net.mograsim.logic.ui.model.wires.GUIWire;\r
29 import net.mograsim.logic.ui.model.wires.WireCrossPoint;\r
30 import net.mograsim.logic.ui.modeladapter.LogicModelParameters;\r
31 import net.mograsim.logic.ui.modeladapter.ViewLogicModelAdapter;\r
32 \r
33 public class TestableAm2901Impl implements TestableAm2901\r
34 {\r
35         private GUIAm2901 am2901;\r
36         private Timeline timeline;\r
37         private ManualSwitch I8, I7, I6, I5, I4, I3, I2, I1, I0;\r
38         private ManualSwitch C;\r
39         private ManualSwitch Cn;\r
40         private ManualSwitch D1, D2, D3, D4;\r
41         private ManualSwitch A0, A1, A2, A3;\r
42         private ManualSwitch B0, B1, B2, B3;\r
43         private ManualSwitch IRAMn, IRAMn_3, IQn, IQn_3;\r
44         private BitDisplay Y1, Y2, Y3, Y4;\r
45         private BitDisplay F_0, Cn_4, OVR, F3;\r
46         private BitDisplay ORAMn, ORAMn_3, OQn, OQn_3;\r
47 \r
48         private Set<GUIWire> allWires;\r
49         private Set<GUIComponent> allComponents;\r
50 \r
51         private Set<String> wireDebugChangeSet;\r
52         private boolean debugWires = false;\r
53         public int debugEventThreshold = 10_000;\r
54         public int debugEventCount = 500;\r
55 \r
56         private int eventCounter;\r
57 \r
58         @Override\r
59         public Result run()\r
60         {\r
61                 // Normal execution until completion or eventLimit\r
62                 int eventLimit = debugEventThreshold;\r
63                 eventCounter = 0;\r
64                 debugWires = false;\r
65                 while (eventCounter < eventLimit)\r
66                 {\r
67                         timeline.executeNext();\r
68                         if (!timeline.hasNext())\r
69                         {\r
70                                 System.out.println("run() took " + eventCounter + " events");\r
71                                 return Result.SUCCESS;\r
72                         }\r
73                 }\r
74                 // Start debugging if event limit is reached\r
75                 debugWires = true;\r
76                 wireDebugChangeSet = new TreeSet<>();\r
77                 Set<String> oldChangeSet;\r
78                 // observe wire changes to detect, if we are really stuck in an endless loop\r
79                 do\r
80                 {\r
81                         eventLimit += debugEventCount;\r
82                         oldChangeSet = wireDebugChangeSet;\r
83                         wireDebugChangeSet = new TreeSet<>();\r
84                         while (eventCounter < eventLimit)\r
85                         {\r
86                                 timeline.executeNext();\r
87                                 if (!timeline.hasNext())\r
88                                 {\r
89                                         // no endless loop, but more events needed than expected\r
90                                         System.out.println("run() took longer than expected: " + eventCounter);\r
91                                         return Result.SUCCESS;\r
92                                 }\r
93                         }\r
94                 } while (!oldChangeSet.equals(wireDebugChangeSet));\r
95                 // if stuck, abort execution and print wires\r
96                 System.err.print("Problematic Wire updates:");\r
97                 wireDebugChangeSet.forEach(System.out::println);\r
98                 System.err.println("run() failed: " + eventCounter);\r
99                 return Result.OUT_OF_TIME;\r
100         }\r
101 \r
102         @SuppressWarnings("unused")\r
103         @Override\r
104         public void setup()\r
105         {\r
106                 // Create view model\r
107                 ViewModelModifiable viewModel = new ViewModelModifiable();\r
108                 am2901 = new GUIAm2901(viewModel);\r
109                 // Get switches\r
110                 HashMap<String, GUIManualSwitch> idSwitchMap = new HashMap<>();\r
111                 for (String id : am2901.getInputPinNames())\r
112                 {\r
113                         GUIManualSwitch sw = new GUIManualSwitch(viewModel);\r
114                         new GUIWire(viewModel, am2901.getPin(id), sw.getOutputPin());\r
115                         idSwitchMap.put(id, sw);\r
116                 }\r
117                 // Get displays\r
118                 HashMap<String, GUIBitDisplay> idDisplayMap = new HashMap<>();\r
119                 for (String id : am2901.getOutputPinNames())\r
120                 {\r
121                         GUIBitDisplay bd = new GUIBitDisplay(viewModel);\r
122                         new GUIWire(viewModel, am2901.getPin(id), bd.getInputPin());\r
123                         idDisplayMap.put(id, bd);\r
124                 }\r
125                 // Create logic model\r
126                 LogicModelParameters params = new LogicModelParameters();\r
127                 params.gateProcessTime = 50;\r
128                 params.wireTravelTime = 10;\r
129                 timeline = ViewLogicModelAdapter.convert(viewModel, params);\r
130                 // Bind switches/displays to this test class\r
131                 for (var entry : idSwitchMap.entrySet())\r
132                         setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getManualSwitch());\r
133                 for (var entry : idDisplayMap.entrySet())\r
134                         setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getBitDisplay());\r
135                 // Switch Clock off first\r
136                 C.switchOff();\r
137 \r
138                 // Debug code\r
139                 allWires = new HashSet<>();\r
140                 allComponents = new HashSet<>();\r
141                 ModelAccumulator accumulator = new ModelAccumulator();\r
142                 accumulator.visit(viewModel);\r
143                 allWires.forEach(w -> w.addRedrawListener(() ->\r
144                 {\r
145                         if (debugWires)\r
146                         {\r
147                                 System.out.println(w);\r
148                                 wireDebugChangeSet.add(w.toString());\r
149                         }\r
150                 }));\r
151                 timeline.addEventAddedListener(te -> eventCounter++);\r
152         }\r
153 \r
154         @Override\r
155         public void setDest(Am2901_Dest dest)\r
156         {\r
157                 var bits = of(dest.ordinal(), 3);\r
158                 I8.setToValueOf(bits.getBit(0));\r
159                 I7.setToValueOf(bits.getBit(1));\r
160                 I6.setToValueOf(bits.getBit(2));\r
161         }\r
162 \r
163         @Override\r
164         public void setFunc(Am2901_Func func)\r
165         {\r
166                 var bits = of(func.ordinal(), 3);\r
167                 I5.setToValueOf(bits.getBit(0));\r
168                 I4.setToValueOf(bits.getBit(1));\r
169                 I3.setToValueOf(bits.getBit(2));\r
170         }\r
171 \r
172         @Override\r
173         public void setSrc(Am2901_Src src)\r
174         {\r
175                 var bits = of(src.ordinal(), 3);\r
176                 I2.setToValueOf(bits.getBit(0));\r
177                 I1.setToValueOf(bits.getBit(1));\r
178                 I0.setToValueOf(bits.getBit(2));\r
179         }\r
180 \r
181         @Override\r
182         public void setReg_A(String val_4_bit)\r
183         {\r
184                 var bits = BitVector.parse(val_4_bit);\r
185                 A3.setToValueOf(bits.getBit(0));\r
186                 A2.setToValueOf(bits.getBit(1));\r
187                 A1.setToValueOf(bits.getBit(2));\r
188                 A0.setToValueOf(bits.getBit(3));\r
189         }\r
190 \r
191         @Override\r
192         public void setReg_B(String val_4_bit)\r
193         {\r
194                 var bits = BitVector.parse(val_4_bit);\r
195                 B3.setToValueOf(bits.getBit(0));\r
196                 B2.setToValueOf(bits.getBit(1));\r
197                 B1.setToValueOf(bits.getBit(2));\r
198                 B0.setToValueOf(bits.getBit(3));\r
199         }\r
200 \r
201         @Override\r
202         public void setCarryIn(String val_1_bit)\r
203         {\r
204                 Cn.setToValueOf(Bit.parse(val_1_bit));\r
205         }\r
206 \r
207         @Override\r
208         public void setNotOutEnable(String val_1_bit)\r
209         {\r
210                 throw new UnsupportedOperationException(); // TODO\r
211         }\r
212 \r
213         @Override\r
214         public void setD(String val_4_bit)\r
215         {\r
216                 var bits = BitVector.parse(val_4_bit);\r
217                 D4.setToValueOf(bits.getBit(0));\r
218                 D3.setToValueOf(bits.getBit(1));\r
219                 D2.setToValueOf(bits.getBit(2));\r
220                 D1.setToValueOf(bits.getBit(3));\r
221         }\r
222 \r
223         @Override\r
224         public void setQ_0(String val_1_bit)\r
225         {\r
226                 IQn.setToValueOf(Bit.parse(val_1_bit));\r
227         }\r
228 \r
229         @Override\r
230         public void setQ_3(String val_1_bit)\r
231         {\r
232                 IQn_3.setToValueOf(Bit.parse(val_1_bit));\r
233         }\r
234 \r
235         @Override\r
236         public void setRAM_0(String val_1_bit)\r
237         {\r
238                 IRAMn.setToValueOf(Bit.parse(val_1_bit));\r
239         }\r
240 \r
241         @Override\r
242         public void setRAM_3(String val_1_bit)\r
243         {\r
244                 IRAMn_3.setToValueOf(Bit.parse(val_1_bit));\r
245         }\r
246 \r
247         @Override\r
248         public void toogleClock()\r
249         {\r
250                 C.toggle();\r
251         }\r
252 \r
253         @Override\r
254         public String getQ_0()\r
255         {\r
256                 return OQn.getDisplayedValue().toString();\r
257         }\r
258 \r
259         @Override\r
260         public String getQ_3()\r
261         {\r
262                 return OQn_3.getDisplayedValue().toString();\r
263         }\r
264 \r
265         @Override\r
266         public String getRAM_0()\r
267         {\r
268                 return ORAMn.getDisplayedValue().toString();\r
269         }\r
270 \r
271         @Override\r
272         public String getRAM_3()\r
273         {\r
274                 return ORAMn_3.getDisplayedValue().toString();\r
275         }\r
276 \r
277         @Override\r
278         public String getNotP()\r
279         {\r
280                 throw new UnsupportedOperationException(); // TODO\r
281         }\r
282 \r
283         @Override\r
284         public String getNotG()\r
285         {\r
286                 throw new UnsupportedOperationException(); // TODO\r
287         }\r
288 \r
289         @Override\r
290         public String getCarryOut()\r
291         {\r
292                 return Cn_4.getDisplayedValue().toString();\r
293         }\r
294 \r
295         @Override\r
296         public String getSign()\r
297         {\r
298                 return F3.getDisplayedValue().toString();\r
299         }\r
300 \r
301         @Override\r
302         public String getZero()\r
303         {\r
304                 return F_0.getDisplayedValue().toString();\r
305         }\r
306 \r
307         @Override\r
308         public String getOverflow()\r
309         {\r
310                 return OVR.getDisplayedValue().toString();\r
311         }\r
312 \r
313         @Override\r
314         public String getY()\r
315         {\r
316                 var y3 = Y4.getDisplayedValue();\r
317                 var y2 = Y3.getDisplayedValue();\r
318                 var y1 = Y2.getDisplayedValue();\r
319                 var y0 = Y1.getDisplayedValue();\r
320                 return y3.concat(y2).concat(y1).concat(y0).toString();\r
321         }\r
322 \r
323         private void setField(String name, Object value)\r
324         {\r
325                 try\r
326                 {\r
327                         Field f = TestableAm2901Impl.class.getDeclaredField(name);\r
328                         f.setAccessible(true);\r
329                         f.set(this, Objects.requireNonNull(value));\r
330                 }\r
331                 catch (Exception e)\r
332                 {\r
333                         fail(e);\r
334                 }\r
335         }\r
336 \r
337         private static BitVector of(int value, int length)\r
338         {\r
339                 BitVectorMutator mutator = BitVectorMutator.ofLength(length);\r
340                 int val = value;\r
341                 for (int i = length - 1; i >= 0; i--)\r
342                 {\r
343                         mutator.setBit(i, Bit.lastBitOf(val));\r
344                         val >>>= 1;\r
345                 }\r
346                 return mutator.toBitVector();\r
347         }\r
348 \r
349         class ModelAccumulator implements ModelVisitor\r
350         {\r
351                 @Override\r
352                 public void visit(GUIWire w)\r
353                 {\r
354                         allWires.add(w);\r
355                 }\r
356 \r
357                 @Override\r
358                 public void visit(SimpleRectangularGUIGate simpleRectangularGUIGate)\r
359                 {\r
360                         allComponents.add(simpleRectangularGUIGate);\r
361                 }\r
362 \r
363                 @Override\r
364                 public void visit(SimpleRectangularSubmodelComponent simpleRectangularSubmodelComponent)\r
365                 {\r
366                         allComponents.add(simpleRectangularSubmodelComponent);\r
367                         simpleRectangularSubmodelComponent.getWires().forEach(w -> w.accept(this));\r
368                         simpleRectangularSubmodelComponent.getComponents().forEach(w -> w.accept(this));\r
369                 }\r
370 \r
371                 @Override\r
372                 public void visit(WireCrossPoint wireCrossPoint)\r
373                 {\r
374                         // nothing\r
375                 }\r
376 \r
377                 @Override\r
378                 public void visit(GUIBitDisplay guiBitDisplay)\r
379                 {\r
380                         allComponents.add(guiBitDisplay);\r
381                 }\r
382 \r
383                 @Override\r
384                 public void visit(GUIManualSwitch guiManualSwitch)\r
385                 {\r
386                         allComponents.add(guiManualSwitch);\r
387                 }\r
388 \r
389                 @Override\r
390                 public void visit(SubmodelInterface submodelInterface)\r
391                 {\r
392                         // nothing\r
393                 }\r
394 \r
395                 @Override\r
396                 public void visit(ViewModel viewModel)\r
397                 {\r
398                         viewModel.getWires().forEach(w -> w.accept(this));\r
399                         viewModel.getComponents().forEach(w -> w.accept(this));\r
400                 }\r
401         }\r
402 }\r