added splitter to new model

This commit is contained in:
hneemann 2018-03-23 18:54:46 +01:00
parent 3abfbe460b
commit 366535ace6
7 changed files with 293 additions and 2 deletions

View File

@ -5,6 +5,7 @@
*/
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.BitsException;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.basic.Not;
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.wiring.Break;
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.model.InverterConfig;
import de.neemann.digital.draw.model.Net;
@ -77,6 +79,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider, Pr
HDLPort.Direction.IN,
v.getElementAttributes().getBits())
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)));
else if (v.equalsDescription(Splitter.DESCRIPTION))
handleSplitter(c.createNode(v, this));
else if (isRealElement(v))
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 {
final ElementAttributes attr = new ElementAttributes().setBits(p.getBits());
HDLNodeExpression n = new HDLNodeExpression(Not.DESCRIPTION.getName(), attr, name -> p.getBits());

View File

@ -22,7 +22,7 @@ public class HDLNode {
private final ArrayList<HDLPort> outputs;
/**
* Creates e new intance
* Creates e new instance
*
* @param elementName the instances name
* @param elementAttributes the attributes

View File

@ -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());
}
}
}

View File

@ -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(")");
}
}
}

View File

@ -124,4 +124,53 @@ public class HDLCircuitTest extends TestCase {
"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());
}
}

View File

@ -57,7 +57,7 @@ public class TestInSimulator extends TestCase {
File examples = new File(Resources.getRoot(), "/dig/hdl");
try {
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
assertEquals(33, tested);
assertEquals(34, tested);
} catch (FileScanner.SkipAllException e) {
// if ghdl is not installed its also ok
}

View 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>