/// <summary> /// Parse Logisim Xml to model. /// </summary> /// <param name="source">Logisim Circuit</param> /// <returns>Model</returns> public static LogisimModel LoadModel(XmlDocument source) { // Get circuit XmlNode circuit = null; foreach (XmlNode node in source.DocumentElement.ChildNodes) { if (node.Name == "circuit") { circuit = node; break; } } if (circuit == null) { throw new Exception("Invalid format. Missing circuit."); } // Processing LogisimModel model = new LogisimModel(); if (circuit.Attributes["name"] != null) { model.name = circuit.Attributes["name"].Value; } // Get components foreach (XmlNode node in circuit) { if (node.Name == "comp") { LogisimComp comp = new LogisimComp(); if (node.Attributes["lib"] != null) { comp.lib = int.Parse(node.Attributes["lib"].Value); } comp.loc = ParseLoc(node.Attributes["loc"].Value); comp.name = node.Attributes["name"].Value; comp.id = GetNextId(model); foreach (XmlNode a in node) { if (a.Name == "a") { string k = a.Attributes["name"].Value; string v = a.Attributes["val"].Value; comp.props[k] = v; } } model.comps.Add(comp); } } // Get wires foreach (XmlNode node in circuit) { if (node.Name == "wire") { Point start = ParseLoc(node.Attributes["from"].Value); Point end = ParseLoc(node.Attributes["to"].Value); LogisimWire wire = new LogisimWire(start, end); model.wires.Add(wire); } } // Connect wires with components PreProcessing(model); // Get wires interconnections (produce viases) foreach (var wire in model.wires) { foreach (var another in model.wires) { if (wire != another) { if (wire.From().Equals(another.From()) || wire.From().Equals(another.To())) { LogisimVias vias = new LogisimVias(wire.From()); if (!model.ViasExists(vias)) { vias.id = GetNextId(model); model.viases.Add(vias); } } if (wire.To().Equals(another.To()) || wire.To().Equals(another.From())) { LogisimVias vias = new LogisimVias(wire.To()); if (!model.ViasExists(vias)) { vias.id = GetNextId(model); model.viases.Add(vias); } } } } } PostProcessing(model); Reduce(model); DumpLogisimModel(model); return(model); }
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); } }