Exemplo n.º 1
0
        public void UpdateSubnets(List <Wire> added, List <Wire> removed)
        {
            List <Subnet> checkSplitSubnets = new List <Subnet>();

            foreach (var old in removed)
            {
                var startNet = FindSubnet(old.Pos);
                var endNet   = FindSubnet(old.EndPos);

                // This is null if there was an error removing the wire
                Subnet?removedFromSubnet;
                if (startNet != null && endNet != null)
                {
                    if (startNet == endNet)
                    {
                        // We are removing a wire from a subnet
                        // So here we want to figure out if we have to split this subnet
                        startNet.RemoveWire(old);

                        // If there are wires left, we need to check if
                        // the deletion led to any splits in the subnet
                        if (startNet.Wires.Count > 0)
                        {
                            if (checkSplitSubnets.Contains(startNet) == false)
                            {
                                checkSplitSubnets.Add(startNet);
                            }
                        }

                        removedFromSubnet = startNet;
                    }
                    else
                    {
                        // This is f***ed in more ways than one...
                        Console.WriteLine($"Error! This should not happen! Trying to remove a wire containing to more than one subnet! (Wire: {old}, Subnet1: {startNet}, Subnet2:{endNet})");
                        removedFromSubnet = null;
                    }
                }
                else if (startNet != null)
                {
                    // We are removing from one subnet
                    if (startNet.RemoveWire(old))
                    {
                        Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {startNet})");
                    }

                    removedFromSubnet = startNet;

                    Console.WriteLine($"Removed wire to subnet: {startNet}");
                }
                else if (endNet != null)
                {
                    // We are removing from one subnet
                    if (endNet.RemoveWire(old))
                    {
                        Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {endNet})");
                    }

                    removedFromSubnet = endNet;

                    Console.WriteLine($"Removed wire to subnet: {endNet}");
                }
                else
                {
                    // Here we are removing a wire that didn't belong to any subnet!?
                    Console.WriteLine($"Error! This should not happen! Trying to remove a wire not contained in any subnet! (Wire: {old})");
                    removedFromSubnet = null;
                }

                // If we removed a wire from a subnet, check if we need to deleted that subnet
                if (removedFromSubnet?.Wires.Count <= 0)
                {
                    Console.WriteLine($"Removed subnet: {removedFromSubnet}");
                    LogikUI.Simulation.RemoveSubnet(removedFromSubnet.ID);
                    removedFromSubnet.ID = SubnetID.Invalid;

                    Subnets.Remove(removedFromSubnet);
                }
            }

            List <Subnet>         addedSubnets = new List <Subnet>();
            List <(Wire, Subnet)> addedWiresAndTheirNewSubnet = new List <(Wire, Subnet)>();

            foreach (var @new in added)
            {
                var startNet = FindSubnet(@new.Pos);
                var endNet   = FindSubnet(@new.EndPos);

                Subnet subnetAddedTo;
                if (startNet != null && endNet != null)
                {
                    if (startNet == endNet)
                    {
                        // Here they are the same subnet.
                        // So we just add the wire.
                        startNet.AddWire(@new);
                        subnetAddedTo = startNet;
                    }
                    else
                    {
                        // Figure out what subnet to merge into.
                        var(merged, mergee) = startNet.ID != 0 ?
                                              (startNet, endNet) :
                                              (endNet, startNet);

                        Console.WriteLine($"Merging subnet ({mergee}) into subnet ({merged}).");
                        Subnets.Remove(mergee);
                        merged.Merge(mergee);

                        // Transfer over all of the added wires if there are any
                        for (int i = 0; i < addedWiresAndTheirNewSubnet.Count; i++)
                        {
                            var(wire, subnet) = addedWiresAndTheirNewSubnet[i];
                            if (subnet == mergee)
                            {
                                addedWiresAndTheirNewSubnet[i] = (wire, merged);
                            }
                        }

                        // Don't forget to add the wire that merged these subnets
                        merged.AddWire(@new);
                        subnetAddedTo = merged;

                        Console.WriteLine($"\tResult: {merged}");
                    }
                }
                else if (startNet != null)
                {
                    // Here we just add this wire to the subnet,
                    // it's not going to change anything.
                    startNet.AddWire(@new);
                    subnetAddedTo = startNet;
                    Console.WriteLine($"Added wire to subnet: {startNet}");
                }
                else if (endNet != null)
                {
                    // Here we just add this wire to the subnet,
                    // it's not going to change anything.
                    endNet.AddWire(@new);
                    subnetAddedTo = endNet;
                    Console.WriteLine($"Added wire to subnet: {endNet}");
                }
                else
                {
                    // This means that this wire should be in it's own subnet.
                    // It might get merged into another subnet later though..
                    var sub = new Subnet(0);
                    sub.AddWire(@new);

                    addedSubnets.Add(sub);

                    // NOTE: do we want to do this?
                    Subnets.Add(sub);

                    subnetAddedTo = sub;
                    Console.WriteLine($"Added single wire subnet: {sub}");
                }

                addedWiresAndTheirNewSubnet.Add((@new, subnetAddedTo));
            }

            // Because we have figured out all of the merging we know
            // that all of the subnets in this list will have their own
            // id. When splitting we can only ever create new subnets
            // so we don't have to worry about merging so we give those
            // subnets their id directly when they are created.
            foreach (var addedNet in addedSubnets)
            {
                // Here we should figure out a new subnet id
                addedNet.ID = (SubnetID)SubnetIDCounter++;
                LogikUI.Simulation.AddSubnet(addedNet.ID);
                Console.WriteLine($"Added new subnet: {addedNet}");
            }

            // Here we go though all new wires and their subnet to see if the new wires
            // connects any new components to the subnet.
            foreach (var(wire, subnet) in addedWiresAndTheirNewSubnet)
            {
                foreach (var comp in Gates.Instances)
                {
                    // FIXME: This stackalloc is going to blow up...
                    Span <Vector2i> portLocs = stackalloc Vector2i[Gates.GetNumberOfPorts(comp)];
                    Gates.GetTransformedPorts(comp, portLocs);

                    for (int i = 0; i < portLocs.Length; i++)
                    {
                        var loc = portLocs[i];
                        if (wire.IsConnectionPoint(loc))
                        {
                            if (subnet.ComponentPorts.Contains((comp, i)) == false)
                            {
                                subnet.AddComponent(comp, i);
                                Console.WriteLine($"Added component ({comp}, port: {i}) to the subnet: {subnet}.");
                            }
                        }
                    }
                }
            }

            // Here we check all of the splitting that needs to be done.
            foreach (var split in checkSplitSubnets)
            {
                // Here we need to check if this subnet
                // has to be split into multiple subnets

                if (split.ID == 0)
                {
                    Console.WriteLine($"We don't need to check for splits on this subnet because it has been removed! Subnet: {split}");
                    continue;
                }

                if (split.Wires.Count == 0)
                {
                    Console.WriteLine($"We don't need to try to split a subnet without wires. Subnet: {split}");
                    continue;
                }

                Console.WriteLine($"Checking subnet ({split}) for splits!");

                List <Wire> wiresLeft = new List <Wire>(split.Wires);

                bool assignedOriginal = false;
                var  newSubnets       = new List <Subnet>();

                while (wiresLeft.Count > 0)
                {
Exemplo n.º 2
0
        public void UpdateSubnets(List <Wire> added, List <Wire> removed)
        {
            List <Subnet> addedSubnets   = new List <Subnet>();
            List <Subnet> deletedSubnets = new List <Subnet>();

            // FIXME: Implement equality checks and hash function for subnets or
            // don't use a hashset for this...
            HashSet <Subnet> checkSplitSubnets = new HashSet <Subnet>();

            foreach (var old in removed)
            {
                var startNet = FindSubnet(old.Pos);
                var endNet   = FindSubnet(old.EndPos);

                if (startNet != null && endNet != null)
                {
                    if (startNet == endNet)
                    {
                        // We are removing a wire from a subnet
                        // So here we want to figure out if we have to split this subnet
                        startNet.RemoveWire(old);

                        // If there are no wires left, delete this subnet
                        // otherwise we need to check if the deletion
                        // led to any splits in the subnet
                        if (startNet.Wires.Count == 0)
                        {
                            deletedSubnets.Add(startNet);
                        }
                        else
                        {
                            checkSplitSubnets.Add(startNet);
                        }
                    }
                    else
                    {
                        // This is f***ed in more ways than one...
                        Console.WriteLine($"Error! This should not happen! Trying to remove a wire containing to more than one subnet! (Wire: {old}, Subnet1: {startNet}, Subnet2:{endNet})");
                    }
                }
                else if (startNet != null)
                {
                    // We are removing from one subnet
                    if (startNet.RemoveWire(old))
                    {
                        Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {startNet})");
                    }

                    if (startNet.Wires.Count == 0)
                    {
                        deletedSubnets.Add(startNet);
                    }

                    Console.WriteLine($"Removed wire to subnet: {startNet}");
                }
                else if (endNet != null)
                {
                    // We are removing from one subnet
                    if (endNet.RemoveWire(old))
                    {
                        Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {endNet})");
                    }

                    if (endNet.Wires.Count == 0)
                    {
                        deletedSubnets.Add(endNet);
                    }

                    Console.WriteLine($"Removed wire to subnet: {endNet}");
                }
                else
                {
                    // Here we are removing a wire that didn't belong to any subnet!?
                    Console.WriteLine($"Error! This should not happen! Trying to remove a wire not contained in any subnet! (Wire: {old})");
                }
            }

            foreach (var @new in added)
            {
                var startNet = FindSubnet(@new.Pos);
                var endNet   = FindSubnet(@new.EndPos);

                if (startNet != null && endNet != null)
                {
                    if (startNet == endNet)
                    {
                        // Here they are the same subnet.
                        // So we just add the wire.
                        startNet.AddWire(@new);
                    }
                    else
                    {
                        // Here we need to merge the different subnets.
                        // FIXME: Should ID zero subnets even be allowed here?
                        // Should we check for merges later?
                        // Should we make a list?
                        Subnet merged;
                        if (startNet.ID != 0 && endNet.ID != 0)
                        {
                            Console.WriteLine($"Merging subnet ({endNet}) into subnet ({startNet}).");
                            Subnets.Remove(endNet);
                            startNet.Merge(endNet);
                            merged = startNet;
                        }
                        else if (startNet.ID != 0)
                        {
                            Console.WriteLine($"Merging subnet ({endNet}) into subnet ({startNet}).");
                            Subnets.Remove(endNet);
                            startNet.Merge(endNet);
                            merged = startNet;
                        }
                        else if (endNet.ID != 0)
                        {
                            Console.WriteLine($"Merging subnet ({startNet}) into subnet ({endNet}).");
                            Subnets.Remove(startNet);
                            endNet.Merge(startNet);
                            merged = endNet;
                        }
                        else
                        {
                            Console.WriteLine($"Warn? We are merging two subnets that both have ID zero. Subnet1: {startNet}, Subnet2: {endNet}");
                            Subnets.Remove(endNet);
                            startNet.Merge(endNet);
                            merged = startNet;
                        }

                        // Don't forget to add the wire that merged these subnets
                        merged.AddWire(@new);

                        Console.WriteLine($"\tResult: {startNet}");
                    }
                }
                else if (startNet != null)
                {
                    // Here we just add this wire to the subnet,
                    // it's not going to change anything.
                    startNet.AddWire(@new);
                    Console.WriteLine($"Added wire to subnet: {startNet}");
                }
                else if (endNet != null)
                {
                    // Here we just add this wire to the subnet,
                    // it's not going to change anything.
                    endNet.AddWire(@new);
                    Console.WriteLine($"Added wire to subnet: {endNet}");
                }
                else
                {
                    // This means that this wire should be in it's own subnet.
                    // It might get merged into another subnet later though..
                    var sub = new Subnet(0);
                    sub.AddWire(@new);
                    addedSubnets.Add(sub);

                    // NOTE: do we want to do this?
                    Subnets.Add(sub);
                    Console.WriteLine($"Added single wire subnet: {sub}");
                }
            }

            foreach (var split in checkSplitSubnets)
            {
                // Here we need to check if this subnet
                // has to be split into multiple subnets

                if (split.ID == 0)
                {
                    Console.WriteLine($"We don't need to check for splits on this subnet because it has been removed! Subnet: {split}");
                    continue;
                }

                Console.WriteLine($"Checking subnet ({split}) for splits!");

                List <Wire> wiresLeft = new List <Wire>(split.Wires);

                bool usedSplitSubnet = false;

                bool noSplit             = false;
                var  unclaimedComponents = new List <(InstanceData, int)>(split.ComponentPorts);

                while (wiresLeft.Count > 0)
                {