/// <summary> /// Reduce simple vias connections /// </summary> /// <param name="model"></param> public static void Reduce(LogisimModel model) { bool found = false; do { found = false; foreach (var vias in model.viases) { // Count inputs/outputs for vias int inputCount = 0; int outputCount = 0; LogisimWire wireIn = null; LogisimWire wireOut = null; foreach (var wire in model.wires) { if (wire.dest == vias) { if (wireIn == null) { wireIn = wire; } inputCount++; } if (wire.source == vias) { if (wireOut == null) { wireOut = wire; } outputCount++; } } // If exactly 1/1 - delete vias and reduce wire if (inputCount == 1 && outputCount == 1) { Point last = wireIn.To(); wireIn.path.Remove(last); wireIn.path.AddRange(wireOut.path); wireIn.dest = wireOut.dest; model.wires.Remove(wireOut); model.viases.Remove(vias); if (wireIn.name == "") { wireIn.name = wireOut.name; } found = true; break; } } } while (found); }
private static void AddTrans(Rectangle bbox, LogisimComp comp, LogisimModel model) { LogisimWire source = null; LogisimWire drain = null; LogisimWire gate = null; LogisimVias sourcePad = null; LogisimVias drainPad = null; LogisimVias gatePad = null; int delta = 12; bool br = false; // Gate direction (br? wtf is br?) if (comp.props.ContainsKey("gate")) { br = comp.props["gate"] == "br" ? true : false; } // Facing of drain // TODO: Some translational symmetry here.. make code more compact.. and complicated switch (comp.props["facing"]) { case "north": source = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height + delta), new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height)); drain = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y), new Point(bbox.X + bbox.Width / 2, bbox.Y - delta)); if (br) { gate = new LogisimWire( new Point(bbox.X + bbox.Width + delta, bbox.Y + bbox.Height / 2), new Point(bbox.X + bbox.Width, bbox.Y + bbox.Height / 2)); } else { gate = new LogisimWire( new Point(bbox.X - delta, bbox.Y + bbox.Height / 2), new Point(bbox.X, bbox.Y + bbox.Height / 2)); } break; case "south": source = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y - delta), new Point(bbox.X + bbox.Width / 2, bbox.Y)); drain = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height), new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height + delta)); if (br) { gate = new LogisimWire( new Point(bbox.X + bbox.Width + delta, bbox.Y + bbox.Height / 2), new Point(bbox.X + bbox.Width, bbox.Y + bbox.Height / 2)); } else { gate = new LogisimWire( new Point(bbox.X - delta, bbox.Y + bbox.Height / 2), new Point(bbox.X, bbox.Y + bbox.Height / 2)); } break; case "west": source = new LogisimWire( new Point(bbox.X + bbox.Width + delta, bbox.Y + bbox.Height / 2), new Point(bbox.X + bbox.Width, bbox.Y + bbox.Height / 2)); drain = new LogisimWire( new Point(bbox.X, bbox.Y + bbox.Height / 2), new Point(bbox.X - delta, bbox.Y + bbox.Height / 2)); if (br) { gate = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height + delta), new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height)); } else { gate = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y - delta), new Point(bbox.X + bbox.Width / 2, bbox.Y)); } break; case "east": source = new LogisimWire( new Point(bbox.X - delta, bbox.Y + bbox.Height / 2), new Point(bbox.X, bbox.Y + bbox.Height / 2)); drain = new LogisimWire( new Point(bbox.X + bbox.Width, bbox.Y + bbox.Height / 2), new Point(bbox.X + bbox.Width + delta, bbox.Y + bbox.Height / 2)); if (br) { gate = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height + delta), new Point(bbox.X + bbox.Width / 2, bbox.Y + bbox.Height)); } else { gate = new LogisimWire( new Point(bbox.X + bbox.Width / 2, bbox.Y - delta), new Point(bbox.X + bbox.Width / 2, bbox.Y)); } break; } // Create actual nodes/edges and link them sourcePad = GetViasByLoc(model, source.From()); if (sourcePad == null) { sourcePad = new LogisimVias(source.From()); } drainPad = GetViasByLoc(model, drain.To()); if (drainPad == null) { drainPad = new LogisimVias(drain.To()); } gatePad = GetViasByLoc(model, gate.From()); if (gatePad == null) { gatePad = new LogisimVias(gate.From()); } int nextId = GetNextId(model); sourcePad.id = nextId; drainPad.id = nextId + 1; gatePad.id = nextId + 2; gate.name = "g"; // Required by GraphFlow // Source LogisimComp sourceComp = ViasIntersectComp(model, sourcePad); if (sourceComp != null) { source.source = sourceComp; sourcePad = null; } else { source.source = sourcePad; } source.dest = comp; model.wires.Add(source); if (sourcePad != null) { model.viases.Add(sourcePad); } // Drain LogisimComp drainComp = ViasIntersectComp(model, drainPad); if (drainComp != null) { drain.dest = drainComp; drainPad = null; } else { drain.dest = drainPad; } drain.source = comp; model.wires.Add(drain); if (drainPad != null) { model.viases.Add(drainPad); } // Gate LogisimComp gateComp = ViasIntersectComp(model, gatePad); if (gateComp != null) { gate.source = gateComp; gatePad = null; } else { gate.source = gatePad; } gate.dest = comp; model.wires.Add(gate); if (gatePad != null) { model.viases.Add(gatePad); } }