Example #1
0
        /// <summary>
        /// Read nodes for a component
        /// </summary>
        /// <param name="c">The circuit component</param>
        /// <param name="parameters">The parameters</param>
        /// <param name="index">The index where to start reading, defaults to 0</param>
        public static void ReadNodes(this ICircuitComponent c, SubcircuitPath path, List <Token> parameters, int index = 0)
        {
            int count = c.PinCount;

            // Check that there are enough parameters left to read
            if (parameters.Count < index + count)
            {
                if (parameters.Count > 0)
                {
                    throw new ParseException(parameters[parameters.Count - 1], $"{count} nodes expected");
                }
                throw new ParseException($"Unexpected end of line, {count} nodes expected");
            }

            // Extract the nodes
            CircuitIdentifier[] nodes = new CircuitIdentifier[count];
            for (int i = index; i < index + count; i++)
            {
                if (IsNode(parameters[i]))
                {
                    // Map to a new node if necessary, else make the node local to the current path
                    CircuitIdentifier node = new CircuitIdentifier(parameters[i].image);
                    if (path.NodeMap.TryGetValue(node, out CircuitIdentifier mapped))
                    {
                        node = mapped;
                    }
                    else if (path.InstancePath != null)
                    {
                        node = path.InstancePath.Grow(node);
                    }

                    // Store the node
                    nodes[i] = node;
                }
                else
                {
                    throw new ParseException(parameters[i], "Node expected");
                }
            }

            // Succeeded
            c.Connect(nodes);
        }
        /// <summary>
        /// Read subcircuit definitions
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        public override bool Read(string type, Statement st, Netlist netlist)
        {
            if (st.Parameters.Count < 2)
            {
                throw new ParseException(st.Name, "Subcircuit name expected", false);
            }

            // Create the identifier of the subcircuit definition
            CircuitIdentifier name = new CircuitIdentifier(st.Parameters[0].image);

            if (netlist.Path.DefinitionPath != null)
            {
                name = netlist.Path.DefinitionPath.Grow(name);
            }

            // Extract the subcircuit definition statements
            StatementsToken      body       = (StatementsToken)st.Parameters[st.Parameters.Count - 1];
            SubcircuitDefinition definition = new SubcircuitDefinition(name, body);

            // Parse nodes and parameters
            bool mode = true; // true = nodes, false = parameters

            for (int i = 1; i < st.Parameters.Count - 1; i++)
            {
                if (mode)
                {
                    // After this, only parameters will follow
                    if (st.Parameters[i].image.ToLower() == "params:")
                    {
                        mode = false;
                    }

                    // Parameters have started, so we will keep reading parameters
                    else if (st.Parameters[i].kind == ASSIGNMENT)
                    {
                        mode = false;
                        AssignmentToken at = st.Parameters[i] as AssignmentToken;
                        definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value);
                    }

                    // Still reading nodes
                    else if (ReaderExtension.IsNode(st.Parameters[i]))
                    {
                        definition.Pins.Add(new CircuitIdentifier(st.Parameters[i].image));
                    }
                }
                else if (st.Parameters[i].kind == ASSIGNMENT)
                {
                    AssignmentToken at = st.Parameters[i] as AssignmentToken;
                    definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value);
                }
            }

            // Create a new subcircuit path
            SubcircuitPath orig = netlist.Path;

            netlist.Path = new SubcircuitPath(orig, definition);
            foreach (var s in definition.Body.Statements(StatementType.Subcircuit))
            {
                netlist.Readers.Read(s, netlist);
            }

            // Restore
            netlist.Path = orig;

            // Return values
            netlist.Definitions.Add(definition.Name, definition);
            Generated = definition;
            return(true);
        }
Example #3
0
        /// <summary>
        /// Read
        /// </summary>
        /// <param name="type">Type</param>
        /// <param name="st">Statement</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        public override bool Read(string type, Statement st, Netlist netlist)
        {
            // Initialize
            List <CircuitIdentifier> instancepins = new List <CircuitIdentifier>();
            Dictionary <CircuitIdentifier, Token> instanceparameters = new Dictionary <CircuitIdentifier, Token>();
            CircuitIdentifier definition = null;

            // Get the name
            CircuitIdentifier name;

            if (netlist.Path.InstancePath != null)
            {
                name = netlist.Path.InstancePath.Grow(st.Name.image);
            }
            else
            {
                name = new CircuitIdentifier(st.Name.image);
            }

            // Format: <NAME> <NODES>* <SUBCKT> <PAR1>=<VAL1> ...
            // Or: <NAME> <NODES>* <SUBCKT> params: <PAR1>=<VAL1> ...
            bool mode = true; // true = nodes, false = parameters

            for (int i = 0; i < st.Parameters.Count; i++)
            {
                // Reading nodes
                if (mode)
                {
                    if (ReaderExtension.IsNode(st.Parameters[i]))
                    {
                        instancepins.Add(definition = new CircuitIdentifier(st.Parameters[i].image));
                    }
                    else
                    {
                        instancepins.RemoveAt(instancepins.Count - 1);
                        mode = false;
                    }
                }

                // Reading parameters
                // Don't use ELSE! We still need to read the last parameter
                if (!mode)
                {
                    if (st.Parameters[i].kind == ASSIGNMENT)
                    {
                        AssignmentToken at = st.Parameters[i] as AssignmentToken;
                        switch (at.Name.kind)
                        {
                        case WORD:
                        case IDENTIFIER:
                            instanceparameters.Add(new CircuitIdentifier(at.Name.image), at.Value);
                            break;

                        default:
                            throw new ParseException(at.Name, "Parameter name expected");
                        }
                    }
                }
            }

            // If there are only node-like tokens, then the last one is the definition by default
            if (mode)
            {
                instancepins.RemoveAt(instancepins.Count - 1);
            }

            // Modify the instancepins to be local or use the nodemap
            for (int i = 0; i < instancepins.Count; i++)
            {
                if (netlist.Path.NodeMap.TryGetValue(instancepins[i], out CircuitIdentifier node))
                {
                    instancepins[i] = node;
                }
                else if (netlist.Path.InstancePath != null)
                {
                    instancepins[i] = netlist.Path.InstancePath.Grow(instancepins[i].Name);
                }
            }

            // Find the subcircuit definition
            if (netlist.Path.DefinitionPath != null)
            {
                definition = netlist.Path.DefinitionPath.Grow(definition);
            }
            SubcircuitDefinition subcktdef = netlist.Path.FindDefinition(netlist.Definitions, definition) ??
                                             throw new ParseException(st.Parameters[st.Parameters.Count - 1], "Cannot find subcircuit definition");
            Subcircuit subckt = new Subcircuit(subcktdef, name, instancepins, instanceparameters);

            SubcircuitPath orig = netlist.Path;

            netlist.Path = new SubcircuitPath(netlist, orig, subckt);

            // Read all control statements
            foreach (var s in subcktdef.Body.Statements(StatementType.Control))
            {
                netlist.Readers.Read(s, netlist);
            }

            // Read all model statements
            foreach (var s in subcktdef.Body.Statements(StatementType.Model))
            {
                netlist.Readers.Read(s, netlist);
            }

            // Read all component statements
            foreach (var s in subcktdef.Body.Statements(StatementType.Component))
            {
                netlist.Readers.Read(s, netlist);
            }

            // Restore
            netlist.Path = orig;
            Generated    = subckt;
            return(true);
        }