1 /* 2 * Copyright (c) 2018 Helmut Neemann. 3 * Use of this source code is governed by the GPL v3 license 4 * that can be found in the LICENSE file. 5 */ 6 package de.neemann.digital.hdl.model2.optimizations; 7 8 import de.neemann.digital.hdl.model2.*; 9 import de.neemann.digital.hdl.model2.expression.ExprVarRange; 10 import de.neemann.digital.hdl.model2.expression.Expression; 11 import de.neemann.digital.hdl.model2.expression.Visitor; 12 13 import java.util.ArrayList; 14 15 /** 16 * Merges the bool expression by inlining nodes which also represent a bool expression. 17 */ 18 public class MergeAssignments implements Optimization { 19 private HDLCircuit circuit; 20 private ArrayList<HDLNode> nodes; 21 22 @Override optimize(HDLCircuit circuit)23 public void optimize(HDLCircuit circuit) { 24 this.circuit = circuit; 25 this.nodes = circuit.getNodes(); 26 27 boolean wasOptimization; 28 do { 29 wasOptimization = false; 30 outer: 31 for (int i = 0; i < nodes.size(); i++) { 32 HDLNode n1 = nodes.get(i); 33 if (n1 instanceof HDLNodeAssignment) { 34 HDLNodeAssignment host = (HDLNodeAssignment) n1; 35 for (HDLPort p : host.getInputs()) { 36 HDLNode n2 = searchCreator(p.getNet()); 37 if (n2 != null && n2 instanceof HDLNodeAssignment) { 38 HDLNodeAssignment include = (HDLNodeAssignment) n2; 39 if (include.getOutputs().size() == 1 && include.getOutput().getNet().getInputs().size() == 1) { 40 if (allowedToReplaceNet(host.getExpression(), include.getOutput().getNet())) { 41 nodes.set(i, merge(host, include)); 42 nodes.remove(n2); 43 wasOptimization = true; 44 break outer; 45 } 46 } 47 } 48 } 49 } 50 } 51 } while (wasOptimization); 52 } 53 allowedToReplaceNet(Expression expression, HDLNet net)54 private boolean allowedToReplaceNet(Expression expression, HDLNet net) { 55 final CheckVarRangeVisitor visitor = new CheckVarRangeVisitor(net); 56 expression.traverse(visitor); 57 return visitor.ok; 58 } 59 merge(HDLNodeAssignment host, HDLNodeAssignment include)60 private HDLNodeAssignment merge(HDLNodeAssignment host, HDLNodeAssignment include) { 61 final Expression expression = host.getExpression(); 62 final HDLNet obsoleteNet = include.getOutput().getNet(); 63 expression.replace(obsoleteNet, include.getExpression()); 64 65 HDLNodeAssignment node = new HDLNodeAssignment("merged expression", 66 null, name -> host.getOutput().getBits()); 67 node.setExpression(expression); 68 69 circuit.removeNet(obsoleteNet); 70 71 node.addPort(host.getOutput()); 72 for (HDLPort i : host.getInputs()) 73 if (i.getNet() != obsoleteNet) 74 node.addPort(i); 75 76 for (HDLPort i : include.getInputs()) 77 if (!node.hasInput(i)) 78 node.addPort(i); 79 else 80 i.getNet().remove(i); 81 82 return node; 83 } 84 searchCreator(HDLNet net)85 private HDLNode searchCreator(HDLNet net) { 86 for (HDLNode n : nodes) 87 for (HDLPort p : n.getOutputs()) 88 if (p.getNet() == net) 89 return n; 90 return null; 91 } 92 93 private static final class CheckVarRangeVisitor implements Visitor { 94 private final HDLNet net; 95 private boolean ok; 96 CheckVarRangeVisitor(HDLNet net)97 private CheckVarRangeVisitor(HDLNet net) { 98 this.net = net; 99 ok = true; 100 } 101 102 @Override visit(Expression expression)103 public void visit(Expression expression) { 104 if (expression instanceof ExprVarRange) { 105 ExprVarRange evr = (ExprVarRange) expression; 106 if (evr.getNet() == net) 107 ok = false; 108 } 109 } 110 } 111 } 112