From 4d2b7ef86a38b37485f7d8c932b7b73ec7cc3b27 Mon Sep 17 00:00:00 2001 From: hneemann Date: Thu, 27 Jun 2019 11:53:15 +0200 Subject: [PATCH] playing around with new substituting algorithm --- .../digital/analyse/ModelAnalyser.java | 77 +----- .../digital/analyse/SubstituteLibrary.java | 104 +++++++ .../digital/draw/library/ElementLibrary.java | 7 +- .../draw/library/LibraryInterface.java | 23 ++ .../digital/draw/model/ModelCreator.java | 9 +- .../java/de/neemann/digital/gui/Main.java | 3 +- src/main/resources/analyser/Counter.dig | 254 ++++++++++++++++++ src/main/resources/analyser/JK_FF.dig | 212 +++++++++++++++ src/main/resources/analyser/T_FF.dig | 110 ++++++++ src/main/resources/analyser/T_FF_EN.dig | 210 +++++++++++++++ 10 files changed, 929 insertions(+), 80 deletions(-) create mode 100644 src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java create mode 100644 src/main/java/de/neemann/digital/draw/library/LibraryInterface.java create mode 100644 src/main/resources/analyser/Counter.dig create mode 100644 src/main/resources/analyser/JK_FF.dig create mode 100644 src/main/resources/analyser/T_FF.dig create mode 100644 src/main/resources/analyser/T_FF_EN.dig diff --git a/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java b/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java index 76a17c8ab..b14099098 100644 --- a/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java +++ b/src/main/java/de/neemann/digital/analyse/ModelAnalyser.java @@ -8,14 +8,10 @@ package de.neemann.digital.analyse; import de.neemann.digital.analyse.expression.BitSetter; import de.neemann.digital.analyse.quinemc.BoolTableByteArray; import de.neemann.digital.core.*; -import de.neemann.digital.core.basic.And; -import de.neemann.digital.core.basic.Not; -import de.neemann.digital.core.basic.Or; -import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.flipflops.FlipflopD; -import de.neemann.digital.core.flipflops.FlipflopJK; -import de.neemann.digital.core.flipflops.FlipflopT; -import de.neemann.digital.core.switching.*; +import de.neemann.digital.core.switching.NFET; +import de.neemann.digital.core.switching.Relay; +import de.neemann.digital.core.switching.RelayDT; import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.core.wiring.Splitter; import de.neemann.digital.draw.elements.PinException; @@ -49,13 +45,6 @@ public class ModelAnalyser { public ModelAnalyser(Model model) throws AnalyseException { this.model = model; - try { - replaceTFF(); - replaceJKFF(); - } catch (NodeException e) { - throw new AnalyseException(e); - } - modelAnalyzerInfo = new ModelAnalyserInfo(model); inputs = checkBinaryInputs(model.getInputs()); @@ -274,66 +263,6 @@ public class ModelAnalyser { return out; } - private void replaceJKFF() throws NodeException, AnalyseException { - List jkList = model.findNode(FlipflopJK.class); - - for (FlipflopJK jk : jkList) { - checkClock(jk); - - jk.getClockVal().removeObserver(jk); - jk.getjVal().removeObserver(jk); - jk.getkVal().removeObserver(jk); - - // create d ff - ObservableValue q = jk.getOutputs().get(0); - ObservableValue qn = jk.getOutputs().get(1); - FlipflopD d = new FlipflopD(jk.getLabel(), q, qn); - - And a1 = new And(new ElementAttributes()); - a1.setInputs(new ObservableValues(jk.getjVal(), qn)); - And a2 = new And(new ElementAttributes()); - Not nk = new Not(new ElementAttributes()); - nk.setInputs(jk.getkVal().asList()); - a2.setInputs(new ObservableValues(nk.getOutput(), q)); - - Or or = new Or(new ElementAttributes()); - or.setInputs(new ObservableValues(a1.getOutput(), a2.getOutput())); - - d.setInputs(new ObservableValues(or.getOutputs().get(0), jk.getClockVal())); - - model.add(a1); - model.add(a2); - model.add(nk); - model.add(or); - model.replace(jk, d); - } - } - - private void replaceTFF() throws NodeException, AnalyseException { - List tList = model.findNode(FlipflopT.class); - - for (FlipflopT tff : tList) { - checkClock(tff); - tff.getClockVal().removeObserver(tff); - ObservableValue q = tff.getOutputs().get(0); - ObservableValue qn = tff.getOutputs().get(1); - - ObservableValue enable = tff.getEnableVal(); - if (enable == null) { - // create d ff - FlipflopD d = new FlipflopD(tff.getLabel(), q, qn); - d.setInputs(new ObservableValues(qn, getClock())); - model.replace(tff, d); - } else { - // create jk ff - enable.removeObserver(tff); - FlipflopJK jk = new FlipflopJK(tff.getLabel(), q, qn); - jk.setInputs(new ObservableValues(enable, getClock(), enable)); - model.replace(tff, jk); - } - } - } - /** * @return the models inputs */ diff --git a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java new file mode 100644 index 000000000..fcd9aae2c --- /dev/null +++ b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.analyse; + +import de.neemann.digital.core.element.ElementAttributes; +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.library.CustomElement; +import de.neemann.digital.draw.library.ElementLibrary; +import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.LibraryInterface; +import de.neemann.digital.lang.Lang; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * Used to substitute certain complex builtin components by simple custom components. + * Used to allow to analyse this components in a more simple way. + */ +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")); + } + + private final ElementLibrary parent; + + public SubstituteLibrary(ElementLibrary parent) { + this.parent = parent; + } + + @Override + public ElementTypeDescription getElementType(String elementName, ElementAttributes attr) throws ElementNotFoundException { + SubstituteInterface subst = map.get(elementName); + if (subst != null) { + try { + ElementTypeDescription type = subst.getElementType(attr, parent); + if (type != null) + return type; + } catch (PinException | IOException e) { + throw new ElementNotFoundException(Lang.get("err_substitutingError"), e); + } + } + return parent.getElementType(elementName, attr); + } + + private interface SubstituteInterface { + ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException; + } + + private static final class Substitute implements SubstituteInterface { + private final String filename; + private ElementLibrary.ElementTypeDescriptionCustom typeDescriptionCustom; + + private Substitute(String filename) { + this.filename = filename; + } + + @Override + public ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException { + if (typeDescriptionCustom == 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 = modify(Circuit.loadCircuit(in, library.getShapeFactory())); + + typeDescriptionCustom = + new ElementLibrary.ElementTypeDescriptionCustom(new File(filename), + attributes -> new CustomElement(circuit, library), + circuit); + } + return typeDescriptionCustom; + } + + private Circuit modify(Circuit circuit) { + return circuit; + } + } + +} diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index 484020e4e..2bec384f2 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -52,7 +52,7 @@ import java.util.*; * This is done because the loading of a circuit and the creation of an icon is very time consuming and should * be avoided if not necessary. It's a kind of lazy loading. */ -public class ElementLibrary implements Iterable { +public class ElementLibrary implements Iterable, LibraryInterface { private static final Logger LOGGER = LoggerFactory.getLogger(ElementLibrary.class); private static final long MIN_RESCAN_INTERVAL = 5000; @@ -403,6 +403,11 @@ public class ElementLibrary implements Iterable return map.get(elementName); } + @Override + public ElementTypeDescription getElementType(String elementName, ElementAttributes attr) throws ElementNotFoundException { + return getElementType(elementName); + } + /** * Returns a {@link ElementTypeDescription} by a given name. * If not found its tried to load it. diff --git a/src/main/java/de/neemann/digital/draw/library/LibraryInterface.java b/src/main/java/de/neemann/digital/draw/library/LibraryInterface.java new file mode 100644 index 000000000..e4c09421b --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/library/LibraryInterface.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.library; + +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.ElementTypeDescription; + +/** + * Library interface used by the model creator + */ +public interface LibraryInterface { + /** + * Creates a element description. + * + * @param elementName the name of the element + * @param attr the elements attributes + * @return the ElementTypeDescription + */ + ElementTypeDescription getElementType(String elementName, ElementAttributes attr) throws ElementNotFoundException; +} diff --git a/src/main/java/de/neemann/digital/draw/model/ModelCreator.java b/src/main/java/de/neemann/digital/draw/model/ModelCreator.java index 1683350e2..66f68385c 100644 --- a/src/main/java/de/neemann/digital/draw/model/ModelCreator.java +++ b/src/main/java/de/neemann/digital/draw/model/ModelCreator.java @@ -20,6 +20,7 @@ import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.library.CustomElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.LibraryInterface; import de.neemann.digital.draw.shapes.Drawable; import de.neemann.digital.lang.Lang; @@ -48,7 +49,7 @@ public class ModelCreator implements Iterable { * @throws NodeException NodeException * @throws ElementNotFoundException ElementNotFoundException */ - public ModelCreator(Circuit circuit, ElementLibrary library) throws PinException, NodeException, ElementNotFoundException { + public ModelCreator(Circuit circuit, LibraryInterface library) throws PinException, NodeException, ElementNotFoundException { this(circuit, library, false); } @@ -62,7 +63,7 @@ public class ModelCreator implements Iterable { * @throws NodeException NodeException * @throws ElementNotFoundException ElementNotFoundException */ - public ModelCreator(Circuit circuit, ElementLibrary library, boolean readAsCustom) throws PinException, NodeException, ElementNotFoundException { + public ModelCreator(Circuit circuit, LibraryInterface library, boolean readAsCustom) throws PinException, NodeException, ElementNotFoundException { this(circuit, library, readAsCustom, new NetList(circuit), "", 0, null); } @@ -80,7 +81,7 @@ public class ModelCreator implements Iterable { * @throws NodeException NodeException * @throws ElementNotFoundException ElementNotFoundException */ - public ModelCreator(Circuit circuit, ElementLibrary library, boolean isNestedCircuit, NetList netList, String subName, int depth, VisualElement containingVisualElement) throws PinException, NodeException, ElementNotFoundException { + public ModelCreator(Circuit circuit, LibraryInterface library, boolean isNestedCircuit, NetList netList, String subName, int depth, VisualElement containingVisualElement) throws PinException, NodeException, ElementNotFoundException { this.circuit = circuit; this.netList = netList; entries = new ArrayList<>(); @@ -99,8 +100,8 @@ public class ModelCreator implements Iterable { cve = containingVisualElement; Pins pins = ve.getPins(); - ElementTypeDescription elementType = library.getElementType(ve.getElementName()); ElementAttributes attr = ve.getElementAttributes(); + ElementTypeDescription elementType = library.getElementType(ve.getElementName(), attr); if (attr.getLabel().contains("*") && !ve.equalsDescription(In.DESCRIPTION) && !ve.equalsDescription(Out.DESCRIPTION)) { diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 1897cc3f0..90a798813 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -5,6 +5,7 @@ */ package de.neemann.digital.gui; +import de.neemann.digital.analyse.SubstituteLibrary; import de.neemann.digital.analyse.AnalyseException; import de.neemann.digital.analyse.ModelAnalyser; import de.neemann.digital.analyse.TruthTable; @@ -1128,7 +1129,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS @Override public void actionPerformed(ActionEvent e) { try { - Model model = new ModelCreator(circuitComponent.getCircuit(), library).createModel(false); + Model model = new ModelCreator(circuitComponent.getCircuit(), new SubstituteLibrary(library)).createModel(false); try { model.checkForInvalidSignals(); new TableDialog(Main.this, diff --git a/src/main/resources/analyser/Counter.dig b/src/main/resources/analyser/Counter.dig new file mode 100644 index 000000000..de536f148 --- /dev/null +++ b/src/main/resources/analyser/Counter.dig @@ -0,0 +1,254 @@ + + + 1 + + + + In + + + Label + en + + + + + + Clock + + + Label + C + + + + + + In + + + Label + clr + + + + + + Out + + + Label + out + + + Bits + 4 + + + + + + Out + + + Label + ovf + + + + + + D_FF + + + Label + * + + + Bits + 4 + + + + + + Multiplexer + + + Bits + 4 + + + + + + Ground + + + Bits + 4 + + + + + + Multiplexer + + + Bits + 4 + + + + + + Add + + + Bits + 4 + + + + + + Ground + + + + + Const + + + Bits + 4 + + + + + + And + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/analyser/JK_FF.dig b/src/main/resources/analyser/JK_FF.dig new file mode 100644 index 000000000..002275efe --- /dev/null +++ b/src/main/resources/analyser/JK_FF.dig @@ -0,0 +1,212 @@ + + + 1 + + + + D_FF + + + Label + * + + + Inputs + 1 + + + + + + Or + + + + + And + + + inverterConfig + + In_2 + + + + + + + And + + + + + Out + + + Label + Q + + + Inputs + 1 + + + + + + Out + + + Label + ~Q + + + Inputs + 1 + + + + + + In + + + Label + J + + + + + + Clock + + + runRealTime + true + + + Label + C + + + Frequency + 2 + + + + + + In + + + Label + K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/analyser/T_FF.dig b/src/main/resources/analyser/T_FF.dig new file mode 100644 index 000000000..72580f1cb --- /dev/null +++ b/src/main/resources/analyser/T_FF.dig @@ -0,0 +1,110 @@ + + + 1 + + + + D_FF + + + Label + * + + + Inputs + 1 + + + + + + Out + + + Label + Q + + + Inputs + 1 + + + + + + Out + + + Label + ~Q + + + Inputs + 1 + + + + + + Clock + + + runRealTime + true + + + Label + C + + + Frequency + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/analyser/T_FF_EN.dig b/src/main/resources/analyser/T_FF_EN.dig new file mode 100644 index 000000000..42a43e656 --- /dev/null +++ b/src/main/resources/analyser/T_FF_EN.dig @@ -0,0 +1,210 @@ + + + 1 + + + + D_FF + + + Label + * + + + Inputs + 1 + + + + + + Or + + + + + And + + + inverterConfig + + In_2 + + + + + + + And + + + + + Out + + + Label + Q + + + Inputs + 1 + + + + + + Out + + + Label + ~Q + + + Inputs + 1 + + + + + + In + + + Label + T + + + + + + Clock + + + runRealTime + true + + + Label + C + + + Frequency + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file