示例#1
0
        /// <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);
        }
示例#2
0
        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);
            }
        }