1 package net.mograsim.logic.model.verilog.converter;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Comparator;
6 import java.util.HashMap;
7 import java.util.HashSet;
11 import java.util.function.BiFunction;
12 import java.util.function.Function;
13 import java.util.stream.Collectors;
15 import com.google.gson.JsonElement;
17 import net.mograsim.logic.model.model.components.ModelComponent;
18 import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
19 import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
20 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
21 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
22 import net.mograsim.logic.model.model.wires.Pin;
23 import net.mograsim.logic.model.serializing.IdentifyParams;
24 import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
25 import net.mograsim.logic.model.verilog.converter.components.SubmodelComponentConverter;
26 import net.mograsim.logic.model.verilog.converter.components.TriStateBufferConverter;
27 import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
28 import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
29 import net.mograsim.logic.model.verilog.model.signals.IOPort;
30 import net.mograsim.logic.model.verilog.model.signals.Input;
31 import net.mograsim.logic.model.verilog.model.signals.Output;
32 import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
33 import net.mograsim.logic.model.verilog.utils.UnionFind;
35 public class ModelComponentToVerilogConverter
37 private final String verilogComponentIDPrefix;
38 private final Map<String, Map<JsonElement, ModelComponentToVerilogComponentDeclarationMapping>> componentMappingsPerModelIDPerParams;
39 private final Set<VerilogComponentImplementation> verilogComponents;
40 private final IdentifierGenerator verilogComponentIDGen;
42 public ModelComponentToVerilogConverter(String verilogComponentIDPrefix,
43 Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings)
45 this.verilogComponentIDPrefix = verilogComponentIDPrefix;
46 this.componentMappingsPerModelIDPerParams = new HashMap<>(atomicComponentMappings.stream().collect(Collectors
47 .groupingBy(m -> m.getModelComponentID(), Collectors.toMap(m -> m.getModelComponentParams(), Function.identity()))));
48 this.verilogComponents = new HashSet<>();
49 this.verilogComponentIDGen = new IdentifierGenerator(
50 componentMappingsPerModelIDPerParams.values().stream().map(Map::values).flatMap(Collection::stream)
51 .map(ModelComponentToVerilogComponentDeclarationMapping::getVerilogComponentDeclaration)
52 .map(VerilogComponentDeclaration::getID).collect(Collectors.toSet()),
53 ModelComponentToVerilogConverter::sanitizeVerilogID);
56 public void convert(ModelComponent modelComponent)
58 // these are handled elsewhere
59 if (modelComponent instanceof ModelSplitter || modelComponent instanceof ModelWireCrossPoint)
62 String modelID = modelComponent.getIDForSerializing(new IdentifyParams());
63 JsonElement params = modelComponent.getParamsForSerializingJSON(new IdentifyParams());
64 if (componentMappingsPerModelIDPerParams.getOrDefault(modelID, Map.of()).containsKey(params))
65 // we already converted that component, or it was specified externally
68 String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params));
70 ComponentConversionResult result;
71 // TODO don't rely on instanceof
73 if (modelComponent instanceof SubmodelComponent)
74 result = new SubmodelComponentConverter(this).convert((SubmodelComponent) modelComponent, modelID, params, verilogID);
75 else if (modelComponent instanceof ModelTriStateBuffer)
76 result = new TriStateBufferConverter().convert((ModelTriStateBuffer) modelComponent, modelID, params, verilogID);
78 throw new IllegalArgumentException(
79 "Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params);
81 componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, result.getMapping());
82 verilogComponents.add(result.getImplementation());
85 public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
86 UnionFind<PinNameBit> connectedPins, String modelID, JsonElement params, String verilogID)
88 IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID);
89 List<IOPort> ioPorts = new ArrayList<>();
90 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping = new HashMap<>();
91 for (Type t : Type.values())
92 pinMapping.put(t, new HashMap<>());
93 for (Pin modelPin : (Iterable<Pin>) () -> modelComponent.getPins().values().stream().sorted(Comparator.comparing(p -> p.name))
95 for (int bit = 0; bit < modelPin.logicWidth; bit++)
97 PinNameBit pinbit = new PinNameBit(modelPin.name, bit);
98 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.PRE, "pre");
99 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Output::new, Type.OUT, "out");
100 addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.RES, "res");
103 VerilogComponentDeclaration declaration = new VerilogComponentDeclaration(verilogID, ioPorts);
104 Set<VerilogEmulatedModelPin> finalPinMapping = pinMapping.values().stream().map(Map::values).flatMap(Collection::stream)
105 .map(VerilogEmulatedModelPinBuilder::build).collect(Collectors.toSet());
106 return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, finalPinMapping);
109 private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, UnionFind<PinNameBit> connectedPins,
110 Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping, PinNameBit pinbit,
111 BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
113 Map<PinNameBit, VerilogEmulatedModelPinBuilder> pinMappingCorrectType = pinMapping.get(type);
114 pinMappingCorrectType.computeIfAbsent(connectedPins.find(pinbit), p ->
116 String portID = ioPortIDGen.generateID(pinbit.getName() + "_" + pinbit.getBit() + "_" + suffix);
117 IOPort ioPort = constr.apply(portID, 2);
118 int index = ioPorts.size();
120 return new VerilogEmulatedModelPinBuilder(ioPort, index, type);
121 }).addPinbit(pinbit);
124 private static class VerilogEmulatedModelPinBuilder
126 private final IOPort verilogPort;
127 private final int portIndex;
128 private final Set<PinNameBit> pinbits;
129 private final Type type;
131 public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type)
133 this.verilogPort = verilogPort;
134 this.portIndex = portIndex;
135 this.pinbits = new HashSet<>();
139 public void addPinbit(PinNameBit pinbit)
144 public VerilogEmulatedModelPin build()
146 return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type);
150 public ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component)
152 ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams
153 .get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams()));
154 return subcomponentMapping;
157 public Set<VerilogComponentImplementation> getVerilogComponents()
159 return verilogComponents;
162 public static Set<VerilogComponentImplementation> convert(
163 Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings, Set<ModelComponent> components,
164 String verilogComponentIDPrefix)
166 ModelComponentToVerilogConverter converter = new ModelComponentToVerilogConverter(verilogComponentIDPrefix,
167 atomicComponentMappings);
168 for (ModelComponent modelComponent : components)
169 converter.convert(modelComponent);
170 return converter.getVerilogComponents();
173 public static IdentifierGenerator generateIdentifierGenerator(VerilogComponentDeclaration declaration)
175 IdentifierGenerator idGen = new IdentifierGenerator(
176 declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
177 ModelComponentToVerilogConverter::sanitizeVerilogID);
181 public static String sanitizeVerilogID(String id)
183 return (id.matches("[0-9].*") ? "_" + id : id).replaceAll("[^A-Za-z0-9_]", "_");