diff --git a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java index a8e3b740b..4bc08685d 100644 --- a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java +++ b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java @@ -10,6 +10,7 @@ import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.Keys; import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.library.CustomElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; @@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -31,18 +33,14 @@ import java.util.Map; public class SubstituteLibrary implements LibraryInterface { private static final Logger LOGGER = LoggerFactory.getLogger(SubstituteLibrary.class); private static final Map MAP = new HashMap<>(); - private static final SubstituteInterface T_FF_WITH_ENABLE = new Substitute("T_FF_EN.dig"); - private static final SubstituteInterface T_FF_WITHOUT_ENABLE = new Substitute("T_FF.dig"); static { MAP.put("JK_FF", new Substitute("JK_FF.dig")); - MAP.put("T_FF", (attr, library) -> { - if (attr.get(Keys.WITH_ENABLE)) - return T_FF_WITH_ENABLE.getElementType(attr, library); - else - return T_FF_WITHOUT_ENABLE.getElementType(attr, library); - }); - MAP.put("Counter", new Substitute("Counter.dig")); + MAP.put("T_FF", new SubstituteMatching() + .add(attr -> attr.get(Keys.WITH_ENABLE), new Substitute("T_FF_EN.dig")) + .add(attr -> true, new Substitute("T_FF.dig")) + ); + MAP.put("Counter", new SubstituteGenericBits("Counter.dig")); } private final ElementLibrary parent; @@ -75,6 +73,50 @@ public class SubstituteLibrary implements LibraryInterface { ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException; } + private static final class SubstituteMatching implements SubstituteInterface { + private final ArrayList matcher; + + private SubstituteMatching() { + matcher = new ArrayList<>(); + } + + private SubstituteMatching add(Accept accept, SubstituteInterface substituteInterface) { + matcher.add(new Matcher(accept, substituteInterface)); + return this; + } + + @Override + public ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException { + for (Matcher m : matcher) { + ElementTypeDescription type = m.getElementType(attr, library); + if (type != null) + return type; + } + return null; + } + } + + private static final class Matcher implements SubstituteInterface { + private final Accept accept; + private final SubstituteInterface substituteInterface; + + private Matcher(Accept accept, SubstituteInterface substituteInterface) { + this.accept = accept; + this.substituteInterface = substituteInterface; + } + + @Override + public ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException { + if (accept.accept(attr)) + return substituteInterface.getElementType(attr, library); + return null; + } + } + + private interface Accept { + boolean accept(ElementAttributes attr); + } + private static final class Substitute implements SubstituteInterface { private final String filename; private ElementLibrary.ElementTypeDescriptionCustom typeDescriptionCustom; @@ -91,7 +133,7 @@ public class SubstituteLibrary implements LibraryInterface { if (in == null) throw new IOException("substituting failed: could not find file " + filename); - Circuit circuit = modify(Circuit.loadCircuit(in, library.getShapeFactory())); + Circuit circuit = Circuit.loadCircuit(in, library.getShapeFactory()); typeDescriptionCustom = new ElementLibrary.ElementTypeDescriptionCustom(new File(filename), @@ -101,9 +143,56 @@ public class SubstituteLibrary implements LibraryInterface { return typeDescriptionCustom; } - private Circuit modify(Circuit circuit) { - return circuit; - } } + private static abstract class SubstituteGeneric implements SubstituteInterface { + private final String filename; + private Circuit circuit; + + private SubstituteGeneric(String filename) { + this.filename = filename; + } + + @Override + public ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException { + if (circuit == null) { + LOGGER.info("load substitute circuit " + filename); + InputStream in = getClass().getClassLoader().getResourceAsStream("analyser/" + filename); + if (in == null) + throw new IOException("substituting failed: could not find file " + filename); + + circuit = Circuit.loadCircuit(in, library.getShapeFactory()); + } + + Circuit c = circuit.createDeepCopy(); + generify(attr, c); + + return new ElementLibrary.ElementTypeDescriptionCustom(new File(filename), + attributes -> new CustomElement(c, library), + c); + } + + private void generify(ElementAttributes attr, Circuit circuit) { + for (VisualElement v : circuit.getElements()) { + String gen = v.getElementAttributes().get(Keys.GENERIC).trim(); + if (!gen.isEmpty()) + generify(attr, gen, v.getElementAttributes()); + } + } + + abstract void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes); + } + + private static class SubstituteGenericBits extends SubstituteGeneric { + + private SubstituteGenericBits(String filename) { + super(filename); + } + + @Override + void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes) { + if (gen.equals("bits")) + nodeAttributes.setBits(sourceAttributes.getBits()); + } + } } diff --git a/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java b/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java index f2a8353af..930d2300a 100644 --- a/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java +++ b/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java @@ -7,6 +7,7 @@ package de.neemann.digital.core.element; import de.neemann.digital.core.NodeException; import de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.gui.Main; import de.neemann.digital.lang.Lang; import java.lang.reflect.Constructor; @@ -70,6 +71,8 @@ public class ElementTypeDescription { if (p.getDirection() != PinDescription.Direction.input) throw new RuntimeException("pin direction error"); attributeList = new ArrayList<>(); + if (Main.isExperimentalMode()) + attributeList.add(Keys.GENERIC); } /** 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 1a996f729..6cae93e16 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -784,4 +784,10 @@ public final class Keys { public static final Key SETTINGS_TOOLCHAIN_CONFIG = new Key.KeyFile("toolChainConfig", new File("")).setSecondary().setRequiresRestart(); + /** + * Selects the midi channel + */ + public static final Key GENERIC = + new Key<>("generic", "").allowGroupEdit(); + } diff --git a/src/main/resources/analyser/Counter.dig b/src/main/resources/analyser/Counter.dig index de536f148..4b6c7ae1a 100644 --- a/src/main/resources/analyser/Counter.dig +++ b/src/main/resources/analyser/Counter.dig @@ -44,6 +44,10 @@ Bits 4 + + generic + bits + @@ -68,6 +72,10 @@ Bits 4 + + generic + bits + @@ -78,6 +86,10 @@ Bits 4 + + generic + bits + @@ -88,6 +100,10 @@ Bits 4 + + generic + bits + @@ -98,6 +114,10 @@ Bits 4 + + generic + bits + @@ -108,6 +128,10 @@ Bits 4 + + generic + bits + @@ -123,6 +147,10 @@ Bits 4 + + generic + bits + diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 1ac83c682..0a62f33c0 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1341,6 +1341,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Kann für eine Integration einer externen Toolchain verwendet werden. Erlaubt den Start externer Tools, um z.B. einen FPGA zu programmieren o.ä. + Generisch + String für das Erzeugen generischer Schaltungen. + Leitung eingefügt. Aus Zwischenablage eingefügt. Wert ''{0}'' in Element ''{1}'' verändert. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 8f9317b02..23e46c50f 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1329,6 +1329,9 @@ Used to configurate an integration of a toolchain. Allows the start of external tools, e.g. to program an FPGA or similar. + Generic + String used to create generic circuits. + Inserted wire. Insert from clipboard. Value ''{0}'' in component ''{1}'' modified.