Exemple #1
0
        /// <summary>
        /// Restore wire linkage
        /// </summary>
        /// <param name="model"></param>
        public static void RestoreLinkage(LogisimModel model)
        {
            foreach (var wire in model.wires)
            {
                foreach (var comp in model.comps)
                {
                    if (wire.sourceId == comp.id)
                    {
                        wire.source = comp;
                    }
                    if (wire.destId == comp.id)
                    {
                        wire.dest = comp;
                    }
                }

                foreach (var vias in model.viases)
                {
                    if (wire.sourceId == vias.id)
                    {
                        wire.source = vias;
                    }
                    if (wire.destId == vias.id)
                    {
                        wire.dest = vias;
                    }
                }
            }
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
 private static LogisimVias GetViasByLoc(LogisimModel model, Point loc)
 {
     foreach (var vias in model.viases)
     {
         if (vias.loc.Equals(loc))
         {
             return(vias);
         }
     }
     return(null);
 }
Exemple #4
0
        private static LogisimComp ViasIntersectComp(LogisimModel model, LogisimVias vias)
        {
            foreach (var comp in model.comps)
            {
                Rectangle rect = new Rectangle(comp.loc.X, comp.loc.Y, CompSize + 2, CompSize + 2);

                if (rect.Contains(vias.loc))
                {
                    return(comp);
                }
            }

            return(null);
        }
Exemple #5
0
        /// <summary>
        /// Connect wires with components
        /// </summary>
        /// <param name="model"></param>
        private static void PreProcessing(LogisimModel model)
        {
            foreach (var wire in model.wires)
            {
                foreach (var comp in model.comps)
                {
                    if (comp.loc.Equals(wire.From()) && wire.source.id < 0)
                    {
                        wire.source = comp;
                    }

                    if (comp.loc.Equals(wire.To()) && wire.dest.id < 0)
                    {
                        wire.dest = comp;
                    }
                }
            }
        }
Exemple #6
0
        public static void DumpLogisimModel(LogisimModel model)
        {
            Console.WriteLine(model.name + ":");

            foreach (var comp in model.comps)
            {
                comp.Dump();
            }

            foreach (var wire in model.wires)
            {
                wire.Dump();
            }

            foreach (var vias in model.viases)
            {
                vias.Dump();
            }
        }
Exemple #7
0
        public static int GetNextId(LogisimModel model)
        {
            int id = -1;

            foreach (var comp in model.comps)
            {
                if (comp.id > id)
                {
                    id = comp.id;
                }
            }

            foreach (var vias in model.viases)
            {
                if (vias.id > id)
                {
                    id = vias.id;
                }
            }

            return(id + 1);
        }
Exemple #8
0
        /// <summary>
        /// Convert logisim model to yEd Xml
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static XmlDocument ToYed(LogisimModel model)
        {
            XmlDocument doc = new XmlDocument();

            // Create an XML declaration
            XmlDeclaration xmldecl;

            xmldecl = doc.CreateXmlDeclaration("1.0", "UTF-8", "no");

            // Add the new node to the document
            XmlElement root = doc.DocumentElement;

            doc.InsertBefore(xmldecl, root);

            // Convert Logisim Model to Yed Model

            YedModel yed = new YedModel();

            AddYedKeys(yed);

            YedData graphData = new YedData();

            graphData.key      = "d0";
            graphData.xmlSpace = "preserve";

            yed.graph.data.Add(graphData);

            foreach (var comp in model.comps)
            {
                YedNode node = new YedNode();
                node.id = "n" + comp.id.ToString();

                YedData d6 = new YedData();

                node.data.Add(d6);

                d6.key = "d6";

                d6.node          = new YedShapeNode();
                d6.node.geometry = new YedGeometry();
                d6.node.fill     = new YedFill();
                d6.node.label    = new YedNodeLabel();
                d6.node.shape    = new YedShape();

                d6.node.geometry.x      = comp.loc.X;
                d6.node.geometry.y      = comp.loc.Y;
                d6.node.geometry.width  = CompSize;
                d6.node.geometry.height = CompSize;

                if (comp.name == "1")
                {
                    d6.node.fill.color = "#FF6600";
                }
                else if (comp.name == "0")
                {
                    d6.node.fill.color = "#339966";
                }
                else
                {
                    d6.node.fill.color = "#FFCC00";
                }
                d6.node.fill.transparent = false;

                d6.node.label.text = comp.name;

                d6.node.shape.type = "rectangle";

                yed.graph.nodes.Add(node);
            }

            foreach (var vias in model.viases)
            {
                YedNode node = new YedNode();
                node.id = "n" + vias.id.ToString();

                YedData d6 = new YedData();

                node.data.Add(d6);

                d6.key = "d6";

                d6.node          = new YedShapeNode();
                d6.node.geometry = new YedGeometry();
                d6.node.fill     = new YedFill();
                d6.node.shape    = new YedShape();

                d6.node.geometry.width  = 5;
                d6.node.geometry.height = 5;
                d6.node.geometry.x      = vias.loc.X - d6.node.geometry.width / 2;
                d6.node.geometry.y      = vias.loc.Y - d6.node.geometry.height / 2;

                d6.node.fill.color       = "#FFCC00";
                d6.node.fill.transparent = false;

                d6.node.shape.type = "ellipse";

                yed.graph.nodes.Add(node);
            }

            int edgeId = 0;     // Doesn't matter..

            foreach (var wire in model.wires)
            {
                // Skip wires to nowhere
                if (wire.source.id < 0 || wire.dest.id < 0)
                {
                    continue;
                }

                YedEdge edge = new YedEdge();
                edge.id     = "e" + edgeId.ToString();
                edge.source = "n" + wire.source.id.ToString();
                edge.target = "n" + wire.dest.id.ToString();
                edgeId++;

                YedData d10 = new YedData();
                d10.key = "d10";
                edge.data.Add(d10);

                d10.edge = new YedPolyLineEdge();

                if (wire.path.Count > 2)
                {
                    for (int i = 1; i < wire.path.Count - 1; i++)
                    {
                        d10.edge.path.points.Add(new YedPoint(wire.path[i].X, wire.path[i].Y));
                    }
                }

                if (wire.name != "")
                {
                    d10.edge.label = new YedEdgeLabel(wire.name);
                }

                yed.graph.edges.Add(edge);
            }

            // Convert Yed Model to Xml

            var nav = doc.CreateNavigator();
            var ns  = new XmlSerializerNamespaces();

            ns.Add("java", "http://www.yworks.com/xml/yfiles-common/1.0/java");
            ns.Add("sys", "http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0");
            ns.Add("x", "http://www.yworks.com/xml/yfiles-common/markup/2.0");
            ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
            ns.Add("y", "http://www.yworks.com/xml/graphml");
            ns.Add("yed", "http://www.yworks.com/xml/yed/3");

            using (var writer = nav.AppendChild())
            {
                var ser = new XmlSerializer(typeof(YedModel));
                ser.Serialize(writer, yed, ns);
            }

            return(doc);
        }
Exemple #9
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);
        }
Exemple #10
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);
            }
        }
Exemple #11
0
        /// <summary>
        /// Modify model to look nice
        /// </summary>
        /// <param name="model"></param>
        private static void PostProcessing(LogisimModel model)
        {
            int nfetCounter = 1;
            int pfetCounter = 1;

            // Comps

            foreach (var comp in model.comps)
            {
                string facingDefault = "east";

                if (comp.name == "Transistor")
                {
                    if (comp.props.ContainsKey("type"))
                    {
                        if (comp.props["type"] == "n")
                        {
                            comp.name = "nfet_" + nfetCounter.ToString();
                            nfetCounter++;
                        }
                        else
                        {
                            comp.name = "pfet_" + pfetCounter.ToString();
                            pfetCounter++;
                        }
                    }
                    else
                    {
                        comp.name = "pfet_" + pfetCounter.ToString();
                        pfetCounter++;
                    }
                    if (!comp.props.ContainsKey("facing"))
                    {
                        comp.props["facing"] = facingDefault;
                    }
                    switch (comp.props["facing"])
                    {
                    case "north":
                        comp.loc = new Point(
                            comp.loc.X,
                            comp.loc.Y + CompSize - 4);
                        break;

                    case "south":
                        comp.loc = new Point(
                            comp.loc.X,
                            comp.loc.Y - CompSize + 4);
                        break;

                    case "west":
                        comp.loc = new Point(
                            comp.loc.X + CompSize - 4,
                            comp.loc.Y);
                        break;

                    case "east":
                        comp.loc = new Point(
                            comp.loc.X - CompSize + 4,
                            comp.loc.Y);
                        break;
                    }
                }
                else if (comp.name == "Power")
                {
                    comp.name = "1";
                    if (!comp.props.ContainsKey("facing"))
                    {
                        comp.props["facing"] = facingDefault;
                    }
                    if (comp.props["facing"] == "west")
                    {
                        comp.props["facing"] = "east";
                    }
                    else if (comp.props["facing"] == "east")
                    {
                        comp.props["facing"] = "west";
                    }
                }
                else if (comp.name == "Ground")
                {
                    comp.name = "0";
                    if (!comp.props.ContainsKey("facing"))
                    {
                        comp.props["facing"] = facingDefault;
                    }
                    if (comp.props["facing"] == "west")
                    {
                        comp.props["facing"] = "east";
                    }
                    else if (comp.props["facing"] == "east")
                    {
                        comp.props["facing"] = "west";
                    }
                }
                else if (comp.name == "Pin")
                {
                    if (comp.props.ContainsKey("label"))
                    {
                        comp.name = comp.props["label"];
                    }
                    if (!comp.props.ContainsKey("facing"))
                    {
                        comp.props["facing"] = facingDefault;
                    }
                }

                if (comp.props.ContainsKey("facing"))
                {
                    switch (comp.props["facing"])
                    {
                    case "north":
                        comp.loc = new Point(
                            comp.loc.X - CompSize / 2,
                            comp.loc.Y);
                        break;

                    case "south":
                        comp.loc = new Point(
                            comp.loc.X - CompSize / 2,
                            comp.loc.Y - CompSize);
                        break;

                    case "west":
                        comp.loc = new Point(
                            comp.loc.X,
                            comp.loc.Y - CompSize / 2);
                        break;

                    case "east":
                        comp.loc = new Point(
                            comp.loc.X - CompSize,
                            comp.loc.Y - CompSize / 2);
                        break;
                    }
                }

                if (comp.name.Contains("nfet") || comp.name.Contains("pfet"))
                {
                    AddTrans(new Rectangle(comp.loc.X, comp.loc.Y, CompSize, CompSize), comp, model);
                }
            }

            // Link wires with viases

            foreach (var wire in model.wires)
            {
                foreach (var vias in model.viases)
                {
                    if (vias.loc.Equals(wire.From()) && wire.source.id < 0)
                    {
                        wire.source = vias;
                    }

                    if (vias.loc.Equals(wire.To()) && wire.dest.id < 0)
                    {
                        wire.dest = vias;
                    }
                }
            }
        }