1 package net.mograsim.logic.ui.am2900;
3 import static org.junit.jupiter.api.Assertions.fail;
5 import java.lang.reflect.Field;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Objects;
10 import java.util.TreeSet;
12 import net.mograsim.logic.core.components.BitDisplay;
13 import net.mograsim.logic.core.components.ManualSwitch;
14 import net.mograsim.logic.core.timeline.Timeline;
15 import net.mograsim.logic.core.types.Bit;
16 import net.mograsim.logic.core.types.BitVector;
17 import net.mograsim.logic.core.types.BitVector.BitVectorMutator;
18 import net.mograsim.logic.ui.model.ModelVisitor;
19 import net.mograsim.logic.ui.model.ViewModel;
20 import net.mograsim.logic.ui.model.ViewModelModifiable;
21 import net.mograsim.logic.ui.model.components.GUIBitDisplay;
22 import net.mograsim.logic.ui.model.components.GUIComponent;
23 import net.mograsim.logic.ui.model.components.GUIManualSwitch;
24 import net.mograsim.logic.ui.model.components.SimpleRectangularGUIGate;
25 import net.mograsim.logic.ui.model.components.SimpleRectangularSubmodelComponent;
26 import net.mograsim.logic.ui.model.components.SubmodelInterface;
27 import net.mograsim.logic.ui.model.components.mi.nandbased.am2901.GUIAm2901;
28 import net.mograsim.logic.ui.model.wires.GUIWire;
29 import net.mograsim.logic.ui.model.wires.WireCrossPoint;
30 import net.mograsim.logic.ui.modeladapter.LogicModelParameters;
31 import net.mograsim.logic.ui.modeladapter.ViewLogicModelAdapter;
33 public class TestableAm2901Impl implements TestableAm2901
35 private GUIAm2901 am2901;
36 private Timeline timeline;
37 private ManualSwitch I8, I7, I6, I5, I4, I3, I2, I1, I0;
38 private ManualSwitch C;
39 private ManualSwitch Cn;
40 private ManualSwitch D1, D2, D3, D4;
41 private ManualSwitch A0, A1, A2, A3;
42 private ManualSwitch B0, B1, B2, B3;
43 private ManualSwitch IRAMn, IRAMn_3, IQn, IQn_3;
44 private BitDisplay Y1, Y2, Y3, Y4;
45 private BitDisplay F_0, Cn_4, OVR, F3;
46 private BitDisplay ORAMn, ORAMn_3, OQn, OQn_3;
48 private Set<GUIWire> allWires;
49 private Set<GUIComponent> allComponents;
51 private Set<String> wireDebugChangeSet;
52 private boolean debugWires = false;
53 public int debugEventThreshold = 10_000;
54 public int debugEventCount = 500;
56 private int eventCounter;
61 // Normal execution until completion or eventLimit
62 int eventLimit = debugEventThreshold;
65 while (eventCounter < eventLimit)
67 timeline.executeNext();
68 if (!timeline.hasNext())
70 System.out.println("run() took " + eventCounter + " events");
71 return Result.SUCCESS;
74 // Start debugging if event limit is reached
76 wireDebugChangeSet = new TreeSet<>();
77 Set<String> oldChangeSet;
78 // observe wire changes to detect, if we are really stuck in an endless loop
81 eventLimit += debugEventCount;
82 oldChangeSet = wireDebugChangeSet;
83 wireDebugChangeSet = new TreeSet<>();
84 while (eventCounter < eventLimit)
86 timeline.executeNext();
87 if (!timeline.hasNext())
89 // no endless loop, but more events needed than expected
90 System.out.println("run() took longer than expected: " + eventCounter);
91 return Result.SUCCESS;
94 } while (!oldChangeSet.equals(wireDebugChangeSet));
95 // if stuck, abort execution and print wires
96 System.err.print("Problematic Wire updates:");
97 wireDebugChangeSet.forEach(System.out::println);
98 System.err.println("run() failed: " + eventCounter);
99 return Result.OUT_OF_TIME;
102 @SuppressWarnings("unused")
107 ViewModelModifiable viewModel = new ViewModelModifiable();
108 am2901 = new GUIAm2901(viewModel);
110 HashMap<String, GUIManualSwitch> idSwitchMap = new HashMap<>();
111 for (String id : am2901.getInputPinNames())
113 GUIManualSwitch sw = new GUIManualSwitch(viewModel);
114 new GUIWire(viewModel, am2901.getPin(id), sw.getOutputPin());
115 idSwitchMap.put(id, sw);
118 HashMap<String, GUIBitDisplay> idDisplayMap = new HashMap<>();
119 for (String id : am2901.getOutputPinNames())
121 GUIBitDisplay bd = new GUIBitDisplay(viewModel);
122 new GUIWire(viewModel, am2901.getPin(id), bd.getInputPin());
123 idDisplayMap.put(id, bd);
125 // Create logic model
126 LogicModelParameters params = new LogicModelParameters();
127 params.gateProcessTime = 50;
128 params.wireTravelTime = 10;
129 timeline = ViewLogicModelAdapter.convert(viewModel, params);
130 // Bind switches/displays to this test class
131 for (var entry : idSwitchMap.entrySet())
132 setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getManualSwitch());
133 for (var entry : idDisplayMap.entrySet())
134 setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getBitDisplay());
135 // Switch Clock off first
139 allWires = new HashSet<>();
140 allComponents = new HashSet<>();
141 ModelAccumulator accumulator = new ModelAccumulator();
142 accumulator.visit(viewModel);
143 allWires.forEach(w -> w.addRedrawListener(() ->
147 System.out.println(w);
148 wireDebugChangeSet.add(w.toString());
151 timeline.addEventAddedListener(te -> eventCounter++);
155 public void setDest(Am2901_Dest dest)
157 var bits = of(dest.ordinal(), 3);
158 I8.setToValueOf(bits.getBit(0));
159 I7.setToValueOf(bits.getBit(1));
160 I6.setToValueOf(bits.getBit(2));
164 public void setFunc(Am2901_Func func)
166 var bits = of(func.ordinal(), 3);
167 I5.setToValueOf(bits.getBit(0));
168 I4.setToValueOf(bits.getBit(1));
169 I3.setToValueOf(bits.getBit(2));
173 public void setSrc(Am2901_Src src)
175 var bits = of(src.ordinal(), 3);
176 I2.setToValueOf(bits.getBit(0));
177 I1.setToValueOf(bits.getBit(1));
178 I0.setToValueOf(bits.getBit(2));
182 public void setReg_A(String val_4_bit)
184 var bits = BitVector.parse(val_4_bit);
185 A3.setToValueOf(bits.getBit(0));
186 A2.setToValueOf(bits.getBit(1));
187 A1.setToValueOf(bits.getBit(2));
188 A0.setToValueOf(bits.getBit(3));
192 public void setReg_B(String val_4_bit)
194 var bits = BitVector.parse(val_4_bit);
195 B3.setToValueOf(bits.getBit(0));
196 B2.setToValueOf(bits.getBit(1));
197 B1.setToValueOf(bits.getBit(2));
198 B0.setToValueOf(bits.getBit(3));
202 public void setCarryIn(String val_1_bit)
204 Cn.setToValueOf(Bit.parse(val_1_bit));
208 public void setNotOutEnable(String val_1_bit)
210 throw new UnsupportedOperationException(); // TODO
214 public void setD(String val_4_bit)
216 var bits = BitVector.parse(val_4_bit);
217 D4.setToValueOf(bits.getBit(0));
218 D3.setToValueOf(bits.getBit(1));
219 D2.setToValueOf(bits.getBit(2));
220 D1.setToValueOf(bits.getBit(3));
224 public void setQ_0(String val_1_bit)
226 IQn.setToValueOf(Bit.parse(val_1_bit));
230 public void setQ_3(String val_1_bit)
232 IQn_3.setToValueOf(Bit.parse(val_1_bit));
236 public void setRAM_0(String val_1_bit)
238 IRAMn.setToValueOf(Bit.parse(val_1_bit));
242 public void setRAM_3(String val_1_bit)
244 IRAMn_3.setToValueOf(Bit.parse(val_1_bit));
248 public void toogleClock()
254 public String getQ_0()
256 return OQn.getDisplayedValue().toString();
260 public String getQ_3()
262 return OQn_3.getDisplayedValue().toString();
266 public String getRAM_0()
268 return ORAMn.getDisplayedValue().toString();
272 public String getRAM_3()
274 return ORAMn_3.getDisplayedValue().toString();
278 public String getNotP()
280 throw new UnsupportedOperationException(); // TODO
284 public String getNotG()
286 throw new UnsupportedOperationException(); // TODO
290 public String getCarryOut()
292 return Cn_4.getDisplayedValue().toString();
296 public String getSign()
298 return F3.getDisplayedValue().toString();
302 public String getZero()
304 return F_0.getDisplayedValue().toString();
308 public String getOverflow()
310 return OVR.getDisplayedValue().toString();
316 var y3 = Y4.getDisplayedValue();
317 var y2 = Y3.getDisplayedValue();
318 var y1 = Y2.getDisplayedValue();
319 var y0 = Y1.getDisplayedValue();
320 return y3.concat(y2).concat(y1).concat(y0).toString();
323 private void setField(String name, Object value)
327 Field f = TestableAm2901Impl.class.getDeclaredField(name);
328 f.setAccessible(true);
329 f.set(this, Objects.requireNonNull(value));
337 private static BitVector of(int value, int length)
339 BitVectorMutator mutator = BitVectorMutator.ofLength(length);
341 for (int i = length - 1; i >= 0; i--)
343 mutator.setBit(i, Bit.lastBitOf(val));
346 return mutator.toBitVector();
349 class ModelAccumulator implements ModelVisitor
352 public void visit(GUIWire w)
358 public void visit(SimpleRectangularGUIGate simpleRectangularGUIGate)
360 allComponents.add(simpleRectangularGUIGate);
364 public void visit(SimpleRectangularSubmodelComponent simpleRectangularSubmodelComponent)
366 allComponents.add(simpleRectangularSubmodelComponent);
367 simpleRectangularSubmodelComponent.getWires().forEach(w -> w.accept(this));
368 simpleRectangularSubmodelComponent.getComponents().forEach(w -> w.accept(this));
372 public void visit(WireCrossPoint wireCrossPoint)
378 public void visit(GUIBitDisplay guiBitDisplay)
380 allComponents.add(guiBitDisplay);
384 public void visit(GUIManualSwitch guiManualSwitch)
386 allComponents.add(guiManualSwitch);
390 public void visit(SubmodelInterface submodelInterface)
396 public void visit(ViewModel viewModel)
398 viewModel.getWires().forEach(w -> w.accept(this));
399 viewModel.getComponents().forEach(w -> w.accept(this));