ModelComponentToVerilogConverter almost supports connected pins
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Sun, 13 Dec 2020 02:49:28 +0000 (03:49 +0100)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Thu, 14 Jan 2021 14:44:02 +0000 (15:44 +0100)
plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogComponentDeclarationMapping.java
plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java
plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/VerilogEmulatedModelPin.java
tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java

index 5a230db..808ac51 100644 (file)
@@ -1,12 +1,12 @@
 package net.mograsim.logic.model.verilog.converter;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
 
 import com.google.gson.JsonElement;
 
@@ -45,8 +45,15 @@ public class ModelComponentToVerilogComponentDeclarationMapping
                List<VerilogEmulatedModelPin> reverseMapping = new ArrayList<>(pinMapping.size());
                for (int i = 0; i < pinMapping.size(); i++)
                        reverseMapping.add(null);
+               Map<Type, Set<PinNameBit>> usedPinNameBits = new HashMap<>();
+               for (Type t : Type.values())
+                       usedPinNameBits.put(t, new HashSet<>());
                for (VerilogEmulatedModelPin verilogEmulatedModelPin : pinMapping)
                {
+                       // TODO check if pre, out, res pins are consistent with each other
+                       for (PinNameBit pinbit : verilogEmulatedModelPin.getPinbits())
+                               if (!usedPinNameBits.get(verilogEmulatedModelPin.getType()).add(pinbit))
+                                       throw new IllegalArgumentException("Pinbit occurs twice: " + pinbit);
                        int verilogPinIndex = verilogEmulatedModelPin.getPortIndex();
                        if (verilogComponentDeclaration.getIOPorts().get(verilogPinIndex) != verilogEmulatedModelPin.getVerilogPort())
                                throw new IllegalArgumentException("Incorrect IO port index for port: " + verilogEmulatedModelPin);
@@ -62,8 +69,12 @@ public class ModelComponentToVerilogComponentDeclarationMapping
 
        private Map<PinNameBit, VerilogEmulatedModelPin> filterPinMapping(Type filteredType)
        {
-               return pinMapping.stream().filter(p -> p.getType() == filteredType)
-                               .collect(Collectors.toMap(VerilogEmulatedModelPin::getPinbit, Function.identity()));
+               Map<PinNameBit, VerilogEmulatedModelPin> result = new HashMap<>();
+               for (VerilogEmulatedModelPin p : pinMapping)
+                       if (p.getType() == filteredType)
+                               for (PinNameBit pinbit : p.getPinbits())
+                                       result.put(pinbit, p);
+               return Map.copyOf(result);
        }
 
        public String getModelComponentID()
index d2a7e57..b7e8772 100644 (file)
@@ -25,7 +25,6 @@ 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;
@@ -72,75 +71,137 @@ public class ModelComponentToVerilogConverter
                                        "Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params);
                SubmodelComponent modelComponentC = (SubmodelComponent) modelComponent;
 
-               ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponentC, modelID, params);
+               UnionFind<PinBit> connectedPins = findConnectedPins(modelComponentC);
+
+               ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponentC, connectedPins, 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))
+                       if (!(subcomponent instanceof ModelSplitter) && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
                                convert(subcomponent);
 
-               verilogComponents.add(mapImplementation(modelComponentC, mapping));
+               verilogComponents.add(mapImplementation(modelComponentC, connectedPins, mapping));
+       }
+
+       private static UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
+       {
+               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));
+
+               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));
+                       }
+
+               // TODO connected pins of subcomponents
+
+               return connectedPins;
        }
 
-       private ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(ModelComponent modelComponent, String modelID,
-                       JsonElement params)
+       private ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
+                       UnionFind<PinBit> connectedPins, String modelID, JsonElement params)
        {
-               return generateCanonicalDeclarationMapping(modelComponent, modelID, params,
+               // TODO this is probably slow
+               Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
+               UnionFind<PinNameBit> 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,
                                verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params)));
        }
 
        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));
+               private final IOPort verilogPort;
+               private final int portIndex;
+               private final Set<PinNameBit> pinbits;
+               private final Type type;
 
-               Map<UnionFindElement<PinBit>, Signal> currentPreSignals = new HashMap<>();
-               Map<UnionFindElement<PinBit>, NamedSignal> finalOutSignals = new HashMap<>();
-               Map<UnionFindElement<PinBit>, NamedSignal> resSignals = new HashMap<>();
+               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<PinBit> connectedPins,
+                       ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
+       {
+               Map<PinBit, Signal> currentPreSignals = new HashMap<>();
+               Map<PinBit, NamedSignal> finalOutSignals = new HashMap<>();
+               Map<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));
+                               PinBit root = connectedPins.find(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");
+                               assert previousPrePort != null && !previousPrePort.equals(prePort);
                        }
 
                IdentifierGenerator idGen = new IdentifierGenerator(
@@ -166,7 +227,7 @@ public class ModelComponentToVerilogConverter
                                for (int bit = 0; bit < pin.logicWidth; bit++)
                                {
                                        PinBit pinbit = new PinBit(pin, bit);
-                                       UnionFindElement<PinBit> root = UnionFind.find(connectedPins.getElement(pinbit));
+                                       PinBit root = connectedPins.find(pinbit);
                                        Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
                                        internalWires.add(outSignal);
                                        Signal preSignal = currentPreSignals.put(root, outSignal);
@@ -190,7 +251,7 @@ public class ModelComponentToVerilogConverter
                }
 
                Set<Assign> assigns = new HashSet<>();
-               for (Entry<UnionFindElement<PinBit>, NamedSignal> e : finalOutSignals.entrySet())
+               for (Entry<PinBit, NamedSignal> e : finalOutSignals.entrySet())
                        assigns.add(new Assign(currentPreSignals.get(e.getKey()), e.getValue()));
 
                return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), internalWires, assigns,
index 6948824..b27b485 100644 (file)
@@ -1,6 +1,7 @@
 package net.mograsim.logic.model.verilog.converter;
 
 import java.util.Objects;
+import java.util.Set;
 
 import net.mograsim.logic.model.verilog.model.IOPort;
 import net.mograsim.logic.model.verilog.model.Signal;
@@ -9,14 +10,14 @@ public class VerilogEmulatedModelPin
 {
        private final IOPort verilogPort;
        private final int portIndex;
-       private final PinNameBit pinbit;
+       private final Set<PinNameBit> pinbits;
        private final Type type;
 
-       public VerilogEmulatedModelPin(IOPort verilogPort, int portIndex, PinNameBit pinbit, Type type)
+       public VerilogEmulatedModelPin(IOPort verilogPort, int portIndex, Set<PinNameBit> pinbits, Type type)
        {
                this.verilogPort = Objects.requireNonNull(verilogPort);
                this.portIndex = portIndex;
-               this.pinbit = Objects.requireNonNull(pinbit);
+               this.pinbits = Set.copyOf(pinbits);
                this.type = Objects.requireNonNull(type);
 
                check();
@@ -57,9 +58,9 @@ public class VerilogEmulatedModelPin
                return portIndex;
        }
 
-       public PinNameBit getPinbit()
+       public Set<PinNameBit> getPinbits()
        {
-               return pinbit;
+               return pinbits;
        }
 
        public Type getType()
@@ -72,7 +73,7 @@ public class VerilogEmulatedModelPin
        {
                final int prime = 31;
                int result = 1;
-               result = prime * result + ((pinbit == null) ? 0 : pinbit.hashCode());
+               result = prime * result + ((pinbits == null) ? 0 : pinbits.hashCode());
                result = prime * result + portIndex;
                result = prime * result + ((type == null) ? 0 : type.hashCode());
                result = prime * result + ((verilogPort == null) ? 0 : verilogPort.hashCode());
@@ -89,11 +90,11 @@ public class VerilogEmulatedModelPin
                if (getClass() != obj.getClass())
                        return false;
                VerilogEmulatedModelPin other = (VerilogEmulatedModelPin) obj;
-               if (pinbit == null)
+               if (pinbits == null)
                {
-                       if (other.pinbit != null)
+                       if (other.pinbits != null)
                                return false;
-               } else if (!pinbit.equals(other.pinbit))
+               } else if (!pinbits.equals(other.pinbits))
                        return false;
                if (portIndex != other.portIndex)
                        return false;
index 6e9decd..3e0f33d 100644 (file)
@@ -24,8 +24,6 @@ import net.mograsim.logic.model.model.components.atomic.ModelClock;
 import net.mograsim.logic.model.model.components.atomic.ModelClock.ModelClockParams;
 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.ModelSplitter;
-import net.mograsim.logic.model.model.components.atomic.ModelSplitter.SplitterParams;
 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;
@@ -34,6 +32,7 @@ import net.mograsim.logic.model.serializing.IdentifyParams;
 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
 import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter;
+import net.mograsim.logic.model.verilog.helper.UnionFind;
 import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
 
 public class ExportAm2900
@@ -41,108 +40,69 @@ public class ExportAm2900
        public static void main(String[] args) throws IOException
        {
                Am2900Loader.setup();
+               Path target;
+               String rootComponentID;
                try (Scanner sysin = new Scanner(System.in))
                {
                        System.out.print("Directory to export Verilog into >");
-                       Path target = Paths.get(sysin.nextLine());
+                       target = Paths.get(sysin.nextLine());
                        if (!Files.exists(target))
                                Files.createDirectories(target);
                        else if (!Files.isDirectory(target))
                                throw new IllegalArgumentException("Target exists and is not a directory");
 
                        System.out.print("Component ID to serialize recursively >");
-                       String rootComponentID = sysin.nextLine();
-                       {
-                               if (!Files.exists(target))
-                                       Files.createDirectories(target);
-                               else if (!Files.isDirectory(target))
-                                       throw new IllegalArgumentException("Target exists and is not a directory");
+                       rootComponentID = sysin.nextLine();
+               }
 
-                               LogicModelModifiable model = new LogicModelModifiable();
+               if (!Files.exists(target))
+                       Files.createDirectories(target);
+               else if (!Files.isDirectory(target))
+                       throw new IllegalArgumentException("Target exists and is not a directory");
 
-                               Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings = Stream.of(//
-                                               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 ModelWireCrossPoint(model, 1), //
-                                               new ModelWireCrossPoint(model, 2), //
-                                               new ModelWireCrossPoint(model, 4), //
-                                               new ModelWireCrossPoint(model, 9), //
-                                               new ModelWireCrossPoint(model, 12), //
-                                               new ModelWireCrossPoint(model, 16), //
-                                               new ModelSplitter(model, new SplitterParams(2, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(2, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(2, Orientation.UP)), //
-                                               new ModelSplitter(model, new SplitterParams(2, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(3, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(3, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(3, Orientation.UP)), //
-                                               new ModelSplitter(model, new SplitterParams(3, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(3, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(4, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(4, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(4, Orientation.UP)), //
-                                               new ModelSplitter(model, new SplitterParams(4, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(4, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(5, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(5, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(6, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(6, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(6, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(6, Orientation.UP)), //
-                                               new ModelSplitter(model, new SplitterParams(6, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(8, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(8, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(9, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(9, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(12, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(12, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(12, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(12, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(13, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(13, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(16, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(16, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(16, Orientation.UP)), //
-                                               new ModelSplitter(model, new SplitterParams(16, Orientation.DOWN)), //
-                                               new ModelSplitter(model, new SplitterParams(16, Orientation.DOWN_ALT)), //
-                                               new ModelSplitter(model, new SplitterParams(80, Orientation.LEFT)), //
-                                               new ModelSplitter(model, new SplitterParams(80, Orientation.RIGHT)), //
-                                               new ModelSplitter(model, new SplitterParams(80, Orientation.UP_ALT)), //
-                                               new ModelClock(model, new ModelClockParams(7000, Orientation.RIGHT)), //
-                                               new ModelTextComponent(model, "A bus"), //
-                                               new ModelTextComponent(model, "MPM addr"), //
-                                               new ModelTextComponent(model, "D bus"), //
-                                               new ModelAm2900MainMemory(model, null), //
-                                               new ModelAm2900MPROM(model, null), //
-                                               new ModelAm2900MicroInstructionMemory(model, null), //
-                                               new ModelBitDisplay(model, 12), //
-                                               new ModelBitDisplay(model, 16)//
-                               ).map(c ->
-                               {
-                                       String id = c.getIDForSerializing(new IdentifyParams());
-                                       JsonElement params = c.getParamsForSerializingJSON(new IdentifyParams());
-                                       ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping = ModelComponentToVerilogConverter
-                                                       .generateCanonicalDeclarationMapping(c, id, params, ModelComponentToVerilogConverter
-                                                                       .sanitizeVerilogID("mgs_" + id + (params.isJsonNull() ? "" : "_" + params)));
-                                       return generateCanonicalDeclarationMapping;
-                               }).collect(Collectors.toSet());
+               LogicModelModifiable model = new LogicModelModifiable();
 
-                               ModelComponent root = IndirectModelComponentCreator.createComponent(model, rootComponentID);
-                               Set<VerilogComponentImplementation> convertResult = ModelComponentToVerilogConverter.convert(atomicComponentMappings,
-                                               Set.of(root), "mgs_conv_");
-                               for (VerilogComponentImplementation convertedComponent : convertResult)
-                                       Files.writeString(target.resolve(convertedComponent.getDeclaration().getID() + ".v"),
-                                                       convertedComponent.toVerilogCode());
-                       }
-               }
+               Set<ModelComponentToVerilogComponentDeclarationMapping> atomicComponentMappings = Stream.of(//
+                               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 ModelWireCrossPoint(model, 1), //
+                               new ModelWireCrossPoint(model, 2), //
+                               new ModelWireCrossPoint(model, 4), //
+                               new ModelWireCrossPoint(model, 9), //
+                               new ModelWireCrossPoint(model, 12), //
+                               new ModelWireCrossPoint(model, 16), //
+                               new ModelClock(model, new ModelClockParams(7000, Orientation.RIGHT)), //
+                               new ModelTextComponent(model, "A bus"), //
+                               new ModelTextComponent(model, "MPM addr"), //
+                               new ModelTextComponent(model, "D bus"), //
+                               new ModelAm2900MainMemory(model, null), //
+                               new ModelAm2900MPROM(model, null), //
+                               new ModelAm2900MicroInstructionMemory(model, null), //
+                               new ModelBitDisplay(model, 12), //
+                               new ModelBitDisplay(model, 16)//
+               ).map(c ->
+               {
+                       String id = c.getIDForSerializing(new IdentifyParams());
+                       JsonElement params = c.getParamsForSerializingJSON(new IdentifyParams());
+                       ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping = ModelComponentToVerilogConverter
+                                       .generateCanonicalDeclarationMapping(c, new UnionFind<>(), id, params,
+                                                       ModelComponentToVerilogConverter.sanitizeVerilogID("mgs_" + id + (params.isJsonNull() ? "" : "_" + params)));
+                       return generateCanonicalDeclarationMapping;
+               }).collect(Collectors.toSet());
+
+               ModelComponent root = IndirectModelComponentCreator.createComponent(model, rootComponentID);
+               Set<VerilogComponentImplementation> convertResult = ModelComponentToVerilogConverter.convert(atomicComponentMappings, Set.of(root),
+                               "mgs_conv_");
+               for (VerilogComponentImplementation convertedComponent : convertResult)
+                       Files.writeString(target.resolve(convertedComponent.getDeclaration().getID() + ".v"), convertedComponent.toVerilogCode());
        }
 }