Interface pins are now sorted
[Mograsim.git] / plugins / net.mograsim.logic.model.verilog / src / net / mograsim / logic / model / verilog / converter / components / SubmodelComponentConverter.java
1 package net.mograsim.logic.model.verilog.converter.components;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Map.Entry;
8 import java.util.Set;
9 import java.util.stream.Collectors;
10
11 import com.google.gson.JsonElement;
12
13 import net.mograsim.logic.core.types.Bit;
14 import net.mograsim.logic.core.types.BitVector;
15 import net.mograsim.logic.model.model.components.ModelComponent;
16 import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
17 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
18 import net.mograsim.logic.model.model.wires.ModelWire;
19 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
20 import net.mograsim.logic.model.model.wires.Pin;
21 import net.mograsim.logic.model.verilog.converter.ComponentConversionResult;
22 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
23 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter;
24 import net.mograsim.logic.model.verilog.converter.PinBit;
25 import net.mograsim.logic.model.verilog.converter.PinNameBit;
26 import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
27 import net.mograsim.logic.model.verilog.model.expressions.Constant;
28 import net.mograsim.logic.model.verilog.model.expressions.Expression;
29 import net.mograsim.logic.model.verilog.model.expressions.SignalReference;
30 import net.mograsim.logic.model.verilog.model.signals.Signal;
31 import net.mograsim.logic.model.verilog.model.signals.Wire;
32 import net.mograsim.logic.model.verilog.model.statements.Assign;
33 import net.mograsim.logic.model.verilog.model.statements.ComponentReference;
34 import net.mograsim.logic.model.verilog.model.statements.Statement;
35 import net.mograsim.logic.model.verilog.model.statements.WireDeclaration;
36 import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
37 import net.mograsim.logic.model.verilog.utils.UnionFind;
38
39 public class SubmodelComponentConverter implements ComponentConverter<SubmodelComponent>
40 {
41         private final ModelComponentToVerilogConverter converter;
42
43         public SubmodelComponentConverter(ModelComponentToVerilogConverter converter)
44         {
45                 this.converter = converter;
46         }
47
48         @Override
49         public ComponentConversionResult convert(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID)
50         {
51                 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
52                         if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
53                                 converter.convert(subcomponent);
54
55                 UnionFind<PinBit> connectedPins = findConnectedPins(modelComponent);
56
57                 ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params,
58                                 verilogID);
59
60                 VerilogComponentImplementation implementation = mapImplementation(modelComponent, connectedPins, mapping);
61
62                 return new ComponentConversionResult(mapping, implementation);
63         }
64
65         private UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
66         {
67                 UnionFind<PinBit> connectedPins = new UnionFind<>();
68                 for (ModelWire w : modelComponent.submodel.getWiresByName().values())
69                         for (int bit = 0; bit < w.getPin1().logicWidth; bit++)
70                                 connectedPins.union(new PinBit(w.getPin1(), bit), new PinBit(w.getPin2(), bit));
71
72                 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
73                         if (subcomponent instanceof ModelSplitter)
74                         {
75                                 ModelSplitter splitter = (ModelSplitter) subcomponent;
76                                 for (int bit = 0; bit < splitter.logicWidth; bit++)
77                                         connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0));
78                         } else if (!(subcomponent instanceof ModelWireCrossPoint)
79                                         && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
80                         {
81                                 ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
82                                 for (Set<PinNameBit> connected : subcomponentMapping.getInternallyConnectedPins())
83                                         connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList()));
84                         }
85
86                 return connectedPins;
87         }
88
89         private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
90                         UnionFind<PinBit> connectedPins, String modelID, JsonElement params, String verilogID)
91         {
92                 // TODO this is probably slow
93                 Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
94                 UnionFind<PinNameBit> connectedPinsByName = new UnionFind<>();
95                 for (Pin p : modelComponent.getSubmodelPins().values())
96                         for (int bit = 0; bit < p.logicWidth; bit++)
97                         {
98                                 PinNameBit pinnamebit = new PinNameBit(p.name, bit);
99                                 PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit);
100                                 connectedPinsByName.union(pinnamebit, representative);
101                         }
102
103                 return ModelComponentToVerilogConverter.generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params,
104                                 verilogID);
105         }
106
107         private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind<PinBit> connectedPins,
108                         ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
109         {
110                 Map<PinBit, Expression> currentPreExprs = new HashMap<>();
111                 Map<PinBit, Signal> finalOutSignals = new HashMap<>();
112                 Map<PinBit, Expression> resExprs = new HashMap<>();
113                 for (Set<PinNameBit> connectedPinGroup : declarationMapping.getInternallyConnectedPins())
114                 {
115                         PinNameBit pinnamebit = connectedPinGroup.iterator().next();
116                         PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent));
117                         resExprs.put(root, new SignalReference(declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()));
118                         finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort());
119                         currentPreExprs.put(root, new SignalReference(declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort()));
120                 }
121
122                 IdentifierGenerator idGen = ModelComponentToVerilogConverter
123                                 .generateIdentifierGenerator(declarationMapping.getVerilogComponentDeclaration());
124                 List<Statement> statements = new ArrayList<>();
125                 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
126                 {
127                         // TODO do we really want to use instanceof?
128                         if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint
129                                         || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
130                                 continue;
131
132                         String subcomponentVerilogName = idGen.generateID(subcomponent.getName());
133                         ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
134                         int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size();
135                         List<Expression> arguments = new ArrayList<>(parameterCount);
136                         for (int i = 0; i < parameterCount; i++)
137                                 arguments.add(null);
138                         for (Pin pin : subcomponent.getPins().values())
139                                 for (int bit = 0; bit < pin.logicWidth; bit++)
140                                 {
141                                         PinBit pinbit = new PinBit(pin, bit);
142                                         PinBit root = connectedPins.find(pinbit);
143                                         Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
144                                         statements.add(new WireDeclaration(outSignal));
145                                         Expression preExpr = currentPreExprs.put(root, new SignalReference(outSignal));
146                                         Expression outExpr = new SignalReference(outSignal);
147                                         Expression resExpr = resExprs.get(root);
148                                         if (resExpr == null)
149                                         {
150                                                 preExpr = new Constant(BitVector.of(Bit.ZERO, 2));
151                                                 Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2);
152                                                 resExpr = new SignalReference(resWire);
153                                                 statements.add(new WireDeclaration(resWire));
154                                                 finalOutSignals.put(root, resWire);
155                                                 resExprs.put(root, resExpr);
156                                         }
157                                         PinNameBit pinnamebit = pinbit.toPinNameBit();
158                                         arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preExpr);
159                                         arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outExpr);
160                                         arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resExpr);
161                                 }
162                         statements
163                                         .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments));
164                 }
165
166                 for (Entry<PinBit, Signal> e : finalOutSignals.entrySet())
167                         statements.add(new Assign(e.getValue(), currentPreExprs.get(e.getKey())));
168
169                 return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements);
170         }
171 }