From 473cf9329748a88592e92fa535dc4cb4ca4ad065 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 15 Apr 2017 18:50:04 +0200 Subject: [PATCH] Added a floating gate P channel fet --- .../core/element/ElementTypeDescription.java | 9 + .../digital/core/switching/FGNFET.java | 2 +- .../digital/core/switching/FGPFET.java | 45 +++++ .../digital/draw/elements/Circuit.java | 14 +- .../neemann/digital/draw/graphics/Style.java | 5 +- .../digital/draw/library/ElementLibrary.java | 27 ++- .../digital/draw/library/LibraryNode.java | 10 ++ .../digital/draw/shapes/FGFETShapeN.java | 5 +- .../digital/draw/shapes/FGFETShapeP.java | 64 ++++++++ .../digital/draw/shapes/ShapeFactory.java | 1 + .../java/de/neemann/digital/gui/Main.java | 2 +- .../gui/components/CircuitComponent.java | 14 +- src/main/resources/lang/lang_de.xml | 7 + src/main/resources/lang/lang_en.xml | 13 +- .../digital/integration/TestExamples.java | 4 +- src/test/resources/dig/shapes.dig | 10 ++ .../resources/dig/test/switch/FGNFETs.dig | 155 ++++++++++++++++++ .../resources/dig/test/switch/FGPFETs.dig | 155 ++++++++++++++++++ 18 files changed, 509 insertions(+), 33 deletions(-) create mode 100644 src/main/java/de/neemann/digital/core/switching/FGPFET.java create mode 100644 src/main/java/de/neemann/digital/draw/shapes/FGFETShapeP.java create mode 100644 src/test/resources/dig/test/switch/FGNFETs.dig create mode 100644 src/test/resources/dig/test/switch/FGPFETs.dig 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 64010aa22..475610231 100644 --- a/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java +++ b/src/main/java/de/neemann/digital/core/element/ElementTypeDescription.java @@ -195,4 +195,13 @@ public class ElementTypeDescription { return elementFactory.create(elementAttributes); } + /** + * Returns true if this description contains the given key + * + * @param key the key + * @return true if this description contains the given key + */ + public boolean hasAttribute(Key key) { + return attributeList.contains(key); + } } diff --git a/src/main/java/de/neemann/digital/core/switching/FGNFET.java b/src/main/java/de/neemann/digital/core/switching/FGNFET.java index 121016f68..4693d0c22 100644 --- a/src/main/java/de/neemann/digital/core/switching/FGNFET.java +++ b/src/main/java/de/neemann/digital/core/switching/FGNFET.java @@ -8,7 +8,7 @@ import de.neemann.digital.core.element.Keys; import static de.neemann.digital.core.element.PinInfo.input; /** - * P-Channel MOS FET + * N-Channel floating gate MOS FET * Created by hneemann on 22.02.17. */ public class FGNFET extends NFET { diff --git a/src/main/java/de/neemann/digital/core/switching/FGPFET.java b/src/main/java/de/neemann/digital/core/switching/FGPFET.java new file mode 100644 index 000000000..8043c93d4 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/switching/FGPFET.java @@ -0,0 +1,45 @@ +package de.neemann.digital.core.switching; + +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.ElementTypeDescription; +import de.neemann.digital.core.element.Keys; + +import static de.neemann.digital.core.element.PinInfo.input; + +/** + * P-Channel floating gate MOS FET + * Created by hneemann on 22.02.17. + */ +public class FGPFET extends NFET { + /** + * The switch description + */ + public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(FGPFET.class, input("G")) + .addAttribute(Keys.ROTATE) + .addAttribute(Keys.BITS) + .addAttribute(Keys.LABEL) + .addAttribute(Keys.BLOWN); + + private final boolean programmed; + + /** + * Create a new instance + * + * @param attr the attributes + */ + public FGPFET(ElementAttributes attr) { + super(attr); + getOutput1().setPinDescription(DESCRIPTION); + getOutput2().setPinDescription(DESCRIPTION); + programmed = attr.get(Keys.BLOWN); + } + + @Override + boolean getClosed(ObservableValue input) { + if (input.isHighZ() || programmed) + return false; + else + return !input.getBool(); + } +} 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 ac42b9701..56d69a10f 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Circuit.java +++ b/src/main/java/de/neemann/digital/draw/elements/Circuit.java @@ -12,15 +12,12 @@ import de.neemann.digital.core.io.IntFormat; import de.neemann.digital.core.io.Out; import de.neemann.digital.core.memory.DataField; import de.neemann.digital.core.memory.DataFieldConverter; -import de.neemann.digital.core.pld.Diode; -import de.neemann.digital.core.pld.DiodeBackward; -import de.neemann.digital.core.pld.DiodeForeward; -import de.neemann.digital.core.switching.FGNFET; import de.neemann.digital.core.wiring.Clock; 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.library.ElementLibrary; import de.neemann.digital.draw.shapes.Drawable; import de.neemann.digital.draw.shapes.InputShape; import de.neemann.digital.draw.shapes.ShapeFactory; @@ -610,13 +607,12 @@ public class Circuit { /** * All fuses (diodes) are set to unprogramed so that they are working again. + * + * @param library library to determine which elements are programmable */ - public void unprogramAllFuses() { + public void unprogramAllFuses(ElementLibrary library) { for (VisualElement ve : visualElements) - if (ve.equalsDescription(DiodeForeward.DESCRIPTION) - || ve.equalsDescription(DiodeBackward.DESCRIPTION) - || ve.equalsDescription(Diode.DESCRIPTION) - || ve.equalsDescription(FGNFET.DESCRIPTION)) { + if (library.isProgrammable(ve.getElementName())) { ve.getElementAttributes().set(Keys.BLOWN, false); modified = true; } diff --git a/src/main/java/de/neemann/digital/draw/graphics/Style.java b/src/main/java/de/neemann/digital/draw/graphics/Style.java index 98d25321f..d837593ae 100644 --- a/src/main/java/de/neemann/digital/draw/graphics/Style.java +++ b/src/main/java/de/neemann/digital/draw/graphics/Style.java @@ -12,10 +12,13 @@ public class Style { * maximal line thickness */ public static final int MAXLINETHICK = 4; + /** + * thickness of thin lines + */ + public static final int LINETHIN = MAXLINETHICK / 2; private static final int WIRETHICK = MAXLINETHICK; private static final int LINETHICK = MAXLINETHICK; - private static final int LINETHIN = MAXLINETHICK / 2; private static final int LINEDASH = 1; /** 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 a104bf24b..c2a18d28e 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -1,6 +1,7 @@ package de.neemann.digital.draw.library; import de.neemann.digital.core.arithmetic.*; +import de.neemann.digital.core.arithmetic.Comparator; import de.neemann.digital.core.basic.*; import de.neemann.digital.core.element.*; import de.neemann.digital.core.flipflops.FlipflopD; @@ -30,10 +31,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; +import java.util.*; /** * The ElementLibrary is responsible for storing all the components which can be used in a circuit. @@ -50,6 +48,7 @@ public class ElementLibrary implements Iterable private static final Logger LOGGER = LoggerFactory.getLogger(ElementLibrary.class); private final HashMap map = new HashMap<>(); + private final HashSet isProgrammable = new HashSet<>(); private final ArrayList listeners = new ArrayList<>(); private final LibraryNode root; private ShapeFactory shapeFactory; @@ -128,8 +127,9 @@ public class ElementLibrary implements Iterable .add(DiodeBackward.DESCRIPTION) .add(Switch.DESCRIPTION) .add(Relay.DESCRIPTION) - .add(NFET.DESCRIPTION) .add(PFET.DESCRIPTION) + .add(NFET.DESCRIPTION) + .add(FGPFET.DESCRIPTION) .add(FGNFET.DESCRIPTION) .add(Reset.DESCRIPTION) .add(Break.DESCRIPTION)) @@ -137,6 +137,23 @@ public class ElementLibrary implements Iterable .add(TestCaseElement.TESTCASEDESCRIPTION)); populateNodeMap(); + + isProgrammable.clear(); + root.traverse(libraryNode -> { + ElementTypeDescription d = libraryNode.getDescriptionOrNull(); + if (d != null && d.hasAttribute(Keys.BLOWN)) + isProgrammable.add(d.getName()); + }); + } + + /** + * Returns true if element is programmable + * + * @param name the name + * @return true if it is programmable + */ + public boolean isProgrammable(String name) { + return isProgrammable.contains(name); } /** diff --git a/src/main/java/de/neemann/digital/draw/library/LibraryNode.java b/src/main/java/de/neemann/digital/draw/library/LibraryNode.java index c944e7aa9..9a3fc7346 100644 --- a/src/main/java/de/neemann/digital/draw/library/LibraryNode.java +++ b/src/main/java/de/neemann/digital/draw/library/LibraryNode.java @@ -120,6 +120,16 @@ public class LibraryNode implements Iterable { return description != null; } + + /** + * Returns the description of the element + * + * @return the description, null if not available + **/ + public ElementTypeDescription getDescriptionOrNull() { + return description; + } + /** * Returns the description of the element * diff --git a/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeN.java b/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeN.java index 2ce4266ad..21ea31d2d 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeN.java +++ b/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeN.java @@ -10,6 +10,8 @@ import de.neemann.digital.draw.graphics.Polygon; import de.neemann.digital.draw.graphics.Style; import de.neemann.digital.draw.graphics.Vector; +import java.awt.*; + import static de.neemann.digital.draw.shapes.GenericShape.SIZE; import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; @@ -17,6 +19,7 @@ import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; * The n-chan FET shape */ public class FGFETShapeN extends FETShape { + static final Style CHARGED_GATE = new Style(Style.MAXLINETHICK, false, Color.RED); private final boolean programmed; @@ -46,7 +49,7 @@ public class FGFETShapeN extends FETShape { super.drawTo(graphic, highLight); if (programmed) - graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), Style.HIGHLIGHT); + graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), CHARGED_GATE); else graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), Style.THIN); diff --git a/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeP.java b/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeP.java new file mode 100644 index 000000000..235776ba7 --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/shapes/FGFETShapeP.java @@ -0,0 +1,64 @@ +package de.neemann.digital.draw.shapes; + +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.Pin; +import de.neemann.digital.draw.elements.Pins; +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 static de.neemann.digital.draw.shapes.FGFETShapeN.CHARGED_GATE; +import static de.neemann.digital.draw.shapes.GenericShape.SIZE; +import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; + +/** + * The p-chan FET shape + */ +public class FGFETShapeP extends FETShape { + + private final boolean programmed; + + /** + * Creates a new instance + * + * @param attributes the attributes + * @param inputs the inputs + * @param outputs the outputs + */ + public FGFETShapeP(ElementAttributes attributes, PinDescriptions inputs, PinDescriptions outputs) { + super(attributes, inputs, outputs); + programmed = attributes.get(Keys.BLOWN); + setXOffs(SIZE2 + 1); + } + + @Override + public Pins getPins() { + return new Pins() + .add(new Pin(new Vector(0, 0), getInputs().get(0))) + .add(new Pin(new Vector(SIZE, 0), getOutputs().get(0))) + .add(new Pin(new Vector(SIZE, SIZE * 2), getOutputs().get(1))); + } + + + @Override + public void drawTo(Graphic graphic, boolean highLight) { + super.drawTo(graphic, highLight); + + if (programmed) + graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), CHARGED_GATE); + else + graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), Style.THIN); + + + // the arrow + graphic.drawLine(new Vector(SIZE2 +1, SIZE), new Vector(SIZE2 + 6, SIZE), Style.THIN); + graphic.drawPolygon(new Polygon(true) + .add(SIZE - SIZE2 / 3 + 4, SIZE) + .add(SIZE2 + 6, SIZE - SIZE2 / 4) + .add(SIZE2 + 6, SIZE + SIZE2 / 4), Style.THIN_FILLED); + } + +} 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 9d2e717eb..2b09c6529 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java @@ -86,6 +86,7 @@ public final class ShapeFactory { map.put(Relay.DESCRIPTION.getName(), RelayShape::new); map.put(NFET.DESCRIPTION.getName(), FETShapeN::new); map.put(FGNFET.DESCRIPTION.getName(), FGFETShapeN::new); + map.put(FGPFET.DESCRIPTION.getName(), FGFETShapeP::new); map.put(PFET.DESCRIPTION.getName(), FETShapeP::new); map.put(Out.DESCRIPTION.getName(), OutputShape::new); map.put(Out.LEDDESCRIPTION.getName(), LEDShape::new); diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 1884bc45e..935406567 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -540,7 +540,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E ToolTipAction unprogramAllFuses = new ToolTipAction(Lang.get("menu_unprogramAllFuses")) { @Override public void actionPerformed(ActionEvent e) { - circuitComponent.getCircuit().unprogramAllFuses(); + circuitComponent.getCircuit().unprogramAllFuses(library); stoppedState.enter(); } }.setToolTip(Lang.get("menu_unprogramAllFuses_tt")); 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 cce67ef14..07d529b74 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -7,10 +7,6 @@ import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ImmutableList; import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Keys; -import de.neemann.digital.core.pld.Diode; -import de.neemann.digital.core.pld.DiodeBackward; -import de.neemann.digital.core.pld.DiodeForeward; -import de.neemann.digital.core.switching.FGNFET; import de.neemann.digital.draw.elements.*; import de.neemann.digital.draw.graphics.*; import de.neemann.digital.draw.library.ElementLibrary; @@ -167,7 +163,7 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe @Override public void actionPerformed(ActionEvent e) { if (activeMouseController instanceof MouseControllerNormal) { - programDiodeAt(getPosVector(lastMousePos.x, lastMousePos.y)); + programElementAt(getPosVector(lastMousePos.x, lastMousePos.y)); } } }; @@ -233,14 +229,12 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe setToolTipText(""); } - private void programDiodeAt(Vector pos) { + private void programElementAt(Vector pos) { VisualElement ve = circuit.getElementAt(pos); - if (ve != null && (ve.equalsDescription(DiodeBackward.DESCRIPTION) - || ve.equalsDescription(DiodeForeward.DESCRIPTION) - || ve.equalsDescription(Diode.DESCRIPTION) - || ve.equalsDescription(FGNFET.DESCRIPTION))) { + if (ve != null && library.isProgrammable(ve.getElementName())) { boolean blown = ve.getElementAttributes().get(Keys.BLOWN); ve.getElementAttributes().set(Keys.BLOWN, !blown); + circuit.modified(); hasChanged(); } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 27da7da37..d66552201 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -380,6 +380,13 @@ Die gesammte Speichergröße beträgt damit damit dx*dy*2 Speicherworte.Source Drain + P-Kanal Floating Gate FET + P-Kanal Feldeffekttransistor mit Floating Gate. Der Bulk ist mit Masse verbunden jedoch wird der Transistor ohne eine Body-Diode simuliert. + Ist das Floating Gate geladen, ist der Transistor immer sperrend. + Gate + Source + Drain + Drehencoder Drehknopf mit Drehencoder zur zustandsfreien Erfassung der Drehbewegung. Encodersignal A diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index a53b0d135..f2f31f4ae 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -350,20 +350,27 @@ A "weak low". N-Channel FET - N-Channel Field Effect Transitor. The bulk is connected to ground and the transistor is simulated without a body diode. + N-Channel Field Effect Transistor. The bulk is connected to ground and the transistor is simulated without a body diode. Gate Source Drain N-Channel floating gate FET - N-Channel Floating Gate Field Effect Transitor. The bulk is connected to ground and the transistor is simulated without a body diode. + N-Channel Floating Gate Field Effect Transistor. The bulk is connected to ground and the transistor is simulated without a body diode. If there is a charge stored in the floating gate, the fet isn't conducting even if the gate is high. Gate Source Drain + P-Channel floating gate FET + P-Channel Floating Gate Field Effect Transistor. The bulk is connected to ground and the transistor is simulated without a body diode. + If there is a charge stored in the floating gate, the fet isn't conducting even if the gate is low. + Gate + Source + Drain + P-Channel FET - P-Channel Field Effect Transitor. The bulk is connected to the pos. voltage rail and the transistor is simulated without a body diode. + P-Channel Field Effect Transistor. The bulk is connected to the pos. voltage rail and the transistor is simulated without a body diode. Gate Source Drain diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index cb0ff6e68..014284cd6 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -39,8 +39,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(54, new FileScanner(this::check).scan(examples)); - assertEquals(48, testCasesInFiles); + assertEquals(56, new FileScanner(this::check).scan(examples)); + assertEquals(52, testCasesInFiles); } diff --git a/src/test/resources/dig/shapes.dig b/src/test/resources/dig/shapes.dig index 6fa9a5473..a44ac3471 100644 --- a/src/test/resources/dig/shapes.dig +++ b/src/test/resources/dig/shapes.dig @@ -412,6 +412,16 @@ + + FGPFET + + + + + FGNFET + + + \ No newline at end of file diff --git a/src/test/resources/dig/test/switch/FGNFETs.dig b/src/test/resources/dig/test/switch/FGNFETs.dig new file mode 100644 index 000000000..64e7d8baf --- /dev/null +++ b/src/test/resources/dig/test/switch/FGNFETs.dig @@ -0,0 +1,155 @@ + + + 1 + + + FGNFET + + + + + PullUp + + + + + Ground + + + + + In + + + Label + A_1 + + + + + + Out + + + Label + Y_1 + + + + + + FGNFET + + + Blown + true + + + + + + PullUp + + + + + Ground + + + + + In + + + Label + A_2 + + + + + + Out + + + Label + Y_2 + + + + + + Testcase + + + Testdata + + A_1 Y_1 + 0 1 + 1 0 + z 1 + + + + + + + + Testcase + + + Testdata + + A_2 Y_2 + 0 1 + 1 1 + z 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dig/test/switch/FGPFETs.dig b/src/test/resources/dig/test/switch/FGPFETs.dig new file mode 100644 index 000000000..698537a32 --- /dev/null +++ b/src/test/resources/dig/test/switch/FGPFETs.dig @@ -0,0 +1,155 @@ + + + 1 + + + In + + + Label + A_1 + + + + + + Out + + + Label + Y_1 + + + + + + Testcase + + + Testdata + + A_1 Y_1 + 0 1 + 1 0 + Z 0 + + + + + + + + FGPFET + + + + + PullDown + + + + + VDD + + + + + In + + + Label + A_2 + + + + + + Out + + + Label + Y_2 + + + + + + FGPFET + + + Blown + true + + + + + + PullDown + + + + + VDD + + + + + Testcase + + + Testdata + + A_2 Y_2 + 0 0 + 1 0 + Z 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file