diff --git a/src/main/dig/74xx/lib/flipflops/7476.dig b/src/main/dig/74xx/lib/flipflops/7476.dig
index cf4232a61..9c849efee 100644
--- a/src/main/dig/74xx/lib/flipflops/7476.dig
+++ b/src/main/dig/74xx/lib/flipflops/7476.dig
@@ -36,7 +36,7 @@
1
-
+
Out
@@ -82,7 +82,7 @@
1
-
+
In
@@ -104,7 +104,7 @@
1
-
+
In
@@ -126,11 +126,6 @@
1
-
-
-
- Not
-
@@ -153,11 +148,6 @@
1
-
-
-
- Not
-
@@ -180,7 +170,7 @@
1
-
+
Out
@@ -226,7 +216,7 @@
6
-
+
In
@@ -248,7 +238,7 @@
1
-
+
In
@@ -270,7 +260,7 @@
1
-
+
In
@@ -292,38 +282,36 @@
1
-
-
-
- JK_FF_AS
-
-
-
-
- Not
-
-
-
-
- Not
-
JK_FF_AS
-
+
+
+ inverterConfig
+
+ Set
+ C
+ Clr
+
+
+
+
+
+
+ JK_FF_AS
+
+
+ inverterConfig
+
+ Set
+ C
+ Clr
+
+
+
-
- Not
-
-
-
-
- Not
-
-
-
@@ -331,11 +319,11 @@
-
-
+
+
-
+
@@ -343,11 +331,11 @@
-
-
+
+
-
+
@@ -355,35 +343,27 @@
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
-
-
+
+
-
+
@@ -395,11 +375,11 @@
-
-
+
+
-
+
@@ -411,40 +391,24 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
@@ -471,20 +435,21 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
\ No newline at end of file
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 69786217a..a93a04514 100644
--- a/src/main/java/de/neemann/digital/core/basic/FanIn.java
+++ b/src/main/java/de/neemann/digital/core/basic/FanIn.java
@@ -18,6 +18,11 @@ import static de.neemann.digital.core.element.PinInfo.input;
*/
public abstract class FanIn extends Node implements Element {
+ /**
+ * The inputs name prefix
+ */
+ public static final String PREFIX = "In_";
+
private final ArrayList inputs;
private final ObservableValue output;
private final int bits;
@@ -71,6 +76,7 @@ public abstract class FanIn extends Node implements Element {
addAttribute(Keys.ROTATE);
addAttribute(Keys.BITS);
addAttribute(Keys.INPUT_COUNT);
+ addAttribute(Keys.INVERTERCONFIG);
}
@Override
@@ -78,7 +84,7 @@ public abstract class FanIn extends Node implements Element {
int count = elementAttributes.get(Keys.INPUT_COUNT);
PinDescription[] names = new PinDescription[count];
for (int i = 0; i < count; i++)
- names[i] = input("in_" + i, Lang.get("elem_Basic_In", i));
+ names[i] = input(PREFIX + (i+1), Lang.get("elem_Basic_In", i));
return new PinDescriptions(names);
}
}
diff --git a/src/main/java/de/neemann/digital/core/basic/XNOr.java b/src/main/java/de/neemann/digital/core/basic/XNOr.java
index e275f4f53..6307c084d 100644
--- a/src/main/java/de/neemann/digital/core/basic/XNOr.java
+++ b/src/main/java/de/neemann/digital/core/basic/XNOr.java
@@ -19,7 +19,8 @@ public class XNOr extends XOr {
public static final ElementTypeDescription DESCRIPTION
= new ElementTypeDescription(XNOr.class, input("a"), input("b"))
.addAttribute(Keys.ROTATE)
- .addAttribute(Keys.BITS);
+ .addAttribute(Keys.BITS)
+ .addAttribute(Keys.INVERTERCONFIG);
/**
* Creates a new instance
diff --git a/src/main/java/de/neemann/digital/core/basic/XOr.java b/src/main/java/de/neemann/digital/core/basic/XOr.java
index 959ef2ffa..9649af0da 100644
--- a/src/main/java/de/neemann/digital/core/basic/XOr.java
+++ b/src/main/java/de/neemann/digital/core/basic/XOr.java
@@ -19,7 +19,8 @@ public class XOr extends Node implements Element {
public static final ElementTypeDescription DESCRIPTION
= new ElementTypeDescription(XOr.class, input("a"), input("b"))
.addAttribute(Keys.ROTATE)
- .addAttribute(Keys.BITS);
+ .addAttribute(Keys.BITS)
+ .addAttribute(Keys.INVERTERCONFIG);
private final int bits;
private final ObservableValue out;
diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java
index 2de0afea7..44056f256 100644
--- a/src/main/java/de/neemann/digital/core/element/Keys.java
+++ b/src/main/java/de/neemann/digital/core/element/Keys.java
@@ -3,6 +3,7 @@ package de.neemann.digital.core.element;
import de.neemann.digital.analyse.expression.format.FormatToExpression;
import de.neemann.digital.core.io.IntFormat;
import de.neemann.digital.core.memory.DataField;
+import de.neemann.digital.draw.model.InverterConfig;
import de.neemann.gui.language.Language;
import java.awt.*;
@@ -353,4 +354,11 @@ public final class Keys {
public static final Key IS_DIL
= new Key<>("isDIL", false);
+ /**
+ * contains the input inverter config
+ */
+ public static final Key INVERTERCONFIG
+ = new Key<>("inverterConfig", new InverterConfig());
+
+
}
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java
index ecb8461ef..7ad75a06c 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java
@@ -25,6 +25,7 @@ public class FlipflopD extends Node implements Element {
.addAttribute(Keys.BITS)
.addAttribute(Keys.LABEL)
.addAttribute(Keys.DEFAULT)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final int bits;
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopDAsync.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopDAsync.java
index 5d97c1b3e..519c309c8 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopDAsync.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopDAsync.java
@@ -25,6 +25,7 @@ public class FlipflopDAsync extends Node implements Element {
.addAttribute(Keys.BITS)
.addAttribute(Keys.LABEL)
.addAttribute(Keys.DEFAULT)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final int bits;
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopJK.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopJK.java
index a81fd259f..9a9d2ae8b 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopJK.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopJK.java
@@ -24,6 +24,7 @@ public class FlipflopJK extends Node implements Element {
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.LABEL)
.addAttribute(Keys.DEFAULT)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final Boolean isProbe;
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopJKAsync.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopJKAsync.java
index 83c14b10b..9036abbb6 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopJKAsync.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopJKAsync.java
@@ -29,6 +29,7 @@ public class FlipflopJKAsync extends Node implements Element {
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.LABEL)
.addAttribute(Keys.DEFAULT)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final Boolean isProbe;
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopRS.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopRS.java
index 5f95bf9e9..5675183dc 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopRS.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopRS.java
@@ -23,6 +23,7 @@ public class FlipflopRS extends Node implements Element {
= new ElementTypeDescription("RS_FF", FlipflopRS.class, input("S"), input("C"), input("R"))
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.LABEL)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final boolean isProbe;
diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopT.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopT.java
index a61a7a333..64a24a2a2 100644
--- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopT.java
+++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopT.java
@@ -23,6 +23,7 @@ public class FlipflopT extends Node implements Element {
= new ElementTypeDescription("T_FF", FlipflopT.class, input("C"))
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.LABEL)
+ .addAttribute(Keys.INVERTERCONFIG)
.addAttribute(Keys.VALUE_IS_PROBE);
private final boolean isProbe;
diff --git a/src/main/java/de/neemann/digital/draw/elements/Circuit.java b/src/main/java/de/neemann/digital/draw/elements/Circuit.java
index a34ca9017..ae8993bfe 100644
--- a/src/main/java/de/neemann/digital/draw/elements/Circuit.java
+++ b/src/main/java/de/neemann/digital/draw/elements/Circuit.java
@@ -20,6 +20,7 @@ import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.Polygon;
import de.neemann.digital.draw.graphics.Style;
import de.neemann.digital.draw.graphics.Vector;
+import de.neemann.digital.draw.model.InverterConfig;
import de.neemann.digital.draw.shapes.Drawable;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.sync.NoSync;
@@ -77,6 +78,8 @@ public class Circuit {
xStream.alias("data", DataField.class);
xStream.registerConverter(new DataFieldConverter());
xStream.alias("testData", TestData.class);
+ xStream.alias("inverterConfig", InverterConfig.class);
+ xStream.addImplicitCollection(InverterConfig.class, "inputs");
xStream.ignoreUnknownElements();
return xStream;
}
diff --git a/src/main/java/de/neemann/digital/draw/model/InverterConfig.java b/src/main/java/de/neemann/digital/draw/model/InverterConfig.java
new file mode 100644
index 000000000..f601b978a
--- /dev/null
+++ b/src/main/java/de/neemann/digital/draw/model/InverterConfig.java
@@ -0,0 +1,103 @@
+package de.neemann.digital.draw.model;
+
+import de.neemann.digital.core.ObservableValue;
+
+import java.util.HashSet;
+
+/**
+ * Manages the input inverting of a component
+ * Created by hneemann on 28.05.17.
+ */
+public class InverterConfig {
+
+ private HashSet inputs;
+
+ /**
+ * Creates a new instance.
+ * No input is inverted.
+ */
+ public InverterConfig() {
+ inputs = null;
+ }
+
+ /**
+ * Adds a signal to invert
+ *
+ * @param name the signale
+ * @return this for chained calls
+ */
+ public InverterConfig add(String name) {
+ if (inputs == null)
+ inputs = new HashSet<>();
+ inputs.add(name);
+ return this;
+ }
+
+ /**
+ * Handles the inverting of a input signal
+ * if the given input is not to invert, the original input is returned,
+ * If the input is to invert, a inverted input is returned. This invert does not add
+ * a additional delay time.
+ *
+ * @param name the name of the signal
+ * @param orig the original input signal
+ * @return the inverted or the original input
+ */
+ public ObservableValue invert(String name, ObservableValue orig) {
+ if (inputs == null)
+ return orig;
+
+ if (!inputs.contains(name))
+ return orig;
+
+ ObservableValue out = new ObservableValue("~" + orig.getName(), orig.getBits());
+ orig.addObserver(() -> out.set(~orig.getValue(), orig.isHighZ()));
+ out.set(~orig.getValue(), orig.isHighZ());
+ return out;
+ }
+
+ /**
+ * @return the string representation of the inverter config
+ */
+ public String toString() {
+ return inputs.toString();
+ }
+
+ /**
+ * Returns true if the input with the given name is to invert.
+ *
+ * @param name the name of the signal
+ * @return true if the given input is to invert.
+ */
+ public boolean contains(String name) {
+ if (inputs == null)
+ return false;
+
+ return inputs.contains(name);
+ }
+
+ /**
+ * @return true if no signal is to invert
+ */
+ public boolean isEmpty() {
+ if (inputs == null)
+ return true;
+
+ return inputs.isEmpty();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InverterConfig that = (InverterConfig) o;
+
+ return inputs != null ? inputs.equals(that.inputs) : that.inputs == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return inputs != null ? inputs.hashCode() : 0;
+ }
+}
diff --git a/src/main/java/de/neemann/digital/draw/model/ModelEntry.java b/src/main/java/de/neemann/digital/draw/model/ModelEntry.java
index 63f5f092a..0704a02ba 100644
--- a/src/main/java/de/neemann/digital/draw/model/ModelEntry.java
+++ b/src/main/java/de/neemann/digital/draw/model/ModelEntry.java
@@ -5,6 +5,7 @@ import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.Element;
+import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.elements.*;
@@ -54,6 +55,8 @@ public class ModelEntry {
public void applyInputs() throws PinException, NodeException {
HashMap ins = pins.getInputs();
+ InverterConfig ic = visualElement.getElementAttributes().get(Keys.INVERTERCONFIG);
+
ObservableValues values = ObservableValues.EMPTY_LIST;
ArrayList inputs = new ArrayList<>();
for (PinDescription inputName : inputNames) {
@@ -65,7 +68,7 @@ public class ModelEntry {
if (value == null)
throw new PinException(Lang.get("err_noValueSetFor_N0_atElement_N1", inputName, visualElement), visualElement);
- inputs.add(value);
+ inputs.add(ic.invert(inputName.getName(), value));
}
ArrayList bidirect = null;
diff --git a/src/main/java/de/neemann/digital/draw/shapes/GenericShape.java b/src/main/java/de/neemann/digital/draw/shapes/GenericShape.java
index 708affb5b..e9e9d2bcb 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/GenericShape.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/GenericShape.java
@@ -7,6 +7,7 @@ import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.Pins;
import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon;
+import de.neemann.digital.draw.model.InverterConfig;
import java.awt.*;
@@ -38,6 +39,7 @@ public class GenericShape implements Shape {
private transient Pins pins;
private boolean showPinLabels;
+ private InverterConfig inverterConfig;
/**
* Creates a new generic shape.
@@ -112,7 +114,7 @@ public class GenericShape implements Shape {
@Override
public Pins getPins() {
if (pins == null) {
- pins = createPins(inputs, outputs, invert, width, symmetric);
+ pins = createPins(inputs, outputs, invert, width, symmetric, inverterConfig);
}
return pins;
}
@@ -123,10 +125,11 @@ public class GenericShape implements Shape {
* @param inputs the inputs
* @param outputs the outputs
* @param invert true if invert output
+ * @param ic iput inverter configuration
* @return the pins
*/
- public static Pins createPins(PinDescriptions inputs, PinDescriptions outputs, boolean invert) {
- return createPins(inputs, outputs, invert, 3, true);
+ public static Pins createPins(PinDescriptions inputs, PinDescriptions outputs, boolean invert, InverterConfig ic) {
+ return createPins(inputs, outputs, invert, 3, true, ic);
}
/**
@@ -137,19 +140,25 @@ public class GenericShape implements Shape {
* @param invert true if invert output
* @param width with of symbol
* @param symmetric true if outputs in the center
+ * @param ic iput inverter configuration
* @return the pins
*/
- public static Pins createPins(PinDescriptions inputs, PinDescriptions outputs, boolean invert, int width, boolean symmetric) {
+ public static Pins createPins(PinDescriptions inputs, PinDescriptions outputs, boolean invert, int width, boolean symmetric, InverterConfig ic) {
Pins pins = new Pins();
int offs = symmetric ? inputs.size() / 2 * SIZE : 0;
+
for (int i = 0; i < inputs.size(); i++) {
int correct = 0;
if (symmetric && ((inputs.size() & 1) == 0) && i >= inputs.size() / 2)
correct = SIZE;
- pins.add(new Pin(new Vector(0, i * SIZE + correct), inputs.get(i)));
+ int dx = 0;
+ if (isInverted(inputs.get(i).getName(), ic))
+ dx = -SIZE;
+
+ pins.add(new Pin(new Vector(dx, i * SIZE + correct), inputs.get(i)));
}
@@ -165,6 +174,10 @@ public class GenericShape implements Shape {
return pins;
}
+ private static boolean isInverted(String name, InverterConfig ic) {
+ return ic != null && ic.contains(name);
+ }
+
@Override
public Interactor applyStateMonitor(IOState ioState, Observer guiObserver) {
return null;
@@ -202,8 +215,11 @@ public class GenericShape implements Shape {
if (showPinLabels) {
for (Pin p : getPins()) {
+ int dx = 4;
+ if (isInverted(p.getName(), inverterConfig))
+ dx += SIZE;
if (p.getDirection() == Pin.Direction.input)
- graphic.drawText(p.getPos().add(4, 0), p.getPos().add(5, 0), p.getName(), Orientation.LEFTCENTER, Style.SHAPE_PIN);
+ graphic.drawText(p.getPos().add(dx, 0), p.getPos().add(dx + 1, 0), p.getName(), Orientation.LEFTCENTER, Style.SHAPE_PIN);
else
graphic.drawText(p.getPos().add(-4, 0), p.getPos().add(5, 0), p.getName(), Orientation.RIGHTCENTER, Style.SHAPE_PIN);
}
@@ -217,6 +233,42 @@ public class GenericShape implements Shape {
graphic.drawText(pos, pos.add(1, 0), name, Orientation.CENTERTOP, Style.SHAPE_PIN);
}
}
+
+ drawInputInvert(graphic, inverterConfig, getPins());
+
+
}
+ /**
+ * Draw the inverted inputs
+ *
+ * @param graphic the graphic to paint on
+ * @param inverterConfig the inverter configuration
+ * @param pins the pins containing the inputs
+ */
+ public static void drawInputInvert(Graphic graphic, InverterConfig inverterConfig, Pins pins) {
+ if (inverterConfig != null && !inverterConfig.isEmpty())
+ for (Pin p : pins) {
+ if (p.getDirection() == Pin.Direction.input) {
+ if (inverterConfig.contains(p.getName())) {
+ graphic.drawCircle(p.getPos().add(2, -SIZE2 + 2),
+ p.getPos().add(SIZE - 2, SIZE2 - 2), Style.NORMAL);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the inverter config
+ *
+ * @param inverterConfig the inverter config
+ * @return this for chained calls
+ */
+ public GenericShape setInverterConfig(InverterConfig inverterConfig) {
+ if (inverterConfig.isEmpty())
+ this.inverterConfig = null;
+ else
+ this.inverterConfig = inverterConfig;
+ return this;
+ }
}
diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java
index 81a659f9a..6d945e3dd 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java
@@ -55,12 +55,12 @@ public final class ShapeFactory {
this.library = library;
library.setShapeFactory(this);
if (ieee) {
- map.put(And.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, false));
- map.put(NAnd.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, true));
- map.put(Or.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEOrShape(inputs, outputs, false));
- map.put(NOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEOrShape(inputs, outputs, true));
- map.put(XOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEXOrShape(inputs, outputs, false));
- map.put(XNOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEXOrShape(inputs, outputs, true));
+ map.put(And.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, false, attributes));
+ map.put(NAnd.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, true, attributes));
+ map.put(Or.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEOrShape(inputs, outputs, false, attributes));
+ map.put(NOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEOrShape(inputs, outputs, true, attributes));
+ map.put(XOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEXOrShape(inputs, outputs, false, attributes));
+ map.put(XNOr.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEXOrShape(inputs, outputs, true, attributes));
map.put(Not.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEENotShape(inputs, outputs));
} else {
map.put(And.DESCRIPTION.getName(), new CreatorSimple("&", false));
@@ -157,13 +157,15 @@ public final class ShapeFactory {
customDescr.getAttributes().get(Keys.WIDTH))
.setColor(customDescr.getAttributes().get(Keys.BACKGROUND_COLOR));
}
- } else
+ } else {
return new GenericShape(
pt.getShortName(),
pt.getInputDescription(elementAttributes),
pt.getOutputDescriptions(elementAttributes),
elementAttributes.getLabel(),
- true);
+ true)
+ .setInverterConfig(elementAttributes.get(Keys.INVERTERCONFIG));
+ }
}
} else {
ElementTypeDescription pt = library.getElementType(elementName);
@@ -194,7 +196,9 @@ public final class ShapeFactory {
@Override
public Shape create(ElementAttributes attributes, PinDescriptions inputs, PinDescriptions outputs) throws NodeException {
- return new GenericShape(name, inputs, outputs).invert(invers);
+ return new GenericShape(name, inputs, outputs)
+ .invert(invers)
+ .setInverterConfig(attributes.get(Keys.INVERTERCONFIG));
}
}
}
diff --git a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEAndShape.java b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEAndShape.java
index 07449180c..c7016f6d2 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEAndShape.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEAndShape.java
@@ -1,5 +1,6 @@
package de.neemann.digital.draw.shapes.ieee;
+import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.Polygon;
@@ -34,9 +35,10 @@ public class IEEEAndShape extends IEEEGenericShape {
* @param inputs inputs
* @param outputs outputs
* @param invert true if NAnd
+ * @param attr the attributes
*/
- public IEEEAndShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert) {
- super(inputs, outputs, invert);
+ public IEEEAndShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert, ElementAttributes attr) {
+ super(inputs, outputs, invert, attr);
}
@Override
diff --git a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEGenericShape.java b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEGenericShape.java
index 2f9246fd9..dbd3515d5 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEGenericShape.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEGenericShape.java
@@ -1,6 +1,8 @@
package de.neemann.digital.draw.shapes.ieee;
import de.neemann.digital.core.Observer;
+import de.neemann.digital.core.element.ElementAttributes;
+import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.elements.IOState;
import de.neemann.digital.draw.elements.Pins;
@@ -8,6 +10,7 @@ import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.GraphicTransform;
import de.neemann.digital.draw.graphics.Style;
import de.neemann.digital.draw.graphics.Vector;
+import de.neemann.digital.draw.model.InverterConfig;
import de.neemann.digital.draw.shapes.GenericShape;
import de.neemann.digital.draw.shapes.InteractorInterface;
import de.neemann.digital.draw.shapes.Shape;
@@ -25,6 +28,7 @@ public abstract class IEEEGenericShape implements Shape {
private final PinDescriptions inputs;
private final PinDescriptions outputs;
private final boolean invert;
+ private final InverterConfig inverterConfig;
private Pins pins;
@@ -34,17 +38,19 @@ public abstract class IEEEGenericShape implements Shape {
* @param inputs inputs
* @param outputs outputs
* @param invert true if NAnd, NOr
+ * @param attr the elements attributes
*/
- public IEEEGenericShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert) {
+ public IEEEGenericShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert, ElementAttributes attr) {
this.inputs = inputs;
this.outputs = outputs;
this.invert = invert;
+ inverterConfig = attr.get(Keys.INVERTERCONFIG);
}
@Override
public Pins getPins() {
if (pins == null)
- pins = GenericShape.createPins(inputs, outputs, invert);
+ pins = GenericShape.createPins(inputs, outputs, invert, inverterConfig);
return pins;
}
@@ -64,6 +70,8 @@ public abstract class IEEEGenericShape implements Shape {
graphic.drawLine(new Vector(1, h), new Vector(1, h - offs + SIZE2 + 1), Style.NORMAL);
}
+ GenericShape.drawInputInvert(graphic, inverterConfig, getPins());
+
if (invert) {
int o = inputs.size() / 2 * SIZE;
for (int i = 0; i < outputs.size(); i++)
diff --git a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEOrShape.java b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEOrShape.java
index a2e66011c..6a8fd9288 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEOrShape.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEOrShape.java
@@ -1,5 +1,6 @@
package de.neemann.digital.draw.shapes.ieee;
+import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.Polygon;
@@ -38,13 +39,13 @@ public class IEEEOrShape extends IEEEGenericShape {
/**
* Creates a new instance
- *
- * @param inputs inputs
+ * @param inputs inputs
* @param outputs outputs
* @param invert true if NOr
+ * @param attr the elements attributes
*/
- public IEEEOrShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert) {
- super(inputs, outputs, invert);
+ public IEEEOrShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert, ElementAttributes attr) {
+ super(inputs, outputs, invert, attr);
center = (inputs.size() & 1) != 0;
}
diff --git a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEXOrShape.java b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEXOrShape.java
index 3a51a4adf..4c8b03d16 100644
--- a/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEXOrShape.java
+++ b/src/main/java/de/neemann/digital/draw/shapes/ieee/IEEEXOrShape.java
@@ -1,5 +1,6 @@
package de.neemann.digital.draw.shapes.ieee;
+import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.Polygon;
@@ -47,9 +48,10 @@ public class IEEEXOrShape extends IEEEGenericShape {
* @param inputs inputs
* @param outputs outputs
* @param invert true if XNOr
+ * @param attr the elements attributes
*/
- public IEEEXOrShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert) {
- super(inputs, outputs, invert);
+ public IEEEXOrShape(PinDescriptions inputs, PinDescriptions outputs, boolean invert, ElementAttributes attr) {
+ super(inputs, outputs, invert, attr);
}
@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 8b820c059..158cec2e2 100644
--- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java
+++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java
@@ -923,6 +923,13 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
return ve;
}
+ /**
+ * @return the used element library
+ */
+ public ElementLibrary getLibrary() {
+ return library;
+ }
+
private final class PlusMinusAction extends ToolTipAction {
private final int delta;
diff --git a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java
index c142b6681..f432d7615 100644
--- a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java
+++ b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java
@@ -1,13 +1,14 @@
package de.neemann.digital.gui.components;
import de.neemann.digital.analyse.expression.format.FormatToExpression;
-import de.neemann.digital.core.element.ElementAttributes;
-import de.neemann.digital.core.element.Key;
-import de.neemann.digital.core.element.Keys;
-import de.neemann.digital.core.element.Rotation;
+import de.neemann.digital.core.NodeException;
+import de.neemann.digital.core.element.*;
import de.neemann.digital.core.io.IntFormat;
import de.neemann.digital.core.memory.DataField;
import de.neemann.digital.core.memory.ROM;
+import de.neemann.digital.draw.elements.VisualElement;
+import de.neemann.digital.draw.library.ElementNotFoundException;
+import de.neemann.digital.draw.model.InverterConfig;
import de.neemann.digital.gui.SaveAsHelper;
import de.neemann.digital.gui.components.testing.TestDataEditor;
import de.neemann.digital.gui.sync.NoSync;
@@ -25,6 +26,7 @@ import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -51,6 +53,7 @@ public final class EditorFactory {
add(Language.class, LanguageEditor.class);
add(TestData.class, TestDataEditor.class);
add(FormatToExpression.class, FormatEditor.class);
+ add(InverterConfig.class, InverterConfigEditor.class);
}
private void add(Class clazz, Class extends Editor> editor) {
@@ -477,4 +480,100 @@ public final class EditorFactory {
return (FormatToExpression) comb.getSelectedItem();
}
}
+
+ private static class InverterConfigEditor extends LabelEditor {
+
+ private final JButton button;
+ private InverterConfig inverterConfig;
+ private ElementAttributes elementAttributes;
+
+ public InverterConfigEditor(InverterConfig aInverterConfig, Key key) {
+ this.inverterConfig = aInverterConfig;
+ button = new JButton(new ToolTipAction(getButtonText()) {
+ @Override
+ public void actionPerformed(ActionEvent actionEvent) {
+ VisualElement ve = getAttributeDialog().getVisualElement();
+ Component p = getAttributeDialog().getDialogParent();
+ if (ve != null && p instanceof CircuitComponent) {
+ try {
+ getAttributeDialog().storeEditedValues();
+ ElementTypeDescription d = ((CircuitComponent) p).getLibrary().getElementType(ve.getElementName());
+ PinDescriptions in = d.getInputDescription(elementAttributes);
+ InputSelectDialog dialog = new InputSelectDialog(getAttributeDialog(), in, inverterConfig);
+ if (dialog.showDialog()) {
+ inverterConfig = dialog.getInverterConfig();
+ button.setText(getButtonText());
+ }
+ } catch (ElementNotFoundException | NodeException e) {
+ new ErrorMessage(Lang.get("msg_errGettingPinNames")).addCause(e).show(getAttributeDialog());
+ }
+ }
+ }
+ });
+ }
+
+ private String getButtonText() {
+ if (inverterConfig.isEmpty())
+ return Lang.get("msg_none");
+ return inverterConfig.toString();
+ }
+
+ @Override
+ public InverterConfig getValue() {
+ return inverterConfig;
+ }
+
+ @Override
+ protected JComponent getComponent(ElementAttributes elementAttributes) {
+ this.elementAttributes = elementAttributes;
+ return button;
+ }
+ }
+
+ private final static class InputSelectDialog extends JDialog {
+ private final ArrayList boxes;
+ private boolean ok = false;
+
+ private InputSelectDialog(JDialog parent, PinDescriptions pins, InverterConfig inverterConfig) {
+ super(parent, Lang.get("msg_inputsToInvert"), true);
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ boxes = new ArrayList<>();
+ for (PinDescription p : pins) {
+ JCheckBox cb = new JCheckBox(p.getName());
+ cb.setSelected(inverterConfig.contains(p.getName()));
+ boxes.add(cb);
+ panel.add(cb);
+ }
+ int pad = Screen.getInstance().getFontSize();
+ panel.setBorder(BorderFactory.createEmptyBorder(pad, pad, pad, pad));
+ getContentPane().add(panel);
+ getContentPane().add(new JButton(new AbstractAction(Lang.get("ok")) {
+ @Override
+ public void actionPerformed(ActionEvent actionEvent) {
+ ok = true;
+ dispose();
+ }
+ }), BorderLayout.SOUTH);
+
+ pack();
+ setLocationRelativeTo(parent);
+ }
+
+ public boolean showDialog() {
+ setVisible(true);
+ return ok;
+ }
+
+ private InverterConfig getInverterConfig() {
+ InverterConfig ic = new InverterConfig();
+ for (JCheckBox cb : boxes) {
+ if (cb.isSelected())
+ ic.add(cb.getText());
+ }
+ return ic;
+ }
+ }
}
diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml
index 38d4847ad..d411b0b2c 100644
--- a/src/main/resources/lang/lang_de.xml
+++ b/src/main/resources/lang/lang_de.xml
@@ -644,6 +644,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig?
Anzahl der Pins des DILs. Wird hier eine 0 eingetragen, wird die Anzahl automatisch bestimmt.
Baumansicht beim Start aktivieren.
Wenn gesetzt, wird die Baumansicht beim Start automatisch aktiviert.
+ inverse Eingänge
+ Es können die Eingänge ausgewählt werden, welche invertiert werden sollen.
Leitung eingefügt.
Aus Zwischenablage eingefügt.
@@ -890,6 +892,9 @@ Die Icons stammen aus dem Tango Desktop Project.
Die GIF-Datei wird abgeschlossen.
GIF-Export
verursacht durch
+ Zu invertierende Eingänge
+ keine
+ Die Namen der Pins konnten nicht ermittelt werden.
Ok
0°
diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml
index 066966320..229a723c8 100644
--- a/src/main/resources/lang/lang_en.xml
+++ b/src/main/resources/lang/lang_en.xml
@@ -634,6 +634,8 @@ The names of the variables may not be unique.
Number of pins. A zero means that the number od pins is determined automatically.
Component tree view is visible at startup.
If set, the component tree view is enabled at startup.
+ inverted Inputs
+ You can select the inputs that are to be inverted.
Inserted wire.
Insert from clipboard.
@@ -878,6 +880,9 @@ The icons are taken from the Tango Desktop Project.
The GIF file is finalized and closed.
GIF Export
caused by
+ Inputs to invert
+ none
+ Could not determine the names of the pins.
Ok
0°
diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java
index 35735ccb4..94db7aca8 100644
--- a/src/test/java/de/neemann/digital/integration/TestExamples.java
+++ b/src/test/java/de/neemann/digital/integration/TestExamples.java
@@ -39,13 +39,13 @@ public class TestExamples extends TestCase {
*/
public void testTestExamples() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test");
- assertEquals(62, new FileScanner(this::check).scan(examples));
- assertEquals(58, testCasesInFiles);
+ assertEquals(65, new FileScanner(this::check).scan(examples));
+ assertEquals(62, testCasesInFiles);
}
/**
- * Loads the model and initializes and tests it if test cases are present
+ * Loads the model and initializes and test it if test cases are present
*
* @param dig the model file
*/
diff --git a/src/test/resources/dig/test/inputInvert/invClock.dig b/src/test/resources/dig/test/inputInvert/invClock.dig
new file mode 100644
index 000000000..fac39a553
--- /dev/null
+++ b/src/test/resources/dig/test/inputInvert/invClock.dig
@@ -0,0 +1,88 @@
+
+
+ 1
+
+
+
+ Out
+
+
+ Label
+ Y
+
+
+
+
+
+ Clock
+
+
+ Label
+ C
+
+
+
+
+
+ D_FF
+
+
+ inverterConfig
+
+ C
+ D
+
+
+
+
+
+
+ Testcase
+
+
+ Testdata
+
+ C Y
+0 0
+1 0
+0 1
+1 1
+0 0
+1 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/dig/test/inputInvert/simpleTest1.dig b/src/test/resources/dig/test/inputInvert/simpleTest1.dig
new file mode 100644
index 000000000..c26365be3
--- /dev/null
+++ b/src/test/resources/dig/test/inputInvert/simpleTest1.dig
@@ -0,0 +1,159 @@
+
+
+ 1
+
+
+
+ Out
+
+
+ Label
+ 2Y
+
+
+
+
+
+ In
+
+
+ Label
+ 2A
+
+
+
+
+
+ In
+
+
+ Label
+ 2B
+
+
+
+
+
+ XOr
+
+
+ inverterConfig
+
+ a
+
+
+
+
+
+
+ Out
+
+
+ Label
+ 1Y
+
+
+
+
+
+ In
+
+
+ Label
+ 1A
+
+
+
+
+
+ In
+
+
+ Label
+ 1B
+
+
+
+
+
+ And
+
+
+ inverterConfig
+
+ In_1
+
+
+
+
+
+
+ Testcase
+
+
+ Label
+ AND
+
+
+ Testdata
+
+ 1A 1B 1Y
+0 0 0
+0 1 1
+1 0 0
+1 1 0
+
+
+
+
+
+
+
+ Testcase
+
+
+ Label
+ XOR
+
+
+ Testdata
+
+ 2A 2B 2Y
+0 0 1
+0 1 0
+1 0 0
+1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/dig/test/inputInvert/simpleTest2.dig b/src/test/resources/dig/test/inputInvert/simpleTest2.dig
new file mode 100644
index 000000000..0559f10b3
--- /dev/null
+++ b/src/test/resources/dig/test/inputInvert/simpleTest2.dig
@@ -0,0 +1,104 @@
+
+
+ 1
+
+
+
+ JK_FF_AS
+
+
+ inverterConfig
+
+ Set
+ Clr
+
+
+
+
+
+
+ VDD
+
+
+
+
+ In
+
+
+ Label
+ C
+
+
+
+
+
+ Out
+
+
+ Label
+ Q
+
+
+
+
+
+ Testcase
+
+
+ Testdata
+
+ C Q
+0 0
+C 1
+C 0
+C 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file