+++ /dev/null
-package net.mograsim.logic.model.am2900;
-
-import net.mograsim.logic.core.components.BitDisplay;
-import net.mograsim.logic.core.components.ManualSwitch;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.model.model.ViewModelModifiable;
-import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay;
-import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.model.wires.WireCrossPoint;
-import net.mograsim.logic.model.util.ModellingTool;
-
-public class SwitchWithDisplay
-{
- private final Pin pin;
- private final GUIBitDisplay guiBitDisplay;
- private final GUIManualSwitch guiManualSwitch;
-
- public SwitchWithDisplay(ViewModelModifiable model, Pin target)
- {
- pin = target;
- guiBitDisplay = new GUIBitDisplay(model, pin.logicWidth);
- guiManualSwitch = new GUIManualSwitch(model, pin.logicWidth);
-
- ModellingTool tool = ModellingTool.createFor(model);
- WireCrossPoint crossPoint = new WireCrossPoint(model, pin.logicWidth);
- tool.connect(guiBitDisplay.getInputPin(), crossPoint);
- tool.connect(guiManualSwitch.getOutputPin(), crossPoint);
- }
-
- public final BitVector getDisplayedValue()
- {
- return guiBitDisplay.getBitDisplay().getDisplayedValue();
- }
-
- public final void setState(BitVector bits)
- {
- guiManualSwitch.getManualSwitch().setState(bits);
- }
-
- public final Pin getPin()
- {
- return pin;
- }
-
- public final BitDisplay getBitDisplay()
- {
- return guiBitDisplay.getBitDisplay();
- }
-
- public final ManualSwitch getManualSwitch()
- {
- return guiManualSwitch.getManualSwitch();
- }
-
- final GUIBitDisplay getGuiBitDisplay()
- {
- return guiBitDisplay;
- }
-
- final GUIManualSwitch getGuiManualSwitch()
- {
- return guiManualSwitch;
- }
-}
+++ /dev/null
-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<String, GUIManualSwitch> idSwitchMap = new HashMap<>();
- private HashMap<String, GUIBitDisplay> idDisplayMap = new HashMap<>();
-
- private DebugState debug = DebugState.NO_DEBUG;
- private Set<String> 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 if (SwitchWithDisplay.class.isAssignableFrom(type))
- {
- SwitchWithDisplay swd = new SwitchWithDisplay(viewModel, p);
- setField(f, swd);
- } 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<GUIWire> wiresIncludingSubmodels = new HashSet<>();
- Queue<ViewModel> 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<String> 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 <S> void setField(Field f, S value)
- {
- try
- {
- f.set(testEnvInstance, Objects.requireNonNull(value));
- }
- catch (Exception e)
- {
- fail(e);
- }
- }
-
- private <S> 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;
- }
-}
+++ /dev/null
-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()
- {
-
- }
-
- /**
- * Transforms the last four bits of an int to a string that contains the binary ('1' and '0') representation of the 4 bits
- *
- * @author Christian Femers
- */
- public static String to4bitBin(int x)
- {
- StringBuilder sb = new StringBuilder(4);
- sb.append((x & 0b1000) == 0 ? '0' : '1');
- sb.append((x & 0b0100) == 0 ? '0' : '1');
- sb.append((x & 0b0010) == 0 ? '0' : '1');
- sb.append((x & 0b0001) == 0 ? '0' : '1');
- return sb.toString();
- }
-
- /**
- * Transforms the given boolean to a string that contains the binary ('1' and '0') representation of the bit
- *
- * @author Christian Femers
- */
- public static String to1bitBin(boolean bitIsSet)
- {
- return bitIsSet ? "1" : "0";
- }
-
- /**
- * Transforms the given int to a string that contains the binary ('1' and '0') representation of the int. "0" is only returned when the
- * int is equal to zero.
- *
- * @author Christian Femers
- */
- public static String to1bitBin(int someInt)
- {
- return someInt != 0 ? "1" : "0";
- }
-
- /**
- * Transforms a 4 bit signed integer (-8 to 7) to a int representing the same number. (Adding leading 1-bits if the 4 bit int is
- * negative)
- *
- * @author Christian Femers
- */
- public static int signed4ToSigned32(int signed4bit)
- {
- if ((signed4bit & 0b1000) > 0)
- return signed4bit | 0xFF_FF_FF_F0;
- return signed4bit & 0x00_00_00_0F;
- }
-
- /**
- * Transforms a 16 bit signed integer (-32768 to 32767 - a short) to a int representing the same number. (Adding leading 1-bits if the
- * 16 bit int is negative)
- *
- * @author Christian Femers
- */
- public static int signed16ToSigned32(int signed16bit)
- {
- return (short) signed16bit;
- }
-
- /**
- * Transforms the last n bits of an int to a string that contains the binary ('1' and '0') representation of the n bits
- *
- * @author Christian Femers
- */
- public static String toNbitString(int x, int n)
- {
- StringBuilder sb = new StringBuilder(n);
- for (int i = 0; i < n; i++)
- {
- sb.append((x >> i) & 1);
- }
- 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();
- }
-}
import static org.junit.jupiter.api.Assertions.assertEquals;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper;
+
public interface TestableCircuit
{
void setup();
void clockOn(boolean isClockOn);
+ TestEnvironmentHelper getTestEnvironmentHelper();
+
default void assertRunSuccess()
{
assertEquals(Result.SUCCESS, run());
assertRunSuccess();
}
+ default void displayState()
+ {
+ getTestEnvironmentHelper().displayState();
+ }
+
public enum Result
{
SUCCESS, OUT_OF_TIME, ERROR;
package net.mograsim.logic.model.am2900.am2901;
-import static net.mograsim.logic.model.am2900.TestUtil.*;
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 net.mograsim.logic.model.am2900.util.TestUtil.*;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Point;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import net.mograsim.logic.model.am2900.am2901.TestableAm2901.Register;
+import net.mograsim.logic.model.am2900.util.DisplayStateOnFailure;
@DisplayName("Am2901 Tests")
@TestMethodOrder(OrderAnnotation.class)
public class Am2901Test
{
- private TestableAm2901 am2901;
+ private TestableAm2901 am2901 = new TestableAm2901Impl();
+
+ @RegisterExtension
+ DisplayStateOnFailure failureRule = new DisplayStateOnFailure(am2901);
@BeforeEach
void initialize()
void createAndSetup()
{
- am2901 = new TestableAm2901Impl();
am2901.setup();
}
import java.util.Arrays;
import java.util.stream.Stream;
-import net.mograsim.logic.model.am2900.TestUtil;
import net.mograsim.logic.model.am2900.TestableCircuit;
+import net.mograsim.logic.model.am2900.util.TestUtil;
public interface TestableAm2901 extends TestableCircuit
{
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.am2900.util.TestEnvironmentHelper;
+import net.mograsim.logic.model.am2900.util.TestUtil;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper.DebugState;
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;
return "qreg.q";
return "regs.c" + r.toBitString() + ".q";
}
+
+ @Override
+ public TestEnvironmentHelper getTestEnvironmentHelper()
+ {
+ return testHelper;
+ }
}
--- /dev/null
+package net.mograsim.logic.model.am2900.am2904;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import net.mograsim.logic.model.am2900.am2904.TestableAm2904.Am2904_Carry;
+import net.mograsim.logic.model.am2900.am2904.TestableAm2904.Am2904_Inst;
+import net.mograsim.logic.model.am2900.am2904.TestableAm2904.Am2904_ShiftDir;
+import net.mograsim.logic.model.am2900.am2904.TestableAm2904.Register;
+import net.mograsim.logic.model.am2900.util.DisplayStateOnFailure;
+
+@DisplayName("Am2904 Tests")
+@TestMethodOrder(OrderAnnotation.class)
+public class Am2904Test
+{
+ private TestableAm2904 am2904 = new TestableAm2904Impl();
+
+ @RegisterExtension
+ DisplayStateOnFailure failureRule = new DisplayStateOnFailure(am2904);
+
+ @BeforeEach
+ void initialize()
+ {
+ createAndSetup();
+ setStandardInputs();
+ }
+
+ void createAndSetup()
+ {
+ am2904.setup();
+ }
+
+ void setStandardInputs()
+ {
+ am2904.set_CEµ("0");
+ am2904.set_CEM("0");
+ am2904.setI("0000");
+ am2904.set_E("0000");
+ am2904.set_OEY("1");
+ am2904.set_OECT("0");
+ am2904.setCarry(Am2904_Carry.CI0);
+ am2904.setCX("0");
+ am2904.setI10(Am2904_ShiftDir.RIGHT);
+ am2904.setShiftCode("0000");
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_Z);
+ am2904.setSIO0("Z");
+ am2904.setSIO3("Z");
+ am2904.setQIO0("Z");
+ am2904.setQIO3("Z");
+ am2904.set_SE("1");
+ am2904.setY("ZZZZ");
+ am2904.clockOn(true);
+ am2904.assertRunSuccess();
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @Order(1)
+ @DisplayName("Direct / high level access")
+ @EnumSource(Register.class)
+ void testDirectAccess(Register r)
+ {
+ assertEquals("U", am2904.getDirectly(r));
+
+ am2904.setDirectly(r, "1");
+
+ assertEquals("1", am2904.getDirectly(r));
+ }
+
+ @Test
+ @Order(2)
+ void testBasicStateAndOutputs()
+ {
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getC0());
+ assertEquals("0", am2904.getCT());
+ assertEquals("Z", am2904.getQIO0());
+ assertEquals("Z", am2904.getQIO3());
+ assertEquals("Z", am2904.getSIO0());
+ assertEquals("Z", am2904.getSIO3());
+ assertEquals("ZZZZ", am2904.getY());
+ }
+
+ @Test
+ @Order(3)
+ void testSimpleLoadTestIZ()
+ {
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_Z);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("1000");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_notZ);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0000");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+ }
+
+ @Test
+ @Order(3)
+ void testSimpleLoadTestIC()
+ {
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_C);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0100");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_notC);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0000");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+ }
+
+ @Test
+ @Order(3)
+ void testSimpleLoadTestIN()
+ {
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_N);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0010");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_notN);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0000");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+ }
+
+ @Test
+ @Order(3)
+ void testSimpleLoadTestIOVR()
+ {
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_OVR);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0001");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+
+ am2904.setInstruction(Am2904_Inst.Load_Load_I_notOVR);
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("0", am2904.getCT());
+
+ am2904.setI("0000");
+ am2904.assertFullCycleSuccess();
+
+ assertEquals("1", am2904.getCT());
+ }
+}
\ No newline at end of file
void setCX(String val_1_bit);
- void setY3(String val_1_bit);
+ void setY(String ovr_n_c_z);
void setIZ(String val_1_bit);
void setIN(String val_1_bit);
- default void setI(String z_c_ovr_n)
+ default void setI(String z_c_n_ovr)
{
- setIZ(z_c_ovr_n.substring(0, 1));
- setIC(z_c_ovr_n.substring(1, 2));
- setIOVR(z_c_ovr_n.substring(2, 3));
- setIN(z_c_ovr_n.substring(3, 4));
+ setIZ(z_c_n_ovr.substring(0, 1));
+ setIC(z_c_n_ovr.substring(1, 2));
+ setIN(z_c_n_ovr.substring(2, 3));
+ setIOVR(z_c_n_ovr.substring(3, 4));
}
void set_CEM(String val_1_bit);
void set_EN(String val_1_bit);
- default void set_E(String z_c_ovr_n)
+ default void set_E(String z_c_n_ovr)
{
- set_EZ(z_c_ovr_n.substring(0, 1));
- set_EC(z_c_ovr_n.substring(1, 2));
- set_EOVR(z_c_ovr_n.substring(2, 3));
- set_EN(z_c_ovr_n.substring(3, 4));
+ set_EZ(z_c_n_ovr.substring(0, 1));
+ set_EC(z_c_n_ovr.substring(1, 2));
+ set_EN(z_c_n_ovr.substring(2, 3));
+ set_EOVR(z_c_n_ovr.substring(3, 4));
}
void setSIO0(String val_1_bit);
void setQIO3(String val_1_bit);
+ void setDirectly(Register r, String val_1_bit);
+
String getC0();
String getCT();
- String getY3();
+ String getY();
String getSIO0();
String getQIO3();
+ String getDirectly(Register r);
+
enum Am2904_ShiftDir
{
RIGHT, LEFT;
return (code & 0b001_110) == 0b001_000;
}
}
+
+ enum Register
+ {
+ µZ, µC, µN, µOVR, MZ, MC, MN, MOVR;
+ }
}
package net.mograsim.logic.model.am2900.am2904;
+import net.mograsim.logic.core.components.BitDisplay;
+import net.mograsim.logic.core.components.ManualSwitch;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.am2900.util.SwitchWithDisplay;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper.DebugState;
+import net.mograsim.logic.model.model.components.GUIComponent;
+
public class TestableAm2904Impl implements TestableAm2904
{
+ private GUIComponent am2904;
+ private ManualSwitch I;
+ private ManualSwitch C;
+ private ManualSwitch Cx;
+ private ManualSwitch IC, IN, IOVR, IZ;
+ private ManualSwitch _CEM, _CEmu;
+ private ManualSwitch _EC, _EN, _EOVR, _EZ;
+ private ManualSwitch _OECT, _OEY;
+ private ManualSwitch _SE;
+ private BitDisplay C0;
+ private BitDisplay CT;
+ private SwitchWithDisplay SIO0, SIOn, QIO0, QIOn;
+ private SwitchWithDisplay YC, YN, YOVR, YZ;
+
+ private final TestEnvironmentHelper testHelper = new TestEnvironmentHelper(this, "file:components/am2904/GUIAm2904.json");
+
@Override
public void setup()
{
- // TODO Auto-generated method stub
-
+ testHelper.setup(DebugState.NO_DEBUG);
}
@Override
public Result run()
{
- // TODO Auto-generated method stub
- return null;
+ return testHelper.run();
}
@Override
public void clockOn(boolean isClockOn)
{
- // TODO Auto-generated method stub
-
+ if (isClockOn)
+ C.switchFullOn();
+ else
+ C.switchFullOff();
}
@Override
public void setInstruction(Am2904_Inst inst)
{
- // TODO Auto-generated method stub
-
+ var old = I.getValues();
+ var newPart = BitVector.from(inst.ordinal(), 6);
+ I.setState(old.subVector(0, 7).concat(newPart));
}
@Override
- public void setCarry(Am2904_Carry carry)
+ public void setShiftCode(String val_4_bit)
{
- // TODO Auto-generated method stub
-
+ var old = I.getValues();
+ var newPart = BitVector.parse(val_4_bit);
+ I.setState(old.subVector(0, 3).concat(newPart).concat(old.subVector(7)));
}
@Override
- public void setShiftCode(String val_4_bit)
+ public void setI10(Am2904_ShiftDir dir)
{
- // TODO Auto-generated method stub
-
+ var old = I.getValues();
+ var newPart = BitVector.from(dir.ordinal(), 1);
+ I.setState(old.subVector(0, 2).concat(newPart).concat(old.subVector(3)));
}
@Override
- public void setI10(Am2904_ShiftDir dir)
+ public void setCarry(Am2904_Carry carry)
{
- // TODO Auto-generated method stub
-
+ var old = I.getValues();
+ var newPart = BitVector.from(carry.ordinal(), 2);
+ I.setState(newPart.concat(old.subVector(2)));
}
@Override
public void setCX(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ Cx.setState(BitVector.parse(val_1_bit));
}
@Override
- public void setY3(String val_1_bit)
+ public void setY(String ovr_n_c_z)
{
- // TODO Auto-generated method stub
-
+ var bv = BitVector.parse(ovr_n_c_z);
+ // correct order apparently unknown :/
+ YOVR.setState(bv.getLSBit(3).toVector());
+ YN.setState(bv.getLSBit(2).toVector());
+ YC.setState(bv.getLSBit(1).toVector());
+ YZ.setState(bv.getLSBit(0).toVector());
}
@Override
public void setIZ(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ IZ.setState(BitVector.parse(val_1_bit));
}
@Override
public void setIC(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ IC.setState(BitVector.parse(val_1_bit));
}
@Override
public void setIOVR(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ IOVR.setState(BitVector.parse(val_1_bit));
}
@Override
public void setIN(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ IN.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_CEM(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _CEM.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_CEµ(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _CEmu.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_OEY(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _OEY.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_OECT(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _OECT.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_SE(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _SE.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_EZ(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _EZ.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_EC(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _EC.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_EOVR(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _EOVR.setState(BitVector.parse(val_1_bit));
}
@Override
public void set_EN(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ _EN.setState(BitVector.parse(val_1_bit));
}
@Override
public void setSIO0(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ SIO0.setState(BitVector.parse(val_1_bit));
}
@Override
public void setSIO3(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ SIOn.setState(BitVector.parse(val_1_bit));
}
@Override
public void setQIO0(String val_1_bit)
{
- // TODO Auto-generated method stub
-
+ QIO0.setState(BitVector.parse(val_1_bit));
}
@Override
public void setQIO3(String val_1_bit)
{
- // TODO Auto-generated method stub
+ QIOn.setState(BitVector.parse(val_1_bit));
+ }
+ @Override
+ public void setDirectly(Register r, String val_1_bit)
+ {
+ var bv = (BitVector) am2904.getHighLevelState(regToStateID(r));
+ bv = bv.withBitChanged(3 - r.ordinal() % 4, b -> Bit.parse(val_1_bit));
+ am2904.setHighLevelState(regToStateID(r), bv);
}
@Override
public String getC0()
{
- // TODO Auto-generated method stub
- return null;
+ return C0.getDisplayedValue().toString();
}
@Override
public String getCT()
{
- // TODO Auto-generated method stub
- return null;
+ return CT.getDisplayedValue().toString();
}
@Override
- public String getY3()
+ public String getY()
{
- // TODO Auto-generated method stub
- return null;
+ // correct order apparently unknown :/
+ var y3 = YOVR.getDisplayedValue();
+ var y2 = YN.getDisplayedValue();
+ var y1 = YC.getDisplayedValue();
+ var y0 = YZ.getDisplayedValue();
+ return y3.concat(y2).concat(y1).concat(y0).toString();
}
@Override
public String getSIO0()
{
- // TODO Auto-generated method stub
- return null;
+ return SIO0.getDisplayedValue().toString();
}
@Override
public String getSIO3()
{
- // TODO Auto-generated method stub
- return null;
+ return SIOn.getDisplayedValue().toString();
}
@Override
public String getQIO0()
{
- // TODO Auto-generated method stub
- return null;
+ return QIO0.getDisplayedValue().toString();
}
@Override
public String getQIO3()
{
- // TODO Auto-generated method stub
- return null;
+ return QIOn.getDisplayedValue().toString();
+ }
+
+ @Override
+ public String getDirectly(Register r)
+ {
+ var bv = (BitVector) am2904.getHighLevelState(regToStateID(r));
+ return bv.getLSBit(r.ordinal() % 4).getSymbol();
}
+ private static String regToStateID(Register r)
+ {
+ if (r.ordinal() > 3)
+ return "msr.q";
+ return "musr.q";
+ }
+
+ @Override
+ public TestEnvironmentHelper getTestEnvironmentHelper()
+ {
+ return testHelper;
+ }
}
--- /dev/null
+package net.mograsim.logic.model.am2900.am2910;
+
+import static net.mograsim.logic.model.am2900.am2910.TestableAm2910.Am2910_Inst.*;
+import static net.mograsim.logic.core.types.Bit.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.am2900.am2910.TestableAm2910.Register;
+import net.mograsim.logic.model.am2900.util.DisplayStateOnFailure;
+
+@DisplayName("Am2910 Tests")
+@TestMethodOrder(OrderAnnotation.class)
+public class Am2910Test
+{
+ private TestableAm2910 am2910 = new TestableAm2910Impl();
+
+ @RegisterExtension
+ DisplayStateOnFailure failureRule = new DisplayStateOnFailure(am2910);
+
+ @BeforeEach
+ void initialize()
+ {
+ createAndSetup();
+ setStandardInputs();
+ }
+
+ void createAndSetup()
+ {
+ am2910.setup();
+ }
+
+ void setStandardInputs()
+ {
+ am2910.set_CC("0");
+ am2910.set_CCEN("0");
+ am2910.set_OE("0");
+ am2910.set_RLD("1");
+ am2910.setCI("1");
+ am2910.setD("000000000000");
+ am2910.setInstruction(JZ);
+ am2910.clockOn(true);
+ am2910.assertRunSuccess();
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @Order(1)
+ @DisplayName("Direct / high level access")
+ @EnumSource(Register.class)
+ void testDirectAccess(Register r)
+ {
+ String us = U.toVector(r.size()).toString();
+ String three = BitVector.from(3, r.size()).toString();
+
+ assertEquals(us, am2910.getDirectly(r));
+
+ am2910.setDirectly(r, three);
+
+ assertEquals(three, am2910.getDirectly(r));
+ }
+}
import net.mograsim.logic.model.SimpleLogicUIStandalone.VisualisationObjects;
import net.mograsim.logic.model.model.ViewModelModifiable;
import net.mograsim.logic.model.model.components.GUIComponent;
+import net.mograsim.logic.model.model.components.Orientation;
import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay;
+import net.mograsim.logic.model.model.components.atomic.GUIClock;
+import net.mograsim.logic.model.model.components.atomic.GUIClock.GUIClockParams;
import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch;
import net.mograsim.logic.model.model.wires.GUIWire;
import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
public static void create(ViewModelModifiable model)
{
GUIComponent am2910 = IndirectGUIComponentCreator.createComponent(model, "file:components/am2910/GUIAm2910.json", "Am2910");
- GUIManualSwitch C = new GUIManualSwitch(model, 1, "C");
+ GUIClock C = new GUIClock(model, new GUIClockParams(1000, Orientation.RIGHT));
GUIManualSwitch D = new GUIManualSwitch(model, 12, "D");
GUIManualSwitch _RLD = new GUIManualSwitch(model, 1, "_RLD");
GUIManualSwitch _CC = new GUIManualSwitch(model, 1, "_CC");
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.BitVector;
-import net.mograsim.logic.model.am2900.TestEnvironmentHelper;
-import net.mograsim.logic.model.am2900.TestEnvironmentHelper.DebugState;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper;
+import net.mograsim.logic.model.am2900.util.TestEnvironmentHelper.DebugState;
import net.mograsim.logic.model.model.components.GUIComponent;
public class TestableAm2910Impl implements TestableAm2910
{
private GUIComponent am2901;
- private Timeline timeline;
private ManualSwitch I;
private ManualSwitch C;
private ManualSwitch CI;
throw new IllegalArgumentException("unknown: " + r);
}
}
+
+ @Override
+ public TestEnvironmentHelper getTestEnvironmentHelper()
+ {
+ return testHelper;
+ }
}
--- /dev/null
+package net.mograsim.logic.model.am2900.util;
+
+import java.util.Objects;
+
+import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import net.mograsim.logic.model.am2900.TestableCircuit;
+
+public class DisplayStateOnFailure implements AfterTestExecutionCallback
+{
+ public static final boolean ACTIVE = true;
+
+ private final TestableCircuit circuitUnderTest;
+
+ public DisplayStateOnFailure(TestableCircuit circuitUnderTest)
+ {
+ this.circuitUnderTest = Objects.requireNonNull(circuitUnderTest);
+ }
+
+ @Override
+ public void afterTestExecution(ExtensionContext context) throws Exception
+ {
+ if (ACTIVE && context.getExecutionException().isPresent())
+ {
+ context.getExecutionException().get().printStackTrace();
+ circuitUnderTest.displayState();
+ }
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.am2900.util;
+
+import net.mograsim.logic.core.components.BitDisplay;
+import net.mograsim.logic.core.components.ManualSwitch;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.model.ViewModelModifiable;
+import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay;
+import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.model.wires.WireCrossPoint;
+import net.mograsim.logic.model.util.ModellingTool;
+
+public class SwitchWithDisplay
+{
+ private final Pin pin;
+ private final GUIBitDisplay guiBitDisplay;
+ private final GUIManualSwitch guiManualSwitch;
+
+ public SwitchWithDisplay(ViewModelModifiable model, Pin target)
+ {
+ pin = target;
+ guiBitDisplay = new GUIBitDisplay(model, pin.logicWidth);
+ guiManualSwitch = new GUIManualSwitch(model, pin.logicWidth);
+
+ ModellingTool tool = ModellingTool.createFor(model);
+ WireCrossPoint crossPoint = new WireCrossPoint(model, pin.logicWidth);
+ tool.connect(guiBitDisplay.getInputPin(), crossPoint);
+ tool.connect(guiManualSwitch.getOutputPin(), crossPoint);
+ }
+
+ public final BitVector getDisplayedValue()
+ {
+ return guiBitDisplay.getBitDisplay().getDisplayedValue();
+ }
+
+ public final void setState(BitVector bits)
+ {
+ guiManualSwitch.getManualSwitch().setState(bits);
+ }
+
+ public final Pin getPin()
+ {
+ return pin;
+ }
+
+ public final BitDisplay getBitDisplay()
+ {
+ return guiBitDisplay.getBitDisplay();
+ }
+
+ public final ManualSwitch getManualSwitch()
+ {
+ return guiManualSwitch.getManualSwitch();
+ }
+
+ final GUIBitDisplay getGuiBitDisplay()
+ {
+ return guiBitDisplay;
+ }
+
+ final GUIManualSwitch getGuiManualSwitch()
+ {
+ return guiManualSwitch;
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.am2900.util;
+
+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.Optional;
+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.LogicUIStandaloneGUI;
+import net.mograsim.logic.model.am2900.TestableCircuit;
+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 Optional<Field> timelineField = Optional.empty();
+
+ private GUIComponent component;
+ private Timeline timeline;
+ private ViewModelModifiable viewModel;
+ private ModellingTool modellingTool;
+ private HashMap<String, GUIManualSwitch> idSwitchMap = new HashMap<>();
+ private HashMap<String, GUIBitDisplay> idDisplayMap = new HashMap<>();
+
+ private DebugState debug = DebugState.NO_DEBUG;
+ private Set<String> 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()))
+ {
+ f.setAccessible(true);
+ timelineField = Optional.of(f);
+ }
+ }
+ if (componentField == 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);
+ timelineField.ifPresent(f -> setField(f, 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 if (SwitchWithDisplay.class.isAssignableFrom(type))
+ {
+ SwitchWithDisplay swd = new SwitchWithDisplay(viewModel, p);
+ setField(f, swd);
+ } 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<GUIWire> wiresIncludingSubmodels = new HashSet<>();
+ Queue<ViewModel> 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<String> 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 <S> void setField(Field f, S value)
+ {
+ try
+ {
+ f.setAccessible(true);
+ f.set(testEnvInstance, Objects.requireNonNull(value));
+ }
+ catch (Exception e)
+ {
+ fail(e);
+ }
+ }
+
+ private <S> 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 void displayState()
+ {
+ try
+ {
+ new LogicUIStandaloneGUI(viewModel).run();
+ viewModel.setRedrawHandler(null);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public enum DebugState
+ {
+ NO_DEBUG, DEBUG_AT_PERFORMANCE_COST;
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.am2900.util;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.core.types.BitVector.BitVectorMutator;
+
+public final class TestUtil
+{
+ private TestUtil()
+ {
+
+ }
+
+ /**
+ * Transforms the last four bits of an int to a string that contains the binary ('1' and '0') representation of the 4 bits
+ *
+ * @author Christian Femers
+ */
+ public static String to4bitBin(int x)
+ {
+ StringBuilder sb = new StringBuilder(4);
+ sb.append((x & 0b1000) == 0 ? '0' : '1');
+ sb.append((x & 0b0100) == 0 ? '0' : '1');
+ sb.append((x & 0b0010) == 0 ? '0' : '1');
+ sb.append((x & 0b0001) == 0 ? '0' : '1');
+ return sb.toString();
+ }
+
+ /**
+ * Transforms the given boolean to a string that contains the binary ('1' and '0') representation of the bit
+ *
+ * @author Christian Femers
+ */
+ public static String to1bitBin(boolean bitIsSet)
+ {
+ return bitIsSet ? "1" : "0";
+ }
+
+ /**
+ * Transforms the given int to a string that contains the binary ('1' and '0') representation of the int. "0" is only returned when the
+ * int is equal to zero.
+ *
+ * @author Christian Femers
+ */
+ public static String to1bitBin(int someInt)
+ {
+ return someInt != 0 ? "1" : "0";
+ }
+
+ /**
+ * Transforms a 4 bit signed integer (-8 to 7) to a int representing the same number. (Adding leading 1-bits if the 4 bit int is
+ * negative)
+ *
+ * @author Christian Femers
+ */
+ public static int signed4ToSigned32(int signed4bit)
+ {
+ if ((signed4bit & 0b1000) > 0)
+ return signed4bit | 0xFF_FF_FF_F0;
+ return signed4bit & 0x00_00_00_0F;
+ }
+
+ /**
+ * Transforms a 16 bit signed integer (-32768 to 32767 - a short) to a int representing the same number. (Adding leading 1-bits if the
+ * 16 bit int is negative)
+ *
+ * @author Christian Femers
+ */
+ public static int signed16ToSigned32(int signed16bit)
+ {
+ return (short) signed16bit;
+ }
+
+ /**
+ * Transforms the last n bits of an int to a string that contains the binary ('1' and '0') representation of the n bits
+ *
+ * @author Christian Femers
+ */
+ public static String toNbitString(int x, int n)
+ {
+ StringBuilder sb = new StringBuilder(n);
+ for (int i = 0; i < n; i++)
+ {
+ sb.append((x >> i) & 1);
+ }
+ 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();
+ }
+}