1 package net.mograsim.logic.model.verilog.converter;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.HashSet;
10 import java.util.function.BiFunction;
11 import java.util.function.Function;
12 import java.util.stream.Collectors;
14 import com.google.gson.JsonElement;
16 import net.mograsim.logic.model.model.components.ModelComponent;
17 import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
18 import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
19 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
20 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
21 import net.mograsim.logic.model.model.wires.Pin;
22 import net.mograsim.logic.model.serializing.IdentifyParams;
23 import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
24 import net.mograsim.logic.model.verilog.converter.components.SubmodelComponentConverter;
25 import net.mograsim.logic.model.verilog.converter.components.TriStateBufferConverter;
26 import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
27 import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
28 import net.mograsim.logic.model.verilog.model.signals.IOPort;
29 import net.mograsim.logic.model.verilog.model.signals.Input;
30 import net.mograsim.logic.model.verilog.model.signals.Output;
31 import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
32 import net.mograsim.logic.model.verilog.utils.UnionFind;
34 public class ModelComponentToVerilogConverter
36 private final String verilogComponentIDPrefix;
37 private final Map<String, Map<JsonElement, ModelComponentToVerilogComponentDeclarationMapping>> componentMappingsPerModelIDPerParams;
38 private final Set<VerilogComponentImplementation> verilogComponents;
39 private final IdentifierGenerator verilogComponentIDGen;
41 public ModelComponentToVerilogConverter(String verilogComponentIDPrefix,
42 Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings)
44 this.verilogComponentIDPrefix = verilogComponentIDPrefix;
45 this.componentMappingsPerModelIDPerParams = new HashMap<>(atomicComponentMappings.stream().collect(Collectors
46 .groupingBy(m -> m.getModelComponentID(), Collectors.toMap(m -> m.getModelComponentParams(), Function.identity()))));
47 this.verilogComponents = new HashSet<>();
48 this.verilogComponentIDGen = new IdentifierGenerator(
49 componentMappingsPerModelIDPerParams.values().stream().map(Map::values).flatMap(Collection::stream)
50 .map(ModelComponentToVerilogComponentDeclarationMapping::getVerilogComponentDeclaration)
51 .map(VerilogComponentDeclaration::getID).collect(Collectors.toSet()),
52 ModelComponentToVerilogConverter::sanitizeVerilogID);
55 public void convert(ModelComponent modelComponent)
57 // these are handled elsewhere
58 if (modelComponent instanceof ModelSplitter || modelComponent instanceof ModelWireCrossPoint)
61 String modelID = modelComponent.getIDForSerializing(new IdentifyParams());
62 JsonElement params = modelComponent.getParamsForSerializingJSON(new IdentifyParams());
63 if (componentMappingsPerModelIDPerParams.getOrDefault(modelID, Map.of()).containsKey(params))
64 // we already converted that component, or it was specified externally
67 String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params));
69 ComponentConversionResult result;
70 // TODO don't rely on instanceof
72 if (modelComponent instanceof SubmodelComponent)
73 result = new SubmodelComponentConverter(this).convert((SubmodelComponent) modelComponent, modelID, params, verilogID);
74 else if (modelComponent instanceof ModelTriStateBuffer)
75 result = new TriStateBufferConverter().convert((ModelTriStateBuffer) modelComponent, modelID, params, verilogID);
77 throw new IllegalArgumentException(
78 "Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params);
80 componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, result.getMapping());
81 verilogComponents.add(result.getImplementation());
84 public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
85 UnionFind<PinNameBit> connectedPins, String modelID, JsonElement params, String verilogID)
87 IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID);
88 List<IOPort> ioPorts = new ArrayList<>();
89 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping = new HashMap<>();
90 for (Type t : Type.values())
91 pinMapping.put(t, new HashMap<>());
92 for (Pin modelPin : modelComponent.getPins().values())
93 for (int bit = 0; bit < modelPin.logicWidth; bit++)
95 PinNameBit pinbit = new PinNameBit(modelPin.name, bit);
96 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.PRE, "pre");
97 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Output::new, Type.OUT, "out");
98 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.RES, "res");
101 VerilogComponentDeclaration declaration = new VerilogComponentDeclaration(verilogID, ioPorts);
102 Set<VerilogEmulatedModelPin> finalPinMapping = pinMapping.values().stream().map(Map::values).flatMap(Collection::stream)
103 .map(VerilogEmulatedModelPinBuilder::build).collect(Collectors.toSet());
104 return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, finalPinMapping);
107 private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, UnionFind<PinNameBit> connectedPins,
108 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping, PinNameBit pinbit,
109 BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
111 Map<PinNameBit, VerilogEmulatedModelPinBuilder> pinMappingCorrectType = pinMapping.get(type);
112 pinMappingCorrectType.computeIfAbsent(connectedPins.find(pinbit), p ->
114 String portID = ioPortIDGen.generateID(p.getName() + "_" + p.getBit() + "_" + suffix);
115 IOPort ioPort = constr.apply(portID, 2);
116 int index = ioPorts.size();
118 return new VerilogEmulatedModelPinBuilder(ioPort, index, type);
119 }).addPinbit(pinbit);
122 private static class VerilogEmulatedModelPinBuilder
124 private final IOPort verilogPort;
125 private final int portIndex;
126 private final Set<PinNameBit> pinbits;
127 private final Type type;
129 public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type)
131 this.verilogPort = verilogPort;
132 this.portIndex = portIndex;
133 this.pinbits = new HashSet<>();
137 public void addPinbit(PinNameBit pinbit)
142 public VerilogEmulatedModelPin build()
144 return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type);
148 public ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component)
150 ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams
151 .get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams()));
152 return subcomponentMapping;
155 public Set<VerilogComponentImplementation> getVerilogComponents()
157 return verilogComponents;
160 public static Set<VerilogComponentImplementation> convert(
161 Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings, Set<ModelComponent> components,
162 String verilogComponentIDPrefix)
164 ModelComponentToVerilogConverter converter = new ModelComponentToVerilogConverter(verilogComponentIDPrefix,
165 atomicComponentMappings);
166 for (ModelComponent modelComponent : components)
167 converter.convert(modelComponent);
168 return converter.getVerilogComponents();
171 public static IdentifierGenerator generateIdentifierGenerator(VerilogComponentDeclaration declaration)
173 IdentifierGenerator idGen = new IdentifierGenerator(
174 declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
175 ModelComponentToVerilogConverter::sanitizeVerilogID);
179 public static String sanitizeVerilogID(String id)
181 return (id.matches("[0-9].*") ? "_" + id : id).replaceAll("[^A-Za-z0-9_]", "_");