import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.google.gson.JsonElement;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
import net.mograsim.logic.model.model.components.ModelComponent;
import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
+import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
-import net.mograsim.logic.model.model.wires.ModelWire;
+import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
import net.mograsim.logic.model.model.wires.Pin;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
-import net.mograsim.logic.model.verilog.helper.IdentifierGenerator;
-import net.mograsim.logic.model.verilog.helper.UnionFind;
-import net.mograsim.logic.model.verilog.helper.UnionFind.UnionFindElement;
-import net.mograsim.logic.model.verilog.model.Assign;
-import net.mograsim.logic.model.verilog.model.ComponentReference;
-import net.mograsim.logic.model.verilog.model.Constant;
-import net.mograsim.logic.model.verilog.model.IOPort;
-import net.mograsim.logic.model.verilog.model.Input;
-import net.mograsim.logic.model.verilog.model.NamedSignal;
-import net.mograsim.logic.model.verilog.model.Output;
-import net.mograsim.logic.model.verilog.model.Signal;
+import net.mograsim.logic.model.verilog.converter.components.SubmodelComponentConverter;
+import net.mograsim.logic.model.verilog.converter.components.TriStateBufferConverter;
import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
-import net.mograsim.logic.model.verilog.model.Wire;
+import net.mograsim.logic.model.verilog.model.signals.IOPort;
+import net.mograsim.logic.model.verilog.model.signals.Input;
+import net.mograsim.logic.model.verilog.model.signals.Output;
+import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
+import net.mograsim.logic.model.verilog.utils.UnionFind;
public class ModelComponentToVerilogConverter
{
ModelComponentToVerilogConverter::sanitizeVerilogID);
}
- private void convert(ModelComponent modelComponent)
+ public void convert(ModelComponent modelComponent)
{
+ // these are handled elsewhere
+ if (modelComponent instanceof ModelSplitter || modelComponent instanceof ModelWireCrossPoint)
+ return;
+
String modelID = modelComponent.getIDForSerializing(new IdentifyParams());
JsonElement params = modelComponent.getParamsForSerializingJSON(new IdentifyParams());
if (componentMappingsPerModelIDPerParams.getOrDefault(modelID, Map.of()).containsKey(params))
// we already converted that component, or it was specified externally
return;
- if (!(modelComponent instanceof SubmodelComponent))
+ String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params));
+
+ ComponentConversionResult result;
+ // TODO don't rely on instanceof
+ // TODO improve!
+ if (modelComponent instanceof SubmodelComponent)
+ result = new SubmodelComponentConverter(this).convert((SubmodelComponent) modelComponent, modelID, params, verilogID);
+ else if (modelComponent instanceof ModelTriStateBuffer)
+ result = new TriStateBufferConverter(this).convert((ModelTriStateBuffer) modelComponent, modelID, params, verilogID);
+ else
throw new IllegalArgumentException(
"Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params);
- SubmodelComponent modelComponentC = (SubmodelComponent) modelComponent;
-
- ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponentC, modelID, params);
- componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, mapping);
- for (ModelComponent subcomponent : modelComponentC.submodel.getComponentsByName().values())
- if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
- convert(subcomponent);
-
- verilogComponents.add(mapImplementation(modelComponentC, mapping));
- }
-
- private ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(ModelComponent modelComponent, String modelID,
- JsonElement params)
- {
- return generateCanonicalDeclarationMapping(modelComponent, modelID, params,
- verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params)));
+ componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, result.getMapping());
+ verilogComponents.add(result.getImplementation());
}
public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
- String modelID, JsonElement params, String verilogID)
+ UnionFind<PinNameBit> connectedPins, String modelID, JsonElement params, String verilogID)
{
IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID);
List<IOPort> ioPorts = new ArrayList<>();
- Set<VerilogEmulatedModelPin> pinMapping = new HashSet<>();
+ Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping = new HashMap<>();
+ for (Type t : Type.values())
+ pinMapping.put(t, new HashMap<>());
for (Pin modelPin : modelComponent.getPins().values())
for (int bit = 0; bit < modelPin.logicWidth; bit++)
{
- addPinMapping(ioPortIDGen, ioPorts, pinMapping, modelPin, bit, Input::new, Type.PRE, "pre");
- addPinMapping(ioPortIDGen, ioPorts, pinMapping, modelPin, bit, Output::new, Type.OUT, "out");
- addPinMapping(ioPortIDGen, ioPorts, pinMapping, modelPin, bit, Input::new, Type.RES, "res");
+ PinNameBit pinbit = new PinNameBit(modelPin.name, bit);
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.PRE, "pre");
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Output::new, Type.OUT, "out");
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.RES, "res");
}
VerilogComponentDeclaration declaration = new VerilogComponentDeclaration(verilogID, ioPorts);
- return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, pinMapping);
+ Set<VerilogEmulatedModelPin> finalPinMapping = pinMapping.values().stream().map(Map::values).flatMap(Collection::stream)
+ .map(VerilogEmulatedModelPinBuilder::build).collect(Collectors.toSet());
+ return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, finalPinMapping);
}
- private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, Set<VerilogEmulatedModelPin> pinMapping,
- Pin modelPin, int bit, BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
+ private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, UnionFind<PinNameBit> connectedPins,
+ Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping, PinNameBit pinbit,
+ BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
{
- String portID = ioPortIDGen.generateID(modelPin.name + "_" + bit + "_" + suffix);
- IOPort ioPort = constr.apply(portID, 2);
- int index = ioPorts.size();
- ioPorts.add(ioPort);
- pinMapping.add(new VerilogEmulatedModelPin(ioPort, index, new PinNameBit(modelPin.name, bit), type));
+ Map<PinNameBit, VerilogEmulatedModelPinBuilder> pinMappingCorrectType = pinMapping.get(type);
+ pinMappingCorrectType.computeIfAbsent(connectedPins.find(pinbit), p ->
+ {
+ String portID = ioPortIDGen.generateID(p.getName() + "_" + p.getBit() + "_" + suffix);
+ IOPort ioPort = constr.apply(portID, 2);
+ int index = ioPorts.size();
+ ioPorts.add(ioPort);
+ return new VerilogEmulatedModelPinBuilder(ioPort, index, type);
+ }).addPinbit(pinbit);
}
- private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent,
- ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
+ private static class VerilogEmulatedModelPinBuilder
{
- UnionFind<PinBit> connectedPins = new UnionFind<>();
- for (ModelWire w : modelComponent.submodel.getWiresByName().values())
- for (int bit = 0; bit < w.getPin1().logicWidth; bit++)
- connectedPins.union(new PinBit(w.getPin1(), bit), new PinBit(w.getPin2(), bit));
-
- Map<UnionFindElement<PinBit>, Signal> currentPreSignals = new HashMap<>();
- Map<UnionFindElement<PinBit>, NamedSignal> finalOutSignals = new HashMap<>();
- Map<UnionFindElement<PinBit>, NamedSignal> resSignals = new HashMap<>();
- for (Pin submodelPin : modelComponent.getSubmodelPins().values())
- for (int bit = 0; bit < submodelPin.logicWidth; bit++)
- {
- PinBit pinbit = new PinBit(submodelPin, bit);
- PinNameBit pinnamebit = pinbit.toPinNameBit();
- UnionFindElement<PinBit> root = UnionFind.find(connectedPins.getElement(pinbit));
- resSignals.put(root, declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort());
- finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort());
- Signal prePort = declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort();
- Signal previousPrePort = currentPreSignals.put(root, prePort);
- if (previousPrePort != null)
- // TODO implement this
- throw new IllegalArgumentException("Can't convert components with connected pins");
- }
+ private final IOPort verilogPort;
+ private final int portIndex;
+ private final Set<PinNameBit> pinbits;
+ private final Type type;
- IdentifierGenerator idGen = new IdentifierGenerator(
- declarationMapping.getVerilogComponentDeclaration().getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
- ModelComponentToVerilogConverter::sanitizeVerilogID);
- Set<Wire> internalWires = new HashSet<>();
- Set<ComponentReference> subcomponents = new HashSet<>();
- for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
+ public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type)
{
- // TODO do we really want to use instanceof?
- if (subcomponent instanceof ModelSplitter || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
- continue;
-
- String subcomponentVerilogName = idGen.generateID(subcomponent.getName());
- ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams
- .get(subcomponent.getIDForSerializing(new IdentifyParams()))
- .get(subcomponent.getParamsForSerializingJSON(new IdentifyParams()));
- int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size();
- List<Signal> arguments = new ArrayList<>(parameterCount);
- for (int i = 0; i < parameterCount; i++)
- arguments.add(null);
- for (Pin pin : subcomponent.getPins().values())
- for (int bit = 0; bit < pin.logicWidth; bit++)
- {
- PinBit pinbit = new PinBit(pin, bit);
- UnionFindElement<PinBit> root = UnionFind.find(connectedPins.getElement(pinbit));
- Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
- internalWires.add(outSignal);
- Signal preSignal = currentPreSignals.put(root, outSignal);
- Signal resSignal = resSignals.get(root);
- if (resSignal == null)
- {
- preSignal = new Constant(BitVector.of(Bit.ZERO, 2));
- Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2);
- resSignal = resWire;
- internalWires.add(resWire);
- finalOutSignals.put(root, resWire);
- resSignals.put(root, resWire);
- }
- PinNameBit pinnamebit = pinbit.toPinNameBit();
- arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preSignal);
- arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outSignal);
- arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resSignal);
- }
- subcomponents
- .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments));
+ this.verilogPort = verilogPort;
+ this.portIndex = portIndex;
+ this.pinbits = new HashSet<>();
+ this.type = type;
}
- Set<Assign> assigns = new HashSet<>();
- for (Entry<UnionFindElement<PinBit>, NamedSignal> e : finalOutSignals.entrySet())
- assigns.add(new Assign(currentPreSignals.get(e.getKey()), e.getValue()));
+ public void addPinbit(PinNameBit pinbit)
+ {
+ pinbits.add(pinbit);
+ }
+
+ public VerilogEmulatedModelPin build()
+ {
+ return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type);
+ }
+ }
- return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), internalWires, assigns,
- subcomponents);
+ public ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component)
+ {
+ ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams
+ .get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams()));
+ return subcomponentMapping;
}
- private Set<VerilogComponentImplementation> getVerilogComponents()
+ public Set<VerilogComponentImplementation> getVerilogComponents()
{
return verilogComponents;
}
return converter.getVerilogComponents();
}
+ public static IdentifierGenerator generateIdentifierGenerator(VerilogComponentDeclaration declaration)
+ {
+ IdentifierGenerator idGen = new IdentifierGenerator(
+ declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
+ ModelComponentToVerilogConverter::sanitizeVerilogID);
+ return idGen;
+ }
+
public static String sanitizeVerilogID(String id)
{
return (id.matches("[0-9].*") ? "_" + id : id).replaceAll("[^A-Za-z0-9_]", "_");