From 28dc6a583dad7a35ebc81d200fd4b4928ea091db Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 24 Mar 2018 19:23:39 +0100 Subject: [PATCH] added a node sorter --- .../digital/hdl/model2/HDLCircuit.java | 1 + .../digital/hdl/model2/NodeSorter.java | 85 +++++++++++++++++++ .../digital/hdl/model2/HDLCircuitTest.java | 30 +++---- .../digital/hdl/vhdl2/VHDLGeneratorTest.java | 2 +- 4 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 src/main/java/de/neemann/digital/hdl/model2/NodeSorter.java diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java index 99e2e85b5..04b0a18aa 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -122,6 +122,7 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin if (o.getNet().needsVariable()) o.getNet().setIsOutput(o.getName(), o.getNet().getInputs().size() == 1); + nodes = new NodeSorter(inputs, nodes).sort(); } private void handleSplitter(HDLNode node) throws BitsException, HDLException { diff --git a/src/main/java/de/neemann/digital/hdl/model2/NodeSorter.java b/src/main/java/de/neemann/digital/hdl/model2/NodeSorter.java new file mode 100644 index 000000000..7aa9149a1 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/NodeSorter.java @@ -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 inputs; + private final ArrayList nodes; + + /** + * Creates a new instance. + * + * @param inputs the initial inputs + * @param nodes the nodes to sort + */ + public NodeSorter(ArrayList inputs, ArrayList nodes) { + this.inputs = inputs; + this.nodes = nodes; + } + + /** + * Performs the sorting and returns a sorted list. + * + * @return the sorted list + */ + public ArrayList sort() { + HashSet nets = new HashSet<>(); + for (HDLPort p : inputs) + nets.add(p.getNet()); + + ArrayList 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 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 nets) { + for (HDLPort p : n.getInputs()) + if (!nets.contains(p.getNet())) + return false; + return true; + } +} diff --git a/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java b/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java index 13cf183dc..8ae3a7573 100644 --- a/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java +++ b/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java @@ -40,25 +40,25 @@ public class HDLCircuitTest extends TestCase { " out(X:1, Y:1, Z:1, Aident:1)\n" + " sig(Y_temp:1, s0:1, Z_temp:1, s1:1)\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" + " in()\n" + " out(out:1 is s1: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" + " Y:1 := Y_temp:1\n" + " Z:1 := Z_temp:1\n" + diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java index 4c68799fb..319a851ce 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java @@ -40,7 +40,7 @@ public class VHDLGeneratorTest extends TestCase { /* 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); System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));