Пример #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="name">The name of the source to sweep</param>
 /// <param name="start">The starting value</param>
 /// <param name="stop">The stopping value</param>
 /// <param name="step">The step value</param>
 public Sweep(CircuitIdentifier name, double start, double stop, double step) : base()
 {
     ComponentName = name;
     Start         = start;
     Stop          = stop;
     Step          = step;
 }
Пример #2
0
        /// <summary>
        /// Generate a BSIM4 model
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="type">nmos or pmos</param>
        /// <param name="version">Version</param>
        /// <returns></returns>
        public static ICircuitObject GenerateBSIM4Model(CircuitIdentifier name, string type, string version)
        {
            double v = 4.8;

            switch (version)
            {
            case null:
            case "4.8.0": v = 4.8; break;

            default:
                if (!double.TryParse(version, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out v))
                {
                    throw new Exception("Unsupported version \"" + version + "\"");
                }
                break;
            }

            if (Math.Abs(v - 4.8) < 1e-12)
            {
                BSIM4v80Model b4v80 = new BSIM4v80Model(name);
                switch (type)
                {
                case "nmos": b4v80.SetNMOS(true); break;

                case "pmos": b4v80.SetPMOS(true); break;

                default: throw new Exception("Invalid type \"" + type + "\"");
                }
                return(b4v80);
            }
            else
            {
                throw new Exception("Invalid version \"" + v.ToString() + "\"");
            }
        }
Пример #3
0
        /// <summary>
        /// Get both amplitude (in dB) and phase
        /// </summary>
        /// <param name="node">The node name</param>
        /// <param name="reference"></param>
        /// <param name="db">The voltage amplitude in decibels</param>
        /// <param name="phase">The phase in degrees</param>
        public void GetDbPhase(CircuitIdentifier node, CircuitIdentifier reference, out double db, out double phase)
        {
            Complex r = GetPhasor(node, reference);

            db    = 10.0 * Math.Log10(r.Real * r.Real + r.Imaginary * r.Imaginary);
            phase = 180.0 / Math.PI * Math.Atan2(r.Imaginary, r.Real);
        }
Пример #4
0
        /// <summary>
        /// Generate
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateVSW(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            VoltageSwitch vsw = new VoltageSwitch(name);

            vsw.ReadNodes(netlist.Path, parameters);

            // Read the model
            if (parameters.Count < 5)
            {
                throw new ParseException(parameters[3], "Model expected", false);
            }
            vsw.SetModel(netlist.FindModel <VoltageSwitchModel>(parameters[4]));

            // Optional ON or OFF
            if (parameters.Count == 6)
            {
                switch (parameters[5].image.ToLower())
                {
                case "on":
                    vsw.SetOn();
                    break;

                case "off":
                    vsw.SetOff();
                    break;

                default:
                    throw new ParseException(parameters[5], "ON or OFF expected");
                }
            }
            return(vsw);
        }
Пример #5
0
        /// <summary>
        /// Generate a mutual inductance
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateMut(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            MutualInductance mut = new MutualInductance(name);

            switch (parameters.Count)
            {
            case 0: throw new ParseException($"Inductor name expected for mutual inductance \"{name}\"");

            case 1: throw new ParseException(parameters[0], "Inductor name expected", false);

            case 2: throw new ParseException(parameters[1], "Coupling factor expected", false);
            }

            // Read two inductors
            if (!ReaderExtension.IsName(parameters[0]))
            {
                throw new ParseException(parameters[0], "Component name expected");
            }
            mut.MUTind1 = new CircuitIdentifier(parameters[0].image);
            if (!ReaderExtension.IsName(parameters[1]))
            {
                throw new ParseException(parameters[1], "Component name expected");
            }
            mut.MUTind2 = new CircuitIdentifier(parameters[1].image);
            mut.MUTcoupling.Set(netlist.ParseDouble(parameters[2]));
            return(mut);
        }
Пример #6
0
        /// <summary>
        /// Get the voltage of a node in DC or Transient analysis
        /// </summary>
        /// <param name="node">The node name</param>
        /// <param name="reference">The reference (null if no reference)</param>
        /// <returns></returns>
        public double GetVoltage(CircuitIdentifier node, CircuitIdentifier reference = null)
        {
            double result = 0.0;

            // Get the positive node
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (Circuit.Nodes.Contains(node))
            {
                int index = Circuit.Nodes[node].Index;
                result = Circuit.State.Real.Solution[index];
            }
            else
            {
                throw new CircuitException($"Could not find node '{node}'");
            }

            // Get the negative node
            if (reference != null)
            {
                if (Circuit.Nodes.Contains(reference))
                {
                    int index = Circuit.Nodes[reference].Index;
                    result -= Circuit.State.Real.Solution[index];
                }
                else
                {
                    throw new CircuitException($"Could not find node '{reference}'");
                }
            }

            return(result);
        }
Пример #7
0
        /// <summary>
        /// Test a circuit object for all its parameters
        /// </summary>
        /// <param name="n">The netlist</param>
        /// <param name="name">The name of the object</param>
        /// <param name="names">The parameter names</param>
        /// <param name="values">The parameter values</param>
        /// <param name="nodes">The nodes (optional)</param>
        /// <returns></returns>
        protected T Test <T>(Netlist n, CircuitIdentifier name, string[] names = null, double[] values = null, CircuitIdentifier[] nodes = null)
        {
            var obj = n.Circuit.Objects[name];

            Assert.AreEqual(typeof(T), obj.GetType());

            // Test all parameters
            if (names != null)
            {
                TestParameters((IParameterized)obj, names, values);
            }

            // Test all nodes
            if (nodes != null)
            {
                TestNodes((ICircuitComponent)obj, nodes);
            }

            // Make sure there are no warnings
            if (CircuitWarning.Warnings.Count > 0)
            {
                throw new Exception("Warning: " + CircuitWarning.Warnings[0]);
            }
            return((T)obj);
        }
Пример #8
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)
        {
            // Apply the change to the circuit
            CircuitIdentifier id;

            if (netlist.Path.InstancePath != null)
            {
                id = netlist.Path.InstancePath.Grow(st.Name.image);
            }
            else
            {
                id = new CircuitIdentifier(st.Name.image);
            }
            ICircuitObject result = Generate(type, id, st.Parameters, netlist);

            Generated = result;
            if (result != null)
            {
                // Add the circuit component
                netlist.Circuit.Objects.Add(result);
                return(true);
            }
            else
            {
                return(false);
            }
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="name">The name of the current controlled current source</param>
 /// <param name="pos">The positive node</param>
 /// <param name="neg">The negative node</param>
 /// <param name="vsource">The name of the voltage source</param>
 /// <param name="gain">The current gain</param>
 public CurrentControlledCurrentsource(CircuitIdentifier name, CircuitIdentifier pos, CircuitIdentifier neg, CircuitIdentifier vsource, double gain) : base(name)
 {
     Priority = -1;
     Connect(pos, neg);
     CCCScoeff.Set(gain);
     CCCScontName = vsource;
 }
Пример #10
0
        /// <summary>
        /// Generate the mosfet instance
        /// </summary>
        /// <param name="type">Type</param>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected override ICircuitObject Generate(string type, CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            // Errors
            switch (parameters.Count)
            {
            case 0: throw new ParseException($"Node expected for component {name}");

            case 1:
            case 2:
            case 3: throw new ParseException(parameters[parameters.Count - 1], "Node expected", false);

            case 4: throw new ParseException(parameters[3], "Model name expected");
            }

            // Get the model and generate a component for it
            ICircuitObject    model  = netlist.Path.FindModel <ICircuitObject>(netlist.Circuit.Objects, new CircuitIdentifier(parameters[4].image));
            ICircuitComponent mosfet = null;

            if (Mosfets.ContainsKey(model.GetType()))
            {
                mosfet = Mosfets[model.GetType()].Invoke(name, model);
            }
            else
            {
                throw new ParseException(parameters[4], "Invalid model");
            }

            // The rest is all just parameters
            mosfet.ReadNodes(netlist.Path, parameters);
            netlist.ReadParameters((IParameterized)mosfet, parameters, 4);
            return(mosfet);
        }
Пример #11
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="definition">The definition</param>
 /// <param name="name">Name identifier</param>
 public Subcircuit(SubcircuitDefinition definition, CircuitIdentifier name, List <CircuitIdentifier> pins, Dictionary <CircuitIdentifier, Token> parameters = null)
 {
     Definition = definition;
     Name       = name;
     Pins       = pins;
     Parameters = parameters;
 }
Пример #12
0
        /// <summary>
        /// Find a model using the current scope rules
        /// </summary>
        /// <param name="id">Identifier of the model</param>
        /// <returns></returns>
        public T FindModel <T>(CircuitObjects obj, CircuitIdentifier id) where T : class, ICircuitObject
        {
            ICircuitObject co;
            T model = null;
            CircuitIdentifier orig = id;

            switch (ModelScope)
            {
            case ScopeRule.Descend:

                // Find the identifier in all parent paths, starting at the current level
                while (id != null)
                {
                    // Try to find the subcircuit
                    if (obj.TryGetObject(id, out co))
                    {
                        model = co as T;
                        if (model != null)
                        {
                            return(model);
                        }
                    }

                    // We didn't find the model yet, so try the parent path
                    id = id.Shrink();
                }
                break;

            case ScopeRule.GlobalLocal:

                // Find the model locally
                if (obj.TryGetObject(id, out co))
                {
                    model = co as T;
                    if (model != null)
                    {
                        return(model);
                    }
                }

                // Find the model globally
                if (id.Path.Length > 1)
                {
                    id = new CircuitIdentifier(id.Name);
                    if (obj.TryGetObject(id, out co))
                    {
                        model = co as T;
                        if (model != null)
                        {
                            return(model);
                        }
                    }
                }
                break;
            }

            throw new ParseException($"Cannot find model \"{orig}\"");
        }
Пример #13
0
        /// <summary>
        /// Generate a switch
        /// </summary>
        /// <param name="type">Type</param>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected override ICircuitObject Generate(string type, CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            switch (type)
            {
            case "s": return(GenerateVSW(name, parameters, netlist));

            case "w": return(GenerateCSW(name, parameters, netlist));
            }
            return(null);
        }
Пример #14
0
 /// <summary>
 /// Test the nodes of a circuitcomponent
 /// </summary>
 /// <param name="c">The component</param>
 /// <param name="nodes">The expected node names</param>
 protected void TestNodes(ICircuitComponent c, CircuitIdentifier[] nodes)
 {
     // Test all nodes
     for (int i = 0; i < nodes.Length; i++)
     {
         CircuitIdentifier expected = nodes[i];
         CircuitIdentifier actual   = c.GetNode(i);
         Assert.AreEqual(expected, actual);
     }
 }
Пример #15
0
        /// <summary>
        /// Generate a new model
        /// </summary>
        /// <param name="name">The model name</param>
        /// <param name="type">The type</param>
        /// <returns></returns>
        protected override ICircuitObject GenerateModel(CircuitIdentifier name, string type)
        {
            switch (type)
            {
            case "r": return(new ResistorModel(name));

            case "c": return(new CapacitorModel(name));
            }
            return(null);
        }
Пример #16
0
        /// <summary>
        /// Read
        /// </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)
        {
            // Get the nodes
            CircuitIdentifier node, reference = null;

            switch (st.Parameters.Count)
            {
            case 0:
                throw new ParseException(st.Name, "Node expected", false);

            case 2:
                if (!ReaderExtension.IsNode(st.Parameters[1]))
                {
                    throw new ParseException(st.Parameters[1], "Node expected");
                }
                reference = new CircuitIdentifier(st.Parameters[1].image);
                goto case 1;

            case 1:
                if (!ReaderExtension.IsNode(st.Parameters[0]))
                {
                    throw new ParseException(st.Parameters[0], "Node expected");
                }
                node = new CircuitIdentifier(st.Parameters[0].image);
                break;

            default:
                throw new ParseException(st.Name, "Too many nodes specified", false);
            }

            // Add to the exports
            Export ve = null;

            switch (type)
            {
            case "v": ve = new VoltageExport(node, reference); break;

            case "vr": ve = new VoltageRealExport(node, reference); break;

            case "vi": ve = new VoltageImaginaryExport(node, reference); break;

            case "vdb": ve = new VoltageDecibelExport(node, reference); break;

            case "vp": ve = new VoltagePhaseExport(node, reference); break;
            }

            if (ve != null)
            {
                netlist.Exports.Add(ve);
            }
            Generated = ve;
            return(true);
        }
Пример #17
0
        /// <summary>
        /// Generate
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateVCCS(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            VoltageControlledCurrentsource vccs = new VoltageControlledCurrentsource(name);

            vccs.ReadNodes(netlist.Path, parameters);

            if (parameters.Count < 5)
            {
                throw new ParseException(parameters[3], "Value expected", false);
            }
            vccs.VCCScoeff.Set(netlist.ParseDouble(parameters[4]));
            return(vccs);
        }
Пример #18
0
        /// <summary>
        /// Generate the resistor, inductor, capacitor or mutual inductance
        /// </summary>
        /// <param name="type">Type</param>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected override ICircuitObject Generate(string type, CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            switch (type)
            {
            case "r": return(GenerateRes(name, parameters, netlist));

            case "l": return(GenerateInd(name, parameters, netlist));

            case "c": return(GenerateCap(name, parameters, netlist));

            case "k": return(GenerateMut(name, parameters, netlist));
            }
            return(null);
        }
Пример #19
0
        /// <summary>
        /// Generate a current source
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateISRC(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            Currentsource isrc = new Currentsource(name);

            isrc.ReadNodes(netlist.Path, parameters);

            // We can have a value or just DC
            for (int i = 2; i < parameters.Count; i++)
            {
                // DC specification
                if (i == 2 && parameters[i].image.ToLower() == "dc")
                {
                    i++;
                    isrc.ISRCdcValue.Set(netlist.ParseDouble(parameters[i]));
                }
                else if (i == 2 && ReaderExtension.IsValue(parameters[i]))
                {
                    isrc.ISRCdcValue.Set(netlist.ParseDouble(parameters[i]));
                }

                // AC specification
                else if (parameters[i].image.ToLower() == "ac")
                {
                    i++;
                    isrc.ISRCacMag.Set(netlist.ParseDouble(parameters[i]));

                    // Look forward for one more value
                    if (i + 1 < parameters.Count && ReaderExtension.IsValue(parameters[i + 1]))
                    {
                        i++;
                        isrc.ISRCacPhase.Set(netlist.ParseDouble(parameters[i]));
                    }
                }

                // Waveforms
                else if (parameters[i].kind == BRACKET)
                {
                    // Find the reader
                    BracketToken bt = parameters[i] as BracketToken;
                    Statement    st = new Statement(StatementType.Waveform, bt.Name, bt.Parameters);
                    isrc.ISRCwaveform = (IWaveform)netlist.Readers.Read(st, netlist);
                }
                else
                {
                    throw new ParseException(parameters[i], "Unrecognized parameter");
                }
            }

            return(isrc);
        }
Пример #20
0
        /// <summary>
        /// Generate a new model
        /// </summary>
        /// <param name="name">Model name</param>
        /// <param name="type">Model type</param>
        /// <returns></returns>
        protected override ICircuitObject GenerateModel(CircuitIdentifier name, string type)
        {
            BJTModel model = new BJTModel(name);

            if (type == "npn")
            {
                model.SetNPN(true);
            }
            else if (type == "pnp")
            {
                model.SetPNP(true);
            }
            return(model);
        }
Пример #21
0
        /// <summary>
        /// Generate a BSIM3 model
        /// </summary>
        /// <param name="name">Name of the parameter</param>
        /// <param name="type">Type of the parameter</param>
        /// <param name="version">Version of the parameter</param>
        /// <returns></returns>
        public static ICircuitObject GenerateBSIM3Model(CircuitIdentifier name, string type, string version)
        {
            double v = 3.3;

            switch (version)
            {
            case null:
            case "3.3.0": v = 3.3; break;

            case "3.2.4": v = 3.24; break;

            default:
                if (!double.TryParse(version, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out v))
                {
                    throw new Exception("Unsupported version \"" + version + "\"");
                }
                break;
            }

            if (Math.Abs(v - 3.3) < 1e-12)
            {
                var b3v30 = new BSIM3v30Model(name);
                switch (type)
                {
                case "nmos": b3v30.SetNMOS(true); break;

                case "pmos": b3v30.SetPMOS(true); break;

                default: throw new Exception("Invalid type \"" + type + "\"");
                }
                return(b3v30);
            }
            else if (Math.Abs(v - 3.24) < 1e-12)
            {
                var b3v24 = new BSIM3v24Model(name);
                switch (type)
                {
                case "nmos": b3v24.SetNMOS(true); break;

                case "pmos": b3v24.SetPMOS(true); break;

                default: throw new Exception("Invalid type \"" + type + "\"");
                }
                return(b3v24);
            }
            else
            {
                throw new Exception("Unrecognized version \"" + v.ToString() + "\"");
            }
        }
Пример #22
0
        /// <summary>
        /// Generate a capacitor
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateCap(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            Capacitor cap = new Capacitor(name);

            cap.ReadNodes(netlist.Path, parameters);

            // Search for a parameter IC, which is common for both types of capacitors
            for (int i = 3; i < parameters.Count; i++)
            {
                if (parameters[i].kind == ASSIGNMENT)
                {
                    AssignmentToken at = parameters[i] as AssignmentToken;
                    if (at.Name.image.ToLower() == "ic")
                    {
                        double ic = netlist.ParseDouble(at.Value);
                        cap.CAPinitCond.Set(ic);
                        parameters.RemoveAt(i);
                        break;
                    }
                }
            }

            // The rest is just dependent on the number of parameters
            if (parameters.Count == 3)
            {
                cap.CAPcapac.Set(netlist.ParseDouble(parameters[2]));
            }
            else
            {
                cap.SetModel(netlist.FindModel <CapacitorModel>(parameters[2]));
                switch (parameters[2].kind)
                {
                case WORD:
                case IDENTIFIER:
                    cap.SetModel(netlist.Path.FindModel <CapacitorModel>(netlist.Circuit.Objects, new CircuitIdentifier(parameters[2].image)));
                    break;

                default:
                    throw new ParseException(parameters[2], "Model name expected");
                }
                netlist.ReadParameters(cap, parameters, 2);
                if (!cap.CAPlength.Given)
                {
                    throw new ParseException(parameters[1], "L needs to be specified", false);
                }
            }

            return(cap);
        }
Пример #23
0
        /// <summary>
        /// BSIM1 model generator
        /// Version is ignored
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="type">nmos or pmos</param>
        /// <param name="version">Version</param>
        /// <returns></returns>
        public static ICircuitObject GenerateBSIM1Model(CircuitIdentifier name, string type, string version)
        {
            BSIM1Model model = new BSIM1Model(name);

            switch (type)
            {
            case "nmos": model.SetNMOS(true); break;

            case "pmos": model.SetPMOS(true); break;

            default:
                throw new Exception("Invalid type \"" + type + "\"");
            }
            return(model);
        }
Пример #24
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="name">The name of the component</param>
 public CircuitComponent(CircuitIdentifier name)
     : base()
 {
     Name = name;
     if (pins != null)
     {
         connections = new CircuitIdentifier[pins.Length];
         indices     = new int[pins.Length];
     }
     else
     {
         connections = null;
         indices     = null;
     }
 }
Пример #25
0
        /// <summary>
        /// Generate an inductor
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateInd(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            Inductor ind = new Inductor(name);

            ind.ReadNodes(netlist.Path, parameters);

            // Read the value
            if (parameters.Count < 3)
            {
                throw new ParseException(parameters[1], "Inductance expected", false);
            }
            ind.INDinduct.Set(netlist.ParseDouble(parameters[2]));

            // Read initial conditions
            netlist.ReadParameters(ind, parameters, 3);
            return(ind);
        }
Пример #26
0
        /// <summary>
        /// Read
        /// </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)
        {
            // Get the source name
            CircuitIdentifier source;

            switch (st.Parameters.Count)
            {
            case 0:
                throw new ParseException(st.Name, "Voltage source expected", false);

            case 1:
                if (!ReaderExtension.IsName(st.Parameters[0]))
                {
                    throw new ParseException(st.Parameters[0], "Component name expected");
                }
                source = new CircuitIdentifier(st.Parameters[0].image);
                break;

            default:
                throw new ParseException(st.Name, "Too many nodes specified", false);
            }

            // Add to the exports
            Export ce = null;

            switch (type)
            {
            case "i": ce = new CurrentExport(source); break;

            case "ir": ce = new CurrentRealExport(source); break;

            case "ii": ce = new CurrentImaginaryExport(source); break;

            case "im": ce = new CurrentMagnitudeExport(source); break;

            case "ip": ce = new CurrentPhaseExport(source); break;

            case "idb": ce = new CurrentDecibelExport(source); break;
            }
            if (ce != null)
            {
                netlist.Exports.Add(ce);
            }
            Generated = ce;
            return(true);
        }
Пример #27
0
        /// <summary>
        /// Generate a current switch
        /// </summary>
        /// <param name="name">The name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateCSW(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            CurrentSwitch csw = new CurrentSwitch(name);

            csw.ReadNodes(netlist.Path, parameters);
            switch (parameters.Count)
            {
            case 2: throw new ParseException(parameters[1], "Voltage source expected", false);

            case 3: throw new ParseException(parameters[2], "Model expected", false);
            }

            // Get the controlling voltage source
            switch (parameters[2].kind)
            {
            case WORD:
                csw.CSWcontName = new CircuitIdentifier(parameters[2].image);
                break;

            default:
                throw new ParseException(parameters[2], "Voltage source name expected");
            }

            // Get the model
            csw.SetModel(netlist.FindModel <CurrentSwitchModel>(parameters[3]));

            // Optional on or off
            if (parameters.Count > 4)
            {
                switch (parameters[4].image.ToLower())
                {
                case "on":
                    csw.SetOn();
                    break;

                case "off":
                    csw.SetOff();
                    break;

                default:
                    throw new ParseException(parameters[4], "ON or OFF expected");
                }
            }
            return(csw);
        }
Пример #28
0
        /// <summary>
        /// Find a subcircuit definition using the current scope rules
        /// </summary>
        /// <param name="id">Subcircuit definition identifier</param>
        /// <returns></returns>
        public SubcircuitDefinition FindDefinition(Dictionary <CircuitIdentifier, SubcircuitDefinition> definitions, CircuitIdentifier id)
        {
            SubcircuitDefinition result = null;
            CircuitIdentifier    orig   = id;

            switch (DefinitionScope)
            {
            case ScopeRule.Descend:

                while (id != null)
                {
                    // Try to find the definition
                    if (definitions.TryGetValue(id, out result))
                    {
                        return(result);
                    }

                    // Not found, go to the parent path
                    id = id.Shrink();
                }
                break;

            case ScopeRule.GlobalLocal:

                // Try to find the definition locally
                if (definitions.TryGetValue(id, out result))
                {
                    return(result);
                }

                // Try to find the definition globally
                if (id.Path.Length > 1)
                {
                    id = new CircuitIdentifier(id.Name);
                    if (definitions.TryGetValue(id, out result))
                    {
                        return(result);
                    }
                }
                break;
            }
            throw new ParseException($"Cannot find subcircuit \"{orig}\"");
        }
Пример #29
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);
        }
Пример #30
0
        /// <summary>
        /// Generate a CCCS
        /// </summary>
        /// <param name="name">Name</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="netlist">Netlist</param>
        /// <returns></returns>
        protected ICircuitObject GenerateCCCS(CircuitIdentifier name, List <Token> parameters, Netlist netlist)
        {
            CurrentControlledCurrentsource cccs = new CurrentControlledCurrentsource(name);

            cccs.ReadNodes(netlist.Path, parameters);
            switch (parameters.Count)
            {
            case 2: throw new ParseException(parameters[1], "Voltage source expected", false);

            case 3: throw new ParseException(parameters[2], "Value expected", false);
            }

            if (!ReaderExtension.IsName(parameters[2]))
            {
                throw new ParseException(parameters[2], "Component name expected");
            }
            cccs.CCCScontName = new CircuitIdentifier(parameters[2].image);
            cccs.CCCScoeff.Set(netlist.ParseDouble(parameters[3]));
            return(cccs);
        }