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