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(Keyboard.DESCRIPTION)
.add(Terminal.DESCRIPTION) .add(Terminal.DESCRIPTION)
.add(VGA.DESCRIPTION) .add(VGA.DESCRIPTION)
.add(MIDI.DESCRIPTION))) .add(MIDI.DESCRIPTION)
.add(PinControl.DESCRIPTION)))
.add(new LibraryNode(Lang.get("lib_wires")) .add(new LibraryNode(Lang.get("lib_wires"))
.add(Ground.DESCRIPTION) .add(Ground.DESCRIPTION)
.add(VDD.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(DiodeBackward.DESCRIPTION.getName(), DiodeBackwardShape::new);
map.put(PullUp.DESCRIPTION.getName(), PullUpShape::new); map.put(PullUp.DESCRIPTION.getName(), PullUpShape::new);
map.put(PullDown.DESCRIPTION.getName(), PullDownShape::new); map.put(PullDown.DESCRIPTION.getName(), PullDownShape::new);
map.put(PinControl.DESCRIPTION.getName(), PinControlShape::new);
// disables string formatting for external components, see #272 // disables string formatting for external components, see #272
map.put(External.DESCRIPTION.getName(), map.put(External.DESCRIPTION.getName(),

View File

@ -44,6 +44,7 @@ import java.util.*;
*/ */
public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Printable { public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Printable {
private final String elementName; private final String elementName;
private final int depth;
private final ArrayList<HDLPort> outputs; private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inputs; private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLNet> listOfNets; private final ArrayList<HDLNet> listOfNets;
@ -61,12 +62,13 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
* @param circuit the circuit * @param circuit the circuit
* @param elementName the name of the circuit * @param elementName the name of the circuit
* @param c the context to create the circuits * @param c the context to create the circuits
* @param depth the depth of this circuit in the circuits hierarchy
* @throws PinException PinException * @throws PinException PinException
* @throws HDLException HDLException * @throws HDLException HDLException
* @throws NodeException NodeException * @throws NodeException NodeException
*/ */
HDLCircuit(Circuit circuit, String elementName, HDLModel c) throws PinException, HDLException, NodeException { HDLCircuit(Circuit circuit, String elementName, HDLModel c, int depth) throws PinException, HDLException, NodeException {
this(circuit, elementName, c, null); this(circuit, elementName, c, depth, null);
} }
/** /**
@ -75,13 +77,15 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
* @param circuit the circuit * @param circuit the circuit
* @param elementName the name of the circuit * @param elementName the name of the circuit
* @param c the context to create the circuits * @param c the context to create the circuits
* @param depth the depth of this circuit in the circuits hierarchy
* @param clockIntegrator the clock integrator * @param clockIntegrator the clock integrator
* @throws PinException PinException * @throws PinException PinException
* @throws HDLException HDLException * @throws HDLException HDLException
* @throws NodeException NodeException * @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.elementName = elementName;
this.depth = depth;
if (elementName.toLowerCase().endsWith(".dig")) if (elementName.toLowerCase().endsWith(".dig"))
hdlEntityName = elementName.substring(0, elementName.length() - 4); hdlEntityName = elementName.substring(0, elementName.length() - 4);
@ -154,12 +158,18 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
nodes.addAll(newNodes); nodes.addAll(newNodes);
for (HDLPort i : inputs) for (HDLPort i : inputs)
if (i.getNet() != null) if (i.getNet() != null) {
i.getNet().setIsInput(i.getName()); i.getNet().setIsInput(i.getName());
if (i.getNet().isInOutNet())
i.setInOut();
}
for (HDLPort o : outputs) for (HDLPort o : outputs) {
if (o.getNet().needsVariable()) if (o.getNet().needsVariable())
o.getNet().setIsOutput(o.getName(), o.getNet().getInputs().size() == 1); 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 origin;
} }
/**
* @return the depth of this circuit in the circuits hierarchy
*/
public int getDepth() {
return depth;
}
/** /**
* The net naming algorithm * 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.basic.*;
import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription; import de.neemann.digital.core.io.*;
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.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Pin; import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.PinException;
@ -77,7 +73,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
if (c == null) { if (c == null) {
String elementName = v.getElementName(); String elementName = v.getElementName();
elementName = cleanName(elementName.substring(0, elementName.length() - 4) + "_gen" + cache.getNum() + ".dig"); 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()); cache.addHDLCircuit(c, holder.getArgs());
circuitMap.put(holder.getCircuit(), c); circuitMap.put(holder.getCircuit(), c);
} }
@ -90,7 +86,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
HDLCircuit c = circuitMap.get(circuit); HDLCircuit c = circuitMap.get(circuit);
final String elementName = cleanName(v.getElementName()); final String elementName = cleanName(v.getElementName());
if (c == null) { if (c == null) {
c = new HDLCircuit(circuit, elementName, this); c = new HDLCircuit(circuit, elementName, this, parent.getDepth() + 1);
circuitMap.put(circuit, c); circuitMap.put(circuit, c);
} }
@ -151,7 +147,6 @@ public class HDLModel implements Iterable<HDLCircuit> {
td.createElement(v.getElementAttributes()).getOutputs())), td.createElement(v.getElementAttributes()).getOutputs())),
v, parent).createExpressions(); v, parent).createExpressions();
} catch (ElementNotFoundException | PinException | NodeException e) { } catch (ElementNotFoundException | PinException | NodeException e) {
throw new HDLException("error creating node", 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 { private <N extends HDLNode> N addInputsOutputs(N node, VisualElement v, HDLCircuit c) throws HDLException {
for (Pin p : v.getPins()) { for (Pin p : v.getPins()) {
HDLNet net = c.getNetOfPin(p); HDLNet net = c.getNetOfPin(p);
if (p.getDirection().equals(PinDescription.Direction.input)) switch (p.getDirection()) {
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0)); case input:
else node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); 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; return node;
} }
@ -205,7 +212,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
* @throws NodeException NodeException * @throws NodeException NodeException
*/ */
public HDLModel create(Circuit circuit, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, 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); circuitMap.put(circuit, main);
return this; return this;
} }

View File

@ -18,8 +18,9 @@ import java.util.ArrayList;
*/ */
public class HDLNet implements Printable, HasName { public class HDLNet implements Printable, HasName {
private final boolean userNamed; private final boolean userNamed;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> inOutputs;
private String name; private String name;
private ArrayList<HDLPort> inputs;
private HDLPort output; private HDLPort output;
private boolean needsVariable = true; private boolean needsVariable = true;
private boolean isInput; private boolean isInput;
@ -32,6 +33,7 @@ public class HDLNet implements Printable, HasName {
public HDLNet(String name) { public HDLNet(String name) {
this.name = name; this.name = name;
inputs = new ArrayList<>(); inputs = new ArrayList<>();
inOutputs = new ArrayList<>();
userNamed = name != null; userNamed = name != null;
} }
@ -49,16 +51,23 @@ public class HDLNet implements Printable, HasName {
* @throws HDLException HDLException * @throws HDLException HDLException
*/ */
public void addPort(HDLPort hdlPort) throws HDLException { public void addPort(HDLPort hdlPort) throws HDLException {
if (hdlPort.getDirection().equals(HDLPort.Direction.OUT)) { switch (hdlPort.getDirection()) {
if (output != null) { case OUT:
String netName = name; if (output != null) {
if (netName == null) String netName = name;
netName = Lang.get("err_unnamedNet"); if (netName == null)
throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort)); netName = Lang.get("err_unnamedNet");
} throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort));
output = hdlPort; }
} else output = hdlPort;
inputs.add(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 { void fixBits() throws HDLException {
if (output == null) int bits = 0;
throw new HDLException("no output connected to net"); if (output == null) {
final int bits = output.getBits(); if (inOutputs.isEmpty())
if (bits == 0) throw new HDLException("no output connected to net");
throw new HDLException("no bit number set for output " + output.getName()); 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) for (HDLPort i : inputs)
i.setBits(bits); i.setBits(bits);
@ -96,6 +119,8 @@ public class HDLNet implements Printable, HasName {
* @return the constant if this net is a constant, null otherwise * @return the constant if this net is a constant, null otherwise
*/ */
public ExprConstant isConstant() { public ExprConstant isConstant() {
if (output == null)
return null;
return ExprConstant.isConstant(output.getParent()); return ExprConstant.isConstant(output.getParent());
} }
@ -160,9 +185,18 @@ public class HDLNet implements Printable, HasName {
/** /**
* @return the number of bits on this net * @return the number of bits on this net
* @throws HDLException HDLException
*/ */
public int getBits() { public int getBits() throws HDLException {
return output.getBits(); 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); 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 HDLModel.BitProvider bitProvider;
private final ArrayList<HDLPort> inputs; private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> outputs; private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inOutputs;
private String hdlEntityName; private String hdlEntityName;
/** /**
@ -37,6 +38,7 @@ public abstract class HDLNode {
this.bitProvider = bitProvider; this.bitProvider = bitProvider;
inputs = new ArrayList<>(); inputs = new ArrayList<>();
outputs = new ArrayList<>(); outputs = new ArrayList<>();
inOutputs = new ArrayList<>();
} }
/** /**
@ -46,10 +48,17 @@ public abstract class HDLNode {
* @return this for chained calls * @return this for chained calls
*/ */
public HDLNode addPort(HDLPort port) { public HDLNode addPort(HDLPort port) {
if (port.getDirection().equals(HDLPort.Direction.OUT)) switch (port.getDirection()) {
outputs.add(port); case IN:
else inputs.add(port);
inputs.add(port); break;
case OUT:
outputs.add(port);
break;
case INOUT:
inOutputs.add(port);
break;
}
port.setParent(this); port.setParent(this);
@ -96,6 +105,13 @@ public abstract class HDLNode {
return outputs; return outputs;
} }
/**
* @return the list of inOutputs
*/
public ArrayList<HDLPort> getInOutputs() {
return inOutputs;
}
int getBits(String name) { int getBits(String name) {
return bitProvider.getBits(name); return bitProvider.getBits(name);
} }
@ -111,6 +127,10 @@ public abstract class HDLNode {
printWithLocal(out, inputs); printWithLocal(out, inputs);
out.print("out"); out.print("out");
printWithLocal(out, outputs); printWithLocal(out, outputs);
if (!inOutputs.isEmpty()) {
out.print("inOut");
printWithLocal(out, inOutputs);
}
} }
private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException { private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException {
@ -177,6 +197,8 @@ public abstract class HDLNode {
p.rename(renaming); p.rename(renaming);
for (HDLPort p : inputs) for (HDLPort p : inputs)
p.rename(renaming); 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, * Caution: a circuits input components port has type OUT because it defines a value,
* seen from inside the node. * seen from inside the node.
*/ */
OUT OUT,
/**
* Bidirectional port
*/
INOUT
} }
private String name; private String name;
private final Direction direction; private Direction direction;
private int bits; private int bits;
private String description; private String description;
private boolean isClock; private boolean isClock;
@ -213,4 +217,11 @@ public class HDLPort implements Printable, HasName {
name = renaming.checkName(name); 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 * 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 * @param bits the number of bits
* @return the verilog signal type * @return the verilog signal type
*/ */
public static String getType(HDLPort.Direction dir, int bits) { public static String getType(HDLPort.Direction def, HDLPort.Direction dir, int bits) {
String result = (dir == HDLPort.Direction.IN) ? "input" : "output"; String result;
if (dir == HDLPort.Direction.INOUT)
result = "inout";
else
result = (def == HDLPort.Direction.IN) ? "input" : "output";
if (bits > 1) { if (bits > 1) {
result += " [" + (bits - 1) + ":0]"; result += " [" + (bits - 1) + ":0]";
@ -181,12 +186,12 @@ public class VerilogCreator {
for (HDLPort i : circuit.getInputs()) { for (HDLPort i : circuit.getInputs()) {
sep.check(); 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())); if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", i.getDescription()));
} }
for (HDLPort o : circuit.getOutputs()) { for (HDLPort o : circuit.getOutputs()) {
sep.check(); 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())); if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", o.getDescription()));
} }
sep.close(); sep.close();
@ -260,6 +265,12 @@ public class VerilogCreator {
sep.check(); sep.check();
out.print(".").print(o.getName()).print("( ").print(o.getNet().getName()).print(" )"); 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.dec();
out.println().println(");"); out.println().println(");");
} }

View File

@ -178,18 +178,24 @@ public class VHDLCreator {
for (HDLPort i : circuit.getInputs()) { for (HDLPort i : circuit.getInputs()) {
sep.check(); 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())); if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", i.getDescription()));
} }
for (HDLPort o : circuit.getOutputs()) { for (HDLPort o : circuit.getOutputs()) {
sep.check(); 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())); if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", o.getDescription()));
} }
sep.close(); sep.close();
out.println(");").dec(); 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 { private void printManyToOne(HDLNodeSplitterManyToOne node) throws IOException, HDLException {
String target = node.getTargetSignal(); String target = node.getTargetSignal();
@ -250,6 +256,11 @@ public class VHDLCreator {
sep.check(); sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName()); 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(); out.println(");").dec().dec();
} }

View File

@ -338,25 +338,47 @@
<string name="elem_Driver_pin_sel">Eingang zum Steuern des Treibers. <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> 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">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. 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 sel Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht.
Ist der Eingang 1, ist der Ausgang hochohmig. Ist der Eingang 1, ist der Ausgang hochohmig.
</string> </string>
<string name="elem_DriverInvSel_pin_in">Das Eingangssignal des Treibers.</string> <string name="elem_DriverInvSel_pin_in">Das Eingangssignal des Treibers.</string>
<string name="elem_DriverInvSel_pin_sel">Eingang zum Steuern des Treibers. <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> Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1,
<string name="elem_DriverInvSel_pin_out">Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0 gesetzt ist.</string> 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 --> <!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string> <string name="elem_Multiplexer">Multiplexer</string>
<string name="elem_Multiplexer_tt">Ein Baustein, welcher den Wert eines der Eingänge am Ausgang ausgibt. <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_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_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">Demultiplexer</string>
<string name="elem_Demultiplexer_tt">Ein Baustein, welcher einen Eingangswert auf verschiedene Ausgänge ausgeben kann. <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> 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. If the sel input is 1, this output is in high z state.
</string> </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 --> <!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string> <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_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_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> <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 { private HDLCircuit getCircuit(String filename, HDLClockIntegrator ci) throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
ToBreakRunner br = new ToBreakRunner(filename); 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 { public void testSimple() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {

View File

@ -26,7 +26,7 @@ public class DescriptionTest extends TestCase {
br.getCircuit(), br.getCircuit(),
"main" "main"
, new HDLModel(br.getLibrary()), , new HDLModel(br.getLibrary()),
null) 0, null)
.applyDefaultOptimizations(); .applyDefaultOptimizations();
CodePrinterStr out = new CodePrinterStr(); CodePrinterStr out = new CodePrinterStr();
new VerilogCreator(out, br.getLibrary()).printHDLCircuit(circuit, "naming"); 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.gui.Settings;
import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.printer.CodePrinter; 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.FileScanner;
import de.neemann.digital.integration.Resources; import de.neemann.digital.integration.Resources;
import de.neemann.digital.integration.TestExamples; import de.neemann.digital.integration.TestExamples;
@ -42,13 +43,13 @@ public class VerilogSimulatorTest extends TestCase {
/* /*
public void testDebug() throws Exception { 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); ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));
checkVerilogExport(file); checkVerilogExport(file);
}*/ }/**/
public void testInSimulator() throws Exception { public void testInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); 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 { public void testDistributedInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "../../main/dig/hdl"); File examples = new File(Resources.getRoot(), "../../main/dig/hdl");
try { try {
@ -128,7 +144,7 @@ public class VerilogSimulatorTest extends TestCase {
try { try {
File srcFile = new File(dir, file.getName() File srcFile = new File(dir, file.getName()
.replace('.', '_') .replace('.', '_')
.replace('-', '_')+ ".v"); .replace('-', '_') + ".v");
CodePrinter out = new CodePrinter(srcFile); CodePrinter out = new CodePrinter(srcFile);
try (VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out)) { try (VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out)) {
gen.export(br.getCircuit()); gen.export(br.getCircuit());

View File

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

View File

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

View File

@ -34,7 +34,7 @@ public class VHDLSimulatorTest extends TestCase {
/* /*
public void testDebug() throws Exception { 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); ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); 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 { public void testDistributedInSimulator() throws Exception {
File examples = new File(Resources.getRoot(), "../../main/dig/hdl"); File examples = new File(Resources.getRoot(), "../../main/dig/hdl");
try { try {

View File

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

View File

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