Esempio n. 1
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var y = Parameters.Admittance;

            if (_time.UseDc)
            {
                BiasingElements.Add(
                    y, -y, -y, y, 1, 0, -1, -1,
                    y, -y, -y, y, 1, 0, -1, 0,
                    1, -1, 1, 1, 1
                    );
            }
            else
            {
                BiasingElements.Add(
                    y, -y, -y, y, 1, 1, -1, -1,
                    y, -y, -y, y, 1, 1, -1, -1
                    );
            }

            var sol = BiasingState.Solution;

            // Calculate inputs
            var input1 = sol[_pos2] - sol[_neg2] + Parameters.Impedance * sol[_br2];
            var input2 = sol[_pos1] - sol[_neg1] + Parameters.Impedance * sol[_br1];

            Signals.SetProbedValues(input1, input2);

            // Update the branch equations
            _elements.Add(Signals.Values[0], Signals.Values[1]);
        }
Esempio n. 2
0
        /// <summary>
        /// Load behavior.
        /// </summary>
        void IBiasingBehavior.Load()
        {
            if (_time.UseDc)
            {
                return;
            }

            _qcap.Value = _value();
            _qcap.Derive();
            var current = _qcap.Derivative;

            // _qcap.Derivative is the current as integrated by the current integration method
            int i;

            for (i = 0; i < _derivatives.Length; i++)
            {
                var g = _derivatives[i]() * _method.Slope;
                _values[i * 2]     = g;
                _values[i * 2 + 1] = -g;
                current           -= g * _derivativeVariables[i].Value;
            }
            _values[i * 2]     = -current;
            _values[i * 2 + 1] = current;
            _elements.Add(_values);
        }
        public Element AddElement(string name)
        {
            var element = new Element(this, name);

            ElementSet.Add(element);
            return(element);
        }
Esempio n. 4
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            double value;

            // Time domain analysis
            if (_method != null)
            {
                // Use the waveform if possible
                if (Waveform != null)
                {
                    value = Waveform.Value;
                }
                else
                {
                    value = Parameters.DcValue * _iteration.SourceFactor;
                }
            }
            else
            {
                // AC or DC analysis use the DC value
                value = Parameters.DcValue * _iteration.SourceFactor;
            }

            // NOTE: Spice 3f5's documentation is IXXXX POS NEG VALUE but in the code it is IXXXX NEG POS VALUE
            // I solved it by inverting the current when loading the rhs vector
            _elements.Add(-value, value);
            Current = value;
        }
Esempio n. 5
0
        /// <inheritdoc/>
        public override void Load()
        {
            base.Load();
            if (_time.UseDc)
            {
                return;
            }

            // Initialize
            _flux.Value = Inductance * Branch.Value;

            // Allow alterations of the flux
            if (UpdateFlux != null)
            {
                var args = new UpdateFluxEventArgs(Inductance, Branch.Value, _flux);
                UpdateFlux.Invoke(this, args);
            }

            // Finally load the Y-matrix
            _flux.Integrate();
            var info = _flux.GetContributions(Inductance);

            _elements.Add(
                -info.Jacobian,
                info.Rhs
                );
        }
Esempio n. 6
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            var laplace = _complex.Laplace;
            var factor  = Complex.Exp(-laplace * Parameters.Delay);

            // Load the Y-matrix and RHS-vector
            _elements.Add(1, -1, 1, -1, -factor, factor);
        }
Esempio n. 7
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            // NOTE: Spice 3f5's documentation is IXXXX POS NEG VALUE but in the code it is IXXXX NEG POS VALUE
            // I solved it by inverting the current when loading the rhs vector
            var value = Parameters.Phasor * Parameters.ParallelMultiplier;

            _elements.Add(-value, value);
        }
Esempio n. 8
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            // Get the current state
            var gNow = CurrentState ? ModelTemperature.OnConductance : ModelTemperature.OffConductance;

            // Load the Y-matrix
            _elements.Add(gNow, -gNow, -gNow, gNow);
        }
Esempio n. 9
0
 /// <summary>
 /// Loads the Y-matrix and right hand side vector.
 /// </summary>
 void IFrequencyBehavior.Load()
 {
     for (var i = 0; i < _derivatives.Length; i++)
     {
         _values[i] = -_derivatives[i]();
     }
     _elements.Add(_values);
     _coreElements.Add(1.0, -1.0, 1.0, -1.0);
 }
Esempio n. 10
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            if (_time.UseDc)
            {
                return;
            }

            // Load Y-matrix
            _elements.Add(-_conductance, -_conductance);
        }
Esempio n. 11
0
 /// <summary>
 /// Loads the Y-matrix and right hand side vector.
 /// </summary>
 void IFrequencyBehavior.Load()
 {
     for (var i = 0; i < _derivatives.Length; i++)
     {
         var g = _derivatives[i]();
         _values[i * 2]     = g;
         _values[i * 2 + 1] = -g;
     }
     _elements.Add(_values);
 }
Esempio n. 12
0
        /// <summary>
        /// Loads the Y-matrix and right hand side vector.
        /// </summary>
        void IFrequencyBehavior.Load()
        {
            var values = new Complex[_derivatives.Length];

            for (var i = 0; i < _derivatives.Length; i++)
            {
                values[i] = -_derivatives[i]();
            }
            _elements.Add(values);
            _coreElements.Add(1.0, -1.0, 1.0, -1.0);
        }
 /// <summary>
 /// Loads the Y-matrix and right hand side vector.
 /// </summary>
 void IFrequencyBehavior.Load()
 {
     var values = new Complex[_derivatives.Length * 2];
     for (var i = 0; i < _derivatives.Length; i++)
     {
         var g = _derivatives[i]();
         values[i * 2] = g;
         values[i * 2 + 1] = -g;
     }
     _elements.Add(values);
 }
Esempio n. 14
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            var     cstate = _complex;
            var     gcpr   = ModelTemperature.CollectorConduct * Parameters.Area;
            var     gepr   = ModelTemperature.EmitterConduct * Parameters.Area;
            var     gpi    = ConductancePi;
            var     gmu    = ConductanceMu;
            Complex gm     = Transconductance;
            var     go     = OutputConductance;
            var     td     = ModelTemperature.ExcessPhaseFactor;

            if (!td.Equals(0)) // Avoid computations
            {
                var arg = td * cstate.Laplace;

                gm += go;
                gm *= Complex.Exp(-arg);
                gm -= go;
            }
            var gx    = ConductanceX;
            var xcpi  = CapBe * cstate.Laplace;
            var xcmu  = CapBc * cstate.Laplace;
            var xcbx  = CapBx * cstate.Laplace;
            var xccs  = CapCs * cstate.Laplace;
            var xcmcb = Geqcb * cstate.Laplace;

            var m = Parameters.ParallelMultiplier;

            _elements.Add(
                gcpr * m,
                (gx + xcbx) * m,
                gepr * m,
                (gmu + go + gcpr + xcmu + xccs + xcbx) * m,
                (gx + gpi + gmu + xcpi + xcmu + xcmcb) * m,
                (gpi + gepr + gm + go + xcpi) * m,
                -gcpr * m,
                -gx * m,
                -gepr * m,
                -gcpr * m,
                (-gmu + gm - xcmu) * m,
                (-gm - go) * m,
                -gx * m,
                (-gmu - xcmu - xcmcb) * m,
                (-gpi - xcpi) * m,
                -gepr * m,
                (-go + xcmcb) * m,
                (-gpi - gm - xcpi - xcmcb) * m,
                xccs * m,
                -xccs * m,
                -xccs * m,
                -xcbx * m,
                -xcbx * m);
        }
        /// <summary>
        /// Loads the Y-matrix and right hand side vector.
        /// </summary>
        void IBiasingBehavior.Load()
        {
            var total = _value();

            for (var i = 0; i < _derivatives.Length; i++)
            {
                var df = _derivatives[i]();
                total     -= _derivativeVariables[i].Value * df;
                _values[i] = -df;
            }
            _elements.Add(_values);
            _coreElements.Add(1.0, -1.0, 1.0, -1.0, total);
        }
Esempio n. 16
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            var laplace = _complex.Laplace;
            var factor  = Complex.Exp(-laplace * Parameters.Delay.Value);
            var y       = Parameters.Admittance;

            _elements.Add(
                y, -y, -1, y, -1,
                -y, y, 1, y, 1, -1, -factor,
                factor, 1, -factor * Parameters.Impedance,
                -factor, factor, -1, 1, -factor * Parameters.Impedance,
                -y, -y);
        }
Esempio n. 17
0
        /// <inheritdoc/>
        protected override void Load()
        {
            base.Load();
            if (_time.UseDc)
            {
                return;
            }

            // Calculate the states
            var vgs = Vgs;
            var vgd = Vgd;

            CalculateStates(vgs, vgd);

            // Integrate and add contributions
            _qgs.Derive();
            var ggs = _qgs.GetContributions(CapGs).Jacobian;
            var cg  = _qgs.Derivative;

            _qgd.Derive();
            var ggd = _qgd.GetContributions(CapGd).Jacobian;

            cg += _qgd.Derivative;
            var cd  = -_qgd.Derivative;
            var cgd = _qgd.Derivative;

            var m = Parameters.ParallelMultiplier;

            ggd *= m;
            ggs *= m;
            var ceqgd = ModelParameters.JFETType * (cgd - ggd * vgd) * m;
            var ceqgs = ModelParameters.JFETType * (cg - cgd - ggs * vgs) * m;
            var cdreq = ModelParameters.JFETType * (cd + cgd) * m;

            _elements.Add(
                // Y-matrix
                -ggd,
                -ggs,
                -ggd,
                -ggs,
                (ggd + ggs),
                ggd,
                ggs,
                // RHS vector
                -ceqgs - ceqgd,
                -cdreq + ceqgd,
                cdreq + ceqgs);
        }
        /// <summary>
        /// Loads the Y-matrix and right hand side vector.
        /// </summary>
        void IBiasingBehavior.Load()
        {
            double[] values = new double[_derivatives.Length];
            var      total  = Voltage = _value();

            int i;

            for (i = 0; i < values.Length; i++)
            {
                var df = _derivatives[i]();
                total    -= _derivativeVariables[i].Value * df;
                values[i] = -df;
            }
            _elements.Add(values);
            _coreElements.Add(1.0, -1.0, 1.0, -1.0, total);
        }
        /// <summary>
        /// Loads the Y-matrix and right hand side vector.
        /// </summary>
        void IBiasingBehavior.Load()
        {
            var total = Current = _value();
            int i;

            for (i = 0; i < _derivatives.Length; i++)
            {
                var df = _derivatives[i]();
                total             -= _derivativeVariables[i].Value * df;
                _values[i * 2]     = df;
                _values[i * 2 + 1] = -df;
            }
            _values[i * 2]     = -total;
            _values[i * 2 + 1] = total;
            _elements.Add(_values);
        }
Esempio n. 20
0
        /// <summary>
        /// Loads the Y-matrix and right-hand side vector.
        /// </summary>
        public void Load()
        {
            // Let us calculate the derivatives and the current
            double voltage    = _variableA.Value - _variableB.Value;
            double current    = Parameters.Iss * (Math.Exp(voltage / Vte) - 1.0);
            double derivative = current / Vte;

            // Load the Y-matrix and RHS vector
            double rhs = current - voltage * derivative;

            _elements.Add(
                // Y-matrix contributions
                derivative, -derivative,
                -derivative, derivative,
                // RHS vector contributions
                -rhs, rhs);
        }
Esempio n. 21
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var sol   = _biasing.Solution;
            var input = sol[_contPosNode] - sol[_contNegNode];

            Signal.SetProbedValues(input);

            if (_time.UseDc)
            {
                BiasingElements.Add(1, -1, 1, -1, -1, 1);
            }
            else
            {
                BiasingElements.Add(1, -1, 1, -1);
                _elements.Add(Signal.Values[0]);
            }
        }
Esempio n. 22
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            // Don't matter for DC analysis
            if (_time.UseDc)
            {
                return;
            }
            var vcap = _variables.Positive.Value - _variables.Negative.Value;

            // Integrate
            _qcap.Value = Capacitance * vcap;
            _qcap.Derive();
            var info = _qcap.GetContributions(Capacitance);
            var geq  = info.Jacobian;
            var ceq  = info.Rhs;

            // Load matrix and rhs vector
            _elements.Add(geq, -geq, -geq, geq, -ceq, ceq);
        }
Esempio n. 23
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            var state = _complex;

            var gspr = ModelTemperature.Conductance * Parameters.Area;
            var geq  = LocalConductance;
            var xceq = LocalCapacitance * state.Laplace.Imaginary;

            // Load Y-matrix
            var m = Parameters.ParallelMultiplier;
            var n = Parameters.SeriesMultiplier;

            geq  *= m / n;
            gspr *= m / n;
            xceq *= m / n;
            _elements.Add(
                gspr, new Complex(geq, xceq), new Complex(geq + gspr, xceq),
                -new Complex(geq, xceq), -new Complex(geq, xceq), -gspr, -gspr);
        }
Esempio n. 24
0
        /// <summary>
        /// Load the Y-matrix and Rhs-vector.
        /// </summary>
        void IBiasingBehavior.Load()
        {
            // First get the current iteration voltage
            var v = _nodeA.Value - _nodeB.Value;

            // Calculate the derivative w.r.t. one of the voltages
            var    isNegative = v < 0;
            var    c          = Math.Pow(Math.Abs(v) / _bp.A, 1.0 / _bp.B);
            double g;

            // If v=0 the derivative is either 0 or infinity (avoid 0^(negative number) = not a number)
            if (v.Equals(0.0))
            {
                g = _bp.B < 1.0 / _bp.A ? double.PositiveInfinity : 0.0;
            }
            else
            {
                g = Math.Pow(Math.Abs(v) / _bp.A, 1.0 / _bp.B - 1.0) / _bp.A;
            }

            // In order to avoid having a singular matrix, we want to have at least a very small value here.
            g = Math.Max(g, _baseConfig.Gmin);

            // If the voltage was reversed, reverse the current back
            if (isNegative)
            {
                c = -c;
            }

            // Load the RHS vector
            c -= g * v;
            _elements.Add(
                // Y-matrix
                g, -g, -g, g,
                // RHS-vector
                c, -c);
        }
Esempio n. 25
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var m   = Parameters.ParallelMultiplier;
            var y   = Parameters.Admittance * m;
            var sol = BiasingState.Solution;

            // Calculate inputs
            var z      = Parameters.Impedance / m;
            var input1 = sol[_pos2] - sol[_neg2] + z * sol[_br2];
            var input2 = sol[_pos1] - sol[_neg1] + z * sol[_br1];

            Signals.SetProbedValues(input1, input2);

            // Apply contributions to the Y-matrix and right-hand side vector
            if (_time.UseDc)
            {
                BiasingElements.Add(
                    y, -y, -y, y, 1, 0, -1, -1,
                    y, -y, -y, y, 1, 0, -1, 0,
                    1, -1, 1, 1, 1
                    );
            }
            else
            {
                BiasingElements.Add(
                    y, -y, -y, y, 1, 1, -1, -1,
                    y, -y, -y, y, 1, 1, -1, -1
                    );
            }
            double c = Signals.InputDerivative;
            double d = -c * z;

            _elements.Add(
                -c, c, d,
                -c, c, d,
                Signals.Values[0], Signals.Values[1]);
        }
Esempio n. 26
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            double value;

            if (_method != null)
            {
                // Use the waveform if possible
                if (Waveform != null)
                {
                    value = Waveform.Value;
                }
                else
                {
                    value = Parameters.DcValue * _iteration.SourceFactor;
                }
            }
            else
            {
                value = Parameters.DcValue * _iteration.SourceFactor;
            }

            Voltage = value;
            _elements.Add(1, 1, -1, -1, value);
        }
Esempio n. 27
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var con = _contributions;

            con.Reset();

            var    vt = Constants.KOverQ * Parameters.Temperature;
            double DrainSatCur, SourceSatCur;

            if ((Properties.TempSatCurDensity == 0) || (Parameters.DrainArea == 0) || (Parameters.SourceArea == 0))
            {
                DrainSatCur  = Parameters.ParallelMultiplier * Properties.TempSatCur;
                SourceSatCur = Parameters.ParallelMultiplier * Properties.TempSatCur;
            }
            else
            {
                DrainSatCur  = Parameters.ParallelMultiplier * Properties.TempSatCurDensity * Parameters.DrainArea;
                SourceSatCur = Parameters.ParallelMultiplier * Properties.TempSatCurDensity * Parameters.SourceArea;
            }
            var Beta = Properties.TempTransconductance * Parameters.Width * Parameters.ParallelMultiplier / Properties.EffectiveLength;

            // Get the current voltages
            Initialize(out var vgs, out var vds, out var vbs, out var check);
            var vbd = vbs - vds;
            var vgd = vgs - vds;

            if (vbs <= -3 * vt)
            {
                con.Bs.G = _config.Gmin;
                con.Bs.C = con.Bs.G * vbs - SourceSatCur;
            }
            else
            {
                var evbs = Math.Exp(Math.Min(MaximumExponentArgument, vbs / vt));
                con.Bs.G = SourceSatCur * evbs / vt + _config.Gmin;
                con.Bs.C = SourceSatCur * (evbs - 1) + _config.Gmin * vbs;
            }
            if (vbd <= -3 * vt)
            {
                con.Bd.G = _config.Gmin;
                con.Bd.C = con.Bd.G * vbd - DrainSatCur;
            }
            else
            {
                var evbd = Math.Exp(Math.Min(MaximumExponentArgument, vbd / vt));
                con.Bd.G = DrainSatCur * evbd / vt + _config.Gmin;
                con.Bd.C = DrainSatCur * (evbd - 1) + _config.Gmin * vbd;
            }

            if (vds >= 0)
            {
                Mode = 1;
            }
            else
            {
                Mode = -1;
            }

            // An example out in the wild once-good, now-bad spaghetti code... Not touching this too much.
            {
                /* moseq2(vds,vbs,vgs,gm,gds,gmbs,qg,qc,qb,
                 *        cggb,cgdb,cgsb,cbgb,cbdb,cbsb)
                 */
                // Note:  cgdb, cgsb, cbdb, cbsb never used

                /*
                 *     this routine evaluates the drain current, its derivatives and
                 *     the charges associated with the gate, channel and bulk
                 *     for mosfets
                 *
                 */

                double   arg;
                double   sarg;
                double[] a4 = new double[4], b4 = new double[4], x4 = new double[8], poly4 = new double[8];
                double   beta1;
                double   dsrgdb;
                double   d2sdb2;
                double   barg;
                double   d2bdb2;
                double   factor;
                double   dbrgdb;
                double   eta;
                double   vbin;
                double   argd = 0.0;
                double   args = 0.0;
                double   argss;
                double   argsd;
                double   argxs = 0.0;
                double   argxd = 0.0;
                double   daddb2;
                double   dasdb2;
                double   dbargd;
                double   dbargs;
                double   dbxwd;
                double   dbxws;
                double   dgddb2;
                double   dgddvb;
                double   dgdvds;
                double   gamasd;
                double   xwd;
                double   xws;
                double   ddxwd;
                double   gammad;
                double   vth;
                double   cfs;
                double   cdonco;
                double   xn   = 0.0;
                double   argg = 0.0;
                double   vgst;
                double   sarg3;
                double   sbiarg;
                double   dgdvbs;
                double   body;
                double   gdbdv;
                double   dodvbs;
                double   dodvds = 0.0;
                double   dxndvd = 0.0;
                double   dxndvb = 0.0;
                double   udenom;
                double   dudvgs;
                double   dudvds;
                double   dudvbs;
                double   gammd2;
                double   argv;
                double   vgsx;
                double   ufact;
                double   ueff;
                double   dsdvgs;
                double   dsdvbs;
                double   a1;
                double   a3;
                double   a;
                double   b1;
                double   b3;
                double   b;
                double   c1;
                double   c;
                double   d1;
                double   fi;
                double   p0;
                double   p2;
                double   p3;
                double   p4;
                double   p;
                double   r3;
                double   r;
                double   ro;
                double   s2;
                double   s;
                double   v1;
                double   v2;
                double   xv;
                double   y3;
                double   delta4;
                double   xvalid = 0;
                double   bsarg  = 0;
                double   dbsrdb;
                double   bodys  = 0;
                double   gdbdvs = 0;
                double   sargv;
                double   xlfact;
                double   dldsat;
                double   xdv;
                double   xlv;
                double   vqchan;
                double   dqdsat;
                double   vl;
                double   dfundg;
                double   dfunds;
                double   dfundb;
                double   xls;
                double   dldvgs;
                double   dldvds;
                double   dldvbs;
                double   dfact;
                double   clfact;
                double   xleff;
                double   deltal;
                double   xwb;
                double   vdson;
                double   cdson;
                double   didvds;
                double   gdson;
                double   gmw;
                double   gbson;
                double   expg;
                double   xld;
                double   xlamda = ModelParameters.Lambda;

                /* 'local' variables - these switch d & s around appropriately
                 * so that we don't have to worry about vds < 0
                 */
                double lvbs      = Mode == 1 ? vbs : vbd;
                double lvds      = Mode * vds;
                double lvgs      = Mode == 1 ? vgs : vgd;
                double phiMinVbs = Properties.TempPhi - lvbs;
                double tmp; /* a temporary variable, not used for more than */
                /* about 10 lines at a time */
                int iknt;
                int jknt;
                int i;
                int j;

                double sphi;
                double sphi3;

                /*
                 *  compute some useful quantities
                 */

                if (lvbs <= 0.0)
                {
                    sarg   = Math.Sqrt(phiMinVbs);
                    dsrgdb = -0.5 / sarg;
                    d2sdb2 = 0.5 * dsrgdb / phiMinVbs;
                }
                else
                {
                    sphi   = Math.Sqrt(Properties.TempPhi);
                    sphi3  = Properties.TempPhi * sphi;
                    sarg   = sphi / (1.0 + 0.5 * lvbs / Properties.TempPhi);
                    tmp    = sarg / sphi3;
                    dsrgdb = -0.5 * sarg * tmp;
                    d2sdb2 = -dsrgdb * tmp;
                }
                if ((lvbs - lvds) <= 0)
                {
                    barg   = Math.Sqrt(phiMinVbs + lvds);
                    dbrgdb = -0.5 / barg;
                    d2bdb2 = 0.5 * dbrgdb / (phiMinVbs + lvds);
                }
                else
                {
                    sphi   = Math.Sqrt(Properties.TempPhi); /* added by HT 050523 */
                    sphi3  = Properties.TempPhi * sphi;     /* added by HT 050523 */
                    barg   = sphi / (1.0 + 0.5 * (lvbs - lvds) / Properties.TempPhi);
                    tmp    = barg / sphi3;
                    dbrgdb = -0.5 * barg * tmp;
                    d2bdb2 = -dbrgdb * tmp;
                }

                /*
                 *  calculate threshold voltage (von)
                 *     narrow-channel effect
                 */

                // XXX constant per device
                factor = 0.125 * ModelParameters.NarrowFactor * 2.0 * Math.PI * EpsilonSilicon / Properties.OxideCap * Properties.EffectiveLength;
                // XXX constant per device
                eta  = 1.0 + factor;
                vbin = Properties.TempVbi * ModelParameters.MosfetType + factor * phiMinVbs;
                if ((ModelParameters.Gamma > 0.0) || (ModelParameters.SubstrateDoping > 0.0))
                {
                    xwd = ModelTemperature.Properties.Xd * barg;
                    xws = ModelTemperature.Properties.Xd * sarg;

                    // Short-channel effect with vds .ne. 0.0
                    argss  = 0.0;
                    argsd  = 0.0;
                    dbargs = 0.0;
                    dbargd = 0.0;
                    dgdvds = 0.0;
                    dgddb2 = 0.0;
                    if (ModelParameters.JunctionDepth > 0)
                    {
                        tmp   = 2.0 / ModelParameters.JunctionDepth;
                        argxs = 1.0 + xws * tmp;
                        argxd = 1.0 + xwd * tmp;
                        args  = Math.Sqrt(argxs);
                        argd  = Math.Sqrt(argxd);
                        tmp   = .5 * ModelParameters.JunctionDepth / Properties.EffectiveLength;
                        argss = tmp * (args - 1.0);
                        argsd = tmp * (argd - 1.0);
                    }
                    gamasd = ModelParameters.Gamma * (1.0 - argss - argsd);
                    dbxwd  = ModelTemperature.Properties.Xd * dbrgdb;
                    dbxws  = ModelTemperature.Properties.Xd * dsrgdb;
                    if (ModelParameters.JunctionDepth > 0)
                    {
                        tmp    = 0.5 / Properties.EffectiveLength;
                        dbargs = tmp * dbxws / args;
                        dbargd = tmp * dbxwd / argd;
                        dasdb2 = -ModelTemperature.Properties.Xd * (d2sdb2 + dsrgdb * dsrgdb *
                                                                    ModelTemperature.Properties.Xd / (ModelParameters.JunctionDepth * argxs)) /
                                 (Properties.EffectiveLength * args);
                        daddb2 = -ModelTemperature.Properties.Xd * (d2bdb2 + dbrgdb * dbrgdb *
                                                                    ModelTemperature.Properties.Xd / (ModelParameters.JunctionDepth * argxd)) /
                                 (Properties.EffectiveLength * argd);
                        dgddb2 = -0.5 * ModelParameters.Gamma * (dasdb2 + daddb2);
                    }
                    dgddvb = -ModelParameters.Gamma * (dbargs + dbargd);
                    if (ModelParameters.JunctionDepth > 0)
                    {
                        ddxwd  = -dbxwd;
                        dgdvds = -ModelParameters.Gamma * 0.5 * ddxwd / (Properties.EffectiveLength * argd);
                    }
                }
                else
                {
                    gamasd = ModelParameters.Gamma;
                    dgddvb = 0.0;
                    dgdvds = 0.0;
                    dgddb2 = 0.0;
                }
                var von = vbin + gamasd * sarg;
                vth = von;
                var vdsat = 0.0;
                if (ModelParameters.FastSurfaceStateDensity != 0.0 && Properties.OxideCap != 0.0)
                {
                    // XXX constant per model
                    cfs    = Constants.Charge * ModelParameters.FastSurfaceStateDensity * 1e4 /*(cm**2/m**2)*/;
                    cdonco = -(gamasd * dsrgdb + dgddvb * sarg) + factor;
                    xn     = 1.0 + cfs / Properties.OxideCap * Parameters.ParallelMultiplier * Parameters.Width * Properties.EffectiveLength + cdonco;

                    tmp  = vt * xn;
                    von += tmp;
                    argg = 1.0 / tmp;
                    vgst = lvgs - von;
                }
                else
                {
                    vgst = lvgs - von;
                    if (lvgs <= vbin)
                    {
                        // Cutoff region
                        con.Ds.G = 0.0;
                        goto line1050;
                    }
                }

                /*
                 *  compute some more useful quantities
                 */

                sarg3 = sarg * sarg * sarg;
                /* XXX constant per model */
                sbiarg = Math.Sqrt(Properties.TempBulkPotential);
                gammad = gamasd;
                dgdvbs = dgddvb;
                body   = barg * barg * barg - sarg3;
                gdbdv  = 2.0 * gammad * (barg * barg * dbrgdb - sarg * sarg * dsrgdb);
                dodvbs = -factor + dgdvbs * sarg + gammad * dsrgdb;
                if (ModelParameters.FastSurfaceStateDensity == 0.0)
                {
                    goto line400;
                }
                if (Properties.OxideCap == 0.0)
                {
                    goto line410;
                }
                dxndvb  = 2.0 * dgdvbs * dsrgdb + gammad * d2sdb2 + dgddb2 * sarg;
                dodvbs += vt * dxndvb;
                dxndvd  = dgdvds * dsrgdb;
                dodvds  = dgdvds * sarg + vt * dxndvd;

                /*
                 *  evaluate effective mobility and its derivatives
                 */
line400:
                if (Properties.OxideCap <= 0.0)
                {
                    goto line410;
                }
                udenom = vgst;
                tmp    = ModelParameters.CriticalField * 100 /* cm/m */ * EpsilonSilicon / ModelTemperature.Properties.OxideCapFactor;
                if (udenom <= tmp)
                {
                    goto line410;
                }
                ufact  = Math.Exp(ModelParameters.CriticalFieldExp * Math.Log(tmp / udenom));
                ueff   = ModelParameters.SurfaceMobility * 1e-4 /*(m**2/cm**2) */ * ufact;
                dudvgs = -ufact * ModelParameters.CriticalFieldExp / udenom;
                dudvds = 0.0;
                dudvbs = ModelParameters.CriticalFieldExp * ufact * dodvbs / vgst;
                goto line500;
line410:
                ufact  = 1.0;
                ueff   = ModelParameters.SurfaceMobility * 1e-4 /*(m**2/cm**2) */;
                dudvgs = 0.0;
                dudvds = 0.0;
                dudvbs = 0.0;

                /*
                 *     evaluate saturation voltage and its derivatives according to
                 *     grove-frohman equation
                 */
line500:
                vgsx   = lvgs;
                gammad = gamasd / eta;
                dgdvbs = dgddvb;
                if (ModelParameters.FastSurfaceStateDensity != 0 && Properties.OxideCap != 0)
                {
                    vgsx = Math.Max(lvgs, von);
                }
                if (gammad > 0)
                {
                    gammd2 = gammad * gammad;
                    argv   = (vgsx - vbin) / eta + phiMinVbs;
                    if (argv <= 0.0)
                    {
                        vdsat  = 0.0;
                        dsdvgs = 0.0;
                        dsdvbs = 0.0;
                    }
                    else
                    {
                        arg    = Math.Sqrt(1.0 + 4.0 * argv / gammd2);
                        vdsat  = (vgsx - vbin) / eta + gammd2 * (1.0 - arg) / 2.0;
                        vdsat  = Math.Max(vdsat, 0.0);
                        dsdvgs = (1.0 - 1.0 / arg) / eta;
                        dsdvbs = (gammad * (1.0 - arg) + 2.0 * argv / (gammad * arg)) /
                                 eta * dgdvbs + 1.0 / arg + factor * dsdvgs;
                    }
                }
                else
                {
                    vdsat  = (vgsx - vbin) / eta;
                    vdsat  = Math.Max(vdsat, 0.0);
                    dsdvgs = 1.0;
                    dsdvbs = 0.0;
                }
                if (ModelParameters.MaxDriftVelocity > 0)
                {
                    /*
                     *     evaluate saturation voltage and its derivatives
                     *     according to baum's theory of scattering velocity
                     *     saturation
                     */
                    v1 = (vgsx - vbin) / eta + phiMinVbs;
                    v2 = phiMinVbs;
                    xv = ModelParameters.MaxDriftVelocity * Properties.EffectiveLength / ueff;
                    a1 = gammad / 0.75;
                    b1 = -2.0 * (v1 + xv);
                    c1 = -2.0 * gammad * xv;
                    d1 = 2.0 * v1 * (v2 + xv) - v2 * v2 - 4.0 / 3.0 * gammad * sarg3;
                    a  = -b1;
                    b  = a1 * c1 - 4.0 * d1;
                    c  = -d1 * (a1 * a1 - 4.0 * b1) - c1 * c1;
                    r  = -a * a / 3.0 + b;
                    s  = 2.0 * a * a * a / 27.0 - a * b / 3.0 + c;
                    r3 = r * r * r;
                    s2 = s * s;
                    p  = s2 / 4.0 + r3 / 27.0;
                    p0 = Math.Abs(p);
                    p2 = Math.Sqrt(p0);
                    if (p < 0)
                    {
                        ro = Math.Sqrt(s2 / 4.0 + p0);
                        ro = Math.Log(ro) / 3.0;
                        ro = Math.Exp(ro);
                        fi = Math.Atan(-2.0 * p2 / s);
                        y3 = 2.0 * ro * Math.Cos(fi / 3.0) - a / 3.0;
                    }
                    else
                    {
                        p3 = -s / 2.0 + p2;
                        p3 = Math.Exp(Math.Log(Math.Abs(p3)) / 3.0);
                        p4 = -s / 2.0 - p2;
                        p4 = Math.Exp(Math.Log(Math.Abs(p4)) / 3.0);
                        y3 = p3 + p4 - a / 3.0;
                    }
                    iknt = 0;
                    a3   = Math.Sqrt(a1 * a1 / 4.0 - b1 + y3);
                    b3   = Math.Sqrt(y3 * y3 / 4.0 - d1);
                    for (i = 1; i <= 4; i++)
                    {
                        a4[i - 1] = a1 / 2.0 + _sig1[i - 1] * a3;
                        b4[i - 1] = y3 / 2.0 + _sig2[i - 1] * b3;
                        delta4    = a4[i - 1] * a4[i - 1] / 4.0 - b4[i - 1];
                        if (delta4 < 0)
                        {
                            continue;
                        }
                        iknt        += 1;
                        tmp          = Math.Sqrt(delta4);
                        x4[iknt - 1] = -a4[i - 1] / 2.0 + tmp;
                        iknt        += 1;
                        x4[iknt - 1] = -a4[i - 1] / 2.0 - tmp;
                    }
                    jknt = 0;
                    for (j = 1; j <= iknt; j++)
                    {
                        if (x4[j - 1] <= 0)
                        {
                            continue;
                        }
                        /* XXX implement this sanely */
                        poly4[j - 1] = x4[j - 1] * x4[j - 1] * x4[j - 1] * x4[j - 1] + a1 * x4[j - 1] *
                                       x4[j - 1] * x4[j - 1];
                        poly4[j - 1] = poly4[j - 1] + b1 * x4[j - 1] * x4[j - 1] + c1 * x4[j - 1] + d1;
                        if (Math.Abs(poly4[j - 1]) > 1.0e-6)
                        {
                            continue;
                        }
                        jknt += 1;
                        if (jknt <= 1)
                        {
                            xvalid = x4[j - 1];
                        }
                        if (x4[j - 1] > xvalid)
                        {
                            continue;
                        }
                        xvalid = x4[j - 1];
                    }
                    if (jknt > 0)
                    {
                        vdsat = xvalid * xvalid - phiMinVbs;
                    }
                }
                // Evaluate effective channel length and its derivatives
                if (lvds != 0.0)
                {
                    gammad = gamasd;
                    if ((lvbs - vdsat) <= 0)
                    {
                        bsarg  = Math.Sqrt(vdsat + phiMinVbs);
                        dbsrdb = -0.5 / bsarg;
                    }
                    else
                    {
                        sphi   = Math.Sqrt(Properties.TempPhi); /* added by HT 050523 */
                        sphi3  = Properties.TempPhi * sphi;     /* added by HT 050523 */
                        bsarg  = sphi / (1.0 + 0.5 * (lvbs - vdsat) / Properties.TempPhi);
                        dbsrdb = -0.5 * bsarg * bsarg / sphi3;
                    }
                    bodys  = bsarg * bsarg * bsarg - sarg3;
                    gdbdvs = 2.0 * gammad * (bsarg * bsarg * dbsrdb - sarg * sarg * dsrgdb);
                    if (ModelParameters.MaxDriftVelocity <= 0)
                    {
                        if (ModelParameters.SubstrateDoping == 0.0 || xlamda > 0.0)
                        {
                            dldvgs = 0.0;
                            dldvds = 0.0;
                            dldvbs = 0.0;
                        }
                        else
                        {
                            argv   = (lvds - vdsat) / 4.0;
                            sargv  = Math.Sqrt(1.0 + argv * argv);
                            arg    = Math.Sqrt(argv + sargv);
                            xlfact = ModelTemperature.Properties.Xd / (Properties.EffectiveLength * lvds);
                            xlamda = xlfact * arg;
                            dldsat = lvds * xlamda / (8.0 * sargv);
                            dldvgs = dldsat * dsdvgs;
                            dldvds = -xlamda + dldsat;
                            dldvbs = dldsat * dsdvbs;
                        }
                    }
                    else
                    {
                        argv   = (vgsx - vbin) / eta - vdsat;
                        xdv    = ModelTemperature.Properties.Xd / Math.Sqrt(ModelParameters.ChannelCharge);
                        xlv    = ModelParameters.MaxDriftVelocity * xdv / (2.0 * ueff);
                        vqchan = argv - gammad * bsarg;
                        dqdsat = -1.0 + gammad * dbsrdb;
                        vl     = ModelParameters.MaxDriftVelocity * Properties.EffectiveLength;
                        dfunds = vl * dqdsat - ueff * vqchan;
                        dfundg = (vl - ueff * vdsat) / eta;
                        dfundb = -vl * (1.0 + dqdsat - factor / eta) + ueff *
                                 (gdbdvs - dgdvbs * bodys / 1.5) / eta;
                        dsdvgs = -dfundg / dfunds;
                        dsdvbs = -dfundb / dfunds;
                        if (ModelParameters.SubstrateDoping == 0.0 || xlamda > 0.0)
                        {
                            dldvgs = 0.0;
                            dldvds = 0.0;
                            dldvbs = 0.0;
                        }
                        else
                        {
                            argv    = lvds - vdsat;
                            argv    = Math.Max(argv, 0.0);
                            xls     = Math.Sqrt(xlv * xlv + argv);
                            dldsat  = xdv / (2.0 * xls);
                            xlfact  = xdv / (Properties.EffectiveLength * lvds);
                            xlamda  = xlfact * (xls - xlv);
                            dldsat /= Properties.EffectiveLength;
                            dldvgs  = dldsat * dsdvgs;
                            dldvds  = -xlamda + dldsat;
                            dldvbs  = dldsat * dsdvbs;
                        }
                    }
                }
                else
                {
                    dldvgs = 0.0;
                    dldvds = 0.0;
                    dldvbs = 0.0;
                }

                /*
                 *     limit channel shortening at punch-through
                 */
                xwb    = ModelTemperature.Properties.Xd * sbiarg;
                xld    = Properties.EffectiveLength - xwb;
                clfact = 1.0 - xlamda * lvds;
                dldvds = -xlamda - dldvds;
                xleff  = Properties.EffectiveLength * clfact;
                deltal = xlamda * lvds * Properties.EffectiveLength;
                if (ModelParameters.SubstrateDoping == 0.0)
                {
                    xwb = 0.25e-6;
                }
                if (xleff < xwb)
                {
                    xleff  = xwb / (1.0 + (deltal - xld) / xwb);
                    clfact = xleff / Properties.EffectiveLength;
                    dfact  = xleff * xleff / (xwb * xwb);
                    dldvgs = dfact * dldvgs;
                    dldvds = dfact * dldvds;
                    dldvbs = dfact * dldvbs;
                }

                // Evaluate effective beta (effective kp)
                beta1 = Beta * ufact / clfact;

                // Test for mode of operation and branch appropriately
                gammad = gamasd;
                dgdvbs = dgddvb;
                if (lvds <= 1.0e-10)
                {
                    if (lvgs <= von)
                    {
                        if ((ModelParameters.FastSurfaceStateDensity == 0.0) || (Properties.OxideCap == 0.0))
                        {
                            con.Ds.G = 0.0;
                            goto line1050;
                        }

                        con.Ds.G = beta1 * (von - vbin - gammad * sarg) * Math.Exp(argg *
                                                                                   (lvgs - von));
                        goto line1050;
                    }

                    con.Ds.G = beta1 * (lvgs - vbin - gammad * sarg);
                    goto line1050;
                }

                if (ModelParameters.FastSurfaceStateDensity != 0 && Properties.OxideCap != 0)
                {
                    if (lvgs > von)
                    {
                        goto line900;
                    }
                }
                else
                {
                    if (lvgs > vbin)
                    {
                        goto line900;
                    }
                    goto doneval;
                }

                if (lvgs > von)
                {
                    goto line900;
                }

                // Subthreshold region
                if (vdsat <= 0)
                {
                    con.Ds.G = 0.0;
                    if (lvgs > vth)
                    {
                        goto doneval;
                    }
                    goto line1050;
                }
                vdson = Math.Min(vdsat, lvds);
                if (lvds > vdsat)
                {
                    barg  = bsarg;
                    body  = bodys;
                    gdbdv = gdbdvs;
                }
                cdson  = beta1 * ((von - vbin - eta * vdson * 0.5) * vdson - gammad * body / 1.5);
                didvds = beta1 * (von - vbin - eta * vdson - gammad * barg);
                gdson  = -cdson * dldvds / clfact - beta1 * dgdvds * body / 1.5;
                if (lvds < vdsat)
                {
                    gdson += didvds;
                }
                gbson = -cdson * dldvbs / clfact + beta1 * (dodvbs * vdson + factor * vdson - dgdvbs * body / 1.5 - gdbdv);
                if (lvds > vdsat)
                {
                    gbson += didvds * dsdvbs;
                }
                expg     = Math.Exp(argg * (lvgs - von));
                con.Ds.C = cdson * expg;
                gmw      = con.Ds.C * argg;
                Gm       = gmw;
                if (lvds > vdsat)
                {
                    Gm = gmw + didvds * dsdvgs * expg;
                }
                tmp      = gmw * (lvgs - von) / xn;
                con.Ds.G = gdson * expg - Gm * dodvds - tmp * dxndvd;
                Gmbs     = gbson * expg - Gm * dodvbs - tmp * dxndvb;
                goto doneval;

line900:
                if (lvds <= vdsat)
                {
                    // Linear region
                    con.Ds.C = beta1 * ((lvgs - vbin - eta * lvds / 2.0) * lvds - gammad * body / 1.5);
                    arg      = con.Ds.C * (dudvgs / ufact - dldvgs / clfact);
                    Gm       = arg + beta1 * lvds;
                    arg      = con.Ds.C * (dudvds / ufact - dldvds / clfact);
                    con.Ds.G = arg + beta1 * (lvgs - vbin - eta * lvds - gammad * barg - dgdvds * body / 1.5);
                    arg      = con.Ds.C * (dudvbs / ufact - dldvbs / clfact);
                    Gmbs     = arg - beta1 * (gdbdv + dgdvbs * body / 1.5 - factor * lvds);
                }
                else
                {
                    // Saturation region
                    con.Ds.C = beta1 * ((lvgs - vbin - eta * vdsat / 2.0) * vdsat - gammad * bodys / 1.5);
                    arg      = con.Ds.C * (dudvgs / ufact - dldvgs / clfact);
                    Gm       = arg + beta1 * vdsat + beta1 * (lvgs - vbin - eta * vdsat - gammad * bsarg) * dsdvgs;
                    con.Ds.G = -con.Ds.C * dldvds / clfact - beta1 * dgdvds * bodys / 1.5;
                    arg      = con.Ds.C * (dudvbs / ufact - dldvbs / clfact);
                    Gmbs     = arg - beta1 * (gdbdvs + dgdvbs * bodys / 1.5 - factor * vdsat) + beta1 * (lvgs - vbin - eta * vdsat - gammad * bsarg) * dsdvbs;
                }
                // Compute charges for "on" region
                goto doneval;
                // Finish special cases
line1050:
                con.Ds.C = 0.0;
                Gm       = 0.0;
                Gmbs     = 0.0;
                // Finished
doneval:
                Von   = ModelParameters.MosfetType * von;
                Vdsat = ModelParameters.MosfetType * vdsat;
            }

            // COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
            Gds = con.Ds.G;
            Id  = Mode * con.Ds.C - con.Bd.C;

            Vbs = vbs;
            Vbd = vbd;
            Vgs = vgs;
            Vds = vds;

            // Update with time-dependent calculations
            UpdateContributions?.Invoke(this, _args);

            // Check convergence
            if (!Parameters.Off && _iteration.Mode != IterationModes.Fix)
            {
                if (check)
                {
                    _iteration.IsConvergent = false;
                }
            }

            Gbs = con.Bs.G;
            Ibs = con.Bs.C;
            Gbd = con.Bd.G;
            Ibd = con.Bd.C;

            // Right hand side contributions
            double xnrm, xrev;

            con.Bs.C = ModelParameters.MosfetType * (con.Bs.C - con.Bs.G * vbs);
            con.Bd.C = ModelParameters.MosfetType * (con.Bd.C - con.Bd.G * vbd);
            if (Mode >= 0)
            {
                xnrm     = 1;
                xrev     = 0;
                con.Ds.C = ModelParameters.MosfetType * (con.Ds.C - con.Ds.G * vds - Gm * vgs - Gmbs * vbs);
            }
            else
            {
                xnrm     = 0;
                xrev     = 1;
                con.Ds.C = -ModelParameters.MosfetType * (con.Ds.C - con.Ds.G * (-vds) - Gm * vgd - Gmbs * vbd);
            }

            _elements.Add(
                // Y-matrix
                Properties.DrainConductance,
                con.Gd.G + con.Gs.G + con.Gb.G,
                Properties.SourceConductance,
                con.Bd.G + con.Bs.G + con.Gb.G,
                Properties.DrainConductance + con.Ds.G + con.Bd.G + xrev * (Gm + Gmbs) + con.Gd.G,
                Properties.SourceConductance + con.Ds.G + con.Bs.G + xnrm * (Gm + Gmbs) + con.Gs.G,
                -Properties.DrainConductance,
                -con.Gb.G,
                -con.Gd.G,
                -con.Gs.G,
                -Properties.SourceConductance,
                -con.Gb.G,
                -con.Bd.G,
                -con.Bs.G,
                -Properties.DrainConductance,
                (xnrm - xrev) * Gm - con.Gd.G,
                -con.Bd.G + (xnrm - xrev) * Gmbs,
                -con.Ds.G - xnrm * (Gm + Gmbs),
                -(xnrm - xrev) * Gm - con.Gs.G,
                -Properties.SourceConductance,
                -con.Bs.G - (xnrm - xrev) * Gmbs,
                -con.Ds.G - xrev * (Gm + Gmbs),

                // Right hand side vector
                -ModelParameters.MosfetType * (con.Gs.C + con.Gb.C + con.Gd.C),
                -(con.Bs.C + con.Bd.C - ModelParameters.MosfetType * con.Gb.C),
                con.Bd.C - con.Ds.C + ModelParameters.MosfetType * con.Gd.C,
                con.Ds.C + con.Bs.C + ModelParameters.MosfetType * con.Gs.C
                );
        }
Esempio n. 28
0
        /// <inheritdoc/>
        void IFrequencyBehavior.Load()
        {
            var value = Parameters.Transconductance;

            _elements.Add(value, -value, -value, value);
        }
Esempio n. 29
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var con = _contributions;

            con.Reset();

            var    vt = Constants.KOverQ * Parameters.Temperature;
            double DrainSatCur, SourceSatCur;

            if ((Properties.TempSatCurDensity == 0) || (Parameters.DrainArea == 0) || (Parameters.SourceArea == 0))
            {
                DrainSatCur  = Parameters.ParallelMultiplier * Properties.TempSatCur;
                SourceSatCur = Parameters.ParallelMultiplier * Properties.TempSatCur;
            }
            else
            {
                DrainSatCur  = Properties.TempSatCurDensity * Parameters.ParallelMultiplier * Parameters.DrainArea;
                SourceSatCur = Properties.TempSatCurDensity * Parameters.ParallelMultiplier * Parameters.SourceArea;
            }
            var Beta = Properties.TempTransconductance * Parameters.ParallelMultiplier * Parameters.Width / Properties.EffectiveLength;

            // Get the current voltages
            Initialize(out double vgs, out var vds, out var vbs, out var check);
            var vbd = vbs - vds;
            var vgd = vgs - vds;

            /*
             * Bulk-source and bulk-drain diodes
             *   here we just evaluate the ideal diode current and the
             *   corresponding derivative (conductance).
             */
            if (vbs <= -3 * vt)
            {
                con.Bs.G = _config.Gmin;
                con.Bs.C = con.Bs.G * vbs - SourceSatCur;
            }
            else
            {
                var evbs = Math.Exp(Math.Min(MaximumExponentArgument, vbs / vt));
                con.Bs.G = SourceSatCur * evbs / vt + _config.Gmin;
                con.Bs.C = SourceSatCur * (evbs - 1) + _config.Gmin * vbs;
            }
            if (vbd <= -3 * vt)
            {
                con.Bd.G = _config.Gmin;
                con.Bd.C = con.Bd.G * vbd - DrainSatCur;
            }
            else
            {
                var evbd = Math.Exp(Math.Min(MaximumExponentArgument, vbd / vt));
                con.Bd.G = DrainSatCur * evbd / vt + _config.Gmin;
                con.Bd.C = DrainSatCur * (evbd - 1) + _config.Gmin * vbd;
            }
            // Now to determine whether the user was able to correctly identify the source and drain of his device
            if (vds >= 0)
            {
                Mode = 1;
            }
            else
            {
                Mode = -1;
            }

            {
                /*
                 *     this block of code evaluates the drain current and its
                 *     derivatives using the shichman-hodges model and the
                 *     charges associated with the gate, channel and bulk for
                 *     mosfets
                 *
                 */

                /* the following 4 variables are local to this code block until
                 * it is obvious that they can be made global
                 */
                double arg;
                double betap;
                double sarg;
                double vgst;

                if ((Mode > 0 ? vbs : vbd) <= 0)
                {
                    sarg = Math.Sqrt(Properties.TempPhi - (Mode > 0 ? vbs : vbd));
                }
                else
                {
                    sarg  = Math.Sqrt(Properties.TempPhi);
                    sarg -= (Mode > 0 ? vbs : vbd) / (sarg + sarg);
                    sarg  = Math.Max(0, sarg);
                }
                var von = (Properties.TempVbi * ModelParameters.MosfetType) + ModelParameters.Gamma * sarg;
                vgst = (Mode > 0 ? vgs : vgd) - von;
                var vdsat = Math.Max(vgst, 0);
                if (sarg <= 0)
                {
                    arg = 0;
                }
                else
                {
                    arg = ModelParameters.Gamma / (sarg + sarg);
                }
                if (vgst <= 0)
                {
                    // Cutoff region
                    con.Ds.C = 0;
                    Gm       = 0;
                    con.Ds.G = 0;
                    Gmbs     = 0;
                }
                else
                {
                    // Saturation region
                    betap = Beta * (1 + ModelParameters.Lambda * (vds * Mode));
                    if (vgst <= (vds * Mode))
                    {
                        con.Ds.C = betap * vgst * vgst * .5;
                        Gm       = betap * vgst;
                        con.Ds.G = ModelParameters.Lambda * Beta * vgst * vgst * .5;
                        Gmbs     = Gm * arg;
                    }
                    else
                    {
                        // Linear region
                        con.Ds.C = betap * (vds * Mode) *
                                   (vgst - .5 * (vds * Mode));
                        Gm       = betap * (vds * Mode);
                        con.Ds.G = betap * (vgst - (vds * Mode)) +
                                   ModelParameters.Lambda * Beta *
                                   (vds * Mode) *
                                   (vgst - .5 * (vds * Mode));
                        Gmbs = Gm * arg;
                    }
                }

                // now deal with n vs p polarity
                Von   = ModelParameters.MosfetType * von;
                Vdsat = ModelParameters.MosfetType * vdsat;
            }

            // COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
            Gds = con.Ds.G;
            Id  = Mode * con.Ds.C - con.Bd.C;

            Vbs = vbs;
            Vbd = vbd;
            Vgs = vgs;
            Vds = vds;

            // Update with time-dependent calculations
            UpdateContributions?.Invoke(this, _args);

            // Check convergence
            if (!Parameters.Off && _iteration.Mode != IterationModes.Fix)
            {
                if (check)
                {
                    _iteration.IsConvergent = false;
                }
            }

            Gbs = con.Bs.G;
            Ibs = con.Bs.C;
            Gbd = con.Bd.G;
            Ibd = con.Bd.C;

            // Right hand side vector contributions
            con.Bs.C = ModelParameters.MosfetType * (con.Bs.C - con.Bs.G * vbs);
            con.Bd.C = ModelParameters.MosfetType * (con.Bd.C - con.Bd.G * vbd);
            double xnrm, xrev;

            if (Mode >= 0)
            {
                xnrm     = 1;
                xrev     = 0;
                con.Ds.C = ModelParameters.MosfetType * (con.Ds.C - con.Ds.G * vds - Gm * vgs - Gmbs * vbs);
            }
            else
            {
                xnrm     = 0;
                xrev     = 1;
                con.Ds.C = -ModelParameters.MosfetType * (con.Ds.C - con.Ds.G * (-vds) - Gm * vgd - Gmbs * vbd);
            }

            _elements.Add(
                // Y-matrix
                Properties.DrainConductance,
                con.Gd.G + con.Gs.G + con.Gb.G,
                Properties.SourceConductance,
                con.Bd.G + con.Bs.G + con.Gb.G,
                Properties.DrainConductance + con.Ds.G + con.Bd.G + xrev * (Gm + Gmbs) + con.Gd.G,
                Properties.SourceConductance + con.Ds.G + con.Bs.G + xnrm * (Gm + Gmbs) + con.Gs.G,
                -Properties.DrainConductance,
                -con.Gb.G,
                -con.Gd.G,
                -con.Gs.G,
                -Properties.SourceConductance,
                -con.Gb.G,
                -con.Bd.G,
                -con.Bs.G,
                -Properties.DrainConductance,
                (xnrm - xrev) * Gm - con.Gd.G,
                -con.Bd.G + (xnrm - xrev) * Gmbs,
                -con.Ds.G - xnrm * (Gm + Gmbs),
                -(xnrm - xrev) * Gm - con.Gs.G,
                -Properties.SourceConductance,
                -con.Bs.G - (xnrm - xrev) * Gmbs,
                -con.Ds.G - xrev * (Gm + Gmbs),

                // Right hand side vector
                -ModelParameters.MosfetType * (con.Gs.C + con.Gb.C + con.Gd.C),
                -(con.Bs.C + con.Bd.C - ModelParameters.MosfetType * con.Gb.C),
                con.Bd.C - con.Ds.C + ModelParameters.MosfetType * con.Gd.C,
                con.Ds.C + con.Bs.C + ModelParameters.MosfetType * con.Gs.C
                );
        }
Esempio n. 30
0
        /// <inheritdoc/>
        void IBiasingBehavior.Load()
        {
            var val = Parameters.Coefficient;

            _elements.Add(1, -1, 1, -1, -val, val);
        }