From a9a26cf61f9d5cc57657f17a6583fc46b5d8282f Mon Sep 17 00:00:00 2001 From: Daniel Kirschten Date: Sun, 13 Dec 2020 21:20:13 +0100 Subject: [PATCH] ModelComponentToVerilogConverter can now convert TriStateBuffers --- .../converter/ComponentConversionResult.java | 26 ++ .../ModelComponentToVerilogConverter.java | 158 ++---------- .../components/ComponentConverter.java | 11 + .../SubmodelComponentConverter.java | 243 ++++++++++++++++++ .../components/TriStateBufferConverter.java | 99 +++++++ .../{signals => expressions}/Constant.java | 17 +- .../verilog/model/expressions/Expression.java | 8 + .../model/verilog/model/signals/IOPort.java | 2 +- .../verilog/model/signals/NamedSignal.java | 59 ----- .../model/verilog/model/signals/Signal.java | 29 ++- .../model/verilog/model/signals/Wire.java | 2 +- .../verilog/model/statements/Assign.java | 5 +- .../model/statements/ComponentReference.java | 11 +- .../model/verilog/utils/CollectionsUtils.java | 7 +- .../model/verilog/examples/ExportAm2900.java | 10 - 15 files changed, 461 insertions(+), 226 deletions(-) create mode 100644 plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ComponentConversionResult.java create mode 100644 plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/ComponentConverter.java create mode 100644 plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/SubmodelComponentConverter.java create mode 100644 plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/TriStateBufferConverter.java rename plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/{signals => expressions}/Constant.java (75%) delete mode 100644 plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ComponentConversionResult.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ComponentConversionResult.java new file mode 100644 index 00000000..f195dcbd --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ComponentConversionResult.java @@ -0,0 +1,26 @@ +package net.mograsim.logic.model.verilog.converter; + +import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation; + +public class ComponentConversionResult +{ + private final ModelComponentToVerilogComponentDeclarationMapping mapping; + private final VerilogComponentImplementation implementation; + + public ComponentConversionResult(ModelComponentToVerilogComponentDeclarationMapping mapping, + VerilogComponentImplementation implementation) + { + this.mapping = mapping; + this.implementation = implementation; + } + + public ModelComponentToVerilogComponentDeclarationMapping getMapping() + { + return mapping; + } + + public VerilogComponentImplementation getImplementation() + { + return implementation; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java index 673018ed..4e05a225 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java @@ -6,7 +6,6 @@ import java.util.HashMap; 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; @@ -14,30 +13,21 @@ import java.util.stream.Collectors; 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.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.expressions.SignalReference; -import net.mograsim.logic.model.verilog.model.signals.Constant; 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.NamedSignal; import net.mograsim.logic.model.verilog.model.signals.Output; -import net.mograsim.logic.model.verilog.model.signals.Signal; -import net.mograsim.logic.model.verilog.model.signals.Wire; -import net.mograsim.logic.model.verilog.model.statements.Assign; -import net.mograsim.logic.model.verilog.model.statements.ComponentReference; -import net.mograsim.logic.model.verilog.model.statements.Statement; -import net.mograsim.logic.model.verilog.model.statements.WireDeclaration; import net.mograsim.logic.model.verilog.utils.IdentifierGenerator; import net.mograsim.logic.model.verilog.utils.UnionFind; @@ -62,7 +52,7 @@ 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) @@ -76,68 +66,19 @@ public class ModelComponentToVerilogConverter String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params)); + ComponentConversionResult result; // TODO don't rely on instanceof + // TODO improve! if (modelComponent instanceof SubmodelComponent) - convertSubmodelComponent((SubmodelComponent) modelComponent, modelID, params, verilogID); + 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); - } - - private void convertSubmodelComponent(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID) - { - for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) - if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) - convert(subcomponent); - - UnionFind connectedPins = findConnectedPins(modelComponent); - - ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params, - verilogID); - componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, mapping); - - verilogComponents.add(mapImplementation(modelComponent, connectedPins, mapping)); - } - - private UnionFind findConnectedPins(SubmodelComponent modelComponent) - { - UnionFind 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)); - - for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) - if (subcomponent instanceof ModelSplitter) - { - ModelSplitter splitter = (ModelSplitter) subcomponent; - for (int bit = 0; bit < splitter.logicWidth; bit++) - connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0)); - } else if (!(subcomponent instanceof ModelWireCrossPoint) - && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) - { - ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent); - for (Set connected : subcomponentMapping.getInternallyConnectedPins()) - connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList())); - } - - return connectedPins; - } - - private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent, - UnionFind connectedPins, String modelID, JsonElement params, String verilogID) - { - // TODO this is probably slow - Map representantMapping = new HashMap<>(); - UnionFind connectedPinsByName = new UnionFind<>(); - for (Pin p : modelComponent.getSubmodelPins().values()) - for (int bit = 0; bit < p.logicWidth; bit++) - { - PinNameBit pinnamebit = new PinNameBit(p.name, bit); - PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit); - connectedPinsByName.union(pinnamebit, representative); - } - return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID); + componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, result.getMapping()); + verilogComponents.add(result.getImplementation()); } public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent, @@ -204,79 +145,14 @@ public class ModelComponentToVerilogConverter } } - private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind connectedPins, - ModelComponentToVerilogComponentDeclarationMapping declarationMapping) - { - Map currentPreSignals = new HashMap<>(); - Map finalOutSignals = new HashMap<>(); - Map resSignals = new HashMap<>(); - for (Set connectedPinGroup : declarationMapping.getInternallyConnectedPins()) - { - PinNameBit pinnamebit = connectedPinGroup.iterator().next(); - PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent)); - resSignals.put(root, declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()); - finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort()); - currentPreSignals.put(root, declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort()); - } - - IdentifierGenerator idGen = new IdentifierGenerator( - declarationMapping.getVerilogComponentDeclaration().getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()), - ModelComponentToVerilogConverter::sanitizeVerilogID); - List statements = new ArrayList<>(); - for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) - { - // TODO do we really want to use instanceof? - if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint - || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) - continue; - - String subcomponentVerilogName = idGen.generateID(subcomponent.getName()); - ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent); - int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size(); - List 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); - PinBit root = connectedPins.find(pinbit); - Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2); - statements.add(new WireDeclaration(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; - statements.add(new WireDeclaration(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); - } - statements - .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments)); - } - - for (Entry e : finalOutSignals.entrySet()) - statements.add(new Assign(e.getValue(), new SignalReference(currentPreSignals.get(e.getKey())))); - - return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements); - } - - private ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component) + public ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component) { ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams .get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams())); return subcomponentMapping; } - private Set getVerilogComponents() + public Set getVerilogComponents() { return verilogComponents; } @@ -292,6 +168,14 @@ public class ModelComponentToVerilogConverter 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_]", "_"); diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/ComponentConverter.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/ComponentConverter.java new file mode 100644 index 00000000..d0507389 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/ComponentConverter.java @@ -0,0 +1,11 @@ +package net.mograsim.logic.model.verilog.converter.components; + +import com.google.gson.JsonElement; + +import net.mograsim.logic.model.model.components.ModelComponent; +import net.mograsim.logic.model.verilog.converter.ComponentConversionResult; + +public interface ComponentConverter +{ + public ComponentConversionResult convert(C modelComponent, String modelID, JsonElement params, String verilogID); +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/SubmodelComponentConverter.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/SubmodelComponentConverter.java new file mode 100644 index 00000000..bb99bce3 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/SubmodelComponentConverter.java @@ -0,0 +1,243 @@ +package net.mograsim.logic.model.verilog.converter.components; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +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.stream.Collectors; + +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.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.verilog.converter.ComponentConversionResult; +import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping; +import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter; +import net.mograsim.logic.model.verilog.converter.PinBit; +import net.mograsim.logic.model.verilog.converter.PinNameBit; +import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin; +import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type; +import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; +import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation; +import net.mograsim.logic.model.verilog.model.expressions.Constant; +import net.mograsim.logic.model.verilog.model.expressions.Expression; +import net.mograsim.logic.model.verilog.model.expressions.SignalReference; +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.model.signals.Signal; +import net.mograsim.logic.model.verilog.model.signals.Wire; +import net.mograsim.logic.model.verilog.model.statements.Assign; +import net.mograsim.logic.model.verilog.model.statements.ComponentReference; +import net.mograsim.logic.model.verilog.model.statements.Statement; +import net.mograsim.logic.model.verilog.model.statements.WireDeclaration; +import net.mograsim.logic.model.verilog.utils.IdentifierGenerator; +import net.mograsim.logic.model.verilog.utils.UnionFind; + +public class SubmodelComponentConverter implements ComponentConverter +{ + private final ModelComponentToVerilogConverter converter; + + public SubmodelComponentConverter(ModelComponentToVerilogConverter converter) + { + this.converter = converter; + } + + @Override + public ComponentConversionResult convert(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID) + { + for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) + if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + converter.convert(subcomponent); + + UnionFind connectedPins = findConnectedPins(modelComponent); + + ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params, + verilogID); + + VerilogComponentImplementation implementation = mapImplementation(modelComponent, connectedPins, mapping); + + return new ComponentConversionResult(mapping, implementation); + } + + private UnionFind findConnectedPins(SubmodelComponent modelComponent) + { + UnionFind 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)); + + for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) + if (subcomponent instanceof ModelSplitter) + { + ModelSplitter splitter = (ModelSplitter) subcomponent; + for (int bit = 0; bit < splitter.logicWidth; bit++) + connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0)); + } else if (!(subcomponent instanceof ModelWireCrossPoint) + && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + { + ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent); + for (Set connected : subcomponentMapping.getInternallyConnectedPins()) + connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList())); + } + + return connectedPins; + } + + private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent, + UnionFind connectedPins, String modelID, JsonElement params, String verilogID) + { + // TODO this is probably slow + Map representantMapping = new HashMap<>(); + UnionFind connectedPinsByName = new UnionFind<>(); + for (Pin p : modelComponent.getSubmodelPins().values()) + for (int bit = 0; bit < p.logicWidth; bit++) + { + PinNameBit pinnamebit = new PinNameBit(p.name, bit); + PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit); + connectedPinsByName.union(pinnamebit, representative); + } + + return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID); + } + + public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent, + UnionFind connectedPins, String modelID, JsonElement params, String verilogID) + { + IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID); + List ioPorts = new ArrayList<>(); + Map> 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++) + { + 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); + Set 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 ioPorts, UnionFind connectedPins, + Map> pinMapping, PinNameBit pinbit, + BiFunction constr, Type type, String suffix) + { + Map 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 static class VerilogEmulatedModelPinBuilder + { + private final IOPort verilogPort; + private final int portIndex; + private final Set pinbits; + private final Type type; + + public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type) + { + this.verilogPort = verilogPort; + this.portIndex = portIndex; + this.pinbits = new HashSet<>(); + this.type = type; + } + + public void addPinbit(PinNameBit pinbit) + { + pinbits.add(pinbit); + } + + public VerilogEmulatedModelPin build() + { + return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type); + } + } + + private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind connectedPins, + ModelComponentToVerilogComponentDeclarationMapping declarationMapping) + { + Map currentPreExprs = new HashMap<>(); + Map finalOutSignals = new HashMap<>(); + Map resExprs = new HashMap<>(); + for (Set connectedPinGroup : declarationMapping.getInternallyConnectedPins()) + { + PinNameBit pinnamebit = connectedPinGroup.iterator().next(); + PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent)); + resExprs.put(root, new SignalReference(declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort())); + finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort()); + currentPreExprs.put(root, new SignalReference(declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort())); + } + + IdentifierGenerator idGen = ModelComponentToVerilogConverter + .generateIdentifierGenerator(declarationMapping.getVerilogComponentDeclaration()); + List statements = new ArrayList<>(); + for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) + { + // TODO do we really want to use instanceof? + if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint + || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + continue; + + String subcomponentVerilogName = idGen.generateID(subcomponent.getName()); + ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent); + int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size(); + List 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); + PinBit root = connectedPins.find(pinbit); + Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2); + statements.add(new WireDeclaration(outSignal)); + Expression preExpr = currentPreExprs.put(root, new SignalReference(outSignal)); + Expression outExpr = new SignalReference(outSignal); + Expression resExpr = resExprs.get(root); + if (resExpr == null) + { + preExpr = new Constant(BitVector.of(Bit.ZERO, 2)); + Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2); + resExpr = new SignalReference(resWire); + statements.add(new WireDeclaration(resWire)); + finalOutSignals.put(root, resWire); + resExprs.put(root, resExpr); + } + PinNameBit pinnamebit = pinbit.toPinNameBit(); + arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preExpr); + arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outExpr); + arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resExpr); + } + statements + .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments)); + } + + for (Entry e : finalOutSignals.entrySet()) + statements.add(new Assign(e.getValue(), currentPreExprs.get(e.getKey()))); + + return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/TriStateBufferConverter.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/TriStateBufferConverter.java new file mode 100644 index 00000000..deefaf0b --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/components/TriStateBufferConverter.java @@ -0,0 +1,99 @@ +package net.mograsim.logic.model.verilog.converter.components; + +import java.util.ArrayList; +import java.util.List; + +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.atomic.ModelTriStateBuffer; +import net.mograsim.logic.model.model.wires.Pin; +import net.mograsim.logic.model.verilog.converter.ComponentConversionResult; +import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping; +import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter; +import net.mograsim.logic.model.verilog.converter.PinNameBit; +import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; +import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation; +import net.mograsim.logic.model.verilog.model.expressions.Constant; +import net.mograsim.logic.model.verilog.model.expressions.Expression; +import net.mograsim.logic.model.verilog.model.expressions.SignalReference; +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.model.signals.Wire; +import net.mograsim.logic.model.verilog.model.statements.Assign; +import net.mograsim.logic.model.verilog.model.statements.ComponentReference; +import net.mograsim.logic.model.verilog.model.statements.Statement; +import net.mograsim.logic.model.verilog.model.statements.WireDeclaration; +import net.mograsim.logic.model.verilog.utils.IdentifierGenerator; +import net.mograsim.logic.model.verilog.utils.UnionFind; + +public class TriStateBufferConverter implements ComponentConverter +{ + // TODO don't hardcode this + private static final VerilogComponentDeclaration TSBW_COMBINE = new VerilogComponentDeclaration("tsbw_combine", + List.of(new Input("wA", 2), new Input("wB", 2), new Output("res", 2))); + private static final VerilogComponentDeclaration TSBW_CONDITIONAL = new VerilogComponentDeclaration("tsbw_conditional", + List.of(new Input("cond", 2), new Input("onTrue", 2), new Input("onFalse", 2), new Output("res", 2))); + + private final ModelComponentToVerilogConverter converter; + + public TriStateBufferConverter(ModelComponentToVerilogConverter converter) + { + this.converter = converter; + } + + @Override + public ComponentConversionResult convert(ModelTriStateBuffer modelComponent, String modelID, JsonElement params, String verilogID) + { + UnionFind connectedPins = new UnionFind<>(); + ModelComponentToVerilogComponentDeclarationMapping mapping = ModelComponentToVerilogConverter + .generateCanonicalDeclarationMapping(modelComponent, connectedPins, modelID, params, verilogID); + VerilogComponentDeclaration declaration = mapping.getVerilogComponentDeclaration(); + + List statements = new ArrayList<>(); + + PinNameBit condPinbit = new PinNameBit(modelComponent.getEnablePin().name, 0); + IOPort condPre = mapping.getPrePinMapping().get(condPinbit).getVerilogPort(); + IOPort condOut = mapping.getOutPinMapping().get(condPinbit).getVerilogPort(); + IOPort condRes = mapping.getResPinMapping().get(condPinbit).getVerilogPort(); + Expression condrResRef = new SignalReference(condRes); + + statements.add(new Assign(condOut, new SignalReference(condPre))); + + IdentifierGenerator idGen = ModelComponentToVerilogConverter.generateIdentifierGenerator(declaration); + + Pin inputPin = modelComponent.getInputPin(); + Pin outputPin = modelComponent.getOutputPin(); + for (int bit = 0; bit < inputPin.logicWidth; bit++) + { + PinNameBit inputPinbit = new PinNameBit(inputPin.name, bit); + PinNameBit outputPinbit = new PinNameBit(outputPin.name, bit); + + IOPort inPre = mapping.getPrePinMapping().get(inputPinbit).getVerilogPort(); + IOPort inOut = mapping.getOutPinMapping().get(inputPinbit).getVerilogPort(); + IOPort inRes = mapping.getResPinMapping().get(inputPinbit).getVerilogPort(); + IOPort outPre = mapping.getPrePinMapping().get(outputPinbit).getVerilogPort(); + IOPort outOut = mapping.getOutPinMapping().get(outputPinbit).getVerilogPort(); + Expression inPreRef = new SignalReference(inPre); + Expression inResRef = new SignalReference(inRes); + Expression outPreRef = new SignalReference(outPre); + Expression outOutRef = new SignalReference(outOut); + + Wire condTmp = new Wire(idGen.generateID("cond_tmp_" + bit), 2); + SignalReference condTmpRef = new SignalReference(condTmp); + statements.add(new WireDeclaration(condTmp)); + + statements.add(new Assign(inOut, inPreRef)); + statements.add(new ComponentReference(idGen.generateID("cond_" + bit), TSBW_CONDITIONAL, + List.of(condrResRef, inResRef, new Constant(BitVector.of(Bit.ZERO, 2)), condTmpRef))); + statements + .add(new ComponentReference(idGen.generateID("comb_" + bit), TSBW_COMBINE, List.of(outPreRef, condTmpRef, outOutRef))); + } + + VerilogComponentImplementation implementation = new VerilogComponentImplementation(declaration, statements); + + return new ComponentConversionResult(mapping, implementation); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Constant.java similarity index 75% rename from plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java rename to plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Constant.java index 46150b9f..e454a619 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Constant.java @@ -1,14 +1,17 @@ -package net.mograsim.logic.model.verilog.model.signals; +package net.mograsim.logic.model.verilog.model.expressions; + +import java.util.Set; import net.mograsim.logic.core.types.BitVector; +import net.mograsim.logic.model.verilog.model.signals.Signal; -public class Constant extends Signal +public class Constant extends Expression { private final BitVector constant; public Constant(BitVector constant) { - super(Type.CONSTANT, constant.length()); + super(constant.length()); this.constant = constant; check(); @@ -26,11 +29,17 @@ public class Constant extends Signal } @Override - public String toReferenceVerilogCode() + public String toVerilogCode() { return getWidth() + "'b" + constant.toBitstring(); } + @Override + public Set getReferencedSignals() + { + return Set.of(); + } + @Override public int hashCode() { diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java index b5fa9b37..dacf1df5 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java @@ -11,6 +11,14 @@ public abstract class Expression public Expression(int width) { this.width = width; + + check(); + } + + private void check() + { + if (width < 0) + throw new IllegalArgumentException("Width can't be negative"); } public int getWidth() diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java index 7d573bb1..291755db 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java @@ -1,6 +1,6 @@ package net.mograsim.logic.model.verilog.model.signals; -public abstract class IOPort extends NamedSignal +public abstract class IOPort extends Signal { public IOPort(Type type, String name, int width) { diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java deleted file mode 100644 index 9fae34b6..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java +++ /dev/null @@ -1,59 +0,0 @@ -package net.mograsim.logic.model.verilog.model.signals; - -import java.util.Objects; - -public abstract class NamedSignal extends Signal -{ - private final String name; - - public NamedSignal(Type type, String name, int width) - { - super(type, width); - this.name = Objects.requireNonNull(name); - } - - public String getName() - { - return name; - } - - @Override - public String toReferenceVerilogCode() - { - return name; - } - - @Override - public String toString() - { - return name + "[" + getWidth() + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - NamedSignal other = (NamedSignal) obj; - if (name == null) - { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java index e825cede..7ccf9cd9 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java @@ -5,11 +5,13 @@ import java.util.Objects; public abstract class Signal { private final Type type; + private final String name; private final int width; - public Signal(Type type, int width) + public Signal(Type type, String name, int width) { this.type = Objects.requireNonNull(type); + this.name = Objects.requireNonNull(name); this.width = width; check(); @@ -26,18 +28,33 @@ public abstract class Signal return type; } + public String getName() + { + return name; + } + public int getWidth() { return width; } - public abstract String toReferenceVerilogCode(); + public String toReferenceVerilogCode() + { + return name; + } + + @Override + public String toString() + { + return name + "[" + getWidth() + "]"; + } @Override public int hashCode() { final int prime = 31; int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + width; return result; @@ -53,6 +70,12 @@ public abstract class Signal if (getClass() != obj.getClass()) return false; Signal other = (Signal) obj; + if (name == null) + { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; if (type != other.type) return false; if (width != other.width) @@ -62,6 +85,6 @@ public abstract class Signal public static enum Type { - WIRE, IO_INPUT, IO_OUTPUT, CONSTANT; + WIRE, IO_INPUT, IO_OUTPUT; } } diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java index b6d331cc..10e2a504 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java @@ -1,6 +1,6 @@ package net.mograsim.logic.model.verilog.model.signals; -public class Wire extends NamedSignal +public class Wire extends Signal { public Wire(String name, int width) { diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java index e6036f04..2dd7ae08 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java @@ -4,16 +4,15 @@ import java.util.Objects; import java.util.Set; import net.mograsim.logic.model.verilog.model.expressions.Expression; -import net.mograsim.logic.model.verilog.model.signals.NamedSignal; import net.mograsim.logic.model.verilog.model.signals.Signal; import net.mograsim.logic.model.verilog.utils.CollectionsUtils; public class Assign extends Statement { - private final NamedSignal target; + private final Signal target; private final Expression source; - public Assign(NamedSignal target, Expression source) + public Assign(Signal target, Expression source) { this.target = Objects.requireNonNull(target); this.source = Objects.requireNonNull(source); diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java index f676661a..dcce7606 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.stream.Collectors; import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; +import net.mograsim.logic.model.verilog.model.expressions.Expression; import net.mograsim.logic.model.verilog.model.signals.IOPort; import net.mograsim.logic.model.verilog.model.signals.Signal; @@ -13,9 +14,9 @@ public class ComponentReference extends Statement { private final String name; private final VerilogComponentDeclaration referencedComponent; - private final List arguments; + private final List arguments; - public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List arguments) + public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List arguments) { this.name = Objects.requireNonNull(name); this.referencedComponent = Objects.requireNonNull(referencedComponent); @@ -47,7 +48,7 @@ public class ComponentReference extends Statement return referencedComponent; } - public List getArguments() + public List getArguments() { return arguments; } @@ -58,7 +59,7 @@ public class ComponentReference extends Statement StringBuilder sb = new StringBuilder(); sb.append(referencedComponent.getID() + " " + name); - sb.append(arguments.stream().map(Signal::toReferenceVerilogCode).collect(Collectors.joining(", ", "(", ")"))); + sb.append(arguments.stream().map(Expression::toVerilogCode).collect(Collectors.joining(", ", "(", ")"))); sb.append(";"); return sb.toString(); @@ -79,7 +80,7 @@ public class ComponentReference extends Statement @Override public Set getReferencedSignals() { - return Set.copyOf(arguments); + return arguments.stream().map(Expression::getReferencedSignals).flatMap(Set::stream).collect(Collectors.toUnmodifiableSet()); } @Override diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java index 6d118c35..2fe45531 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java @@ -9,11 +9,12 @@ public class CollectionsUtils { } - public static Set union(Set a, Set b) + @SafeVarargs + public static Set union(Set... sets) { Set union = new HashSet<>(); - union.addAll(a); - union.addAll(b); + for (Set set : sets) + union.addAll(set); return Set.copyOf(union); } } diff --git a/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java b/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java index a2e46d9b..610a4669 100644 --- a/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java +++ b/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java @@ -25,8 +25,6 @@ import net.mograsim.logic.model.model.components.atomic.ModelClock.ModelClockPar import net.mograsim.logic.model.model.components.atomic.ModelFixedOutput; import net.mograsim.logic.model.model.components.atomic.ModelNandGate; import net.mograsim.logic.model.model.components.atomic.ModelTextComponent; -import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer; -import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer.ModelTriStateBufferParams; import net.mograsim.logic.model.serializing.IdentifyParams; import net.mograsim.logic.model.serializing.IndirectModelComponentCreator; import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping; @@ -67,14 +65,6 @@ public class ExportAm2900 new ModelNandGate(model, 1), // new ModelFixedOutput(model, BitVector.SINGLE_0, null), // new ModelFixedOutput(model, BitVector.SINGLE_1, null), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.RIGHT)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.RIGHT_ALT)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.DOWN)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(4, Orientation.RIGHT)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(12, Orientation.RIGHT_ALT)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(12, Orientation.DOWN)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.LEFT)), // - new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.RIGHT_ALT)), // new ModelClock(model, new ModelClockParams(7000, Orientation.RIGHT)), // new ModelTextComponent(model, "A bus"), // new ModelTextComponent(model, "MPM addr"), // -- 2.17.1