1 package net.mograsim.logic.model.verilog.converter.components;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.HashSet;
9 import java.util.Map.Entry;
11 import java.util.function.BiFunction;
12 import java.util.stream.Collectors;
14 import com.google.gson.JsonElement;
16 import net.mograsim.logic.core.types.Bit;
17 import net.mograsim.logic.core.types.BitVector;
18 import net.mograsim.logic.model.model.components.ModelComponent;
19 import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
20 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
21 import net.mograsim.logic.model.model.wires.ModelWire;
22 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
23 import net.mograsim.logic.model.model.wires.Pin;
24 import net.mograsim.logic.model.verilog.converter.ComponentConversionResult;
25 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
26 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter;
27 import net.mograsim.logic.model.verilog.converter.PinBit;
28 import net.mograsim.logic.model.verilog.converter.PinNameBit;
29 import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin;
30 import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
31 import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
32 import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
33 import net.mograsim.logic.model.verilog.model.expressions.Constant;
34 import net.mograsim.logic.model.verilog.model.expressions.Expression;
35 import net.mograsim.logic.model.verilog.model.expressions.SignalReference;
36 import net.mograsim.logic.model.verilog.model.signals.IOPort;
37 import net.mograsim.logic.model.verilog.model.signals.Input;
38 import net.mograsim.logic.model.verilog.model.signals.Output;
39 import net.mograsim.logic.model.verilog.model.signals.Signal;
40 import net.mograsim.logic.model.verilog.model.signals.Wire;
41 import net.mograsim.logic.model.verilog.model.statements.Assign;
42 import net.mograsim.logic.model.verilog.model.statements.ComponentReference;
43 import net.mograsim.logic.model.verilog.model.statements.Statement;
44 import net.mograsim.logic.model.verilog.model.statements.WireDeclaration;
45 import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
46 import net.mograsim.logic.model.verilog.utils.UnionFind;
48 public class SubmodelComponentConverter implements ComponentConverter<SubmodelComponent>
50 private final ModelComponentToVerilogConverter converter;
52 public SubmodelComponentConverter(ModelComponentToVerilogConverter converter)
54 this.converter = converter;
58 public ComponentConversionResult convert(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID)
60 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
61 if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
62 converter.convert(subcomponent);
64 UnionFind<PinBit> connectedPins = findConnectedPins(modelComponent);
66 ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params,
69 VerilogComponentImplementation implementation = mapImplementation(modelComponent, connectedPins, mapping);
71 return new ComponentConversionResult(mapping, implementation);
74 private UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
76 UnionFind<PinBit> connectedPins = new UnionFind<>();
77 for (ModelWire w : modelComponent.submodel.getWiresByName().values())
78 for (int bit = 0; bit < w.getPin1().logicWidth; bit++)
79 connectedPins.union(new PinBit(w.getPin1(), bit), new PinBit(w.getPin2(), bit));
81 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
82 if (subcomponent instanceof ModelSplitter)
84 ModelSplitter splitter = (ModelSplitter) subcomponent;
85 for (int bit = 0; bit < splitter.logicWidth; bit++)
86 connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0));
87 } else if (!(subcomponent instanceof ModelWireCrossPoint)
88 && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
90 ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
91 for (Set<PinNameBit> connected : subcomponentMapping.getInternallyConnectedPins())
92 connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList()));
98 private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
99 UnionFind<PinBit> connectedPins, String modelID, JsonElement params, String verilogID)
101 // TODO this is probably slow
102 Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
103 UnionFind<PinNameBit> connectedPinsByName = new UnionFind<>();
104 for (Pin p : modelComponent.getSubmodelPins().values())
105 for (int bit = 0; bit < p.logicWidth; bit++)
107 PinNameBit pinnamebit = new PinNameBit(p.name, bit);
108 PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit);
109 connectedPinsByName.union(pinnamebit, representative);
112 return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID);
115 public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
116 UnionFind<PinNameBit> connectedPins, String modelID, JsonElement params, String verilogID)
118 IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID);
119 List<IOPort> ioPorts = new ArrayList<>();
120 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping = new HashMap<>();
121 for (Type t : Type.values())
122 pinMapping.put(t, new HashMap<>());
123 for (Pin modelPin : modelComponent.getPins().values())
124 for (int bit = 0; bit < modelPin.logicWidth; bit++)
126 PinNameBit pinbit = new PinNameBit(modelPin.name, bit);
127 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.PRE, "pre");
128 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Output::new, Type.OUT, "out");
129 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.RES, "res");
132 VerilogComponentDeclaration declaration = new VerilogComponentDeclaration(verilogID, ioPorts);
133 Set<VerilogEmulatedModelPin> finalPinMapping = pinMapping.values().stream().map(Map::values).flatMap(Collection::stream)
134 .map(VerilogEmulatedModelPinBuilder::build).collect(Collectors.toSet());
135 return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, finalPinMapping);
138 private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, UnionFind<PinNameBit> connectedPins,
139 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping, PinNameBit pinbit,
140 BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
142 Map<PinNameBit, VerilogEmulatedModelPinBuilder> pinMappingCorrectType = pinMapping.get(type);
143 pinMappingCorrectType.computeIfAbsent(connectedPins.find(pinbit), p ->
145 String portID = ioPortIDGen.generateID(p.getName() + "_" + p.getBit() + "_" + suffix);
146 IOPort ioPort = constr.apply(portID, 2);
147 int index = ioPorts.size();
149 return new VerilogEmulatedModelPinBuilder(ioPort, index, type);
150 }).addPinbit(pinbit);
153 private static class VerilogEmulatedModelPinBuilder
155 private final IOPort verilogPort;
156 private final int portIndex;
157 private final Set<PinNameBit> pinbits;
158 private final Type type;
160 public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type)
162 this.verilogPort = verilogPort;
163 this.portIndex = portIndex;
164 this.pinbits = new HashSet<>();
168 public void addPinbit(PinNameBit pinbit)
173 public VerilogEmulatedModelPin build()
175 return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type);
179 private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind<PinBit> connectedPins,
180 ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
182 Map<PinBit, Expression> currentPreExprs = new HashMap<>();
183 Map<PinBit, Signal> finalOutSignals = new HashMap<>();
184 Map<PinBit, Expression> resExprs = new HashMap<>();
185 for (Set<PinNameBit> connectedPinGroup : declarationMapping.getInternallyConnectedPins())
187 PinNameBit pinnamebit = connectedPinGroup.iterator().next();
188 PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent));
189 resExprs.put(root, new SignalReference(declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()));
190 finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort());
191 currentPreExprs.put(root, new SignalReference(declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort()));
194 IdentifierGenerator idGen = ModelComponentToVerilogConverter
195 .generateIdentifierGenerator(declarationMapping.getVerilogComponentDeclaration());
196 List<Statement> statements = new ArrayList<>();
197 for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
199 // TODO do we really want to use instanceof?
200 if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint
201 || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
204 String subcomponentVerilogName = idGen.generateID(subcomponent.getName());
205 ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
206 int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size();
207 List<Expression> arguments = new ArrayList<>(parameterCount);
208 for (int i = 0; i < parameterCount; i++)
210 for (Pin pin : subcomponent.getPins().values())
211 for (int bit = 0; bit < pin.logicWidth; bit++)
213 PinBit pinbit = new PinBit(pin, bit);
214 PinBit root = connectedPins.find(pinbit);
215 Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
216 statements.add(new WireDeclaration(outSignal));
217 Expression preExpr = currentPreExprs.put(root, new SignalReference(outSignal));
218 Expression outExpr = new SignalReference(outSignal);
219 Expression resExpr = resExprs.get(root);
222 preExpr = new Constant(BitVector.of(Bit.ZERO, 2));
223 Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2);
224 resExpr = new SignalReference(resWire);
225 statements.add(new WireDeclaration(resWire));
226 finalOutSignals.put(root, resWire);
227 resExprs.put(root, resExpr);
229 PinNameBit pinnamebit = pinbit.toPinNameBit();
230 arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preExpr);
231 arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outExpr);
232 arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resExpr);
235 .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments));
238 for (Entry<PinBit, Signal> e : finalOutSignals.entrySet())
239 statements.add(new Assign(e.getValue(), currentPreExprs.get(e.getKey())));
241 return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements);