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> 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 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 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