added a node sorter

This commit is contained in:
hneemann 2018-03-24 19:23:39 +01:00
parent 57228748d4
commit 28dc6a583d
4 changed files with 102 additions and 16 deletions

View File

@ -122,6 +122,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
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);
nodes = new NodeSorter(inputs, nodes).sort();
} }
private void handleSplitter(HDLNode node) throws BitsException, HDLException { private void handleSplitter(HDLNode node) throws BitsException, HDLException {

View File

@ -0,0 +1,85 @@
/*
* 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 java.util.ArrayList;
import java.util.HashSet;
/**
* Used to sort the nodes in a more "human typical" order.
* Sorts the nodes from the input side to the output side.
*/
public class NodeSorter {
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLNode> nodes;
/**
* Creates a new instance.
*
* @param inputs the initial inputs
* @param nodes the nodes to sort
*/
public NodeSorter(ArrayList<HDLPort> inputs, ArrayList<HDLNode> nodes) {
this.inputs = inputs;
this.nodes = nodes;
}
/**
* Performs the sorting and returns a sorted list.
*
* @return the sorted list
*/
public ArrayList<HDLNode> sort() {
HashSet<HDLNet> nets = new HashSet<>();
for (HDLPort p : inputs)
nets.add(p.getNet());
ArrayList<HDLNode> newOrder = new ArrayList<>();
// all nodes without an input at top!
for (HDLNode n : nodes)
if (n.getInputs().isEmpty()) {
newOrder.add(n);
for (HDLPort p : n.getOutputs())
if (p.getNet() != null)
nets.add(p.getNet());
}
nodes.removeAll(newOrder);
// than a layer sorting
while (!nodes.isEmpty()) {
ArrayList<HDLNode> layer = new ArrayList<>();
for (HDLNode n : nodes) {
if (dependsOnlyOn(n, nets))
layer.add(n);
}
if (layer.isEmpty())
break;
newOrder.addAll(layer);
nodes.removeAll(layer);
for (HDLNode n : layer)
for (HDLPort p : n.getOutputs())
if (p.getNet() != null)
nets.add(p.getNet());
}
// if there are circular dependencies, keep old order
if (!nodes.isEmpty())
newOrder.addAll(nodes);
return newOrder;
}
private boolean dependsOnlyOn(HDLNode n, HashSet<HDLNet> nets) {
for (HDLPort p : n.getInputs())
if (!nets.contains(p.getNet()))
return false;
return true;
}
}

View File

@ -40,25 +40,25 @@ public class HDLCircuitTest extends TestCase {
" out(X:1, Y:1, Z:1, Aident:1)\n" + " out(X:1, Y:1, Z:1, Aident:1)\n" +
" sig(Y_temp:1, s0:1, Z_temp:1, s1:1)\n" + " sig(Y_temp:1, s0:1, Z_temp:1, s1:1)\n" +
"\n" + "\n" +
" node merged expression\n" +
" in(In_5:1 is Y_temp:1, In_1:1 is A:1, In_2:1 is C:1, In_1:1 is Z_temp:1, In_1:1 is B:1)\n" +
" out(out:1 is s0:1)\n" +
" s0:1 := ((A:1 OR C:1) AND (Z_temp:1 OR C:1) AND 1:1 AND NOT (B:1 OR C:1) AND Y_temp:1)\n" +
" node merged expression\n" +
" in(In_1:1 is B:1, in:1 is C:1)\n" +
" out(out:1 is Y_temp:1)\n" +
" Y_temp:1 := (B:1 OR NOT C:1)\n" +
" node Not\n" +
" in(in:1 is A:1)\n" +
" out(out:1 is Z_temp:1)\n" +
" Z_temp:1 := NOT A:1\n" +
" node D_FF\n" +
" in(D:1 is s0:1, C:1 is s1:1)\n" +
" out(Q:1 is X:1, ~Q:1 is not used)\n" +
" node Const\n" + " node Const\n" +
" in()\n" + " in()\n" +
" out(out:1 is s1:1)\n" + " out(out:1 is s1:1)\n" +
" s1:1 := 1:1\n" + " s1:1 := 1:1\n" +
" node Not\n" +
" in(in:1 is A:1)\n" +
" out(out:1 is Z_temp:1)\n" +
" Z_temp:1 := NOT A:1\n" +
" node merged expression\n" +
" in(In_1:1 is B:1, in:1 is C:1)\n" +
" out(out:1 is Y_temp:1)\n" +
" Y_temp:1 := (B:1 OR NOT C:1)\n" +
" node merged expression\n" +
" in(In_5:1 is Y_temp:1, In_1:1 is A:1, In_2:1 is C:1, In_1:1 is Z_temp:1, In_1:1 is B:1)\n" +
" out(out:1 is s0:1)\n" +
" s0:1 := ((A:1 OR C:1) AND (Z_temp:1 OR C:1) AND 1:1 AND NOT (B:1 OR C:1) AND Y_temp:1)\n" +
" node D_FF\n" +
" in(D:1 is s0:1, C:1 is s1:1)\n" +
" out(Q:1 is X:1, ~Q:1 is not used)\n" +
"\n" + "\n" +
" Y:1 := Y_temp:1\n" + " Y:1 := Y_temp:1\n" +
" Z:1 := Z_temp:1\n" + " Z:1 := Z_temp:1\n" +

View File

@ -40,7 +40,7 @@ public class VHDLGeneratorTest extends TestCase {
/* /*
public void testDebug() throws Exception { public void testDebug() throws Exception {
File file = new File(Resources.getRoot(), "dig/hdl/splitter2.dig"); File file = new File(Resources.getRoot(), "../../main/dig/processor/VHDLExample.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()));