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