Merge branch 'pinControl'

This commit is contained in:
hneemann 2019-12-17 11:44:26 +01:00
commit bd80639035
25 changed files with 854 additions and 81 deletions

View File

@ -0,0 +1,83 @@
/*
* 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.core.io;
import de.neemann.digital.core.Node;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.element.Element;
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;
/**
* The pin control logic
*/
public class PinControl extends Node implements Element {
/**
* The description of the pin control logic
*/
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe"))
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS)
.addAttribute(Keys.MIRROR);
private final int bits;
private final ObservableValue rdValue;
private final ObservableValue outWriteValue;
private ObservableValue wrValue;
private ObservableValue oeValue;
private ObservableValue outReadValue;
private long wr;
private boolean oe;
private long outRead;
/**
* Creates a new instance
*
* @param attr the elements attributes
*/
public PinControl(ElementAttributes attr) {
bits = attr.getBits();
rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION);
outWriteValue = new ObservableValue("pin", bits).setPinDescription(DESCRIPTION).setBidirectional();
}
@Override
public void setInputs(ObservableValues inputs) throws NodeException {
wrValue = inputs.get(0).addObserverToValue(this).checkBits(bits, this);
oeValue = inputs.get(1).addObserverToValue(this).checkBits(1, this);
outReadValue = inputs.get(2).addObserverToValue(this).checkBits(bits, this);
}
@Override
public void readInputs() throws NodeException {
wr = wrValue.getValue();
oe = oeValue.getBool();
outRead = outReadValue.getValue();
}
@Override
public void writeOutputs() throws NodeException {
if (oe) {
outWriteValue.setValue(wr);
rdValue.setValue(wr);
} else {
outWriteValue.setToHighZ();
rdValue.setValue(outRead);
}
}
@Override
public ObservableValues getOutputs() {
return new ObservableValues(rdValue, outWriteValue);
}
}

View File

@ -143,7 +143,8 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
.add(Keyboard.DESCRIPTION)
.add(Terminal.DESCRIPTION)
.add(VGA.DESCRIPTION)
.add(MIDI.DESCRIPTION)))
.add(MIDI.DESCRIPTION)
.add(PinControl.DESCRIPTION)))
.add(new LibraryNode(Lang.get("lib_wires"))
.add(Ground.DESCRIPTION)
.add(VDD.DESCRIPTION)

View File

@ -0,0 +1,66 @@
/*
* 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.shapes;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.elements.IOState;
import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.Pins;
import de.neemann.digital.draw.graphics.*;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE2;
/**
* The shape for the pin control logic
*/
public class PinControlShape implements Shape {
private final PinDescriptions in;
private final PinDescriptions out;
private Pins pins;
/**
* Creates a new instance
*
* @param attr the elements attributes
* @param in the inputs
* @param out the outputs
*/
public PinControlShape(ElementAttributes attr, PinDescriptions in, PinDescriptions out) {
this.in = in;
this.out = out;
}
@Override
public Pins getPins() {
if (pins == null)
pins = new Pins()
.add(new Pin(new Vector(0, 0), in.get(0)))
.add(new Pin(new Vector(SIZE, -SIZE), in.get(1)))
.add(new Pin(new Vector(SIZE * 2, SIZE), out.get(0)))
.add(new Pin(new Vector(SIZE * 3, 0), out.get(1)));
return pins;
}
@Override
public InteractorInterface applyStateMonitor(IOState ioState, Observer guiObserver) {
return null;
}
@Override
public void drawTo(Graphic graphic, Style highLight) {
graphic.drawLine(new Vector(0, 0), new Vector(SIZE2, 0), Style.NORMAL);
graphic.drawLine(new Vector(SIZE + SIZE2, 0), new Vector(SIZE * 3, 0), Style.NORMAL);
graphic.drawLine(new Vector(SIZE * 2, 0), new Vector(SIZE * 2, SIZE), Style.NORMAL);
graphic.drawPolygon(new Polygon()
.add(SIZE2, SIZE2)
.add(SIZE2, -SIZE2)
.add(SIZE + SIZE2, 0), Style.NORMAL);
graphic.drawLine(new Vector(SIZE, -SIZE), new Vector(SIZE, -6), Style.NORMAL);
}
}

View File

@ -163,6 +163,7 @@ public final class ShapeFactory {
map.put(DiodeBackward.DESCRIPTION.getName(), DiodeBackwardShape::new);
map.put(PullUp.DESCRIPTION.getName(), PullUpShape::new);
map.put(PullDown.DESCRIPTION.getName(), PullDownShape::new);
map.put(PinControl.DESCRIPTION.getName(), PinControlShape::new);
// disables string formatting for external components, see #272
map.put(External.DESCRIPTION.getName(),

View File

@ -44,6 +44,7 @@ import java.util.*;
*/
public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Printable {
private final String elementName;
private final int depth;
private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLNet> listOfNets;
@ -61,12 +62,13 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
* @param circuit the circuit
* @param elementName the name of the circuit
* @param c the context to create the circuits
* @param depth the depth of this circuit in the circuits hierarchy
* @throws PinException PinException
* @throws HDLException HDLException
* @throws NodeException NodeException
*/
HDLCircuit(Circuit circuit, String elementName, HDLModel c) throws PinException, HDLException, NodeException {
this(circuit, elementName, c, null);
HDLCircuit(Circuit circuit, String elementName, HDLModel c, int depth) throws PinException, HDLException, NodeException {
this(circuit, elementName, c, depth, null);
}
/**
@ -75,13 +77,15 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
* @param circuit the circuit
* @param elementName the name of the circuit
* @param c the context to create the circuits
* @param depth the depth of this circuit in the circuits hierarchy
* @param clockIntegrator the clock integrator
* @throws PinException PinException
* @throws HDLException HDLException
* @throws NodeException NodeException
*/
public HDLCircuit(Circuit circuit, String elementName, HDLModel c, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException {
public HDLCircuit(Circuit circuit, String elementName, HDLModel c, int depth, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException {
this.elementName = elementName;
this.depth = depth;
if (elementName.toLowerCase().endsWith(".dig"))
hdlEntityName = elementName.substring(0, elementName.length() - 4);
@ -154,12 +158,18 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
nodes.addAll(newNodes);
for (HDLPort i : inputs)
if (i.getNet() != null)
if (i.getNet() != null) {
i.getNet().setIsInput(i.getName());
if (i.getNet().isInOutNet())
i.setInOut();
}
for (HDLPort o : outputs)
for (HDLPort o : outputs) {
if (o.getNet().needsVariable())
o.getNet().setIsOutput(o.getName(), o.getNet().getInputs().size() == 1);
if (o.getNet().isInOutNet())
o.setInOut();
}
}
@ -558,6 +568,13 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
return origin;
}
/**
* @return the depth of this circuit in the circuits hierarchy
*/
public int getDepth() {
return depth;
}
/**
* The net naming algorithm
*/

View File

@ -10,11 +10,7 @@ import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.basic.*;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.core.io.Const;
import de.neemann.digital.core.io.DipSwitch;
import de.neemann.digital.core.io.Ground;
import de.neemann.digital.core.io.VDD;
import de.neemann.digital.core.io.*;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.PinException;
@ -77,7 +73,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
if (c == null) {
String elementName = v.getElementName();
elementName = cleanName(elementName.substring(0, elementName.length() - 4) + "_gen" + cache.getNum() + ".dig");
c = new HDLCircuit(holder.getCircuit(), elementName, this);
c = new HDLCircuit(holder.getCircuit(), elementName, this, parent.getDepth() + 1);
cache.addHDLCircuit(c, holder.getArgs());
circuitMap.put(holder.getCircuit(), c);
}
@ -90,7 +86,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
HDLCircuit c = circuitMap.get(circuit);
final String elementName = cleanName(v.getElementName());
if (c == null) {
c = new HDLCircuit(circuit, elementName, this);
c = new HDLCircuit(circuit, elementName, this, parent.getDepth() + 1);
circuitMap.put(circuit, c);
}
@ -151,7 +147,6 @@ public class HDLModel implements Iterable<HDLCircuit> {
td.createElement(v.getElementAttributes()).getOutputs())),
v, parent).createExpressions();
} catch (ElementNotFoundException | PinException | NodeException e) {
throw new HDLException("error creating node", e);
}
@ -180,10 +175,22 @@ public class HDLModel implements Iterable<HDLCircuit> {
private <N extends HDLNode> N addInputsOutputs(N node, VisualElement v, HDLCircuit c) throws HDLException {
for (Pin p : v.getPins()) {
HDLNet net = c.getNetOfPin(p);
if (p.getDirection().equals(PinDescription.Direction.input))
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
else
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName())));
switch (p.getDirection()) {
case input:
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
break;
case output:
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName())));
break;
case both:
if (v.equalsDescription(PinControl.DESCRIPTION)) {
if (c.getDepth() != 0)
throw new HDLException("PinControl component is allowed only in the top level circuit");
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName())));
} else
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName())));
break;
}
}
return node;
}
@ -205,7 +212,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
* @throws NodeException NodeException
*/
public HDLModel create(Circuit circuit, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException {
main = new HDLCircuit(circuit, "main", this, clockIntegrator);
main = new HDLCircuit(circuit, "main", this, 0, clockIntegrator);
circuitMap.put(circuit, main);
return this;
}

View File

@ -18,8 +18,9 @@ import java.util.ArrayList;
*/
public class HDLNet implements Printable, HasName {
private final boolean userNamed;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> inOutputs;
private String name;
private ArrayList<HDLPort> inputs;
private HDLPort output;
private boolean needsVariable = true;
private boolean isInput;
@ -32,6 +33,7 @@ public class HDLNet implements Printable, HasName {
public HDLNet(String name) {
this.name = name;
inputs = new ArrayList<>();
inOutputs = new ArrayList<>();
userNamed = name != null;
}
@ -49,16 +51,23 @@ public class HDLNet implements Printable, HasName {
* @throws HDLException HDLException
*/
public void addPort(HDLPort hdlPort) throws HDLException {
if (hdlPort.getDirection().equals(HDLPort.Direction.OUT)) {
if (output != null) {
String netName = name;
if (netName == null)
netName = Lang.get("err_unnamedNet");
throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort));
}
output = hdlPort;
} else
inputs.add(hdlPort);
switch (hdlPort.getDirection()) {
case OUT:
if (output != null) {
String netName = name;
if (netName == null)
netName = Lang.get("err_unnamedNet");
throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort));
}
output = hdlPort;
break;
case IN:
inputs.add(hdlPort);
break;
case INOUT:
inOutputs.add(hdlPort);
break;
}
}
/**
@ -81,11 +90,25 @@ public class HDLNet implements Printable, HasName {
}
void fixBits() throws HDLException {
if (output == null)
throw new HDLException("no output connected to net");
final int bits = output.getBits();
if (bits == 0)
throw new HDLException("no bit number set for output " + output.getName());
int bits = 0;
if (output == null) {
if (inOutputs.isEmpty())
throw new HDLException("no output connected to net");
else {
for (HDLPort p : inOutputs) {
if (p.getBits() > 0) {
bits = p.getBits();
break;
}
}
if (bits == 0)
throw new HDLException("no bit number set for inOutputs " + inOutputs);
}
} else {
bits = output.getBits();
if (bits == 0)
throw new HDLException("no bit number set for output " + output.getName());
}
for (HDLPort i : inputs)
i.setBits(bits);
@ -96,6 +119,8 @@ public class HDLNet implements Printable, HasName {
* @return the constant if this net is a constant, null otherwise
*/
public ExprConstant isConstant() {
if (output == null)
return null;
return ExprConstant.isConstant(output.getParent());
}
@ -160,9 +185,18 @@ public class HDLNet implements Printable, HasName {
/**
* @return the number of bits on this net
* @throws HDLException HDLException
*/
public int getBits() {
return output.getBits();
public int getBits() throws HDLException {
if (output != null)
return output.getBits();
for (HDLPort p : inOutputs) {
if (p.getBits() > 0) {
return p.getBits();
}
}
throw new HDLException("no bit number set for inOutputs " + inOutputs);
}
/**
@ -190,4 +224,11 @@ public class HDLNet implements Printable, HasName {
name = renaming.checkName(name);
}
/**
* @return true if this is a inOut net
*/
public boolean isInOutNet() {
return !inOutputs.isEmpty();
}
}

View File

@ -22,6 +22,7 @@ public abstract class HDLNode {
private final HDLModel.BitProvider bitProvider;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inOutputs;
private String hdlEntityName;
/**
@ -37,6 +38,7 @@ public abstract class HDLNode {
this.bitProvider = bitProvider;
inputs = new ArrayList<>();
outputs = new ArrayList<>();
inOutputs = new ArrayList<>();
}
/**
@ -46,10 +48,17 @@ public abstract class HDLNode {
* @return this for chained calls
*/
public HDLNode addPort(HDLPort port) {
if (port.getDirection().equals(HDLPort.Direction.OUT))
outputs.add(port);
else
inputs.add(port);
switch (port.getDirection()) {
case IN:
inputs.add(port);
break;
case OUT:
outputs.add(port);
break;
case INOUT:
inOutputs.add(port);
break;
}
port.setParent(this);
@ -96,6 +105,13 @@ public abstract class HDLNode {
return outputs;
}
/**
* @return the list of inOutputs
*/
public ArrayList<HDLPort> getInOutputs() {
return inOutputs;
}
int getBits(String name) {
return bitProvider.getBits(name);
}
@ -111,6 +127,10 @@ public abstract class HDLNode {
printWithLocal(out, inputs);
out.print("out");
printWithLocal(out, outputs);
if (!inOutputs.isEmpty()) {
out.print("inOut");
printWithLocal(out, inOutputs);
}
}
private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException {
@ -177,6 +197,8 @@ public abstract class HDLNode {
p.rename(renaming);
for (HDLPort p : inputs)
p.rename(renaming);
for (HDLPort p : inOutputs)
p.rename(renaming);
}
/**

View File

@ -30,11 +30,15 @@ public class HDLPort implements Printable, HasName {
* Caution: a circuits input components port has type OUT because it defines a value,
* seen from inside the node.
*/
OUT
OUT,
/**
* Bidirectional port
*/
INOUT
}
private String name;
private final Direction direction;
private Direction direction;
private int bits;
private String description;
private boolean isClock;
@ -213,4 +217,11 @@ public class HDLPort implements Printable, HasName {
name = renaming.checkName(name);
}
/**
* Sets this port to a inOut mode port
*/
public void setInOut() {
direction = Direction.INOUT;
}
}

View File

@ -56,12 +56,17 @@ public class VerilogCreator {
/**
* Returns the verilog type for a signal
*
* @param dir the signal type (input or output)
* @param def the signal type (input or output) used if dir is not "inout"
* @param dir used to check if direction is "inout"
* @param bits the number of bits
* @return the verilog signal type
*/
public static String getType(HDLPort.Direction dir, int bits) {
String result = (dir == HDLPort.Direction.IN) ? "input" : "output";
public static String getType(HDLPort.Direction def, HDLPort.Direction dir, int bits) {
String result;
if (dir == HDLPort.Direction.INOUT)
result = "inout";
else
result = (def == HDLPort.Direction.IN) ? "input" : "output";
if (bits > 1) {
result += " [" + (bits - 1) + ":0]";
@ -181,12 +186,12 @@ public class VerilogCreator {
for (HDLPort i : circuit.getInputs()) {
sep.check();
out.print(getType(HDLPort.Direction.IN, i.getBits())).print(" ").print(i.getName());
out.print(getType(HDLPort.Direction.IN, i.getDirection(), i.getBits())).print(" ").print(i.getName());
if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", i.getDescription()));
}
for (HDLPort o : circuit.getOutputs()) {
sep.check();
out.print(getType(HDLPort.Direction.OUT, o.getBits())).print(" ").print(o.getName());
out.print(getType(HDLPort.Direction.OUT, o.getDirection(), o.getBits())).print(" ").print(o.getName());
if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", o.getDescription()));
}
sep.close();
@ -260,6 +265,12 @@ public class VerilogCreator {
sep.check();
out.print(".").print(o.getName()).print("( ").print(o.getNet().getName()).print(" )");
}
for (HDLPort o : node.getInOutputs())
if (o.getNet() != null) {
sep.check();
out.print(".").print(o.getName()).print("( ").print(o.getNet().getName()).print(" )");
}
out.dec();
out.println().println(");");
}

View File

@ -178,18 +178,24 @@ public class VHDLCreator {
for (HDLPort i : circuit.getInputs()) {
sep.check();
out.print(i.getName()).print(": in ").print(getType(i.getBits()));
out.print(i.getName()).print(": ").print(getDir(i.getDirection(), "in")).print(" ").print(getType(i.getBits()));
if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", i.getDescription()));
}
for (HDLPort o : circuit.getOutputs()) {
sep.check();
out.print(o.getName()).print(": out ").print(getType(o.getBits()));
out.print(o.getName()).print(": ").print(getDir(o.getDirection(), "out")).print(" ").print(getType(o.getBits()));
if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", o.getDescription()));
}
sep.close();
out.println(");").dec();
}
private static String getDir(HDLPort.Direction direction, String def) {
if (direction == HDLPort.Direction.INOUT)
return "inout";
return def;
}
private void printManyToOne(HDLNodeSplitterManyToOne node) throws IOException, HDLException {
String target = node.getTargetSignal();
@ -250,6 +256,11 @@ public class VHDLCreator {
sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName());
}
for (HDLPort o : node.getInOutputs())
if (o.getNet() != null) {
sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName());
}
out.println(");").dec().dec();
}

View File

@ -338,25 +338,47 @@
<string name="elem_Driver_pin_sel">Eingang zum Steuern des Treibers.
Ist dieser Eingang auf 1 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 0, ist der Ausgang hochohmig.</string>
<string name="elem_DriverInvSel">Treiber, invertierte Auswahl</string>
<string name="elem_DriverInvSel_tt">Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen Voraussetzungen auf eine andere Leitung weiterzureichen.
<string name="elem_DriverInvSel_tt">Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen
Voraussetzungen auf eine andere Leitung weiterzureichen.
Gesteuert wird der Treiber durch den sel Eingang.
Ist der sel Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht.
Ist der Eingang 1, ist der Ausgang hochohmig.
</string>
<string name="elem_DriverInvSel_pin_in">Das Eingangssignal des Treibers.</string>
<string name="elem_DriverInvSel_pin_sel">Eingang zum Steuern des Treibers.
Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1, ist der Ausgang hochohmig.</string>
<string name="elem_DriverInvSel_pin_out">Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0 gesetzt ist.</string>
Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1,
ist der Ausgang hochohmig.
</string>
<string name="elem_DriverInvSel_pin_out">Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0
gesetzt ist.
</string>
<string name="elem_PinControl">Pinsteuerung</string>
<string name="elem_PinControl_tt">Steuerlogik für einen bidirektionalen Pin.
Diese ist nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich, um einen bidirektionalen HDL-Port zu
erstellen!
Wenn Sie keinen bidirektionalen IO-Port auf einem FPGA verwenden wollen, verwenden Sie diese Komponente nicht!
Die Pinsteuerung kann nicht in einer eingebetteten Schaltung verwendet werden! Sie ist nur auf der obersten
Schaltungsebene erlaubt!
</string>
<string name="elem_PinControl_pin_wr">Die auszugebenden Daten</string>
<string name="elem_PinControl_pin_oe">Aktiviert die Ausgabe</string>
<string name="elem_PinControl_pin_rd">Die zu lesenden Daten.</string>
<string name="elem_PinControl_pin_pin">Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner
Ausgang angeschlossen werden.
</string>
<!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string>
<string name="elem_Multiplexer_tt">Ein Baustein, welcher den Wert eines der Eingänge am Ausgang ausgibt.
Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll.</string>
Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll.
</string>
<string name="elem_Multiplexer_input">Der {0}. Dateneingang des Multiplexers.</string>
<string name="elem_Multiplexer_output">Ausgeben wird der Wert, der am gewählten Dateneingang anliegt.</string>
<string name="elem_Multiplexer_pin_sel">Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang ausgegeben werden soll.</string>
<string name="elem_Multiplexer_pin_sel">Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang
ausgegeben werden soll.
</string>
<string name="elem_Demultiplexer">Demultiplexer</string>
<string name="elem_Demultiplexer_tt">Ein Baustein, welcher einen Eingangswert auf verschiedene Ausgänge ausgeben kann.
Gibt das Eingangssignal auf einem wählbaren Ausgang aus. Die anderen Ausgänge werden auf den Vorgabewert gesetzt.</string>

View File

@ -363,11 +363,26 @@
If the sel input is 1, this output is in high z state.
</string>
<string name="elem_PinControl">Pin Control</string>
<string name="elem_PinControl_tt">Control logic for a bi-directional pin.
This component is necessary only in the context of VHDL or Verilog generation, in order to create a
bi-directional HDL port!
If you don't want to use a bi-directional IO-port on an FPGA, don't use this component!
The PinControl component cannot be used in an embedded circuit! It is only allowed at the top level circuit!
</string>
<string name="elem_PinControl_pin_wr">The data to be output.</string>
<string name="elem_PinControl_pin_oe">Activates the output.</string>
<string name="elem_PinControl_pin_rd">The data to be read.</string>
<string name="elem_PinControl_pin_pin">The connector for the actual pin. Only a single output should be connected
here.
</string>
<!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string>
<string name="elem_Multiplexer_tt">A component which uses the value of the sel pin to decide which input value is set to the output.</string>
<string name="elem_Multiplexer_tt">A component which uses the value of the sel pin to decide which input value is
set to the output.
</string>
<string name="elem_Multiplexer_input">The {0}. data input of the multiplexer.</string>
<string name="elem_Multiplexer_output">The value of the selected input.</string>
<string name="elem_Multiplexer_pin_sel">This input is used to select the data input which is output.</string>

View File

@ -0,0 +1,26 @@
<?
if (elem.Bits > 1) {
generics[0] := "Bits";
export bitRange := "[(Bits-1):0] ";
export zval := "{Bits{1'bz}}";
}
else {
moduleName = moduleName+"_BUS";
export bitRange := "";
export zval := "1'bz";
}
?>module <?= moduleName ?><?
if (elem.Bits > 1) { ?>
#(
parameter Bits = 2
)
<? } ?>(
inout <?= bitRange ?>pin,
input oe,
input <?= bitRange ?>wr,
output <?= bitRange ?>rd
);
assign pin = oe ? wr : <?= zval ?>;
assign rd = oe ? wr : pin ;
endmodule

View File

@ -0,0 +1,64 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
<?
if (elem.Bits=1) {
export entityName:="PinControl"; ?>
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY PinControl IS
PORT(
pin : INOUT STD_LOGIC;
oe : IN STD_LOGIC;
wr : IN STD_LOGIC;
rd : OUT STD_LOGIC);
END PinControl;
ARCHITECTURE Behavioral OF PinControl IS
BEGIN
PROCESS (oe, pin, wr) -- Behavioral representation
BEGIN -- of tri-states.
IF( oe = '0') THEN
pin <= 'Z';
rd <= pin;
ELSE
pin <= wr;
rd <= wr;
END IF;
END PROCESS;
END Behavioral;
<? } else {
export entityName:="PinControl_BUS"; ?>
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY PinControl_BUS IS
GENERIC (
Bits: integer );<? vhdl.registerGeneric("Bits"); ?>
PORT(
pin : INOUT std_logic_vector((Bits-1) downto 0);
oe : IN STD_LOGIC;
wr : IN std_logic_vector((Bits-1) downto 0);
rd : OUT std_logic_vector((Bits-1) downto 0));
END PinControl_BUS;
ARCHITECTURE Behavioral OF PinControl_BUS IS
BEGIN
PROCESS (oe, pin, wr) -- Behavioral representation
BEGIN -- of tri-states.
IF( oe = '0') THEN
pin <= (others => 'Z');
rd <= pin;
ELSE
pin <= wr;
rd <= wr;
END IF;
END PROCESS;
END Behavioral;
<?
}
?>

View File

@ -21,7 +21,7 @@ public class HDLModelTest extends TestCase {
private HDLCircuit getCircuit(String filename, HDLClockIntegrator ci) throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
ToBreakRunner br = new ToBreakRunner(filename);
return new HDLCircuit(br.getCircuit(), "main", new HDLModel(br.getLibrary()), ci);
return new HDLCircuit(br.getCircuit(), "main", new HDLModel(br.getLibrary()), 0, ci);
}
public void testSimple() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {

View File

@ -26,7 +26,7 @@ public class DescriptionTest extends TestCase {
br.getCircuit(),
"main"
, new HDLModel(br.getLibrary()),
null)
0, null)
.applyDefaultOptimizations();
CodePrinterStr out = new CodePrinterStr();
new VerilogCreator(out, br.getLibrary()).printHDLCircuit(circuit, "naming");

View File

@ -14,6 +14,7 @@ import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.gui.Settings;
import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.FileScanner;
import de.neemann.digital.integration.Resources;
import de.neemann.digital.integration.TestExamples;
@ -42,13 +43,13 @@ public class VerilogSimulatorTest extends TestCase {
/*
public void testDebug() throws Exception {
File file = new File(Resources.getRoot(), "dig/test/vhdl/lut.dig");
File file = new File(Resources.getRoot(), "/dig/test/vhdl/pinControl/simple.dig");
ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));
checkVerilogExport(file);
}*/
}/**/
public void testInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test/vhdl");
@ -71,6 +72,21 @@ public class VerilogSimulatorTest extends TestCase {
}
}
public void testInSimulatorInOut() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test/pinControl");
try {
int tested = new FileScanner(f -> {
if (!f.getName().equals("uniTest.dig"))
checkVerilogExport(f);
}).noOutput().scan(examples);
assertEquals(2, tested);
assertEquals(1, testBenches);
} catch (FileScanner.SkipAllException e) {
// if iverilog is not installed its also ok
}
}
public void testDistributedInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "../../main/dig/hdl");
try {
@ -128,7 +144,7 @@ public class VerilogSimulatorTest extends TestCase {
try {
File srcFile = new File(dir, file.getName()
.replace('.', '_')
.replace('-', '_')+ ".v");
.replace('-', '_') + ".v");
CodePrinter out = new CodePrinter(srcFile);
try (VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out)) {
gen.export(br.getCircuit());

View File

@ -123,7 +123,7 @@ public class ClockTest extends TestCase {
HDLCircuit c = new HDLCircuit(
br.getCircuit(), "main",
new HDLModel(br.getLibrary()),
ci);
0, ci);
c.applyDefaultOptimizations();

View File

@ -26,7 +26,7 @@ public class DescriptionTest extends TestCase {
br.getCircuit(),
"main"
, new HDLModel(br.getLibrary()),
null)
0, null)
.applyDefaultOptimizations();
CodePrinterStr out = new CodePrinterStr();
new VHDLCreator(out, br.getLibrary()).printHDLCircuit(circuit);

View File

@ -34,7 +34,7 @@ public class VHDLSimulatorTest extends TestCase {
/*
public void testDebug() throws Exception {
File file = new File(Resources.getRoot(), "dig/test/vhdl/lut2.dig");
File file = new File(Resources.getRoot(), "/dig/test/pinControl/nesting.dig");
ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));
@ -63,6 +63,17 @@ public class VHDLSimulatorTest extends TestCase {
}
}
public void testInSimulatorInOut() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test/pinControl");
try {
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
assertEquals(2, tested);
assertEquals(2, testBenches);
} catch (FileScanner.SkipAllException e) {
// if ghdl is not installed its also ok
}
}
public void testDistributedInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "../../main/dig/hdl");
try {

View File

@ -43,8 +43,8 @@ public class TestExamples extends TestCase {
*/
public void testTestExamples() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test");
assertEquals(184, new FileScanner(this::check).scan(examples));
assertEquals(172, testCasesInFiles);
assertEquals(186, new FileScanner(this::check).scan(examples));
assertEquals(174, testCasesInFiles);
}
/**

View File

@ -614,6 +614,30 @@
<elementAttributes/>
<pos x="600" y="920"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="780" y="960"/>
</visualElement>
<visualElement>
<elementName>Tunnel</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>NetName</string>
<string>zz</string>
</entry>
</elementAttributes>
<pos x="740" y="1020"/>
</visualElement>
</visualElements>
<wires>
<wire>
@ -668,6 +692,14 @@
<p1 x="580" y="960"/>
<p2 x="600" y="960"/>
</wire>
<wire>
<p1 x="760" y="960"/>
<p2 x="780" y="960"/>
</wire>
<wire>
<p1 x="820" y="960"/>
<p2 x="840" y="960"/>
</wire>
<wire>
<p1 x="240" y="260"/>
<p2 x="260" y="260"/>
@ -716,6 +748,10 @@
<p1 x="1080" y="900"/>
<p2 x="1120" y="900"/>
</wire>
<wire>
<p1 x="580" y="900"/>
<p2 x="800" y="900"/>
</wire>
<wire>
<p1 x="780" y="200"/>
<p2 x="800" y="200"/>
@ -856,6 +892,10 @@
<p1 x="580" y="980"/>
<p2 x="600" y="980"/>
</wire>
<wire>
<p1 x="760" y="980"/>
<p2 x="780" y="980"/>
</wire>
<wire>
<p1 x="280" y="980"/>
<p2 x="300" y="980"/>
@ -1248,6 +1288,22 @@
<p1 x="1160" y="440"/>
<p2 x="1200" y="440"/>
</wire>
<wire>
<p1 x="740" y="1020"/>
<p2 x="760" y="1020"/>
</wire>
<wire>
<p1 x="280" y="1020"/>
<p2 x="300" y="1020"/>
</wire>
<wire>
<p1 x="580" y="1020"/>
<p2 x="600" y="1020"/>
</wire>
<wire>
<p1 x="760" y="1020"/>
<p2 x="840" y="1020"/>
</wire>
<wire>
<p1 x="940" y="700"/>
<p2 x="960" y="700"/>
@ -1272,14 +1328,6 @@
<p1 x="940" y="380"/>
<p2 x="960" y="380"/>
</wire>
<wire>
<p1 x="280" y="1020"/>
<p2 x="300" y="1020"/>
</wire>
<wire>
<p1 x="580" y="1020"/>
<p2 x="600" y="1020"/>
</wire>
<wire>
<p1 x="640" y="500"/>
<p2 x="640" y="520"/>
@ -1330,7 +1378,7 @@
</wire>
<wire>
<p1 x="580" y="860"/>
<p2 x="580" y="920"/>
<p2 x="580" y="900"/>
</wire>
<wire>
<p1 x="580" y="360"/>
@ -1340,6 +1388,10 @@
<p1 x="580" y="380"/>
<p2 x="580" y="420"/>
</wire>
<wire>
<p1 x="580" y="900"/>
<p2 x="580" y="920"/>
</wire>
<wire>
<p1 x="580" y="920"/>
<p2 x="580" y="940"/>
@ -1452,6 +1504,10 @@
<p1 x="520" y="740"/>
<p2 x="520" y="780"/>
</wire>
<wire>
<p1 x="840" y="960"/>
<p2 x="840" y="1020"/>
</wire>
<wire>
<p1 x="460" y="560"/>
<p2 x="460" y="580"/>
@ -1640,6 +1696,10 @@
<p1 x="1120" y="960"/>
<p2 x="1120" y="980"/>
</wire>
<wire>
<p1 x="800" y="900"/>
<p2 x="800" y="940"/>
</wire>
<wire>
<p1 x="360" y="100"/>
<p2 x="360" y="760"/>
@ -1789,12 +1849,8 @@
<p2 x="500" y="840"/>
</wire>
<wire>
<p1 x="440" y="560"/>
<p2 x="440" y="580"/>
</wire>
<wire>
<p1 x="440" y="400"/>
<p2 x="440" y="420"/>
<p1 x="760" y="960"/>
<p2 x="760" y="980"/>
</wire>
<wire>
<p1 x="760" y="220"/>
@ -1812,6 +1868,18 @@
<p1 x="760" y="400"/>
<p2 x="760" y="600"/>
</wire>
<wire>
<p1 x="760" y="980"/>
<p2 x="760" y="1020"/>
</wire>
<wire>
<p1 x="440" y="560"/>
<p2 x="440" y="580"/>
</wire>
<wire>
<p1 x="440" y="400"/>
<p2 x="440" y="420"/>
</wire>
<wire>
<p1 x="1080" y="180"/>
<p2 x="1080" y="320"/>

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>wr_0</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="360" y="180"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>oe</string>
</entry>
</elementAttributes>
<pos x="360" y="140"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="380" y="180"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>rd_0</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="360" y="220"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>wr_1</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="540" y="180"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>mirror</string>
<boolean>true</boolean>
</entry>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="520" y="180"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>rd_1</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="540" y="220"/>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="420" y="140"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>oe wr_0 rd_0 wr_1 rd_1
1 1 x x 1
1 2 x x 2
0 x 1 1 x
0 x 2 2 x
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="400" y="240"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="520" y="180"/>
<p2 x="540" y="180"/>
</wire>
<wire>
<p1 x="360" y="180"/>
<p2 x="380" y="180"/>
</wire>
<wire>
<p1 x="440" y="180"/>
<p2 x="460" y="180"/>
</wire>
<wire>
<p1 x="460" y="140"/>
<p2 x="500" y="140"/>
</wire>
<wire>
<p1 x="360" y="140"/>
<p2 x="400" y="140"/>
</wire>
<wire>
<p1 x="400" y="140"/>
<p2 x="420" y="140"/>
</wire>
<wire>
<p1 x="360" y="220"/>
<p2 x="420" y="220"/>
</wire>
<wire>
<p1 x="480" y="220"/>
<p2 x="540" y="220"/>
</wire>
<wire>
<p1 x="480" y="200"/>
<p2 x="480" y="220"/>
</wire>
<wire>
<p1 x="400" y="140"/>
<p2 x="400" y="160"/>
</wire>
<wire>
<p1 x="420" y="200"/>
<p2 x="420" y="220"/>
</wire>
<wire>
<p1 x="500" y="140"/>
<p2 x="500" y="160"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>wr</string>
</entry>
</elementAttributes>
<pos x="340" y="200"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>oe</string>
</entry>
</elementAttributes>
<pos x="340" y="160"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes/>
<pos x="360" y="200"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>rd</string>
</entry>
</elementAttributes>
<pos x="340" y="240"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>pin</string>
</entry>
</elementAttributes>
<pos x="440" y="200"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>oe wr rd pin
1 0 0 0
1 1 1 1
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="360" y="240"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="340" y="240"/>
<p2 x="400" y="240"/>
</wire>
<wire>
<p1 x="340" y="160"/>
<p2 x="380" y="160"/>
</wire>
<wire>
<p1 x="340" y="200"/>
<p2 x="360" y="200"/>
</wire>
<wire>
<p1 x="420" y="200"/>
<p2 x="440" y="200"/>
</wire>
<wire>
<p1 x="400" y="220"/>
<p2 x="400" y="240"/>
</wire>
<wire>
<p1 x="380" y="160"/>
<p2 x="380" y="180"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>