mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 07:48:29 -04:00
added splitter to new model
This commit is contained in:
parent
3abfbe460b
commit
366535ace6
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package de.neemann.digital.hdl.model2;
|
package de.neemann.digital.hdl.model2;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.BitsException;
|
||||||
import de.neemann.digital.core.NodeException;
|
import de.neemann.digital.core.NodeException;
|
||||||
import de.neemann.digital.core.basic.Not;
|
import de.neemann.digital.core.basic.Not;
|
||||||
import de.neemann.digital.core.element.ElementAttributes;
|
import de.neemann.digital.core.element.ElementAttributes;
|
||||||
@ -17,6 +18,7 @@ import de.neemann.digital.core.pld.PullDown;
|
|||||||
import de.neemann.digital.core.pld.PullUp;
|
import de.neemann.digital.core.pld.PullUp;
|
||||||
import de.neemann.digital.core.wiring.Break;
|
import de.neemann.digital.core.wiring.Break;
|
||||||
import de.neemann.digital.core.wiring.Clock;
|
import de.neemann.digital.core.wiring.Clock;
|
||||||
|
import de.neemann.digital.core.wiring.Splitter;
|
||||||
import de.neemann.digital.draw.elements.*;
|
import de.neemann.digital.draw.elements.*;
|
||||||
import de.neemann.digital.draw.model.InverterConfig;
|
import de.neemann.digital.draw.model.InverterConfig;
|
||||||
import de.neemann.digital.draw.model.Net;
|
import de.neemann.digital.draw.model.Net;
|
||||||
@ -77,6 +79,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider, Pr
|
|||||||
HDLPort.Direction.IN,
|
HDLPort.Direction.IN,
|
||||||
v.getElementAttributes().getBits())
|
v.getElementAttributes().getBits())
|
||||||
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)));
|
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)));
|
||||||
|
else if (v.equalsDescription(Splitter.DESCRIPTION))
|
||||||
|
handleSplitter(c.createNode(v, this));
|
||||||
else if (isRealElement(v))
|
else if (isRealElement(v))
|
||||||
nodes.add(c.createNode(v, this));
|
nodes.add(c.createNode(v, this));
|
||||||
}
|
}
|
||||||
@ -111,6 +115,37 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider, Pr
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleSplitter(HDLNode node) throws BitsException, HDLException {
|
||||||
|
Splitter.Ports inputSplit = new Splitter.Ports(node.getElementAttributes().get(Keys.INPUT_SPLIT));
|
||||||
|
Splitter.Ports outputSplit = new Splitter.Ports(node.getElementAttributes().get(Keys.OUTPUT_SPLIT));
|
||||||
|
if (node.getInputs().size() == 1) {
|
||||||
|
nodes.add(new HDLNodeSplitterOneToMany(node, outputSplit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.getOutputs().size() == 1 && node.getOutput().getBits() == inputSplit.getBits()) {
|
||||||
|
nodes.add(new HDLNodeSplitterManyToOne(node, inputSplit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bits = inputSplit.getBits();
|
||||||
|
HDLNet net = new HDLNet(null);
|
||||||
|
listOfNets.add(net);
|
||||||
|
HDLPort left = new HDLPort("single", net, HDLPort.Direction.OUT, bits);
|
||||||
|
HDLPort right = new HDLPort("single", net, HDLPort.Direction.IN, bits);
|
||||||
|
|
||||||
|
HDLNodeSplitterManyToOne manyToOne = new HDLNodeSplitterManyToOne(node, inputSplit);
|
||||||
|
HDLNodeSplitterOneToMany oneToMany = new HDLNodeSplitterOneToMany(node, outputSplit);
|
||||||
|
|
||||||
|
manyToOne.getOutputs().clear();
|
||||||
|
manyToOne.addOutput(left);
|
||||||
|
|
||||||
|
oneToMany.getInputs().clear();
|
||||||
|
oneToMany.addInput(right);
|
||||||
|
|
||||||
|
nodes.add(manyToOne);
|
||||||
|
nodes.add(oneToMany);
|
||||||
|
}
|
||||||
|
|
||||||
private HDLNode createNot(HDLPort p, HDLNode node) throws HDLException, NodeException, PinException {
|
private HDLNode createNot(HDLPort p, HDLNode node) throws HDLException, NodeException, PinException {
|
||||||
final ElementAttributes attr = new ElementAttributes().setBits(p.getBits());
|
final ElementAttributes attr = new ElementAttributes().setBits(p.getBits());
|
||||||
HDLNodeExpression n = new HDLNodeExpression(Not.DESCRIPTION.getName(), attr, name -> p.getBits());
|
HDLNodeExpression n = new HDLNodeExpression(Not.DESCRIPTION.getName(), attr, name -> p.getBits());
|
||||||
|
@ -22,7 +22,7 @@ public class HDLNode {
|
|||||||
private final ArrayList<HDLPort> outputs;
|
private final ArrayList<HDLPort> outputs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates e new intance
|
* Creates e new instance
|
||||||
*
|
*
|
||||||
* @param elementName the instances name
|
* @param elementName the instances name
|
||||||
* @param elementAttributes the attributes
|
* @param elementAttributes the attributes
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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.hdl.model2;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.wiring.Splitter;
|
||||||
|
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The splitter.
|
||||||
|
* Either the output split or the input split is always one!
|
||||||
|
*/
|
||||||
|
public class HDLNodeSplitterManyToOne extends HDLNode {
|
||||||
|
private final Splitter.Ports inputSplit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param node the original splitter node
|
||||||
|
* @param inputSplit input splitting
|
||||||
|
*/
|
||||||
|
HDLNodeSplitterManyToOne(HDLNode node, Splitter.Ports inputSplit) {
|
||||||
|
super(node.getElementName(), node.getElementAttributes(), null);
|
||||||
|
this.inputSplit = inputSplit;
|
||||||
|
getInputs().addAll(node.getInputs());
|
||||||
|
getOutputs().addAll(node.getOutputs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the input splitting
|
||||||
|
*/
|
||||||
|
public Splitter.Ports getInputSplit() {
|
||||||
|
return inputSplit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(CodePrinter out) throws IOException {
|
||||||
|
super.print(out);
|
||||||
|
int i = 0;
|
||||||
|
HDLPort o = getOutput();
|
||||||
|
for (Splitter.Port sp : inputSplit) {
|
||||||
|
HDLPort p = getInputs().get(i++);
|
||||||
|
out.print(o.getNet().getName())
|
||||||
|
.print("(").print(sp.getPos()).print("-").print(sp.getPos() + sp.getBits() - 1).print(")")
|
||||||
|
.print(" := ").println(p.getNet().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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.hdl.model2;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.wiring.Splitter;
|
||||||
|
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A One to Many splitter
|
||||||
|
*/
|
||||||
|
public class HDLNodeSplitterOneToMany extends HDLNode {
|
||||||
|
private final Splitter.Ports outputSplit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param node the original splitter node
|
||||||
|
* @param outputSplit output splitting
|
||||||
|
*/
|
||||||
|
HDLNodeSplitterOneToMany(HDLNode node, Splitter.Ports outputSplit) {
|
||||||
|
super(node.getElementName(), node.getElementAttributes(), null);
|
||||||
|
this.outputSplit = outputSplit;
|
||||||
|
getInputs().addAll(node.getInputs());
|
||||||
|
getOutputs().addAll(node.getOutputs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the output splitting
|
||||||
|
*/
|
||||||
|
public Splitter.Ports getOutputSplit() {
|
||||||
|
return outputSplit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(CodePrinter out) throws IOException {
|
||||||
|
super.print(out);
|
||||||
|
int i = 0;
|
||||||
|
HDLPort in = getInputs().get(0);
|
||||||
|
for (Splitter.Port sp : outputSplit) {
|
||||||
|
HDLPort p = getOutputs().get(i++);
|
||||||
|
out.print(p.getNet().getName()).print(" := ").print(in.getNet().getName())
|
||||||
|
.print("(").print(sp.getPos()).print("-").print(sp.getPos() + sp.getBits() - 1).println(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -124,4 +124,53 @@ public class HDLCircuitTest extends TestCase {
|
|||||||
"end circuit main\n", cp.toString());
|
"end circuit main\n", cp.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSplitter() throws IOException, PinException, HDLException, NodeException {
|
||||||
|
HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter.dig");
|
||||||
|
hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNaming());
|
||||||
|
|
||||||
|
CodePrinterStr cp = new CodePrinterStr();
|
||||||
|
hdl.print(cp);
|
||||||
|
assertEquals("circuit main\n" +
|
||||||
|
" in(A:4)\n" +
|
||||||
|
" out(X:2)\n" +
|
||||||
|
" sig(s0:2, s1:2)\n" +
|
||||||
|
"\n" +
|
||||||
|
" node Splitter\n" +
|
||||||
|
" in(0-3:4 is A:4)\n" +
|
||||||
|
" out(0,1:2 is s0:2, 2,3:2 is s1:2)\n" +
|
||||||
|
" s0 := A(0-1)\n" +
|
||||||
|
" s1 := A(2-3)\n" +
|
||||||
|
" node merged expression\n" +
|
||||||
|
" in(In_1:2 is s0:2, in:2 is s1:2)\n" +
|
||||||
|
" out(out:2 is X:2)\n" +
|
||||||
|
" X:2 := (s0:2 AND NOT s1:2)\n" +
|
||||||
|
"\n" +
|
||||||
|
"end circuit main\n", cp.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSplitter2() throws IOException, PinException, HDLException, NodeException {
|
||||||
|
HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter2.dig");
|
||||||
|
hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNaming());
|
||||||
|
|
||||||
|
CodePrinterStr cp = new CodePrinterStr();
|
||||||
|
hdl.print(cp);
|
||||||
|
assertEquals("circuit main\n" +
|
||||||
|
" in(A:2, B:2)\n" +
|
||||||
|
" out(X:1, Y:3)\n" +
|
||||||
|
" sig(s0:4)\n" +
|
||||||
|
"\n" +
|
||||||
|
" node Splitter\n" +
|
||||||
|
" in(0,1:2 is A:2, 2,3:2 is B:2)\n" +
|
||||||
|
" out(single:4 is s0:4)\n" +
|
||||||
|
" s0(0-1) := A\n" +
|
||||||
|
" s0(2-3) := B\n" +
|
||||||
|
" node Splitter\n" +
|
||||||
|
" in(single:4 is s0:4)\n" +
|
||||||
|
" out(0:1 is X:1, 1-3:3 is Y:3)\n" +
|
||||||
|
" X := s0(0-0)\n" +
|
||||||
|
" Y := s0(1-3)\n" +
|
||||||
|
"\n" +
|
||||||
|
"end circuit main\n", cp.toString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -57,7 +57,7 @@ public class TestInSimulator extends TestCase {
|
|||||||
File examples = new File(Resources.getRoot(), "/dig/hdl");
|
File examples = new File(Resources.getRoot(), "/dig/hdl");
|
||||||
try {
|
try {
|
||||||
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
|
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
|
||||||
assertEquals(33, tested);
|
assertEquals(34, tested);
|
||||||
} catch (FileScanner.SkipAllException e) {
|
} catch (FileScanner.SkipAllException e) {
|
||||||
// if ghdl is not installed its also ok
|
// if ghdl is not installed its also ok
|
||||||
}
|
}
|
||||||
|
104
src/test/resources/dig/hdl/model2/splitter2.dig
Normal file
104
src/test/resources/dig/hdl/model2/splitter2.dig
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<circuit>
|
||||||
|
<version>1</version>
|
||||||
|
<attributes/>
|
||||||
|
<visualElements>
|
||||||
|
<visualElement>
|
||||||
|
<elementName>Out</elementName>
|
||||||
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>Label</string>
|
||||||
|
<string>X</string>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Inputs</string>
|
||||||
|
<int>1</int>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="0" y="60"/>
|
||||||
|
</visualElement>
|
||||||
|
<visualElement>
|
||||||
|
<elementName>In</elementName>
|
||||||
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>Label</string>
|
||||||
|
<string>A</string>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Bits</string>
|
||||||
|
<int>2</int>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="-100" y="60"/>
|
||||||
|
</visualElement>
|
||||||
|
<visualElement>
|
||||||
|
<elementName>Splitter</elementName>
|
||||||
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>splitterSpreading</string>
|
||||||
|
<int>2</int>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Input Splitting</string>
|
||||||
|
<string>2,2</string>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Output Splitting</string>
|
||||||
|
<string>1,3</string>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="-60" y="60"/>
|
||||||
|
</visualElement>
|
||||||
|
<visualElement>
|
||||||
|
<elementName>In</elementName>
|
||||||
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>Label</string>
|
||||||
|
<string>B</string>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Bits</string>
|
||||||
|
<int>2</int>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="-100" y="100"/>
|
||||||
|
</visualElement>
|
||||||
|
<visualElement>
|
||||||
|
<elementName>Out</elementName>
|
||||||
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>Label</string>
|
||||||
|
<string>Y</string>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Bits</string>
|
||||||
|
<int>3</int>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<string>Inputs</string>
|
||||||
|
<int>1</int>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="0" y="100"/>
|
||||||
|
</visualElement>
|
||||||
|
</visualElements>
|
||||||
|
<wires>
|
||||||
|
<wire>
|
||||||
|
<p1 x="-100" y="100"/>
|
||||||
|
<p2 x="-60" y="100"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="-40" y="100"/>
|
||||||
|
<p2 x="0" y="100"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="-100" y="60"/>
|
||||||
|
<p2 x="-60" y="60"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="-40" y="60"/>
|
||||||
|
<p2 x="0" y="60"/>
|
||||||
|
</wire>
|
||||||
|
</wires>
|
||||||
|
<measurementOrdering/>
|
||||||
|
</circuit>
|
Loading…
x
Reference in New Issue
Block a user