From 75865384f939f597195f7a1a021ad545e2e23ee8 Mon Sep 17 00:00:00 2001 From: Christian Femers Date: Fri, 23 Aug 2019 04:38:40 +0200 Subject: [PATCH] Restructured test classes and improved readability --- .../model/am2900/TestEnvironmentHelper.java | 253 ++++++++++++ .../mograsim/logic/model/am2900/TestUtil.java | 22 + .../model/am2900/TestableAm2901Impl.java | 381 ------------------ .../logic/model/am2900/TestableCircuit.java | 31 ++ .../model/am2900/{ => am2901}/Am2901Test.java | 12 +- .../am2900/{ => am2901}/Am2901Testbench.java | 2 +- .../am2900/{ => am2901}/TestableAm2901.java | 33 +- .../am2900/am2901/TestableAm2901Impl.java | 229 +++++++++++ 8 files changed, 547 insertions(+), 416 deletions(-) create mode 100644 net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java delete mode 100644 net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901Impl.java create mode 100644 net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableCircuit.java rename net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/{ => am2901}/Am2901Test.java (94%) rename net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/{ => am2901}/Am2901Testbench.java (98%) rename net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/{ => am2901}/TestableAm2901.java (76%) create mode 100644 net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901Impl.java diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java new file mode 100644 index 00000000..9390a019 --- /dev/null +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java @@ -0,0 +1,253 @@ +package net.mograsim.logic.model.am2900; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Objects; +import java.util.Queue; +import java.util.Set; +import java.util.TreeSet; + +import net.mograsim.logic.core.components.BitDisplay; +import net.mograsim.logic.core.components.ManualSwitch; +import net.mograsim.logic.core.timeline.Timeline; +import net.mograsim.logic.model.am2900.TestableCircuit.Result; +import net.mograsim.logic.model.model.ViewModel; +import net.mograsim.logic.model.model.ViewModelModifiable; +import net.mograsim.logic.model.model.components.GUIComponent; +import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay; +import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch; +import net.mograsim.logic.model.model.components.submodels.SubmodelComponent; +import net.mograsim.logic.model.model.wires.GUIWire; +import net.mograsim.logic.model.model.wires.Pin; +import net.mograsim.logic.model.modeladapter.LogicModelParameters; +import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter; +import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator; +import net.mograsim.logic.model.util.ModellingTool; + +public class TestEnvironmentHelper +{ + private final TestableCircuit testEnvInstance; + private final Class testEnvClass; + private final String modelId; + private Field componentField; + private Field timelineField; + + private GUIComponent component; + private Timeline timeline; + private ViewModelModifiable viewModel; + private ModellingTool modellingTool; + private HashMap idSwitchMap = new HashMap<>(); + private HashMap idDisplayMap = new HashMap<>(); + + private DebugState debug = DebugState.NO_DEBUG; + private Set wireDebugChangeSet; + private boolean debugWires = false; + public int debugEventThreshold = 10_000; + public int debugEventCount = 500; + private int eventCounter; + + public TestEnvironmentHelper(TestableCircuit testEnv, String modelId) + { + this.testEnvInstance = testEnv; + this.modelId = modelId; + this.testEnvClass = testEnvInstance.getClass(); + for (Field f : testEnvClass.getDeclaredFields()) + { + if (GUIComponent.class.isAssignableFrom(f.getType())) + { + componentField = f; + componentField.setAccessible(true); + } else if (Timeline.class.isAssignableFrom(f.getType())) + { + timelineField = f; + timelineField.setAccessible(true); + } + } + if (componentField == null || timelineField == null) + throw new IllegalStateException("No component or timeline field found!"); + } + + public void setup(DebugState debug) + { + this.debug = debug; + // Create view model + viewModel = new ViewModelModifiable(); + modellingTool = ModellingTool.createFor(viewModel); + component = IndirectGUIComponentCreator.createComponent(viewModel, modelId); + setField(componentField, component); + + component.getPins().values().forEach(this::extendModelPin); + + // Create logic model + LogicModelParameters params = new LogicModelParameters(); + params.gateProcessTime = 50; + params.wireTravelTime = 10; + timeline = ViewLogicModelAdapter.convert(viewModel, params); + setField(timelineField, timeline); + + // Bind switches/displays to this test class + component.getPins().values().forEach(this::bindModelPin); + + if (debug == DebugState.DEBUG_AT_PERFORMANCE_COST) + { + setupDebugging(); + } + timeline.addEventAddedListener(te -> eventCounter++); + } + + private void extendModelPin(Pin p) + { + String javaIdentId = idToJavaIdentifier(p.name); + try + { + Field f = testEnvClass.getDeclaredField(javaIdentId); + Class type = f.getType(); + if (ManualSwitch.class.isAssignableFrom(type)) + { + GUIManualSwitch gms = new GUIManualSwitch(viewModel, p.logicWidth); + modellingTool.connect(p, gms.getOutputPin()); + idSwitchMap.put(p.name, gms); + } else if (BitDisplay.class.isAssignableFrom(type)) + { + GUIBitDisplay gbd = new GUIBitDisplay(viewModel, p.logicWidth); + modellingTool.connect(p, gbd.getInputPin()); + idDisplayMap.put(p.name, gbd); + } else + { + fail("unkown field type " + type); + } + } + catch (NoSuchFieldException | SecurityException e) + { + fail(e); + } + } + + private void bindModelPin(Pin p) + { + String javaIdentId = idToJavaIdentifier(p.name); + if (idDisplayMap.containsKey(p.name)) + setField(javaIdentId, idDisplayMap.get(p.name).getBitDisplay()); + if (idSwitchMap.containsKey(p.name)) + setField(javaIdentId, idSwitchMap.get(p.name).getManualSwitch()); + } + + private void setupDebugging() + { + // Debug code + HashSet wiresIncludingSubmodels = new HashSet<>(); + Queue modelsToIterate = new LinkedList<>(); + modelsToIterate.add(viewModel); + while (modelsToIterate.size() > 0) + { + ViewModel model = modelsToIterate.poll(); + wiresIncludingSubmodels.addAll(model.getWiresByName().values()); + for (GUIComponent comp : model.getComponentsByName().values()) + if (comp instanceof SubmodelComponent) + modelsToIterate.offer(((SubmodelComponent) comp).submodel); + } + System.out.println(wiresIncludingSubmodels.size()); + viewModel.setRedrawHandler(() -> wiresIncludingSubmodels.forEach(w -> + { + if (debugWires) + { + wireDebugChangeSet.add(w.toString()); + } + })); + } + + public Result run() + { + // Normal execution until completion or eventLimit + int eventLimit = debugEventThreshold; + eventCounter = 0; + debugWires = false; + while (eventCounter < eventLimit) + { + timeline.executeNext(); + if (!timeline.hasNext()) + return Result.SUCCESS; + } + + // Start debugging if event limit is reached (if debug is active) + if (debug == DebugState.DEBUG_AT_PERFORMANCE_COST) + return debugThisRun(); + + return Result.OUT_OF_TIME; + } + + private Result debugThisRun() + { + int eventLimit = debugEventThreshold; + debugWires = true; + wireDebugChangeSet = new TreeSet<>(); + Set oldChangeSet; + // observe wire changes to detect, if we are really stuck in an endless loop + do + { + eventLimit += debugEventCount; + oldChangeSet = wireDebugChangeSet; + wireDebugChangeSet = new TreeSet<>(); + while (eventCounter < eventLimit) + { + timeline.executeNext(); + if (!timeline.hasNext()) + { + // no endless loop, but more events needed than expected + System.out.println("run() took longer than expected: " + eventCounter); + return Result.SUCCESS; + } + } + } while (!oldChangeSet.equals(wireDebugChangeSet)); + // if stuck, abort execution and print wires + System.err.print("Problematic Wire updates:"); + wireDebugChangeSet.forEach(System.out::println); + System.err.println("run() failed: " + eventCounter); + return Result.OUT_OF_TIME; + } + + private static String idToJavaIdentifier(String s) + { + StringBuilder sb = new StringBuilder(s.length()); + char c = s.charAt(0); + sb.append(Character.isJavaIdentifierStart(c) ? c : '_'); + for (int i = 1; i < s.length(); i++) + sb.append(Character.isJavaIdentifierPart(c = s.charAt(i)) ? c : '_'); + return sb.toString(); + } + + private void setField(Field f, S value) + { + try + { + f.set(testEnvInstance, Objects.requireNonNull(value)); + } + catch (Exception e) + { + fail(e); + } + } + + private void setField(String name, S value) + { + try + { + Field f = testEnvClass.getDeclaredField(name); + f.setAccessible(true); + f.set(testEnvInstance, Objects.requireNonNull(value)); + } + catch (Exception e) + { + fail(e); + } + } + + public enum DebugState + { + NO_DEBUG, DEBUG_AT_PERFORMANCE_COST; + } +} diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestUtil.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestUtil.java index f85ae04a..46a4b92c 100644 --- a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestUtil.java +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestUtil.java @@ -1,5 +1,15 @@ package net.mograsim.logic.model.am2900; +import static org.junit.jupiter.api.Assertions.fail; + +import java.lang.reflect.Field; +import java.util.Objects; + +import net.mograsim.logic.core.types.Bit; +import net.mograsim.logic.core.types.BitVector; +import net.mograsim.logic.core.types.BitVector.BitVectorMutator; +import net.mograsim.logic.model.am2900.am2901.TestableAm2901Impl; + public final class TestUtil { private TestUtil() @@ -81,4 +91,16 @@ public final class TestUtil } return sb.reverse().toString(); } + + public static BitVector of(int value, int length) + { + BitVectorMutator mutator = BitVectorMutator.ofLength(length); + int val = value; + for (int i = length - 1; i >= 0; i--) + { + mutator.setMSBit(i, Bit.lastBitOf(val)); + val >>>= 1; + } + return mutator.toBitVector(); + } } diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901Impl.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901Impl.java deleted file mode 100644 index e84588d9..00000000 --- a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901Impl.java +++ /dev/null @@ -1,381 +0,0 @@ -package net.mograsim.logic.model.am2900; - -import static org.junit.jupiter.api.Assertions.fail; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; -import java.util.TreeSet; - -import net.mograsim.logic.core.components.BitDisplay; -import net.mograsim.logic.core.components.ManualSwitch; -import net.mograsim.logic.core.timeline.Timeline; -import net.mograsim.logic.core.types.Bit; -import net.mograsim.logic.core.types.BitVector; -import net.mograsim.logic.core.types.BitVector.BitVectorMutator; -import net.mograsim.logic.model.model.ViewModel; -import net.mograsim.logic.model.model.ViewModelModifiable; -import net.mograsim.logic.model.model.components.GUIComponent; -import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay; -import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch; -import net.mograsim.logic.model.model.components.submodels.SubmodelComponent; -import net.mograsim.logic.model.model.wires.GUIWire; -import net.mograsim.logic.model.model.wires.Pin; -import net.mograsim.logic.model.modeladapter.LogicModelParameters; -import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter; -import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator; - -public class TestableAm2901Impl implements TestableAm2901 -{ - private GUIComponent am2901; - private Timeline timeline; - private ManualSwitch I8, I7, I6, I5, I4, I3, I2, I1, I0; - private ManualSwitch C; - private ManualSwitch Cn; - private ManualSwitch D1, D2, D3, D4; - private ManualSwitch A0, A1, A2, A3; - private ManualSwitch B0, B1, B2, B3; - private ManualSwitch IRAMn, IRAMn_3, IQn, IQn_3; - private BitDisplay Y1, Y2, Y3, Y4; - private BitDisplay F_0, Cn_4, OVR, F3; - private BitDisplay ORAMn, ORAMn_3, OQn, OQn_3; - - private Set wireDebugChangeSet; - private boolean debugWires = false; - public int debugEventThreshold = 10_000; - public int debugEventCount = 500; - - private int eventCounter; - - @Override - public Result run() - { - // Normal execution until completion or eventLimit - int eventLimit = debugEventThreshold; - eventCounter = 0; - debugWires = false; - while (eventCounter < eventLimit) - { - timeline.executeNext(); - if (!timeline.hasNext()) - { -// System.out.println("run() took " + eventCounter + " events"); - return Result.SUCCESS; - } - } - // Start debugging if event limit is reached - debugWires = true; - wireDebugChangeSet = new TreeSet<>(); - Set oldChangeSet; - // observe wire changes to detect, if we are really stuck in an endless loop - do - { - eventLimit += debugEventCount; - oldChangeSet = wireDebugChangeSet; - wireDebugChangeSet = new TreeSet<>(); - while (eventCounter < eventLimit) - { - timeline.executeNext(); - if (!timeline.hasNext()) - { - // no endless loop, but more events needed than expected - System.out.println("run() took longer than expected: " + eventCounter); - return Result.SUCCESS; - } - } - } while (!oldChangeSet.equals(wireDebugChangeSet)); - // if stuck, abort execution and print wires - System.err.print("Problematic Wire updates:"); - wireDebugChangeSet.forEach(System.out::println); - System.err.println("run() failed: " + eventCounter); - return Result.OUT_OF_TIME; - } - - @SuppressWarnings("unused") - @Override - public void setup() - { - // Create view model - ViewModelModifiable viewModel = new ViewModelModifiable(); - am2901 = IndirectGUIComponentCreator.createComponent(viewModel, "GUIAm2901"); - // guess which pins are outputs and which are inputs - // TODO this code exists four times... but it seems too "hacky" to put it in a helper class - List inputPinNames = new ArrayList<>(); - List outputPinNames = new ArrayList<>(); - for (Pin p : am2901.getPins().values()) - if (p.getRelX() == 0) - inputPinNames.add(p.name); - else - outputPinNames.add(p.name); - // Get switches - HashMap idSwitchMap = new HashMap<>(); - for (String id : inputPinNames) - { - GUIManualSwitch sw = new GUIManualSwitch(viewModel, 1); - new GUIWire(viewModel, am2901.getPin(id), sw.getOutputPin()); - idSwitchMap.put(id, sw); - } - // Get displays - HashMap idDisplayMap = new HashMap<>(); - for (String id : outputPinNames) - { - GUIBitDisplay bd = new GUIBitDisplay(viewModel, 1); -// bd.addRedrawListener(() -> System.out.println(id + " " + bd.getBitDisplay().getDisplayedValue())); - new GUIWire(viewModel, am2901.getPin(id), bd.getInputPin()); - idDisplayMap.put(id, bd); - } - // Create logic model - LogicModelParameters params = new LogicModelParameters(); - params.gateProcessTime = 50; - params.wireTravelTime = 10; - timeline = ViewLogicModelAdapter.convert(viewModel, params); - // Bind switches/displays to this test class - for (var entry : idSwitchMap.entrySet()) - setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getManualSwitch()); - for (var entry : idDisplayMap.entrySet()) - setField(entry.getKey().replaceAll("\\+|=", "_"), entry.getValue().getBitDisplay()); - - // Debug code - HashSet wiresIncludingSubmodels = new HashSet<>(); - Queue modelsToIterate = new LinkedList<>(); - modelsToIterate.add(viewModel); - while (modelsToIterate.size() > 0) - { - ViewModel model = modelsToIterate.poll(); - wiresIncludingSubmodels.addAll(model.getWiresByName().values()); - for (GUIComponent comp : model.getComponentsByName().values()) - if (comp instanceof SubmodelComponent) - modelsToIterate.offer(((SubmodelComponent) comp).submodel); - } - // NOTE: This commented out code is only used for serious debugging (performance cost!) -// System.out.println(wiresIncludingSubmodels.size()); -// viewModel.setRedrawHandler(() -> wiresIncludingSubmodels.forEach(w -> -// { -// if (debugWires) -// { -// wireDebugChangeSet.add(w.toString()); -// } -// })); - timeline.addEventAddedListener(te -> eventCounter++); - } - - @Override - public void setDest(Am2901_Dest dest) - { - var bits = of(dest.ordinal(), 3); - I8.setState(bits.getLSBit(2)); - I7.setState(bits.getLSBit(1)); - I6.setState(bits.getLSBit(0)); - } - - @Override - public void setFunc(Am2901_Func func) - { - var bits = of(func.ordinal(), 3); - I5.setState(bits.getLSBit(2)); - I4.setState(bits.getLSBit(1)); - I3.setState(bits.getLSBit(0)); - } - - @Override - public void setSrc(Am2901_Src src) - { - var bits = of(src.ordinal(), 3); - I2.setState(bits.getLSBit(2)); - I1.setState(bits.getLSBit(1)); - I0.setState(bits.getLSBit(0)); - } - - @Override - public void setReg_A(String val_4_bit) - { - var bits = BitVector.parse(val_4_bit); - A3.setState(bits.getLSBit(3)); - A2.setState(bits.getLSBit(2)); - A1.setState(bits.getLSBit(1)); - A0.setState(bits.getLSBit(0)); - } - - @Override - public void setReg_B(String val_4_bit) - { - var bits = BitVector.parse(val_4_bit); - B3.setState(bits.getLSBit(3)); - B2.setState(bits.getLSBit(2)); - B1.setState(bits.getLSBit(1)); - B0.setState(bits.getLSBit(0)); - } - - @Override - public void setCarryIn(String val_1_bit) - { - Cn.setState(Bit.parse(val_1_bit)); - } - - @Override - public void setNotOutEnable(String val_1_bit) - { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public void setD(String val_4_bit) - { - var bits = BitVector.parse(val_4_bit); - D4.setState(bits.getLSBit(3)); - D3.setState(bits.getLSBit(2)); - D2.setState(bits.getLSBit(1)); - D1.setState(bits.getLSBit(0)); - } - - @Override - public void setQ_0(String val_1_bit) - { - IQn.setState(Bit.parse(val_1_bit)); - } - - @Override - public void setQ_3(String val_1_bit) - { - IQn_3.setState(Bit.parse(val_1_bit)); - } - - @Override - public void setRAM_0(String val_1_bit) - { - IRAMn.setState(Bit.parse(val_1_bit)); - } - - @Override - public void setRAM_3(String val_1_bit) - { - IRAMn_3.setState(Bit.parse(val_1_bit)); - } - - @Override - public void clockOn(boolean isClockOn) - { - C.setState(isClockOn ? Bit.ONE : Bit.ZERO); - } - - @Override - public String getQ_0() - { - return OQn.getDisplayedValue().toString(); - } - - @Override - public String getQ_3() - { - return OQn_3.getDisplayedValue().toString(); - } - - @Override - public String getRAM_0() - { - return ORAMn.getDisplayedValue().toString(); - } - - @Override - public String getRAM_3() - { - return ORAMn_3.getDisplayedValue().toString(); - } - - @Override - public String getNotP() - { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public String getNotG() - { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public String getCarryOut() - { - return Cn_4.getDisplayedValue().toString(); - } - - @Override - public String getSign() - { - return F3.getDisplayedValue().toString(); - } - - @Override - public String getZero() - { - return F_0.getDisplayedValue().toString(); - } - - @Override - public String getOverflow() - { - return OVR.getDisplayedValue().toString(); - } - - @Override - public String getY() - { - var y3 = Y4.getDisplayedValue(); - var y2 = Y3.getDisplayedValue(); - var y1 = Y2.getDisplayedValue(); - var y0 = Y1.getDisplayedValue(); - return y3.concat(y2).concat(y1).concat(y0).toString(); - } - - private void setField(String name, Object value) - { - try - { - Field f = TestableAm2901Impl.class.getDeclaredField(name); - f.setAccessible(true); - f.set(this, Objects.requireNonNull(value)); - } - catch (Exception e) - { - fail(e); - } - } - - private static BitVector of(int value, int length) - { - BitVectorMutator mutator = BitVectorMutator.ofLength(length); - int val = value; - for (int i = length - 1; i >= 0; i--) - { - mutator.setMSBit(i, Bit.lastBitOf(val)); - val >>>= 1; - } - return mutator.toBitVector(); - } - - @Override - public void setDirectly(Register r, String val_4_bit) - { - am2901.setHighLevelState(regToStateID(r), BitVector.parse(val_4_bit)); - } - - @Override - public String getDirectly(Register r) - { - return ((BitVector) am2901.getHighLevelState(regToStateID(r))).toString(); - } - - private static String regToStateID(Register r) - { - if (r == Register.Q) - return "qreg.q"; - return "regs.c" + r.toBitString() + ".q"; - } -} diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableCircuit.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableCircuit.java new file mode 100644 index 00000000..39dc09ba --- /dev/null +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableCircuit.java @@ -0,0 +1,31 @@ +package net.mograsim.logic.model.am2900; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public interface TestableCircuit +{ + void setup(); + + Result run(); + + void clockOn(boolean isClockOn); + + default void assertRunSuccess() + { + assertEquals(Result.SUCCESS, run()); + } + + default void assertFullCycleSuccess() + { + assertRunSuccess(); + clockOn(false); + assertRunSuccess(); + clockOn(true); + assertRunSuccess(); + } + + public enum Result + { + SUCCESS, OUT_OF_TIME, ERROR; + } +} diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Test.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Test.java similarity index 94% rename from net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Test.java rename to net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Test.java index 7d87f39b..57461c62 100644 --- a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Test.java +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Test.java @@ -1,10 +1,10 @@ -package net.mograsim.logic.model.am2900; +package net.mograsim.logic.model.am2900.am2901; import static net.mograsim.logic.model.am2900.TestUtil.*; -import static net.mograsim.logic.model.am2900.TestableAm2901.Am2901_Dest.*; -import static net.mograsim.logic.model.am2900.TestableAm2901.Am2901_Func.*; -import static net.mograsim.logic.model.am2900.TestableAm2901.Am2901_Src.*; -import static net.mograsim.logic.model.am2900.TestableAm2901.Register.*; +import static net.mograsim.logic.model.am2900.am2901.TestableAm2901.Am2901_Dest.*; +import static net.mograsim.logic.model.am2900.am2901.TestableAm2901.Am2901_Func.*; +import static net.mograsim.logic.model.am2900.am2901.TestableAm2901.Am2901_Src.*; +import static net.mograsim.logic.model.am2900.am2901.TestableAm2901.Register.*; import static org.junit.jupiter.api.Assertions.*; import java.awt.Point; @@ -20,7 +20,7 @@ import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import net.mograsim.logic.model.am2900.TestableAm2901.Register; +import net.mograsim.logic.model.am2900.am2901.TestableAm2901.Register; @DisplayName("Am2901 Tests") @TestMethodOrder(OrderAnnotation.class) diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Testbench.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Testbench.java similarity index 98% rename from net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Testbench.java rename to net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Testbench.java index 731147ce..3a7ffa22 100644 --- a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/Am2901Testbench.java +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/Am2901Testbench.java @@ -1,4 +1,4 @@ -package net.mograsim.logic.model.am2900; +package net.mograsim.logic.model.am2900.am2901; import java.util.ArrayList; import java.util.Comparator; diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901.java similarity index 76% rename from net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901.java rename to net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901.java index d898b399..34c179da 100644 --- a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestableAm2901.java +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901.java @@ -1,15 +1,13 @@ -package net.mograsim.logic.model.am2900; - -import static org.junit.jupiter.api.Assertions.assertEquals; +package net.mograsim.logic.model.am2900.am2901; import java.util.Arrays; import java.util.stream.Stream; -public interface TestableAm2901 -{ - void setup(); +import net.mograsim.logic.model.am2900.TestUtil; +import net.mograsim.logic.model.am2900.TestableCircuit; - Result run(); +public interface TestableAm2901 extends TestableCircuit +{ void setDest(Am2901_Dest dest); @@ -35,8 +33,6 @@ public interface TestableAm2901 void setRAM_3(String val_1_bit); - void clockOn(boolean isClockOn); - void setDirectly(Register r, String val_4_bit); String getQ_0(); @@ -63,25 +59,6 @@ public interface TestableAm2901 String getDirectly(Register r); - default void assertRunSuccess() - { - assertEquals(Result.SUCCESS, run()); - } - - default void assertFullCycleSuccess() - { - assertRunSuccess(); - clockOn(false); - assertRunSuccess(); - clockOn(true); - assertRunSuccess(); - } - - public enum Result - { - SUCCESS, OUT_OF_TIME, ERROR; - } - public enum Am2901_Dest { QREG, NOP, RAMA, RAMF, RAMQD, RAMD, RAMQU, RAMU; diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901Impl.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901Impl.java new file mode 100644 index 00000000..34c68c1e --- /dev/null +++ b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/am2901/TestableAm2901Impl.java @@ -0,0 +1,229 @@ +package net.mograsim.logic.model.am2900.am2901; + +import net.mograsim.logic.core.components.BitDisplay; +import net.mograsim.logic.core.components.ManualSwitch; +import net.mograsim.logic.core.timeline.Timeline; +import net.mograsim.logic.core.types.Bit; +import net.mograsim.logic.core.types.BitVector; +import net.mograsim.logic.model.am2900.TestEnvironmentHelper; +import net.mograsim.logic.model.am2900.TestEnvironmentHelper.DebugState; +import net.mograsim.logic.model.am2900.TestUtil; +import net.mograsim.logic.model.model.components.GUIComponent; + +public class TestableAm2901Impl implements TestableAm2901 +{ + private GUIComponent am2901; + private Timeline timeline; + private ManualSwitch I8, I7, I6, I5, I4, I3, I2, I1, I0; + private ManualSwitch C; + private ManualSwitch Cn; + private ManualSwitch D1, D2, D3, D4; + private ManualSwitch A0, A1, A2, A3; + private ManualSwitch B0, B1, B2, B3; + private ManualSwitch IRAMn, IRAMn_3, IQn, IQn_3; + private BitDisplay Y1, Y2, Y3, Y4; + private BitDisplay F_0, Cn_4, OVR, F3; + private BitDisplay ORAMn, ORAMn_3, OQn, OQn_3; + + private final TestEnvironmentHelper testHelper = new TestEnvironmentHelper(this, "GUIAm2901"); + + @Override + public Result run() + { + return testHelper.run(); + } + + @Override + public void setup() + { + testHelper.setup(DebugState.NO_DEBUG); + } + + @Override + public void setDest(Am2901_Dest dest) + { + var bits = TestUtil.of(dest.ordinal(), 3); + I8.setState(bits.getLSBit(2)); + I7.setState(bits.getLSBit(1)); + I6.setState(bits.getLSBit(0)); + } + + @Override + public void setFunc(Am2901_Func func) + { + var bits = TestUtil.of(func.ordinal(), 3); + I5.setState(bits.getLSBit(2)); + I4.setState(bits.getLSBit(1)); + I3.setState(bits.getLSBit(0)); + } + + @Override + public void setSrc(Am2901_Src src) + { + var bits = TestUtil.of(src.ordinal(), 3); + I2.setState(bits.getLSBit(2)); + I1.setState(bits.getLSBit(1)); + I0.setState(bits.getLSBit(0)); + } + + @Override + public void setReg_A(String val_4_bit) + { + var bits = BitVector.parse(val_4_bit); + A3.setState(bits.getLSBit(3)); + A2.setState(bits.getLSBit(2)); + A1.setState(bits.getLSBit(1)); + A0.setState(bits.getLSBit(0)); + } + + @Override + public void setReg_B(String val_4_bit) + { + var bits = BitVector.parse(val_4_bit); + B3.setState(bits.getLSBit(3)); + B2.setState(bits.getLSBit(2)); + B1.setState(bits.getLSBit(1)); + B0.setState(bits.getLSBit(0)); + } + + @Override + public void setCarryIn(String val_1_bit) + { + Cn.setState(Bit.parse(val_1_bit)); + } + + @Override + public void setNotOutEnable(String val_1_bit) + { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public void setD(String val_4_bit) + { + var bits = BitVector.parse(val_4_bit); + D4.setState(bits.getLSBit(3)); + D3.setState(bits.getLSBit(2)); + D2.setState(bits.getLSBit(1)); + D1.setState(bits.getLSBit(0)); + } + + @Override + public void setQ_0(String val_1_bit) + { + IQn.setState(Bit.parse(val_1_bit)); + } + + @Override + public void setQ_3(String val_1_bit) + { + IQn_3.setState(Bit.parse(val_1_bit)); + } + + @Override + public void setRAM_0(String val_1_bit) + { + IRAMn.setState(Bit.parse(val_1_bit)); + } + + @Override + public void setRAM_3(String val_1_bit) + { + IRAMn_3.setState(Bit.parse(val_1_bit)); + } + + @Override + public void clockOn(boolean isClockOn) + { + C.setState(isClockOn ? Bit.ONE : Bit.ZERO); + } + + @Override + public String getQ_0() + { + return OQn.getDisplayedValue().toString(); + } + + @Override + public String getQ_3() + { + return OQn_3.getDisplayedValue().toString(); + } + + @Override + public String getRAM_0() + { + return ORAMn.getDisplayedValue().toString(); + } + + @Override + public String getRAM_3() + { + return ORAMn_3.getDisplayedValue().toString(); + } + + @Override + public String getNotP() + { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public String getNotG() + { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public String getCarryOut() + { + return Cn_4.getDisplayedValue().toString(); + } + + @Override + public String getSign() + { + return F3.getDisplayedValue().toString(); + } + + @Override + public String getZero() + { + return F_0.getDisplayedValue().toString(); + } + + @Override + public String getOverflow() + { + return OVR.getDisplayedValue().toString(); + } + + @Override + public String getY() + { + var y3 = Y4.getDisplayedValue(); + var y2 = Y3.getDisplayedValue(); + var y1 = Y2.getDisplayedValue(); + var y0 = Y1.getDisplayedValue(); + return y3.concat(y2).concat(y1).concat(y0).toString(); + } + + @Override + public void setDirectly(Register r, String val_4_bit) + { + am2901.setHighLevelState(regToStateID(r), BitVector.parse(val_4_bit)); + } + + @Override + public String getDirectly(Register r) + { + return ((BitVector) am2901.getHighLevelState(regToStateID(r))).toString(); + } + + private static String regToStateID(Register r) + { + if (r == Register.Q) + return "qreg.q"; + return "regs.c" + r.toBitString() + ".q"; + } +} -- 2.17.1