diff --git a/src/main/java/de/neemann/digital/core/Node.java b/src/main/java/de/neemann/digital/core/Node.java index 3fd12d4c9..4d0c75ea3 100644 --- a/src/main/java/de/neemann/digital/core/Node.java +++ b/src/main/java/de/neemann/digital/core/Node.java @@ -39,4 +39,8 @@ public abstract class Node implements Listener { */ public abstract void writeOutputs() throws NodeException; + public void registerNodes(Model model) { + model.add(this); + } + } diff --git a/src/main/java/de/neemann/digital/core/ObservableValue.java b/src/main/java/de/neemann/digital/core/ObservableValue.java index c2fe72fa2..d5291c104 100644 --- a/src/main/java/de/neemann/digital/core/ObservableValue.java +++ b/src/main/java/de/neemann/digital/core/ObservableValue.java @@ -55,6 +55,14 @@ public class ObservableValue extends Value { } } + public boolean getBool() { + return getValue() != 0; + } + + public void setBool(boolean bool) { + setValue(bool ? 1 : 0); + } + public long getValueBits(long value) { return value & mask; } @@ -87,11 +95,12 @@ public class ObservableValue extends Value { public String toString() { return name + "{" + "value=" + (highZ ? "??" : value) + - ", bits=" + bits + + ", setBits=" + bits + '}'; } public String getName() { return name; } + } diff --git a/src/main/java/de/neemann/digital/core/arithmetic/Add.java b/src/main/java/de/neemann/digital/core/arithmetic/Add.java index d331cecd7..503d1cff7 100644 --- a/src/main/java/de/neemann/digital/core/arithmetic/Add.java +++ b/src/main/java/de/neemann/digital/core/arithmetic/Add.java @@ -1,6 +1,9 @@ package de.neemann.digital.core.arithmetic; -import de.neemann.digital.core.*; +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; import de.neemann.digital.core.part.AttributeKey; import de.neemann.digital.core.part.Part; import de.neemann.digital.core.part.PartAttributes; @@ -72,8 +75,4 @@ public class Add extends Node implements Part { return new ObservableValue[]{sum, c_out}; } - @Override - public void registerNodes(Model model) { - model.add(this); - } } diff --git a/src/main/java/de/neemann/digital/core/arithmetic/Mul.java b/src/main/java/de/neemann/digital/core/arithmetic/Mul.java index 83a80ca93..7b6dfd8b4 100644 --- a/src/main/java/de/neemann/digital/core/arithmetic/Mul.java +++ b/src/main/java/de/neemann/digital/core/arithmetic/Mul.java @@ -1,6 +1,5 @@ package de.neemann.digital.core.arithmetic; -import de.neemann.digital.core.Model; import de.neemann.digital.core.Node; import de.neemann.digital.core.NodeException; import de.neemann.digital.core.ObservableValue; @@ -51,8 +50,4 @@ public class Mul extends Node implements Part { return new ObservableValue[]{mul}; } - @Override - public void registerNodes(Model model) { - model.add(this); - } } diff --git a/src/main/java/de/neemann/digital/core/basic/FanIn.java b/src/main/java/de/neemann/digital/core/basic/FanIn.java index 785d1ddcc..9c7fe6754 100644 --- a/src/main/java/de/neemann/digital/core/basic/FanIn.java +++ b/src/main/java/de/neemann/digital/core/basic/FanIn.java @@ -1,6 +1,5 @@ package de.neemann.digital.core.basic; -import de.neemann.digital.core.Model; import de.neemann.digital.core.Node; import de.neemann.digital.core.NodeException; import de.neemann.digital.core.ObservableValue; @@ -42,12 +41,6 @@ public abstract class FanIn extends Node implements Part { return new ObservableValue[]{output}; } - @Override - public void registerNodes(Model model) { - model.add(this); - } - - public static class FanInDescription extends PartTypeDescription { public FanInDescription(Class clazz) { super(clazz); diff --git a/src/main/java/de/neemann/digital/core/basic/Not.java b/src/main/java/de/neemann/digital/core/basic/Not.java index cd59f6709..ff16bc60f 100644 --- a/src/main/java/de/neemann/digital/core/basic/Not.java +++ b/src/main/java/de/neemann/digital/core/basic/Not.java @@ -1,6 +1,5 @@ package de.neemann.digital.core.basic; -import de.neemann.digital.core.Model; import de.neemann.digital.core.Node; import de.neemann.digital.core.NodeException; import de.neemann.digital.core.ObservableValue; @@ -48,8 +47,4 @@ public class Not extends Node implements Part { return new ObservableValue[]{output}; } - @Override - public void registerNodes(Model model) { - model.add(this); - } } diff --git a/src/main/java/de/neemann/digital/core/basic/XNOr.java b/src/main/java/de/neemann/digital/core/basic/XNOr.java new file mode 100644 index 000000000..f9848e4f1 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/basic/XNOr.java @@ -0,0 +1,23 @@ +package de.neemann.digital.core.basic; + +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.part.AttributeKey; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class XNOr extends XOr { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(XNOr.class, "a", "b").addAttribute(AttributeKey.Bits); + + public XNOr(PartAttributes attributes) { + super(attributes); + } + + @Override + public void readInputs() throws NodeException { + value = ~(a.getValue() ^ b.getValue()); + } +} diff --git a/src/main/java/de/neemann/digital/core/basic/XOr.java b/src/main/java/de/neemann/digital/core/basic/XOr.java new file mode 100644 index 000000000..1082b980f --- /dev/null +++ b/src/main/java/de/neemann/digital/core/basic/XOr.java @@ -0,0 +1,58 @@ +package de.neemann.digital.core.basic; + +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.AttributeKey; +import de.neemann.digital.core.part.Part; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class XOr extends Node implements Part { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(XOr.class, "a", "b").addAttribute(AttributeKey.Bits); + private final int bits; + private final ObservableValue out; + protected ObservableValue a; + protected ObservableValue b; + protected long value; + + public XOr(PartAttributes attributes) { + bits = attributes.get(AttributeKey.Bits); + this.out = new ObservableValue("out", bits); + } + + @Override + public void readInputs() throws NodeException { + value = a.getValue() ^ b.getValue(); + } + + @Override + public void writeOutputs() throws NodeException { + out.setValue(value); + } + + @Override + public void setInputs(ObservableValue... inputs) throws BitsException { + a = inputs[0]; + a.addListener(this); + b = inputs[1]; + b.addListener(this); + + if (a.getBits() != bits) + throw new BitsException("wrongBitCount", a); + + if (b.getBits() != bits) + throw new BitsException("wrongBitCount", b); + } + + @Override + public ObservableValue[] getOutputs() { + return new ObservableValue[]{out}; + } + +} diff --git a/src/main/java/de/neemann/digital/core/flipflops/D_FF.java b/src/main/java/de/neemann/digital/core/flipflops/D_FF.java new file mode 100644 index 000000000..6d2ba90c4 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/flipflops/D_FF.java @@ -0,0 +1,65 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.AttributeKey; +import de.neemann.digital.core.part.Part; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class D_FF extends Node implements Part { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(D_FF.class, "D", "C").addAttribute(AttributeKey.Bits); + private final int bits; + private ObservableValue dVal; + private ObservableValue clockVal; + private ObservableValue q; + private ObservableValue qn; + private boolean lastClock; + private long value; + + public D_FF(PartAttributes attributes) { + bits = attributes.getBits(); + this.q = new ObservableValue("Q", bits); + this.qn = new ObservableValue("~Q", bits); + } + + @Override + public void readInputs() throws NodeException { + boolean clock = clockVal.getBool(); + if (clock && !lastClock) + value = dVal.getValue(); + lastClock = clock; + } + + @Override + public void writeOutputs() throws NodeException { + q.setValue(value); + qn.setValue(~value); + } + + @Override + public void setInputs(ObservableValue... inputs) throws BitsException { + dVal = inputs[0]; + dVal.addListener(this); + clockVal = inputs[1]; + clockVal.addListener(this); + + if (dVal.getBits() != bits) + throw new BitsException("wrongBitCount", dVal); + + if (clockVal.getBits() != 1) + throw new BitsException("clockIsABit", clockVal); + } + + @Override + public ObservableValue[] getOutputs() { + return new ObservableValue[]{q, qn}; + } + +} diff --git a/src/main/java/de/neemann/digital/core/flipflops/JK_FF.java b/src/main/java/de/neemann/digital/core/flipflops/JK_FF.java new file mode 100644 index 000000000..31c4a0179 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/flipflops/JK_FF.java @@ -0,0 +1,74 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.Part; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class JK_FF extends Node implements Part { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(JK_FF.class, "J", "C", "K"); + private ObservableValue jVal; + private ObservableValue kVal; + private ObservableValue clockVal; + private ObservableValue q; + private ObservableValue qn; + private boolean lastClock; + private boolean out; + + public JK_FF(PartAttributes attributes) { + this.q = new ObservableValue("Q", 1); + this.qn = new ObservableValue("~Q", 1); + } + + @Override + public void readInputs() throws NodeException { + boolean clock = clockVal.getBool(); + if (clock && !lastClock) { + boolean j = jVal.getBool(); + boolean k = kVal.getBool(); + + if (j && k) out = !out; + else if (j) out = true; + else if (k) out = false; + } + lastClock = clock; + } + + @Override + public void writeOutputs() throws NodeException { + q.setBool(out); + qn.setBool(!out); + } + + @Override + public void setInputs(ObservableValue... inputs) throws BitsException { + jVal = inputs[0]; + jVal.addListener(this); + clockVal = inputs[1]; + clockVal.addListener(this); + kVal = inputs[2]; + kVal.addListener(this); + + if (jVal.getBits() != 1) + throw new BitsException("wrongBitCount", jVal); + + if (kVal.getBits() != 1) + throw new BitsException("wrongBitCount", kVal); + + if (clockVal.getBits() != 1) + throw new BitsException("carryIsABit", clockVal); + } + + @Override + public ObservableValue[] getOutputs() { + return new ObservableValue[]{q, qn}; + } + +} diff --git a/src/main/java/de/neemann/digital/core/flipflops/RS_FF.java b/src/main/java/de/neemann/digital/core/flipflops/RS_FF.java new file mode 100644 index 000000000..43666289f --- /dev/null +++ b/src/main/java/de/neemann/digital/core/flipflops/RS_FF.java @@ -0,0 +1,73 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.Part; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class RS_FF extends Node implements Part { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(RS_FF.class, "R", "C", "S"); + private ObservableValue jVal; + private ObservableValue kVal; + private ObservableValue clockVal; + private ObservableValue q; + private ObservableValue qn; + private boolean lastClock; + private boolean out; + + public RS_FF(PartAttributes attributes) { + this.q = new ObservableValue("Q", 1); + this.qn = new ObservableValue("~Q", 1); + } + + @Override + public void readInputs() throws NodeException { + boolean clock = clockVal.getBool(); + if (clock && !lastClock) { + boolean j = jVal.getBool(); + boolean k = kVal.getBool(); + + if (j && !k) out = true; + else if (!j && k) out = false; + } + lastClock = clock; + } + + @Override + public void writeOutputs() throws NodeException { + q.setBool(out); + qn.setBool(!out); + } + + @Override + public void setInputs(ObservableValue... inputs) throws BitsException { + jVal = inputs[0]; + jVal.addListener(this); + clockVal = inputs[1]; + clockVal.addListener(this); + kVal = inputs[2]; + kVal.addListener(this); + + if (jVal.getBits() != 1) + throw new BitsException("wrongBitCount", jVal); + + if (kVal.getBits() != 1) + throw new BitsException("wrongBitCount", kVal); + + if (clockVal.getBits() != 1) + throw new BitsException("carryIsABit", clockVal); + } + + @Override + public ObservableValue[] getOutputs() { + return new ObservableValue[]{q, qn}; + } + +} diff --git a/src/main/java/de/neemann/digital/core/flipflops/T_FF.java b/src/main/java/de/neemann/digital/core/flipflops/T_FF.java new file mode 100644 index 000000000..1a56dbd38 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/flipflops/T_FF.java @@ -0,0 +1,57 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.core.BitsException; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.Part; +import de.neemann.digital.core.part.PartAttributes; +import de.neemann.digital.core.part.PartTypeDescription; + +/** + * @author hneemann + */ +public class T_FF extends Node implements Part { + + public static final PartTypeDescription DESCRIPTION = new PartTypeDescription(T_FF.class, "C"); + private ObservableValue clockVal; + private ObservableValue q; + private ObservableValue qn; + private boolean lastClock; + private boolean out; + + public T_FF(PartAttributes attributes) { + this.q = new ObservableValue("Q", 1); + this.qn = new ObservableValue("~Q", 1); + } + + @Override + public void readInputs() throws NodeException { + boolean clock = clockVal.getBool(); + if (clock && !lastClock) { + out = !out; + } + lastClock = clock; + } + + @Override + public void writeOutputs() throws NodeException { + q.setBool(out); + qn.setBool(!out); + } + + @Override + public void setInputs(ObservableValue... inputs) throws BitsException { + clockVal = inputs[0]; + clockVal.addListener(this); + + if (clockVal.getBits() != 1) + throw new BitsException("carryIsABit", clockVal); + } + + @Override + public ObservableValue[] getOutputs() { + return new ObservableValue[]{q, qn}; + } + +} diff --git a/src/main/java/de/neemann/digital/core/part/PartAttributes.java b/src/main/java/de/neemann/digital/core/part/PartAttributes.java index 2179fde6b..263515086 100644 --- a/src/main/java/de/neemann/digital/core/part/PartAttributes.java +++ b/src/main/java/de/neemann/digital/core/part/PartAttributes.java @@ -55,7 +55,11 @@ public class PartAttributes { listeners.remove(listener); } - public PartAttributes bits(int bits) { + public int getBits() { + return get(AttributeKey.Bits); + } + + public PartAttributes setBits(int bits) { set(AttributeKey.Bits, bits); return this; } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index ec89e6008..19d32156a 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -170,10 +170,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { setJMenuBar(bar); } - public static void main(String[] args) { - SwingUtilities.invokeLater(() -> new Main().setVisible(true)); - } - private static XStream getxStream() { XStream xStream = new XStream(new StaxDriver()); xStream.alias("visualPart", VisualPart.class); @@ -187,6 +183,10 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { return xStream; } + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> new Main().setVisible(true)); + } + private JFileChooser getjFileChooser() { JFileChooser fileChooser = new JFileChooser(filename == null ? null : filename.getParentFile()); fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Circuit", "dig")); @@ -195,7 +195,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { @Override public boolean isStateChanged() { - return false; + return circuitComponent.getCircuit().isModified(); } @Override diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 61dc6ec10..9d676034d 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -27,7 +27,7 @@ public class CircuitComponent extends JComponent implements Listener { private final PartLibrary library; private Circuit circuit; private Mouse listener; - private AffineTransform transform = AffineTransform.getScaleInstance(1, 1); + private AffineTransform transform = new AffineTransform(); public CircuitComponent(Circuit aCircuit, PartLibrary library) { this.circuit = aCircuit; @@ -56,8 +56,8 @@ public class CircuitComponent extends JComponent implements Listener { @Override public void mouseWheelMoved(MouseWheelEvent e) { Vector pos = getPosVector(e); - transform.translate(pos.x, pos.y); double f = Math.pow(0.9, e.getWheelRotation()); + transform.translate(pos.x, pos.y); transform.scale(f, f); transform.translate(-pos.x, -pos.y); repaint(); @@ -355,7 +355,6 @@ public class CircuitComponent extends JComponent implements Listener { if (vp.matches(pos)) { vp.clicked(CircuitComponent.this, pos); } - } } } diff --git a/src/main/java/de/neemann/digital/gui/draw/library/PartLibrary.java b/src/main/java/de/neemann/digital/gui/draw/library/PartLibrary.java index 82c1ab724..f9e25bf73 100644 --- a/src/main/java/de/neemann/digital/gui/draw/library/PartLibrary.java +++ b/src/main/java/de/neemann/digital/gui/draw/library/PartLibrary.java @@ -1,6 +1,13 @@ package de.neemann.digital.gui.draw.library; +import de.neemann.digital.core.arithmetic.Add; +import de.neemann.digital.core.arithmetic.Mul; +import de.neemann.digital.core.arithmetic.Sub; import de.neemann.digital.core.basic.*; +import de.neemann.digital.core.flipflops.D_FF; +import de.neemann.digital.core.flipflops.JK_FF; +import de.neemann.digital.core.flipflops.RS_FF; +import de.neemann.digital.core.flipflops.T_FF; import de.neemann.digital.core.io.In; import de.neemann.digital.core.io.Out; import de.neemann.digital.core.part.PartTypeDescription; @@ -19,17 +26,24 @@ public class PartLibrary implements Iterable { public PartLibrary() { add(And.DESCRIPTION, "Logic"); - add(Or.DESCRIPTION, "Logic"); add(NAnd.DESCRIPTION, "Logic"); + add(Or.DESCRIPTION, "Logic"); add(NOr.DESCRIPTION, "Logic"); + add(XOr.DESCRIPTION, "Logic"); + add(XNOr.DESCRIPTION, "Logic"); add(Not.DESCRIPTION, "Logic"); add(In.DESCRIPTION, "IO"); add(Out.DESCRIPTION, "IO"); -// add(Add.DESCRIPTION,"Aritmetic"); -// add(Sub.DESCRIPTION,"Aritmetic"); -// add(Mul.DESCRIPTION,"Aritmetic"); + add(RS_FF.DESCRIPTION, "FlipFlops"); + add(JK_FF.DESCRIPTION, "FlipFlops"); + add(D_FF.DESCRIPTION, "FlipFlops"); + add(T_FF.DESCRIPTION, "FlipFlops"); + + add(Add.DESCRIPTION, "Aritmetic"); + add(Sub.DESCRIPTION, "Aritmetic"); + add(Mul.DESCRIPTION, "Aritmetic"); } private void add(PartTypeDescription description, String treePath) { diff --git a/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java b/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java index af3ca774e..8d49fd793 100644 --- a/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java +++ b/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java @@ -14,6 +14,7 @@ public class Circuit implements Drawable { private final ArrayList visualParts; private ArrayList wires; private transient boolean dotsPresent = false; + private transient boolean modified = false; public Circuit() { visualParts = new ArrayList<>(); @@ -35,6 +36,7 @@ public class Circuit implements Drawable { public void add(VisualPart visualPart) { visualParts.add(visualPart); + modified = true; } public void add(Wire newWire) { @@ -58,6 +60,7 @@ public class Circuit implements Drawable { wires = checker.check(); dotsPresent = false; + modified = true; } public ArrayList getParts() { @@ -96,6 +99,7 @@ public class Circuit implements Drawable { } } dotsPresent = false; + modified = true; } public ArrayList getWires() { @@ -108,4 +112,8 @@ public class Circuit implements Drawable { for (Wire w : wires) w.setValue(null); } + + public boolean isModified() { + return modified; + } } diff --git a/src/main/java/de/neemann/digital/gui/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/gui/draw/shapes/ShapeFactory.java index e8a25b762..da37405b9 100644 --- a/src/main/java/de/neemann/digital/gui/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/gui/draw/shapes/ShapeFactory.java @@ -1,6 +1,9 @@ package de.neemann.digital.gui.draw.shapes; import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.arithmetic.Add; +import de.neemann.digital.core.arithmetic.Mul; +import de.neemann.digital.core.arithmetic.Sub; import de.neemann.digital.core.basic.*; import de.neemann.digital.core.io.In; import de.neemann.digital.core.io.Out; @@ -26,6 +29,14 @@ public final class ShapeFactory { map.put(NOr.DESCRIPTION.getName(), new CreatorSimple("\u22651", NOr.DESCRIPTION, true)); map.put(Not.DESCRIPTION.getName(), new CreatorSimple("", Not.DESCRIPTION, true)); + map.put(XOr.DESCRIPTION.getName(), new CreatorSimple("=1", XOr.DESCRIPTION, false)); + map.put(XNOr.DESCRIPTION.getName(), new CreatorSimple("=1", XNOr.DESCRIPTION, true)); + + map.put(Add.DESCRIPTION.getName(), new CreatorSimple("+", Add.DESCRIPTION, false)); + map.put(Sub.DESCRIPTION.getName(), new CreatorSimple("-", Sub.DESCRIPTION, false)); + map.put(Mul.DESCRIPTION.getName(), new CreatorSimple("*", Mul.DESCRIPTION, false)); + + map.put(In.DESCRIPTION.getName(), attributes -> new InputShape(attributes.get(AttributeKey.Bits), attributes.get(AttributeKey.Label))); map.put(Out.DESCRIPTION.getName(), attributes -> new OutputShape(attributes.get(AttributeKey.Bits), attributes.get(AttributeKey.Label))); } @@ -50,12 +61,20 @@ public final class ShapeFactory { throw new RuntimeException("no shape for " + partName); else { PartTypeDescription pt = library.getPartType(partName); - return new GenericShape(partName, pt.getInputNames(partAttributes), outputNames(pt, partAttributes)); + return new GenericShape(createName(partName), pt.getInputNames(partAttributes), outputNames(pt, partAttributes)); } } else return cr.create(partAttributes); } + private String createName(String partName) { + int p = partName.indexOf('_'); + if (p < 0) + return partName; + else + return partName.substring(0, p); + } + private interface Creator { Shape create(PartAttributes attributes); } diff --git a/src/test/java/de/neemann/digital/FlipFlops.java b/src/test/java/de/neemann/digital/FlipFlops.java index ead1a7863..e4f77670e 100644 --- a/src/test/java/de/neemann/digital/FlipFlops.java +++ b/src/test/java/de/neemann/digital/FlipFlops.java @@ -16,8 +16,8 @@ public class FlipFlops extends TestCase { ObservableValue s = new ObservableValue("s", 1); Model model = new Model(); - FanIn a1 = model.add(new NOr(new PartAttributes().bits(1))); - FanIn a2 = model.add(new NOr(new PartAttributes().bits(1))); + FanIn a1 = model.add(new NOr(new PartAttributes().setBits(1))); + FanIn a2 = model.add(new NOr(new PartAttributes().setBits(1))); a1.setInputs(r, a2.getOutput()); a2.setInputs(s, a1.getOutput()); @@ -42,8 +42,8 @@ public class FlipFlops extends TestCase { ObservableValue s = new ObservableValue("s", 1); Model model = new Model(); - FanIn a1 = model.add(new NAnd(new PartAttributes().bits(1))); - FanIn a2 = model.add(new NAnd(new PartAttributes().bits(1))); + FanIn a1 = model.add(new NAnd(new PartAttributes().setBits(1))); + FanIn a2 = model.add(new NAnd(new PartAttributes().setBits(1))); a1.setInputs(r, a2.getOutput()); a2.setInputs(s, a1.getOutput()); @@ -62,7 +62,7 @@ public class FlipFlops extends TestCase { ObservableValue k = new ObservableValue("k", 1); ObservableValue c = new ObservableValue("c", 1); - PartAttributes attr = new PartAttributes().bits(1); + PartAttributes attr = new PartAttributes().setBits(1); Model model = new Model(); FanIn nor3 = model.add(new NOr(attr)); diff --git a/src/test/java/de/neemann/digital/core/arithmetic/AddTest.java b/src/test/java/de/neemann/digital/core/arithmetic/AddTest.java index 51453584d..71ccbbc4f 100644 --- a/src/test/java/de/neemann/digital/core/arithmetic/AddTest.java +++ b/src/test/java/de/neemann/digital/core/arithmetic/AddTest.java @@ -18,7 +18,7 @@ public class AddTest extends TestCase { Model model = new Model(); - Add node = new Add(new PartAttributes().bits(4)); + Add node = new Add(new PartAttributes().setBits(4)); node.setInputs(a, b, c); model.add(node); diff --git a/src/test/java/de/neemann/digital/core/arithmetic/MulTest.java b/src/test/java/de/neemann/digital/core/arithmetic/MulTest.java index 4b8f5ac27..291b8b754 100644 --- a/src/test/java/de/neemann/digital/core/arithmetic/MulTest.java +++ b/src/test/java/de/neemann/digital/core/arithmetic/MulTest.java @@ -16,7 +16,7 @@ public class MulTest extends TestCase { Model model = new Model(); - Mul node = model.add(new Mul(new PartAttributes().bits(4))); + Mul node = model.add(new Mul(new PartAttributes().setBits(4))); node.setInputs(a, b); TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(node.getMul()); diff --git a/src/test/java/de/neemann/digital/core/arithmetic/SubTest.java b/src/test/java/de/neemann/digital/core/arithmetic/SubTest.java index da9908f9d..c3279f934 100644 --- a/src/test/java/de/neemann/digital/core/arithmetic/SubTest.java +++ b/src/test/java/de/neemann/digital/core/arithmetic/SubTest.java @@ -18,7 +18,7 @@ public class SubTest extends TestCase { Model model = new Model(); - Add node = new Sub(new PartAttributes().bits(4)); + Add node = new Sub(new PartAttributes().setBits(4)); node.setInputs(a, b, c); model.add(node); diff --git a/src/test/java/de/neemann/digital/core/basic/AndTest.java b/src/test/java/de/neemann/digital/core/basic/AndTest.java index 31828db60..d0d196167 100644 --- a/src/test/java/de/neemann/digital/core/basic/AndTest.java +++ b/src/test/java/de/neemann/digital/core/basic/AndTest.java @@ -15,9 +15,8 @@ public class AndTest extends TestCase { ObservableValue a = new ObservableValue("a", 1); ObservableValue b = new ObservableValue("b", 1); - Model model = new Model(); - FanIn out = model.add(new And(new PartAttributes().bits(1))); + FanIn out = model.add(new And(new PartAttributes().setBits(1))); out.setInputs(a, b); TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(out.getOutputs()); diff --git a/src/test/java/de/neemann/digital/core/basic/NAndTest.java b/src/test/java/de/neemann/digital/core/basic/NAndTest.java index 721831a2b..78a61f175 100644 --- a/src/test/java/de/neemann/digital/core/basic/NAndTest.java +++ b/src/test/java/de/neemann/digital/core/basic/NAndTest.java @@ -16,7 +16,7 @@ public class NAndTest extends TestCase { ObservableValue b = new ObservableValue("b", 1); Model model = new Model(); - FanIn out = model.add(new NAnd(new PartAttributes().bits(1))); + FanIn out = model.add(new NAnd(new PartAttributes().setBits(1))); out.setInputs(a, b); diff --git a/src/test/java/de/neemann/digital/core/basic/NOrTest.java b/src/test/java/de/neemann/digital/core/basic/NOrTest.java index abba487dc..58783c46f 100644 --- a/src/test/java/de/neemann/digital/core/basic/NOrTest.java +++ b/src/test/java/de/neemann/digital/core/basic/NOrTest.java @@ -16,7 +16,7 @@ public class NOrTest extends TestCase { ObservableValue b = new ObservableValue("b", 1); Model model = new Model(); - NOr nor = model.add(new NOr(new PartAttributes().bits(1))); + NOr nor = model.add(new NOr(new PartAttributes().setBits(1))); nor.setInputs(a, b); TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(nor.getOutputs()); diff --git a/src/test/java/de/neemann/digital/core/basic/OrTest.java b/src/test/java/de/neemann/digital/core/basic/OrTest.java index 079982cd6..788c8fc94 100644 --- a/src/test/java/de/neemann/digital/core/basic/OrTest.java +++ b/src/test/java/de/neemann/digital/core/basic/OrTest.java @@ -16,7 +16,7 @@ public class OrTest extends TestCase { ObservableValue b = new ObservableValue("b", 1); Model model = new Model(); - FanIn and = model.add(new Or(new PartAttributes().bits(1))); + FanIn and = model.add(new Or(new PartAttributes().setBits(1))); and.setInputs(a, b); TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(and.getOutput()); diff --git a/src/test/java/de/neemann/digital/core/basic/XNOrTest.java b/src/test/java/de/neemann/digital/core/basic/XNOrTest.java new file mode 100644 index 000000000..135369a0a --- /dev/null +++ b/src/test/java/de/neemann/digital/core/basic/XNOrTest.java @@ -0,0 +1,29 @@ +package de.neemann.digital.core.basic; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class XNOrTest extends TestCase { + + public void testXor() throws Exception { + ObservableValue a = new ObservableValue("a", 1); + ObservableValue b = new ObservableValue("b", 1); + + + Model model = new Model(); + XNOr out = model.add(new XNOr(new PartAttributes().setBits(1))); + out.setInputs(a, b); + + TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(out.getOutputs()); + sc.check(0, 0, 1); + sc.check(1, 0, 0); + sc.check(0, 1, 0); + sc.check(1, 1, 1); + } +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/basic/XOrTest.java b/src/test/java/de/neemann/digital/core/basic/XOrTest.java new file mode 100644 index 000000000..2685b61cd --- /dev/null +++ b/src/test/java/de/neemann/digital/core/basic/XOrTest.java @@ -0,0 +1,29 @@ +package de.neemann.digital.core.basic; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class XOrTest extends TestCase { + + public void testXor() throws Exception { + ObservableValue a = new ObservableValue("a", 1); + ObservableValue b = new ObservableValue("b", 1); + + + Model model = new Model(); + XOr out = model.add(new XOr(new PartAttributes().setBits(1))); + out.setInputs(a, b); + + TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(out.getOutputs()); + sc.check(0, 0, 0); + sc.check(1, 0, 1); + sc.check(0, 1, 1); + sc.check(1, 1, 0); + } +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/flipflops/D_FFTest.java b/src/test/java/de/neemann/digital/core/flipflops/D_FFTest.java new file mode 100644 index 000000000..0d084a6fa --- /dev/null +++ b/src/test/java/de/neemann/digital/core/flipflops/D_FFTest.java @@ -0,0 +1,31 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class D_FFTest extends TestCase { + public void testFlipFlop() throws Exception { + ObservableValue d = new ObservableValue("s", 8); + ObservableValue c = new ObservableValue("c", 1); + + Model model = new Model(); + D_FF out = model.add(new D_FF(new PartAttributes().setBits(8))); + out.setInputs(d, c); + + TestExecuter sc = new TestExecuter(model).setInputs(d, c).setOutputs(out.getOutputs()); + // D C Q ~Q + sc.check(0, 0, 0, 255); + sc.check(1, 0, 0, 255); + sc.check(1, 1, 1, 254); + sc.check(1, 0, 1, 254); + sc.check(0, 0, 1, 254); + sc.check(7, 0, 1, 254); + sc.check(7, 1, 7, 248); + } +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/flipflops/JK_FFTest.java b/src/test/java/de/neemann/digital/core/flipflops/JK_FFTest.java new file mode 100644 index 000000000..fc1532908 --- /dev/null +++ b/src/test/java/de/neemann/digital/core/flipflops/JK_FFTest.java @@ -0,0 +1,38 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class JK_FFTest extends TestCase { + public void testFlipFlop() throws Exception { + ObservableValue j = new ObservableValue("j", 1); + ObservableValue c = new ObservableValue("c", 1); + ObservableValue k = new ObservableValue("k", 1); + + Model model = new Model(); + JK_FF out = model.add(new JK_FF(new PartAttributes())); + out.setInputs(j, c, k); + + TestExecuter sc = new TestExecuter(model).setInputs(j, c, k).setOutputs(out.getOutputs()); + // J C K Q ~Q + sc.check(0, 0, 0, 0, 1); + sc.check(0, 0, 0, 0, 1); + sc.check(1, 0, 0, 0, 1); + sc.check(0, 1, 0, 0, 1); + sc.check(1, 0, 0, 0, 1); + sc.check(1, 1, 0, 1, 0); + sc.check(1, 0, 1, 1, 0); + sc.check(1, 1, 1, 0, 1); + sc.check(1, 0, 1, 0, 1); + sc.check(1, 1, 1, 1, 0); + sc.check(0, 0, 1, 1, 0); + sc.check(0, 1, 1, 0, 1); + sc.check(0, 0, 0, 0, 1); + } +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/flipflops/RS_FFTest.java b/src/test/java/de/neemann/digital/core/flipflops/RS_FFTest.java new file mode 100644 index 000000000..003bdd5f7 --- /dev/null +++ b/src/test/java/de/neemann/digital/core/flipflops/RS_FFTest.java @@ -0,0 +1,38 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class RS_FFTest extends TestCase { + public void testFlipFlop() throws Exception { + ObservableValue s = new ObservableValue("s", 1); + ObservableValue c = new ObservableValue("c", 1); + ObservableValue r = new ObservableValue("r", 1); + + Model model = new Model(); + RS_FF out = model.add(new RS_FF(new PartAttributes())); + out.setInputs(s, c, r); + + TestExecuter sc = new TestExecuter(model).setInputs(s, c, r).setOutputs(out.getOutputs()); + // S C R Q ~Q + sc.check(0, 0, 0, 0, 1); + sc.check(0, 0, 0, 0, 1); + sc.check(1, 0, 0, 0, 1); + sc.check(0, 1, 0, 0, 1); + sc.check(1, 0, 0, 0, 1); + sc.check(1, 1, 0, 1, 0); + sc.check(1, 0, 1, 1, 0); + sc.check(1, 1, 1, 1, 0); + sc.check(1, 0, 1, 1, 0); + sc.check(1, 1, 1, 1, 0); + sc.check(0, 0, 1, 1, 0); + sc.check(0, 1, 1, 0, 1); + sc.check(0, 0, 0, 0, 1); + } +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/flipflops/T_FFTest.java b/src/test/java/de/neemann/digital/core/flipflops/T_FFTest.java new file mode 100644 index 000000000..7571105b7 --- /dev/null +++ b/src/test/java/de/neemann/digital/core/flipflops/T_FFTest.java @@ -0,0 +1,30 @@ +package de.neemann.digital.core.flipflops; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.part.PartAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class T_FFTest extends TestCase { + public void testFlipFlop() throws Exception { + ObservableValue c = new ObservableValue("c", 1); + + Model model = new Model(); + T_FF out = model.add(new T_FF(new PartAttributes().setBits(1))); + out.setInputs(c); + + TestExecuter sc = new TestExecuter(model).setInputs(c).setOutputs(out.getOutputs()); + // C Q ~Q + sc.check(0, 0, 1); + sc.check(1, 1, 0); + sc.check(1, 1, 0); + sc.check(0, 1, 0); + sc.check(0, 1, 0); + sc.check(1, 0, 1); + sc.check(0, 0, 1); + } +} \ No newline at end of file