package net.mograsim.logic.ui.am2900;
+import static net.mograsim.logic.ui.am2900.TestUtil.*;
import static net.mograsim.logic.ui.am2900.TestableAm2901.Am2901_Dest.*;
import static net.mograsim.logic.ui.am2900.TestableAm2901.Am2901_Func.*;
import static net.mograsim.logic.ui.am2900.TestableAm2901.Am2901_Src.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static net.mograsim.logic.ui.am2900.TestableAm2901.Register.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.awt.Point;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+import net.mograsim.logic.ui.am2900.TestableAm2901.Register;
-import net.mograsim.logic.ui.am2900.TestableAm2901.Result;
-
+@TestMethodOrder(OrderAnnotation.class)
public class Am2901Test
{
private TestableAm2901 am2901;
void initialize()
{
createAndSetup();
- setRegistersToZero();
- }
-
- @Test
- void testInit()
- {
- assertEquals("0", am2901.getCarryOut());
- assertEquals("0", am2901.getOverflow());
- assertEquals("0", am2901.getSign());
- assertEquals("1", am2901.getZero());
- assertEquals("0000", am2901.getY());
- assertEquals("0", am2901.getQ_0());
- assertEquals("0", am2901.getQ_3());
- assertEquals("0", am2901.getRAM_0());
- assertEquals("0", am2901.getRAM_3());
+ setInputsToZero();
}
void createAndSetup()
void setRegistersToZero()
{
setInputsToZero();
- for (Regsiter r : Regsiter.values())
+ for (Register r : Register.values())
{
setRegisterToZero(r);
}
}
- void setRegisterToZero(Regsiter r)
+ void setRegisterToZero(Register r)
{
System.out.println("Setting reg " + r + " to zero");
+
am2901.setD("0000");
am2901.setSrc(DZ);
am2901.setFunc(AND);
- if (r == Regsiter.Q)
+ setRegOutput(r);
+
+ am2901.assertFullCycleSuccess();
+ }
+
+ void setRegOutput(Register r)
+ {
+ if (r == Q)
{
am2901.setDest(QREG);
} else
am2901.setReg_B(r.toBitString());
am2901.setDest(RAMF);
}
- assertRunSuccess();
- am2901.toogleClock();
- assertRunSuccess();
- am2901.toogleClock();
- assertRunSuccess();
}
void setInputsToZero()
am2901.setFunc(ADD);
am2901.setDest(QREG);
// am2901.setNotOutEnable("0"); TODO
- assertRunSuccess();
+ am2901.clockOn(true);
+ am2901.assertRunSuccess();
}
- void assertRunSuccess()
+ @Order(1)
+ @ParameterizedTest
+ @ArgumentsSource(TestableAm2901.RegisterProvider.class)
+ void testDirectAccess(Register r)
{
- assertEquals(Result.SUCCESS, am2901.run());
+ assertEquals("UUUU", am2901.getDirectly(r));
+
+ am2901.setDirectly(r, "1011");
+
+ assertEquals("1011", am2901.getDirectly(r));
}
- public enum Regsiter
+ @Order(2)
+ @ParameterizedTest
+ @ArgumentsSource(TestableAm2901.RegisterProvider.class)
+ void testSetToZero(Register r)
{
- r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, rA, rB, rC, rD, rE, rF, Q;
+ assertEquals("UUUU", am2901.getDirectly(r));
+
+ setRegisterToZero(r);
- public String toBitString()
+ assertEquals("0000", am2901.getDirectly(r));
+ assertEquals("0000", am2901.getY());
+ assertEquals("0", am2901.getCarryOut());
+ assertEquals("0", am2901.getOverflow());
+ assertEquals("0", am2901.getSign());
+ assertEquals("1", am2901.getZero());
+ }
+
+ @Order(3)
+ @Test
+ void testSetAllToZero()
+ {
+ setRegistersToZero();
+
+ assertEquals("0000", am2901.getY());
+ assertEquals("0", am2901.getCarryOut());
+ assertEquals("0", am2901.getOverflow());
+ assertEquals("0", am2901.getSign());
+ assertEquals("1", am2901.getZero());
+ assertEquals("0", am2901.getQ_0());
+ assertEquals("0", am2901.getQ_3());
+ assertEquals("0", am2901.getRAM_0());
+ assertEquals("0", am2901.getRAM_3());
+
+ assertAll("register values", Register.stream().map(r -> () ->
{
- if (this.ordinal() > 0xF)
- throw new UnsupportedOperationException();
- return TestUtil.to4bitBin(this.ordinal());
- }
+ assertEquals("0000", am2901.getDirectly(r), r.name());
+ }));
+ }
+
+ @Order(4)
+ @Test
+ void testADD()
+ {
+ am2901.setSrc(DA);
+ am2901.setFunc(ADD);
+ am2901.setDest(NOP);
+ am2901.setReg_A(r0.toBitString());
+
+ assertAll(getAll4BitPairs().map(xy -> () ->
+ {
+ am2901.setDirectly(r0, to4bitBin(xy.x));
+ am2901.setD(to4bitBin(xy.y));
+
+ am2901.assertFullCycleSuccess();
+
+ int res32Bit = xy.x + xy.y;
+ int res4Bit = res32Bit & 0b1111;
+ int res32Bit_sgn = signed4ToSigned32(xy.x) + signed4ToSigned32(xy.y);
+ int res4Bit_sgn = signed4ToSigned32(res32Bit_sgn);
+
+ String desc = xy.x + " + " + xy.y + " = " + res4Bit + ": ";
+
+ assertEquals(to4bitBin(res4Bit & 0b1111), am2901.getY(), desc + "Y");
+ assertEquals(to1bitBin(res4Bit == 0), am2901.getZero(), desc + "F=0");
+ assertEquals(to1bitBin(res4Bit & 0b1000), am2901.getSign(), desc + "F3");
+ assertEquals(to1bitBin(res32Bit & 0b1_0000), am2901.getCarryOut(), desc + "Cn+4");
+ assertEquals(to1bitBin(res4Bit_sgn != res32Bit_sgn), am2901.getOverflow(), desc + "OVR");
+ }));
+ }
+
+ @Order(4)
+ @Test
+ void testAND()
+ {
+ am2901.setSrc(DA);
+ am2901.setFunc(AND);
+ am2901.setDest(NOP);
+ am2901.setReg_A(r0.toBitString());
+
+ assertAll(getAll4BitPairs().map(xy -> () ->
+ {
+ am2901.setDirectly(r0, to4bitBin(xy.x));
+ am2901.setD(to4bitBin(xy.y));
+
+ am2901.assertFullCycleSuccess();
+
+ int res32Bit = xy.x & xy.y;
+
+ String desc = xy.x + " & " + xy.y + " = " + res32Bit + ": ";
+
+ assertEquals(to4bitBin(res32Bit), am2901.getY(), desc + "Y");
+ assertEquals(to1bitBin(res32Bit == 0), am2901.getZero(), desc + "F=0");
+ assertEquals(to1bitBin(res32Bit & 0b1000), am2901.getSign(), desc + "F3");
+// assertEquals(to1bitBin(res32Bit), am2901.getCarryOut(), desc + "Cn+4"); // TODO
+// assertEquals(to1bitBin(res32Bit), am2901.getOverflow(), desc + "OVR"); // TODO
+ }));
+ }
+
+ @Order(4)
+ @Test
+ void testOR()
+ {
+ am2901.setSrc(DA);
+ am2901.setFunc(OR);
+ am2901.setDest(NOP);
+ am2901.setReg_A(r0.toBitString());
+
+ assertAll(getAll4BitPairs().map(xy -> () ->
+ {
+ am2901.setDirectly(r0, to4bitBin(xy.x));
+ am2901.setD(to4bitBin(xy.y));
+
+ am2901.assertFullCycleSuccess();
+
+ int res32Bit = xy.x | xy.y;
+
+ String desc = xy.x + " | " + xy.y + " = " + res32Bit + ": ";
+
+ assertEquals(to4bitBin(res32Bit), am2901.getY(), desc + "Y");
+ assertEquals(to1bitBin(res32Bit == 0), am2901.getZero(), desc + "F=0");
+ assertEquals(to1bitBin(res32Bit & 0b1000), am2901.getSign(), desc + "F3");
+// assertEquals(to1bitBin(res32Bit != 0b1111), am2901.getCarryOut(), desc + "Cn+4"); // TODO
+// assertEquals(to1bitBin(res32Bit != 0b1111), am2901.getOverflow(), desc + "OVR"); // TODO
+ }));
+ }
+
+ @Order(4)
+ @Test
+ void testXOR()
+ {
+ am2901.setSrc(DA);
+ am2901.setFunc(EXOR);
+ am2901.setDest(NOP);
+ am2901.setReg_A(r0.toBitString());
+
+ assertAll(getAll4BitPairs().map(xy -> () ->
+ {
+ am2901.setDirectly(r0, to4bitBin(xy.x));
+ am2901.setD(to4bitBin(xy.y));
+
+ am2901.assertFullCycleSuccess();
+
+ int res32Bit = xy.x ^ xy.y;
+
+ String desc = xy.x + " ^ " + xy.y + " = " + res32Bit + ": ";
+
+ assertEquals(to4bitBin(res32Bit), am2901.getY(), desc + "Y");
+ assertEquals(to1bitBin(res32Bit == 0), am2901.getZero(), desc + "F=0");
+ assertEquals(to1bitBin(res32Bit & 0b1000), am2901.getSign(), desc + "F3");
+// assertEquals(to1bitBin(res32Bit != 0b1111), am2901.getCarryOut(), desc + "Cn+4"); // TODO
+// assertEquals(to1bitBin(res32Bit != 0b1111), am2901.getOverflow(), desc + "OVR"); // TODO
+ }));
+ }
+
+ @Order(4)
+ @Test
+ void testSUB()
+ {
+ am2901.setSrc(DA);
+ am2901.setCarryIn("1");
+ am2901.setFunc(SUBR);
+ am2901.setDest(NOP);
+ am2901.setReg_A(r0.toBitString());
+
+ assertAll(getAll4BitPairs().map(xy -> () ->
+ {
+ am2901.setDirectly(r0, to4bitBin(xy.x));
+ am2901.setD(to4bitBin(xy.y));
+
+ am2901.assertFullCycleSuccess();
+
+ int res32Bit = xy.x - xy.y;
+ int res4Bit = res32Bit & 0b1111;
+ int res32Bit_sgn = signed4ToSigned32(xy.x) - signed4ToSigned32(xy.y);
+ int res4Bit_sgn = signed4ToSigned32(res32Bit_sgn);
+
+ String desc = xy.x + " - " + xy.y + " = " + res4Bit + ": ";
+
+ assertEquals(to4bitBin(res4Bit & 0b1111), am2901.getY(), desc + "Y");
+ assertEquals(to1bitBin(res4Bit == 0), am2901.getZero(), desc + "F=0");
+ assertEquals(to1bitBin(res4Bit & 0b1000), am2901.getSign(), desc + "F3");
+ assertEquals(to1bitBin(xy.x >= xy.y), am2901.getCarryOut(), desc + "Cn+4");
+ assertEquals(to1bitBin(res4Bit_sgn != res32Bit_sgn), am2901.getOverflow(), desc + "OVR");
+ }));
+ }
+
+ static Stream<Point> getAll4BitPairs()
+ {
+ return IntStream.range(0, 16).boxed().flatMap(x -> IntStream.range(0, 16).mapToObj(y -> new Point(x, y)));
}
}
--- /dev/null
+package net.mograsim.logic.ui.am2900;
+
+import net.mograsim.logic.ui.SimpleLogicUIStandalone;
+import net.mograsim.logic.ui.model.ViewModelModifiable;
+import net.mograsim.logic.ui.model.components.GUIAndGate;
+import net.mograsim.logic.ui.model.components.GUIBitDisplay;
+import net.mograsim.logic.ui.model.components.GUIManualSwitch;
+import net.mograsim.logic.ui.model.components.GUINotGate;
+import net.mograsim.logic.ui.model.components.SimpleRectangularSubmodelComponent;
+import net.mograsim.logic.ui.model.components.TextComponent;
+import net.mograsim.logic.ui.model.components.mi.nandbased.GUIdff;
+import net.mograsim.logic.ui.model.components.mi.nandbased.am2901.GUIAm2901;
+import net.mograsim.logic.ui.model.wires.ConnectionPoint;
+import net.mograsim.logic.ui.model.wires.WireCrossPoint;
+import net.mograsim.logic.ui.util.ModellingTool;
+
+public class Am2901Testbench
+{
+ public static void main(String[] args)
+ {
+ SimpleLogicUIStandalone.executeVisualisation(Am2901Testbench::createTestbench);
+ }
+
+ public static void createTestbench(ViewModelModifiable model)
+ {
+ SimpleRectangularSubmodelComponent comp = new GUIAm2901(model);
+ ModellingTool tool = ModellingTool.createFor(model);
+
+ comp.moveTo(240, 0);
+
+ GUIManualSwitch enable = new GUIManualSwitch(model);
+ WireCrossPoint wcp0 = new WireCrossPoint(model, 1);
+ GUINotGate not1 = new GUINotGate(model, 1);
+ GUINotGate not2 = new GUINotGate(model, 1);
+ GUINotGate not3 = new GUINotGate(model, 1);
+ GUIAndGate and = new GUIAndGate(model, 1);
+ tool.connect(wcp0, enable, "");
+ tool.connect(wcp0, and, "A");
+ tool.connect(wcp0, not1, "A");
+ tool.connect(not1, not2, "Y", "A");
+ tool.connect(not2, not3, "Y", "A");
+ tool.connect(not3, and, "Y", "B");
+ enable.moveTo(20, -32.5);
+ wcp0.moveTo(35, -26);
+ not1.moveTo(50, -20);
+ not2.moveTo(80, -20);
+ not3.moveTo(110, -20);
+ and.moveTo(135, -30);
+ ConnectionPoint last = and.getPin("Y");
+
+ for (int i = 0; i < comp.getInputPinNames().size(); i++)
+ {
+ double x = 55 + 70 * (i % 2);
+ double y = 10 * i;
+
+ WireCrossPoint wcp = new WireCrossPoint(model, 1);
+ GUIdff d_ff = new GUIdff(model);
+ GUIManualSwitch sw = new GUIManualSwitch(model);
+
+ tool.connect(last, wcp);
+ tool.connect(wcp, d_ff, "C");
+ tool.connect(sw, d_ff, "", "D");
+ tool.connect(d_ff, comp, "Q", comp.getInputPinNames().get(i));
+ last = wcp.getPin();
+
+ TextComponent label = new TextComponent(model, comp.getInputPinNames().get(i));
+
+ sw.moveTo(x, y + 7.5);
+ wcp.moveTo(160, y);
+ d_ff.moveTo(170, y);
+ label.moveTo(x - 25, y + 15);
+ }
+
+ for (int i = 0; i < comp.getOutputPinNames().size(); i++)
+ {
+ double x = 300 + 75 * (i % 2);
+ double y = 10 * i - 2.5;
+ GUIBitDisplay bd = new GUIBitDisplay(model);
+ bd.moveTo(x, y);
+ tool.connect(bd.getInputPin(), comp, comp.getOutputPinNames().get(i));
+
+ TextComponent label = new TextComponent(model, comp.getOutputPinNames().get(i));
+ label.moveTo(x + 50, y + 8);
+ }
+ }
+}
\ No newline at end of file