--*******************************************************************
--*   ::::::::::::                                                  *
--*   COMPUTE_PACK                                                  * SPEC
--*   ::::::::::::                                                  *
--*******************************************************************
--| The following packages are used by COMPUTE_PACK:
Library MCC; Use MCC.C_INTERFACE.all;
use STD.TEXTIO.all;
package COMPUTE_PACK is
--| purpose
--|

--*******************************************************************
--*                                                                 *
--*   DATA TYPE                                                     * SPEC
--*                                                                 *
--*******************************************************************
--| The following data types are used in ANAVHDL: 
  type Value_Array is array (natural range<>) of real;
  type Node_Array is array (natural range<>) of integer;
  type AMatrix is array (natural range<>,natural range<>) of real; 
  type Time_Array is array (natural range<>) of Time;
  type Element_name is array (1 to 8) of character;
  type NAME_ARRAY is array (natural range<>) of Element_Name;
  type TEXTIO_FLAG is ('R','C','L','V','I','v','i','M','T','.');
  type PARAM_ELEMENT is array (1 to 42) of real;
  type PARAM_MATRIX is array (1 to 42,1 to 6) of real;  
  type CAPA_ELEMENT is array (1 to 5) of real;
  type CAPA_ARRAY is array (natural range<>) of CAPA_ELEMENT;
  type CHARG_ELEM is array (1 to 3 ) of real;
  type ncap_elem is array (1 to 2 ) of real;
  type ncap_array is array (natural range<> ) of ncap_elem;
  type CHARG_ARRAY is array (natural range<>) of CHARG_ElEM;


--*******************************************************************
--*                                                                 *
--*   LINEQUA_COMP                                                  * SPEC
--*                                                                 *
--*******************************************************************
  procedure LINEQUA_COMP
   (MNODENUM : in INTEGER;
    NOFV     : in INTEGER;
    NOFPV    : in INTEGER;
    G        : inout AMATRIX;
    I0       : inout VALUE_ARRAY;
    V0       : inout VALUE_ARRAY);

--*******************************************************************
--*                                                                 *
--*   DC_POINT                                                      * SPEC
--*                                                                 *
--*******************************************************************
  procedure DC_POINT(
    R         : in VALUE_ARRAY;
    NR1       : in NODE_ARRAY;
    NR2       : in NODE_ARRAY;
    ID        : in VALUE_ARRAY;
    NI1       : in NODE_ARRAY;
    NI2       : in NODE_ARRAY;
    IP1       : in VALUE_ARRAY;
    NP1       : in NODE_ARRAY;
    NP2       : in NODE_ARRAY;
    VD        : in VALUE_ARRAY;
    NV1       : in NODE_ARRAY;
    NV2       : in NODE_ARRAY;
    VP1       : in VALUE_ARRAY;
    NVP1      : in NODE_ARRAY;
    NVP2      : in NODE_ARRAY;
    MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    MODEL_NAME: in NAME_ARRAY;
    MODEL_TYPE: in NAME_ARRAY;
    MODEL_PARA: inout PARAM_MATRIX;
    NRNUM     : in INTEGER;
    NOFR      : in INTEGER;
    NOFC      : in INTEGER;
    NOFL      : in INTEGER;
    NOFV      : in INTEGER;
    NOFI      : in INTEGER;
    NOFPV     : in INTEGER;
    NOFPI     : in INTEGER;
    NOFM      : in INTEGER;
    NOFMOD    : in INTEGER;
    TNOM      : in REAL;
    VBS0      : inout VALUE_ARRAY;
    VBD0      : inout VALUE_ARRAY;
    VGS0      : inout VALUE_ARRAY;
    VDS0      : inout VALUE_ARRAY;
    VON0      : inout VALUE_ARRAY;
    VDSAT0    : inout VALUE_ARRAY;
    Vbi0      : inout VALUE_ARRAY;
    I0        : inout VALUE_ARRAY;
    VOP       : inout VALUE_ARRAY);

--******************************************************************
--*                                                                *
--*   MOSFET_DC                                                    * SPEC 
--*                                                                *
--******************************************************************
  procedure MOSFET_DC
   (MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    NAME      : in NAME_ARRAY;
    T_TYPE    : in NAME_ARRAY;
    TNOM      : in REAL;
    CONCK     : inout NODE_ARRAY;
    MODCOUNT  : in INTEGER;
    MCOUNT    : in INTEGER;
    VOP       : in VALUE_ARRAY;
    Vbi0      : inout VALUE_ARRAY;
    PARA      : inout PARAM_MATRIX;
    TAG       : inout INTEGER;
    NONCON    : inout INTEGER;
    VBS0      : inout VALUE_ARRAY;
    VBD0      : inout VALUE_ARRAY;
    VGS0      : inout VALUE_ARRAY;
    VDS0      : inout VALUE_ARRAY;
    VON0      : inout VALUE_ARRAY;
    VDSAT0    : inout VALUE_ARRAY;
    CD0       : inout VALUE_ARRAY;
    CBS0      : inout VALUE_ARRAY;
    CBD0      : inout VALUE_ARRAY;
    gm0       : inout VALUE_ARRAY;
    gds0      : inout VALUE_ARRAY;
    gmbs0     : inout VALUE_ARRAY;
    GBS0      : inout VALUE_ARRAY;
    GBD0      : inout VALUE_ARRAY;
    G         : inout AMATRIX;
    I0        : inout VALUE_ARRAY);

--*******************************************************************
--                                                                  *
--  MOSEQ1                                                          * SPEC
--                                                                  *
--*******************************************************************
  procedure MOSEQ1(VDS: in real;
                   VBS: in real;
                   VGS: in real;
                   PHI: in real;
                   VBI: in real;
                   GAMMA: in real;
                   LAMDA: in real;
                   BETA:  in real;
                   VON:   inout real;
                   VDSAT: inout real;
                   CDRAIN:inout real;
                   GM :   inout real;
                   GDS:   inout real;
                   GMBS:  inout real);

--*******************************************************************
--*                                                                 *
--*  MOSEQ2                                                         * SPEC
--*                                                                 *
--*******************************************************************
  procedure MOSEQ2(VDS: in real;VBS: in real;VGS: in real;
                   PHI: in real;VBI: in real;GAMMA: in real;
                   LAMDA: inout real; BETA: in real;FNARRW:in real;
                   TWOPI: in real;EPSSIL:in real;COX: in real;
                   W: in real; NSUB: in real;XD: in real;
                   XJ:in real; L: in real;NFS: in real;VT: in real;
                   UO: in real;VBP: in real;UEXP: in real;
                   VMAX: in real;NEFF: in real;VON: inout real;
                   VDSAT:inout real;CDRAIN:inout real;GM: inout real; 
                   GDS: inout real;GMBS: inout real;CHARGE:in real);

--******************************************************************
--*                                                                *
--*  capac					                   * 
--*                                                                *
--******************************************************************
  procedure capac( Vc : in value_array;NC1 : in node_array;
                  NC2 : in node_array;C : in value_array;
                  qcap0 : inout ncap_array; 
                  ccap0 : inout ncap_array; 
                  DELTA : in real; TAG,TAGT,ITFLG,NOFC : in integer; 
                  guess : in boolean;ceq,geq : inout value_array
                  );

--******************************************************************
--*                                                                *
--*  PULSE                                                         *
--*                                                                *
--******************************************************************
  procedure PULSE(T : inout REAL;TDV : in VALUE_ARRAY;
                  TRV : in VALUE_ARRAY;TFV : in VALUE_ARRAY;
                  PWV : in VALUE_ARRAY;PERV: in VALUE_ARRAY;
                  VP1 : in VALUE_ARRAY;VP2 : in VALUE_ARRAY;
                  NVP1: in NODE_ARRAY;NVP2 : in NODE_ARRAY;
                  NOFV: in INTEGER;NOFPV: in INTEGER;
                  VOUT: inout VALUE_ARRAY);

--******************************************************************
--*                                                                *
--*  FETLIM                                                        * SPEC 
--*                                                                *
--******************************************************************
  procedure FETLIM(VNEW: inout real;
                   VOLD: inout real;
                   VTO:  inout real);

--******************************************************************
--*                                                                *
--*  LIMVDS                                                        * SPEC 
--*                                                                *
--******************************************************************
  procedure LIMVDS(VNEW:inout real; VOLD: inout real);

--******************************************************************
--*                                                                *
--*  PNJLIM                                                        * SPEC 
--*                                                                *
--******************************************************************
  procedure PNJLIM(VNEW: inout real;VOLD: inout real;
                   VT: inout real;VCRIT: inout real);

--******************************************************************
--*                                                                *
--*   VDSAT_VMAX                                                   * SPEC 
--*                                                                *
--******************************************************************
  procedure VDSAT_VMAX
   (GAMMAD: in REAL;
    ETA   : in REAL;
    UEFF  : in REAL;
    L     : in REAL;
    VGSX  : in REAL;
    Vbin  : in REAL;
    Vbs   : in REAL;
    PHI   : in REAL;
    SARG3 : in REAL;
    VMAX  : in REAL;
    Vdsat : inout REAL);

--******************************************************************
--*                                                                *
--*   INICUR_COMP                                                  * SPEC
--*                                                                *
--******************************************************************
  procedure INICUR_COMP
   (R     : in VALUE_ARRAY;
    NR1   : in NODE_ARRAY;
    NR2   : in NODE_ARRAY; 
    NL1   : in NODE_ARRAY;
    NL2   : in NODE_ARRAY;
    ID    : in VALUE_ARRAY;
    NI1   : in NODE_ARRAY;
    NI2   : in NODE_ARRAY;
    NV1   : in NODE_ARRAY;
    NV2   : in NODE_ARRAY;
    NVP1  : in NODE_ARRAY;
    NVP2  : in NODE_ARRAY;
    VT    : in VALUE_ARRAY;
    NOFI  : in INTEGER;
    NOFV  : in INTEGER;
    NOFPV : in INTEGER;
    NOFR  : in INTEGER;
    NOFL  : in INTEGER;
    RNUM  : in INTEGER;
    IL    : inout VALUE_ARRAY);

--******************************************************************
--*                                                                *
--*   TRAN_ANA                                                     * SPEC
--*                                                                *
--******************************************************************
 procedure TRAN_ANA
   (R     : in VALUE_ARRAY;
    NR1   : in NODE_ARRAY;
    NR2   : in NODE_ARRAY;
    C     : in VALUE_ARRAY;
    NC1   : in NODE_ARRAY;
    NC2   : in NODE_ARRAY;
    L     : in VALUE_ARRAY;
    NL1   : in NODE_ARRAY;
    NL2   : in NODE_ARRAY;
    ID    : in VALUE_ARRAY;
    NI1   : in NODE_ARRAY;
    NI2   : in NODE_ARRAY;
    IP1   : in VALUE_ARRAY;
    IP2   : in VALUE_ARRAY;
    NP1   : in NODE_ARRAY;
    NP2   : in NODE_ARRAY;
    TDI   : in VALUE_ARRAY;
    TRI   : in VALUE_ARRAY;
    TFI   : in VALUE_ARRAY;
    PWI   : in VALUE_ARRAY;
    PERI  : in VALUE_ARRAY;
    VD    : in VALUE_ARRAY;
    NV1   : in NODE_ARRAY;
    NV2   : in NODE_ARRAY;
    VP1   : in VALUE_ARRAY;
    VP2   : in VALUE_ARRAY;
    NVP1  : in NODE_ARRAY;
    NVP2  : in NODE_ARRAY;
    TDV   : in VALUE_ARRAY;
    TRV   : in VALUE_ARRAY;
    TFV   : in VALUE_ARRAY;
    PWV   : in VALUE_ARRAY;
    PERV  : in VALUE_ARRAY;
    MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    MODEL_NAME: in NAME_ARRAY;
    MODEL_TYPE: in NAME_ARRAY;
    MODEL_PARA: inout PARAM_MATRIX;
    RNUM  : in INTEGER;
    NOFR  : in INTEGER;
    NOFC  : in INTEGER;
    NOFL  : in INTEGER;
    NOFV  : in INTEGER;
    NOFI  : in INTEGER;
    NOFPV : in INTEGER;
    NOFPI : in INTEGER;
    NOFM  : in INTEGER;
    NOFMOD: in INTEGER;
    TNOM  : in REAL;
    T0    : in REAL;
    DELT  : inout REAL;
    STEPV : inout REAL;
    STEPV_2 : inout REAL;
    TSTOP : in TIME;
    TSTEP : in TIME;
    Vbi0  : in VALUE_ARRAY;
    NONCON: inout INTEGER;
    IMEM  : inout VALUE_ARRAY;
    VMEM  : inout VALUE_ARRAY;
    IV    : inout VALUE_ARRAY;
    VT    : inout VALUE_ARRAY;
    IOUT  : inout VALUE_ARRAY;
    VOUT  : inout VALUE_ARRAY;
    IOUT1 : inout VALUE_ARRAY;
    VOUT1 : inout VALUE_ARRAY;
    IOUT2 : inout VALUE_ARRAY;
    VOUT2 : inout VALUE_ARRAY;
    IC    : inout VALUE_ARRAY;
    IL    : inout VALUE_ARRAY;
    QGS   : inout CHARG_ARRAY;
    QGD   : inout CHARG_ARRAY;
    QGB   : inout CHARG_ARRAY;
    QBD   : inout CHARG_ARRAY;
    QBS   : inout CHARG_ARRAY;
    CCAPGS: inout CHARG_ARRAY;
    CCAPGD: inout CHARG_ARRAY;
    CCAPGB: inout CHARG_ARRAY;
    CQBS  : inout CHARG_ARRAY;
    CQBD  : inout CHARG_ARRAY;
    VBS0  : inout VALUE_ARRAY;
    VBD0  : inout VALUE_ARRAY;
    VGS0  : inout VALUE_ARRAY;
    VDS0  : inout VALUE_ARRAY;
    VON0  : inout VALUE_ARRAY;
    VDSAT0: inout VALUE_ARRAY;
    VBS01 : inout VALUE_ARRAY;
    VGS01 : inout VALUE_ARRAY;
    VDS01 : inout VALUE_ARRAY;
    ccap0 : inout ncap_array;
    qcap0 : inout ncap_array;
    outflg: inout INTEGER;
    ITFLG : inout INTEGER;
    MAX   : inout INTEGER;
    TAG   : inout INTEGER);

--******************************************************************
--*                                                                *
--*   MOSFET_TRAN                                                  * SPEC
--*                                                                *
--******************************************************************
  procedure MOSFET_TRAN
   (MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    NAME      : in NAME_ARRAY;
    T_TYPE    : in NAME_ARRAY;
    TNOM      : in REAL;
    CONCK     : inout NODE_ARRAY;
    MODCOUNT  : in INTEGER;
    MCOUNT    : in INTEGER;
    DELTA     : in REAL;
    STEPV     : in REAL;
    V_ITER    : in VALUE_ARRAY;
    ITFLG     : in INTEGER;
    Vbi0      : in VALUE_ARRAY;
    TAG       : inout INTEGER;
    PARA      : inout PARAM_MATRIX;
    Cgd0      : inout VALUE_ARRAY;
    Cgb0      : inout VALUE_ARRAY;
    Cgs0      : inout VALUE_ARRAY;
    QGS0      : inout CHARG_ARRAY;
    QGD0      : inout CHARG_ARRAY;
    QGB0      : inout CHARG_ARRAY;
    QBD0      : inout CHARG_ARRAY;
    QBS0      : inout CHARG_ARRAY;
    CCAPGS0   : inout CHARG_ARRAY;
    CCAPGD0   : inout CHARG_ARRAY;
    CCAPGB0   : inout CHARG_ARRAY;
    CQBS0     : inout CHARG_ARRAY;
    CQBD0     : inout CHARG_ARRAY;
    NONCON    : inout INTEGER;
    VBS0      : inout VALUE_ARRAY;
    VBD0      : inout VALUE_ARRAY;
    VGS0      : inout VALUE_ARRAY;
    VDS0      : inout VALUE_ARRAY;
    VON0      : inout VALUE_ARRAY;
    VDSAT0    : inout VALUE_ARRAY;
    VBS01     : inout VALUE_ARRAY;
    VGS01     : inout VALUE_ARRAY;
    VDS01     : inout VALUE_ARRAY;
    VBS10     : inout VALUE_ARRAY;
    VBD10     : inout VALUE_ARRAY;
    VGS10     : inout VALUE_ARRAY;
    VDS10     : inout VALUE_ARRAY;
    VON10     : inout VALUE_ARRAY;
    VDSAT10   : inout VALUE_ARRAY;
    RIT       : inout INTEGER;
    CD0       : inout VALUE_ARRAY;
    CBS0      : inout VALUE_ARRAY;
    CBD0      : inout VALUE_ARRAY;
    gm0       : inout VALUE_ARRAY;
    gds0      : inout VALUE_ARRAY;
    gmbs0     : inout VALUE_ARRAY;
    GBS0      : inout VALUE_ARRAY;
    GBD0      : inout VALUE_ARRAY;
    G         : inout AMATRIX;
    I0        : inout VALUE_ARRAY;
    TAGT      : inout INTEGER);

--*****************************************************************
--*                                                               *
--*   TIME_TO_REAL                                                * SPEC
--*                                                               *
--***************************************************************** 
  function TIME_TO_REAL(A: in TIME) return REAL;

--*****************************************************************
--*                                                               *
--*   LOG                                                         * SPEC
--*                                                               *
--*****************************************************************
  function LOG(x: in REAL) return REAL;

--*****************************************************************
--*                                                               *
--*   POWER                                                       * SPEC
--*                                                               *
--*****************************************************************
  function POWER(x: in REAL; y: in REAL) return REAL;

--*****************************************************************
--*                                                               *
--*   FACTORIAL                                                   * SPEC
--*                                                               *
--***************************************************************** 
  function FACTORIAL(x: in REAL) return REAL;

--*****************************************************************
--*                                                               *
--*   sqrt                                                        * SPEC
--*                                                               *
--*****************************************************************
  function sqrt(x: in real) return real;

--*****************************************************************
--*                                                               *
--*   con                                                         * SPEC
--*                                                               *
--*****************************************************************
  function cos(x: in real) return real;

--*****************************************************************
--*                                                               *
--*   atan                                                        * SPEC
--*                                                               *
--*****************************************************************
  function atan(x: in real) return real;

end COMPUTE_PACK;

--******************************************************************
--*                                                                *
--*   LINEQUA_COMP                                                 * BODY
--*                                                                *
--******************************************************************
package body COMPUTE_PACK is 

  procedure LINEQUA_COMP
   (MNODENUM : in INTEGER;
    NOFV     : in INTEGER;
    NOFPV    : in INTEGER;
    G        : inout AMATRIX;
    I0       : inout VALUE_ARRAY;
    V0       : inout VALUE_ARRAY)
  is
 file FILE2 : text is out "STD_OUTPUT";
    variable G0 : AMATRIX(1 to MNODENUM,1 to MNODENUM);
    variable IV : VALUE_ARRAY(1 to NOFV+NOFPV);
    variable I  : INTEGER := 0;
    variable J  : INTEGER := 0; 
    variable k  : LINE;
  begin

    G0 := G;
    if NOFV+NOFPV < MNODENUM then  
      if NOFV+NOFPV /= 0 then
        loop1:
        for I in NOFV+NOFPV+1 to MNODENUM loop
          loop2:
          for J in 1 to NOFV+NOFPV loop
            V0(I) := V0(I) - V0(J)*G(I,J);
          end loop loop2;
        end loop loop1;
      end if;
      if NOFV+NOFPV+1 < MNODENUM then
        loop3:
        for I in NOFV+NOFPV+1 to MNODENUM-1 loop 
          assert not (G(I,I)=0.0)               
       	  report "G(I,I)=0.0"                      
  	  severity Error;                        
  	  loop4:                             
  	  for J in I+1 to MNODENUM loop 
            G(J,I) := G(J,I)/G(I,I);             
   	  end loop loop4;                        
          loop5:
   	  for J in I+1 to MNODENUM loop
  	    loop6: 
  	    for K in I+1 to MNODENUM loop 
  	      G(J,K) := G(J,K) - G(J,I) * G(I,K);  
            end loop loop6;                    
   	  end loop loop5;
        end loop loop3;
        loop7:
        for I in NOFV+NOFPV+1 to MNODENUM-1 loop 
          assert not (G(I,I)=0.0)                  -- Assertion  added  here
          report "G(I,I)=0.0"                      -- to  report  the  error
   	  severity Error;                          -- message if d(I,I)=0.0. 
  	  loop8:
  	  for J in I+1 to G'HIGH loop 
            V0(J) := V0(J) - G(J,I) * V0(I);  
  	  end loop loop8;                         
        end loop loop7;
        loop9:
        for I in MNODENUM downto NOFV+NOFPV+2 loop 
  	  V0(I) := V0(I)/G(I,I);              
  	  loop10:                         
  	  for J in NOFV+NOFPV+1 to I-1 loop 
  	    V0(J) := V0(J) - G(J,I) * V0(I);    
  	  end loop loop10;                   
        end loop loop9;
      end if;
      V0(NOFV+NOFPV+1) := V0(NOFV+NOFPV+1)/G(NOFV+NOFPV+1,NOFV+NOFPV+1);
      if NOFV+NOFPV /= 0 then 
        loopA1:
        for I in 1 to NOFV+NOFPV loop
          loopA2:
          for J in 1 to MNODENUM loop
            I0(I) := I0(I) - G0(I,J)*V0(J); 
          end loop loopA2;
        end loop loopA1;
      end if;
    elsif NOFV+NOFPV > MNODENUM then 
      assert not (NOFV+NOFPV>MNODENUM)
      report "NUMBER OF VOLTAGE SOURCES EXCEEDED NODE NUMBER"
      severity error;
    end if;
  return;        
  end LINEQUA_COMP;

--*****************************************************************
--*                                                               *
--*   DC_POINT                                                    * BODY
--*                                                               *  
--***************************************************************** 
  procedure DC_POINT(
    R         : in VALUE_ARRAY;
    NR1       : in NODE_ARRAY;
    NR2       : in NODE_ARRAY;
    ID        : in VALUE_ARRAY;
    NI1       : in NODE_ARRAY;
    NI2       : in NODE_ARRAY;
    IP1       : in VALUE_ARRAY;
    NP1       : in NODE_ARRAY;
    NP2       : in NODE_ARRAY;
    VD        : in VALUE_ARRAY;
    NV1       : in NODE_ARRAY;
    NV2       : in NODE_ARRAY;
    VP1       : in VALUE_ARRAY;
    NVP1      : in NODE_ARRAY;
    NVP2      : in NODE_ARRAY;
    MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    MODEL_NAME: in NAME_ARRAY;
    MODEL_TYPE: in NAME_ARRAY;
    MODEL_PARA: inout PARAM_MATRIX;
    NRNUM     : in INTEGER; 
    NOFR      : in INTEGER;
    NOFC      : in INTEGER;
    NOFL      : in INTEGER;
    NOFV      : in INTEGER;
    NOFI      : in INTEGER;
    NOFPV     : in INTEGER;
    NOFPI     : in INTEGER;
    NOFM      : in INTEGER;
    NOFMOD    : in INTEGER;
    TNOM      : in REAL;
    VBS0      : inout VALUE_ARRAY;
    VBD0      : inout VALUE_ARRAY;
    VGS0      : inout VALUE_ARRAY;
    VDS0      : inout VALUE_ARRAY;
    VON0      : inout VALUE_ARRAY;
    VDSAT0    : inout VALUE_ARRAY;
    Vbi0      : inout VALUE_ARRAY;
    I0        : inout VALUE_ARRAY;
    VOP       : inout VALUE_ARRAY)
  is
    file FILE2 : TEXT is out "STD_OUTPUT"; 
    variable k1     : line;
    variable ADMATR : AMATRIX(1 to NRNUM,1 to NRNUM);
    variable G      : AMATRIX(1 to NRNUM,1 to NRNUM);
    variable Vold   : VALUE_ARRAY(VOP'LOW to VOP'HIGH); 
    variable VOP1   : VALUE_ARRAY(VOP'LOW to VOP'HIGH); 
    variable I01    : VALUE_ARRAY(VOP'LOW to VOP'HIGH); 
    variable I0_tem : VALUE_ARRAY(VOP'LOW to VOP'HIGH); 
    variable CD0    : VALUE_ARRAY(1 to NOFM);
    variable CBS0   : VALUE_ARRAY(1 to NOFM);
    variable CBD0   : VALUE_ARRAY(1 to NOFM);
    variable gm0    : VALUE_ARRAY(1 to NOFM);
    variable gds0   : VALUE_ARRAY(1 to NOFM);
    variable gmbs0  : VALUE_ARRAY(1 to NOFM);
    variable GBS0   : VALUE_ARRAY(1 to NOFM);
    variable GBD0   : VALUE_ARRAY(1 to NOFM);
    variable CONCK  : NODE_ARRAY(1 to NOFM);
    variable TAG1,NONCON,NCOV: integer := 0;
    variable I      : positive;
    variable J      : positive;
    variable k      : positive;
  begin
    loop0:
    for I in 1 to NRNUM loop
      VOP(I) := 0.0;
      Vold(I):= 0.0;
      I0(I) := 0.0;
    end loop loop0;
    loop1:
    for I in 1 to NRNUM loop
      I0_tem(I):=0.0;
      loop2:
      for J in 1 to NRNUM loop
        ADMATR(I,J) := 0.0;
      end loop loop2;
    end loop loop1; 
    if NOFI /= 0 then
      loop3:
      for I in 1 to NRNUM loop
        loop4:
        for k in 1 to NOFI loop
          if NI1(k) = I then              
            I0_tem(I) := I0_tem(I) - ID(k);                  
          elsif NI2(k) = I then      
            I0_tem(I) := I0_tem(I) + ID(k);            
          end if;                         
        end loop loop4;        
      end loop loop3;                  
    end if;
    if NOFPI /= 0 then
      loop5:
      for k in 1 to NOFPI loop  
        loop6:                
        for I in 1 to NRNUM loop 
          if NP1(k)=I then            
            I0_tem(I) := I0_tem(I) - IP1(k);      
          elsif NP2(k) = I then          
            I0_tem(I) := I0_tem(I) + IP1(k);        
          end if;                           
        end loop loop6;                 
      end loop loop5;
    end if;
    if NOFR /= 0 then
      loopB1:
      for I in 1 to NRNUM loop
        loopB2:		
        for k in 1 to NOFR loop               
          if NR1(k)=I then   
            ADMATR(I,I) := ADMATR(I,I) + 1.0/R(k);   
          elsif NR2(k)=I then       
            ADMATR(I,I) := ADMATR(I,I) + 1.0/R(k);
          end if;
        end loop loopB2;
      end loop loopB1;
    end if;
    if NRNUM > 1 then
      loopB3:
      for I in 1 to NRNUM loop
        loopB4:                             
        for J in I+1 to NRNUM loop          
          loopB5:                          
          for k in 1 to NOFR loop      
            if NR1(k)=I and NR2(k)=J then     
              ADMATR(I,J) := ADMATR(I,J) - 1.0/R(k); 
            elsif NR1(k)=J and NR2(k)=I then 
              ADMATR(I,J) := ADMATR(I,J) - 1.0/R(k);
            end if;
            ADMATR(J,I) := ADMATR(I,J);
          end loop loopB5;
        end loop loopB4;
      end loop loopB3;
    end if;
    loopC1:
    loop
      VOP1 := I0_tem;
      G := ADMATR;
      if NOFM /= 0 then
        MOSFET_DC(MNAME,ND,NG,NS1,NB,CHANNEL_L,CHANNEL_W,AD,AS,PD,
          PS,NRD,NRS,OFF,IC_TRAN,MODEL_NAME,MODEL_TYPE,TNOM,CONCK,
          NOFMOD,NOFM,Vold,Vbi0,MODEL_PARA,TAG1,NONCON,VBS0,VBD0,VGS0,
          VDS0,VON0,VDSAT0,CD0,CBS0,CBD0,gm0,gds0,gmbs0,GBS0,GBD0,G,VOP1);
      end if;
      I01 := VOP1;
      if NOFV /= 0 then
        loopA1:
        for k in 1 to NOFV loop
          if NV1(k) /= 0 then
            VOP1(k) := VD(k);
          elsif NV2(k) /= 0 then
            VOP1(k) := - VD(k);
          end if;
        end loop loopA1;
      end if;
      if NOFPV /= 0 then
        loopA2:
        for k in 1 to NOFPV loop
          if NVP1(k) /= 0 then
            VOP1(k+NOFV) := VP1(k);
          elsif NVP2(k) /= 0 then
            VOP1(k+NOFV) := - VP1(k);
          end if;
        end loop loopA2;
      end if;
--|
      LINEQUA_COMP(NRNUM,NOFV,NOFPV,G,I01,VOP1);

      Vold := VOP1;
      VOP := VOP1;
      I0 := I01;
      if NOFM /= 0 then 
        NCOV:=0;
        loopck:
        for I in 1 to NOFM loop
          if CONCK(I) = 1 then
            NCOV:=NCOV+1;
          end if;
        end loop loopck;
        if NCOV = NOFM then  
          exit loopC1;
        end if;
      elsif NOFM = 0 then
        exit loopC1;
      end if;
    end loop loopC1;
  return;
  end DC_POINT;

--******************************************************************
--*                                                                *
--*   MOSFET_DC                                                    * BODY
--*                                                                *
--******************************************************************
    procedure MOSFET_DC
     (MNAME     : in NAME_ARRAY;
      ND        : in NODE_ARRAY;
      NG        : in NODE_ARRAY;
      NS1       : in NODE_ARRAY;
      NB        : in NODE_ARRAY;
      CHANNEL_L : in VALUE_ARRAY;
      CHANNEL_W : in VALUE_ARRAY;
      AD        : in VALUE_ARRAY;
      AS        : in VALUE_ARRAY;
      PD        : in VALUE_ARRAY;
      PS        : in VALUE_ARRAY;
      NRD       : in VALUE_ARRAY;
      NRS       : in VALUE_ARRAY;
      OFF       : in VALUE_ARRAY;
      IC_TRAN   : in VALUE_ARRAY;
      NAME      : in NAME_ARRAY;
      T_TYPE    : in NAME_ARRAY;
      TNOM      : in REAL;
      CONCK     : inout NODE_ARRAY;
      MODCOUNT  : in INTEGER;
      MCOUNT    : in INTEGER;
      VOP       : in VALUE_ARRAY;
      Vbi0      : inout VALUE_ARRAY;
      PARA      : inout PARAM_MATRIX;
      TAG       : inout INTEGER;
      NONCON    : inout INTEGER;
      VBS0      : inout VALUE_ARRAY;
      VBD0      : inout VALUE_ARRAY;
      VGS0      : inout VALUE_ARRAY;
      VDS0      : inout VALUE_ARRAY;
      VON0      : inout VALUE_ARRAY;
      VDSAT0    : inout VALUE_ARRAY;
      CD0       : inout VALUE_ARRAY;
      CBS0      : inout VALUE_ARRAY;
      CBD0      : inout VALUE_ARRAY;
      gm0       : inout VALUE_ARRAY;
      gds0      : inout VALUE_ARRAY;
      gmbs0     : inout VALUE_ARRAY;
      GBS0      : inout VALUE_ARRAY;
      GBD0      : inout VALUE_ARRAY;
      G         : inout AMATRIX;
      I0        : inout VALUE_ARRAY)
    is
      file FILE2 : TEXT is out "STD_OUTPUT";
      variable VTH,VON,VBIN,VBI,Vfb,CDREQ,CBD,CBS,BETA,LEFF,CD,COX,A1,COX1,
               Vgb,Vbs,Vgs,Vds,Vgd,Vbd,VDSAT,gmbs,gds,gm,GBD,GBS,VT,x,y,
               L,DEVMOD,TYPET,VDS1,VBS1,VGS1,VBD1,VGB1,FERMIS,FERMIG,
               Eg,SARG,ARG,VGD0,DELVBS,DELVBD,DELVGS,DELVDS,DELVGD,WKFNG,
               CDHAT,CBHAT,TOL,CDRAIN,VCRIT,VTEM,VTEM0,WKFNGS,XREV,XNRM,
               CEQBS,CEQBD,PHI,EPSSIL,TWOPI,XJ,FNARRW,GAMMA,NSUB,NFS,VBP,
               UEXP,UO,VMAX,NEFF,CHARGE,XD,VGST,TSARG,DSRGDB,D2SDB2,SPHI,
               SPHI3,BARG,DBRGDB,D2BDB2,FACTOR,ETA,WD,WS,ARGSS,ARGSD,DBARGS,
               DBARGD,DGDVDS,DGDDB2,ARGXS,ARGS,ARGXD,ARGD,GAMMASD,GAMASS,
               DBXWD,DBXWS,DASDB2,DADDB2,DGDDVB,DGSDVB,DDXWD,GAMASD,PHIB,
               GAMMAD,CFS,CDONCO,XN,ARGG,SARG3,SBIARG,DGDVBS,BODY1,GDBDV,
               DODVBS,DXNDVB,DXNDVD,DODVDS,UDENOM,UFACT,UEFF,DUDVGS,DUDVDS,
               DUDVBS,VGSX,VPOF,VDSAT1,GAMMD2,ARGV,BODYS,GDBDVS,BSARG,DBSRDB,
               XDV,XLV,VQCHAN,DQDSAT,VL,DFUNDS,DFUNDG,DFUNDB,DSDVGS,DSDVBS,
               XLS,DLDSAT,XLFACT,LAMDA,DLDVGS,DLDVDS,DLDVBS,SARGV,LD,WB,UFF,
               CLFACT,DELTAL,DFACT,BETA1,VDSON,CDSON,GDSON,GBSON,EXPG,DIDVDS,
               GMW: REAL:=0.0;
      variable type0 : ELEMENT_NAME;
      variable I,J,n : positive;
      variable VFF   : integer;
      variable k     : line;
      constant RELTOL: real:= 0.001;
      constant VNTOL : real:= 1.0e-6;
      constant ABSTOL: real:= 1.0e-12;
      
    begin
      VT := 0.25864186384551e-01;
      Eg:=1.16-7.02e-4*TNOM*TNOM/(1108.0+TNOM);
      loopA1:
      for I in 1 to MCOUNT loop 
        loopB1: 
        for J in 1 to MODCOUNT loop
          if MNAME(I) = NAME(J) then
            type0 := T_TYPE(J);
            if type0(1)='N' and type0(2)='M' and type0(3)='O'
              and type0(4)='S' then
              TYPET:=1.0;
            elsif type0(1)='P' and type0(2)='M' and type0(3)='O'
              and type0(4)='S' then
              TYPET:=-1.0;
            end if;
            FERMIS:=TYPET*0.5*PARA(5,J);
            FERMIG:=TYPET*PARA(26,J)*0.5*Eg;
            if PARA(26,J)=0.0 then
              WKFNG:=3.2;
            else
              WKFNG:=3.25+0.5*Eg-FERMIG;
            end if; 
            WKFNGS:=WKFNG-(3.25+0.5*Eg+FERMIS);
            PHI:=PARA(5,J);
            PHIB:=PARA(12,J);
            EPSSIL:=1.0359431399070e-10;
            TWOPI:= 6.2831853071795864769;
            FNARRW:=PARA(39,J);
            XJ:=PARA(27,J);
            GAMMA:=PARA(4,J);
            NSUB:=PARA(23,J);
            LAMDA:=PARA(6,J);
            NFS:=PARA(25,J);
            VBP:=PARA(30,J)*EPSSIL*PARA(22,J)/3.45314379969e-11;
            UEXP:=PARA(31,J);
            UO:=PARA(29,J);
            VMAX:= PARA(33,J);
            NEFF:= PARA(34,J);
            CHARGE:=1.6021918000000e-19;
            if TAG = 0 then
              Vbs := -1.0;
              Vgs := TYPET*PARA(2,J);
              Vds := 0.0; 
              Vbd := Vbs-Vds;
              --|First Newton iteration, initial guess of Vbs,Vgs,Vds;
            else
              if NB(I)/=0 and NS1(I)/=0 and NB(I)/=NS1(I) then
                Vbs := TYPET*(VOP(NB(I))-VOP(NS1(I)));
              elsif NB(I)=0 and NS1(I)/=0 then
                Vbs := - TYPET*VOP(NS1(I));
              elsif NB(I)/=0 and NS1(I)=0 then
                Vbs := TYPET*VOP(NB(I));
              elsif NB(I)=NS1(I) then
                Vbs := 0.0;
              end if; 
              if NG(I)/=0 and NS1(I)/=0 and NG(I)/=NS1(I) then
                Vgs := TYPET*(VOP(NG(I))-VOP(NS1(I)));
              elsif NG(I)=0 and NS1(I)/=0 then
                Vgs := - TYPET*VOP(NS1(I));
              elsif NG(I)/=0 and NS1(I)=0 then
                Vgs := TYPET*VOP(NG(I));
              elsif NG(I)=NS1(I) then
                Vgs := 0.0;
              end if;
              if ND(I)/=0 and NS1(I)/=0 and ND(I)/=NS1(I) then
                Vds := TYPET*(VOP(ND(I))-VOP(NS1(I)));
              elsif ND(I)=0 and NS1(I)/=0 then
                Vds := - TYPET*VOP(NS1(I));
              elsif ND(I)/=0 and NS1(I)=0 then
                Vds := TYPET*VOP(ND(I));
              elsif ND(I)=NS1(I) then
                Vds := 0.0;
              end if;
            end if;
            Vgd:=Vgs-Vds;
            Vgb:=Vgs-Vbs;
            Vbd:=Vbs-Vds;
            CONCK(I):=0;
--|
--| Compute the new and old branch voltage differences;  
--|
            VON:=VON0(I);              
            VGD0:=VGS0(I)-VDS0(I);
            if VDS0(I) < 0.0 then
              DEVMOD := -1.0;
            else
              DEVMOD := 1.0;
            end if;
            if TAG /= 0 then
              DELVBS:=Vbs-VBS0(I);
              DELVBD:=Vbd-VBD0(I);
              DELVGS:=Vgs-VGS0(I);
              DELVDS:=Vds-VDS0(I);
              DELVGD:=Vgd-VGD0;
              CDHAT:=CD0(I)-GBD0(I)*DELVBD+gmbs0(I)*DELVBS
               +gm0(I)*DELVGS+gds0(I)*DELVDS;
              if DEVMOD = -1.0 then
                CDHAT:=CD0(I)-(GBD0(I)-gmbs0(I))*DELVBD
                 -gm0(I)*DELVGD+gds0(I)*DELVDS; 
              end if;
              CBHAT:=CBS0(I)+CBD0(I)+GBD0(I)*DELVBD
                +GBS0(I)*DELVBS;
--|
--| Check the voltage limits;
--|
              TOL:=RELTOL*abs(Vbs) + VNTOL; 
              if abs(Vbs) < abs(VBS0(I)) then
                TOL:=RELTOL*abs(VBS0(I)) + VNTOL;
              end if;
              if abs(DELVBS) <= TOL then
                TOL:=RELTOL*abs(Vbd) + VNTOL;
                IF abs(VBD) < abs(VBD0(I)) then
                  TOL:=RELTOL*abs(VBD0(I)) + VNTOL;
                end if;
                if abs(DELVBD) <= TOL then
                  TOL:=RELTOL*abs(Vgs) + VNTOL;
                  if abs(Vgs) < abs(VGS0(I)) then
                    TOL:=RELTOL*abs(VGS0(I)) + VNTOL;
                  end if;
                  if abs(DELVGS) <= TOL then
                    TOL:=RELTOL*abs(Vds) + VNTOL;
                    if abs(vds) < abs(VDS0(I)) then
                      TOL:=RELTOL*abs(VDS0(I)) + VNTOL;
                    end if;
                    if abs(DELVDS) <= TOL then
                      TOL:=RELTOL*abs(CDHAT) + ABSTOL;
                      if abs(CDHAT) < CD0(I) then
                        TOL:=RELTOL*abs(CD0(I)) + ABSTOL;
                      end if;
                      if abs(CDHAT-CD0(I)) <= TOL then
                        TOL:=RELTOL*abs(CBHAT) + ABSTOL;
                        if abs(CBHAT) < abs(CBS0(I)+CBD0(I)) then
                          TOL:=RELTOL*abs(CBS0(I)+CBD0(I)) + ABSTOL;
                        end if;
                        if abs(CBHAT-(CBS0(I)+CBD0(I))) <= TOL then
                          Vbs:=VBS0(I);
                          Vbd:=VBD0(I);
                          Vgs:=VGS0(I);
                          Vds:=VDS0(I);
                          Vgd:=Vgs-Vds;
                          Vgb:=Vgs-Vbs;
                          CD :=CD0(I);
                          CBS:=CBS0(I);
                          CBD:=CBD0(I);
                          CDRAIN:=DEVMOD*(CD+CBD); 
                          gm:=gm0(I);
                          gds:=gds0(I);
                          gmbs:=gmbs0(I);
                          GBS:=GBS0(I);
                          GBD:=GBD0(I);
                          CONCK(I):=1;
                        end if;
                      end if;
                    end if;
                  end if;
                end if;
              end if;
            end if;
            if CONCK(I) /= 1 and TAG /= 0 then
              if VDS0(I) >= 0.0 then
                FETLIM(Vgs,VGS0(I),VON);
                Vds:=Vgs-Vgd;
                LIMVDS(Vds,VDS0(I));
                Vgd:=Vgs-Vds;
              else  
                FETLIM(Vgd,VGD0,VON);
                Vds:=Vgs-Vgd;
                VTEM:=-Vds;
                VTEM0:=-VDS0(I);
                LIMVDS(VTEM,VTEM0);
                Vgs:=Vgd+Vds;
              end if;
              if Vds >= 0.0 then
                VCRIT:=VT*2.3025850929940457
                 *LOG(VT/(1.4142135623730950*PARA(11,J)));
                PNJLIM(Vbs,VBS0(I),VT,VCRIT);
                Vbd:=Vbs-Vds;
              else
                VCRIT:=VT*2.3025850929940457
                 *LOG(VT/(1.4142135623730950*PARA(11,J)));
                PNJLIM(Vbd,VBD0(I),VT,VCRIT);
                Vbs:=Vbd+Vds;
              end if;
            end if;
--|
--| Check New Device Working Mode
--|
            if Vds < 0.0 then
              DEVMOD := -1.0;
            else
              DEVMOD := 1.0;
            end if;
--|
            if CONCK(I) /= 1 then
              Vbd:=Vbs-Vds;
              Vgd:=Vgs-Vds;
              Vgb:=Vgs-Vbs;
              if Vbs > 0.0 then
                x := Vbs/VT;
                GBS := PARA(11,J)*power(2.71828182845904523536, x)/VT+1.0e-12;
                CBS:= PARA(11,J)*(power(2.71828182845904523536, x)-1.0);
                --|equevalent linearized current source and conductance
                --|for diod;
              else
                GBS := PARA(11,J)/VT;
                CBS:=GBS*Vbs;
                GBS := GBS+1.0e-12;
              end if;
              if Vbd > 0.0 then
                x := Vbd/VT;
                GBD := PARA(11,J)*power(2.71828182845904523536, x)/VT+1.0e-12;
                CBD:= PARA(11,J)*(power(2.71828182845904523536,x)-1.0);
                --|linearized current and conductance of diod;
              else
                GBD := PARA(11,J)/VT;
                CBD:= GBD*Vbd;
                GBD := GBD+1.0e-12;
              end if;
--|
              L := CHANNEL_L(I)-2.0*PARA(28,J);
              COX:=3.45314379969e-11/PARA(22,J);
              COX1:=COX*CHANNEL_W(I)*L;
              x :=1.0e-6*(EPSSIL+EPSSIL)/1.6021918000000e-19;
              XD := sqrt(x/NSUB);
              if PARA(5,J)=0.63 and PARA(23,J)/=0.0 then
              --|PARA(5,J) = 0.6 => default value, no PHI input. 
                x := PARA(23,J)/1.4e+10;
                PARA(5,J) := 2.0*VT*LOG(x)/0.4342944819032518;
              end if;
              if PARA(4,J)=0.0 and PARA(23,J)/=0.0 then
                x := 2.0*(1.6021918e-19)*PARA(23,J)*(1.0443e-4);
                PARA(4,J) := sqrt(x)/COX; 
              end if;
              if PARA(3,J)=0.0 then
                PARA(3,J):=PARA(29,J)*COX;
              end if;
              Vfb:= WKFNGS - (1.6021918e-15)*PARA(24,J)/COX;
              if PARA(2,J)=0.0 then
              --|no VTO input;
                Vbi0(I):=Vfb+TYPET*PARA(5,J);
                PARA(2,J):= Vbi0(I)+TYPET*PARA(4,J)*sqrt(PARA(5,J));
              else
                Vbi0(I):=PARA(2,J)-TYPET*PARA(4,J)*sqrt(PARA(5,J));
              end if;
              VBI:=TYPET*Vbi0(I);
              BETA := CHANNEL_W(I)*PARA(3,J)/L;
--|
--| COMPUTE DRAIN CURRENT AND
--|
              if DEVMOD = -1.0 then
                VDS1:=-Vds;
                VGS1:=Vgd;
                VBS1:=Vbd;
              else
                VDS1:=Vds;
                VGS1:=Vgs;
                VBS1:=Vbs;
              end if;
              VBD1:=VBS1-VDS1;
              VGB1:=VGS1-VBS1;
--|
--| MOSFET Level1 DC Model Drain Current & Derivitive Evaluation; 
--|
              if PARA(1,J)= 1.0 then
                MOSEQ1(VDS1,VBS1,VGS1,PHI,VBI,GAMMA,LAMDA,BETA,
                  VON,VDSAT,CDRAIN,GM,GDS,GMBS);
              elsif PARA(1,J)=2.0 then
--|
--| MOSFET Level2 DC Drain Current & Derivitive Evaluation;.
--|

--|
--| Calculate Some Useful Quantities;
--|
                MOSEQ2(VDS1,VBS1,VGS1,PHI,VBI,GAMMA,LAMDA,BETA,
                  FNARRW,TWOPI,EPSSIL,COX1,CHANNEL_W(I),NSUB,XD,
                  XJ,L,NFS,VT,UO,VBP,UEXP,VMAX,NEFF,VON,VDSAT,
                  CDRAIN,GM,GDS,GMBS,CHARGE);
              end if;
              CD:=DEVMOD*CDRAIN-CBD;
--|
--|  Check Convergence;
--|
              if TAG /= 0 then
                TOL:=RELTOL*abs(CDHAT)+ABSTOL;
                if abs(CDHAT) < abs(CD) then
                  TOL:=RELTOL*abs(CD)+ABSTOL;
                end if;
                if abs(CDHAT-CD) <= TOL then
                  TOL:=RELTOL*abs(CBHAT)+ABSTOL;
                  if abs(CBHAT) < abs(CBS+CBD) then
                    TOL:=RELTOL*abs(CBS+CBD)+ABSTOL;
                  end if;
                  if abs(CBHAT-(CBS+CBD)) <= TOL then
                    CONCK(I):=1;
                  else
                    NONCON := NONCON + 1;
                  end if;
                else
                  NONCON := NONCON + 1;
                end if;
              end if;
              VBS0(I):=Vbs;
              VBD0(I):=Vbd;
              VGS0(I):=Vgs;
              VDS0(I):=Vds;
              CD0(I) :=CD; 
              CBS0(I):=CBS; 
              CBD0(I):=CBD; 
              gm0(I) :=gm;
              gds0(I):=gds;
              gmbs0(I):=gmbs;
              gbs0(I):=gbs;
              gbd0(I):=gbd;
              VON0(I):=VON;
              VDSAT0(I):=VDSAT;
            end if;
--|
            CEQBS:=TYPET*(CBS*1.0e+12-GBS*1.0e+12*Vbs+Vbs)*1.0e-12;
            CEQBD:=TYPET*(CBD*1.0e+12-GBD*1.0e+12*Vbd+Vbd)*1.0e-12;
            if DEVMOD = 1.0 then
              XNRM:=1.0;
              XREV:=0.0;
              CDREQ:=TYPET*(CDRAIN-gmbs*Vbs-gm*Vgs-gds*Vds);
            else
              XNRM:=0.0;
              XREV:=1.0;
              CDREQ:=-TYPET*(CDRAIN-gmbs*Vbd-gm*Vgd-gds*(-Vds));
            end if;
--|
--| Load current vector and nodal admittance matrix;
--|
            if NB(I)/=0 then
              G(NB(I),NB(I)) := G(NB(I),NB(I))+GBS+GBD;
              I0(NB(I)) := I0(NB(I))-CEQBS-CEQBD;
              if ND(I)/= 0 then
                G(NB(I),ND(I)) := G(NB(I),ND(I))-GBD;
              end if;
              if NS1(I)/=0 then
                G(NB(I),NS1(I)):=G(NB(I),NS1(I))-GBS;
              end if;
            end if;
            if ND(I)/=0 then
              G(ND(I),ND(I)) := G(ND(I),ND(I))+gds+GBD+XREV*(gm+gmbs);
              I0(ND(I)) := I0(ND(I))+CEQBD-CDREQ;
              if NG(I)/=0 then
                G(ND(I),NG(I)):= G(ND(I),NG(I))+(XNRM-XREV)*gm;
              end if;
              if NS1(I)/=0 then
                G(ND(I),NS1(I)) := G(ND(I),NS1(I))-gds-XNRM*(gmbs+gm);
              end if;
              if NB(I)/=0 then
                G(ND(I),NB(I)) := G(ND(I),NB(I))+(XNRM-XREV)*gmbs-GBD;
              end if;
            end if;
            if NS1(I)/= 0 then
              G(NS1(I),NS1(I)) := G(NS1(I),NS1(I))+gds+GBS+XNRM*(gmbs+gm);
              I0(NS1(I)) := I0(NS1(I))+CDREQ+CEQBS;
              if NG(I)/=0 then
                G(NS1(I),NG(I)):= G(NS1(I),NG(I))-(XNRM-XREV)*gm;
              end if;
              if ND(I)/= 0 then
                G(NS1(I),ND(I)):= G(NS1(I),ND(I))-gds-XREV*(gm+gmbs);
              end if;
              if NB(I)/= 0 then
                G(NS1(I),NB(I)):= G(NS1(I),NB(I))-GBS-(XNRM-XREV)*gmbs;
              end if;
            end if;
          end if;
        end loop loopB1;
      end loop loopA1;
      TAG := TAG + 1;
    return;
    end MOSFET_DC;

--*******************************************************************
--                                                                  *
--  MOSEQ1                                                          * BODY
--                                                                  *
--*******************************************************************
  procedure MOSEQ1(VDS: in real;
                   VBS: in real;
                   VGS: in real;
                   PHI: in real;
                   VBI: in real;
                   GAMMA: in real;
                   LAMDA: in real;
                   BETA:  in real;
                   VON:   inout real;
                   VDSAT: inout real;
                   CDRAIN:inout real;
                   GM :   inout real;
                   GDS:   inout real;
                   GMBS:  inout real)
    is
      file FILE2 : TEXT is out "STD_OUTPUT";
      variable A1,SARG,ARG,VGST,BETAP : real;
      variable k: line;
    begin

      if VBS <= 0.0 then
        A1:= PHI-VBS;
        SARG:= sqrt(A1);
      else
        SARG:= sqrt(PHI);
        SARG:= SARG-VBS/(SARG+SARG);
        if SARG < 0.0 then
          SARG:=0.0;
        end if;
      end if;
      VON:=VBI+GAMMA*SARG;
      VGST:=VGS-VON;
      VDSAT:=VGS-VON;
      if VDSAT < 0.0 then
        VDSAT:=0.0;
      end if;
      BETAP:=BETA*(1.0+LAMDA*VDS);
      if SARG <= 0.0 then
        ARG:=0.0;
      else
        ARG:=GAMMA/(SARG+SARG);
      end if;
      if VGST > 0.0 then
      --|Strong inversion;
        if VDS >= VGST then
        --|FET working in saturation region;
          CDRAIN:= BETAP*VGST*VGST*0.5;
          gm:= BETAP*VGST;
          gds:= BETA*VGST*VGST*LAMDA/2.0;
          gmbs:=gm*ARG;
        elsif VDS < VGST then
        --|triode regime;
          CDRAIN:= BETAP*(VGST-VDS*0.5)*VDS;
          gm:= BETAP*VDS;
          gds:= BETAP*(VGST-VDS)
            +LAMDA*BETA*VDS*(VGST-VDS*0.5);
          gmbs:= gm*ARG;
        end if;
      elsif VGST <= 0.0 then
      --|Cutoff regime;
        CDRAIN:=0.0;
        gmbs:= 0.0;
        gm := 0.0;
        gds:= 0.0;
      end if;
      return;
    end MOSEQ1;

--*******************************************************************
--*                                                                 *
--*  MOSEQ2                                                         * BODY
--*                                                                 *
--*******************************************************************
  procedure MOSEQ2(VDS: in real;VBS: in real;VGS: in real;
                   PHI: in real;VBI: in real;GAMMA: in real;
                   LAMDA: inout real; BETA: in real;FNARRW:in real;
                   TWOPI: in real;EPSSIL:in real;COX: in real;
                   W: in real; NSUB: in real;XD: in real;
                   XJ:in real; L: in real;NFS: in real;VT: in real;
                   UO: in real;VBP: in real;UEXP: in real;
                   VMAX: in real;NEFF: in real;VON: inout real;
                   VDSAT:inout real;CDRAIN:inout real;GM: inout real; 
                   GDS: inout real;GMBS: inout real;CHARGE:in real)
    is
      file FILE2 : TEXT is out "STD_OUTPUT";
      variable VTH,VBIN,CDREQ,CBD,CBS,LEFF,A1,
               DEVMOD,TYPET,VBD,VGB,
               SARG,ARG,VGD0,DELVBS,DELVBD,DELVGS,DELVDS,DELVGD,
               CDHAT,CBHAT,TOL,XREV,XNRM,
               CEQBS,CEQBD,
               VGST,TSARG,DSRGDB,D2SDB2,SPHI,
               SPHI3,BARG,DBRGDB,D2BDB2,FACTOR,ETA,WD,WS,ARGSS,ARGSD,DBARGS,
               DBARGD,DGDVDS,DGDDB2,ARGXS,ARGS,ARGXD,ARGD,GAMMASD,GAMASS,
               DBXWD,DBXWS,DASDB2,DADDB2,DGDDVB,DGSDVB,DDXWD,GAMASD,PHIB,
               GAMMAD,CFS,CDONCO,XN,ARGG,SARG3,SBIARG,DGDVBS,BODY1,GDBDV,
               DODVBS,DXNDVB,DXNDVD,DODVDS,UDENOM,UFACT,UEFF,DUDVGS,DUDVDS,
               DUDVBS,VGSX,VPOF,VDSAT1,GAMMD2,ARGV,BODYS,GDBDVS,BSARG,DBSRDB,
               XDV,XLV,VQCHAN,DQDSAT,VL,DFUNDS,DFUNDG,DFUNDB,DSDVGS,DSDVBS,
               XLS,DLDSAT,XLFACT,DLDVGS,DLDVDS,DLDVBS,SARGV,LD,WB,UFF,
               CLFACT,DELTAL,DFACT,BETA1,VDSON,CDSON,GDSON,GBSON,EXPG,DIDVDS,
               GMW: REAL:=0.0;
      variable VFF: integer:=0;
      variable k : line;
    begin
      if VBS <= 0.0 then
        SARG:= sqrt(PHI-VBS);
        TSARG:=SARG+SARG;
        DSRGDB:=-0.5/SARG;
        D2SDB2:=0.5*DSRGDB/(PHI-VBS);
      else
        SPHI:=sqrt(PHI);
        SPHI3:=PHI*SPHI;
        SARG:=SPHI/(1.0+0.5*VBS/PHI);
        TSARG:=SARG+SARG;
        DSRGDB:=-0.5*SARG*SARG/SPHI3;
        D2SDB2:=-DSRGDB*SARG/SPHI3;
      end if;
      if VDS-VBS >= 0.0 then
        BARG:=sqrt(PHI+VDS-VBS);
        DBRGDB:=-0.5/BARG;
        D2BDB2:=0.5*DBRGDB/(PHI+VDS-VBS);
      else
        BARG:=SPHI/(1.0+0.5*(VBS-VDS)/PHI);
        DBRGDB:=-0.5*BARG*BARG/SPHI3;
        D2BDB2:=-DBRGDB*BARG/SPHI3;
      end if;
--|
--| Calulate Threshold Voltage (VON) With Narrow-Channel Effect;
--|
      FACTOR:=0.125*FNARRW*TWOPI*EPSSIL/COX*W;
      ETA:=1.0+FACTOR;
      VBIN:=VBI+FACTOR*(PHI-VBS);
      if GAMMA /= 0.0 and NSUB /= 0.0 then
        WD:=XD*BARG;
        WS:=XD*SARG;
        ARGSS:=0.0;
        ARGSD:=0.0;
        DBARGS:=0.0;
        DBARGD:=0.0;
        DGDVDS:=0.0;
        DGDDB2:=0.0;
        if XJ /= 0.0 then
          ARGXS:=1.0+2.0*WS/XJ;
          ARGS:=SQRT(ARGXS);
          ARGSS:=0.5*XJ/L*(ARGS-1.0);
          ARGXD:=1.0+2.0*WD/XJ;
          ARGD:=SQRT(ARGXD);
          ARGSD:=0.5*XJ/L*(ARGD-1.0);
        end if;
        GAMASD:=GAMMA*(1.0-ARGSS-ARGSD);
        GAMASS:=GAMMA*(1.0-2.0*ARGSS);
        DBXWD:=XD*DBRGDB;
        DBXWS:=XD*DSRGDB;
        if XJ /= 0.0 then
          DBARGS:=0.5/L*DBXWS/ARGS;
          DBARGD:=0.5/L*DBXWD/ARGD;
          DASDB2:=-XD*( D2SDB2+DSRGDB*DSRGDB*XD/(XJ*ARGXS) )/(L*ARGS);
          DADDB2:=-XD*(D2BDB2+DBRGDB*DBRGDB*XD/(XJ*ARGXD))/(L*ARGD);
          DGDDB2:=-0.5*GAMMA*(DASDB2+DADDB2);
        end if;
        DGDDVB:=-GAMMA*(DBARGS+DBARGD);
        DGSDVB:=-2.0*GAMMA*DBARGS;
        if XJ /= 0.0 then
          DDXWD:=-DBXWD;
          DGDVDS:=-GAMMA*0.5/L*DDXWD/ARGD;
        end if;
      else
        GAMASD:=GAMMA;
        GAMASS:=GAMMA;
        GAMMAD:=GAMMA;
        DGDDVB:=0.0;
        DGSDVB:=0.0;
        DGDVDS:=0.0;
        DGDDB2:=0.0;
      end if;
      VON:=VBIN+GAMASD*SARG;
      VTH:=VON;
      VDSAT:=0.0;
      VFF := 0;
      if NFS /= 0.0 and COX /= 0.0 then
        CFS:=CHARGE*NFS*1.0e+4;
        CDONCO:=-(GAMASD*DSRGDB+DGDDVB*SARG)+FACTOR;
        XN:=1.0+CFS/COX*W*L+CDONCO;
        VON:=VON+VT*XN;
        ARGG:=1.0/(VT*XN);
        VGST:=VGS-VON;
      else
        VGST:=VGS-VON;
        if VGS <= VON then
          GDS:=0.0;
          GM:=0.0;
          GMBS:=0.0;
          CDRAIN:=0.0;
          VFF:=1;
        end if;
      end if;
--|
--| Compute Some Useful quantities;
--|
      if VFF = 0 then
        SARG3:=SARG*SARG*SARG;
        SBIARG:=SQRT(PHIB);
        GAMMAD:=GAMASD;
        DGDVBS:=DGDDVB;
        BODY1:=BARG*BARG*BARG-SARG3;
        GDBDV:=2.0*GAMMAD*(BARG*BARG*DBRGDB-SARG*SARG*DSRGDB);
        DODVBS:=-FACTOR+DGDVBS*SARG+GAMMAD*DSRGDB;
        if NFS /= 0.0 then
          if COX = 0.0 then
            UFACT:=1.0;
            UEFF:=UO;
            DUDVGS:=0.0;
            DUDVDS:=0.0;
            DUDVBS:=0.0;
          else
            DXNDVB:=2.0*DGDVBS*DSRGDB+GAMMAD*D2SDB2+DGDDB2*SARG;
            DODVBS:=DODVBS+VT*DXNDVB;
            DXNDVD:=DGDVDS*DSRGDB;
            DODVDS:=DGDVDS*SARG+VT*DXNDVD;
          end if;
        end if;
        if COX <= 0.0 then
          UFACT:=1.0;
          UEFF:=UO;
          DUDVGS:=0.0;
          DUDVDS:=0.0;
          DUDVBS:=0.0;
        else
          UDENOM:=VGST;
          if UDENOM <= VBP then
            UFACT:=1.0;
            UEFF:=UO;
            DUDVGS:=0.0;
            DUDVDS:=0.0;
            DUDVBS:=0.0;
          else
            UFF:=UEXP*LOG(VBP/UDENOM)*2.30258509299404568401;
            UFACT:=POWER(2.7182818284590452,UFF);
            UEFF:=UO*UFACT;
            DUDVGS:=-UFACT*UEXP/UDENOM;
            DUDVDS:=0.0;
            DUDVBS:=UEXP*UFACT*DODVBS/VGST;
          end if;
        end if;
--|
--| EVALUATE SATURATION VOLTAGE AND ITS DERIVATIVES ACCORDING TO
--| GROVE-FROHMAN EQUATION
--|
        VGSX:=VGS;
        GAMMAD:=GAMASD/ETA;
        DGDVBS:=DGDDVB;
        if NFS /= 0.0 and COX /= 0.0 then
          if VGS < VON then
            VGSX:=VON;
          end if;
        end if;
        if GAMMAD <= 0.0 then
          VDSAT:=(VGSX-VBIN)/ETA;
          if VDSAT < 0.0 then
            VDSAT := 0.0;
          end if;
          VPOF:=ETA*VDS+VBIN;
          if VPOF < 0.0 then
            VPOF := 0.0;
          end if;
          VDSAT1:=(VPOF-VBIN)/ETA;
          if VDSAT1 < 0.0 then
            VDSAT1 := 0.0;
          end if;
          DSDVGS:=1.0;
          DSDVBS:=0.0;
        else
          GAMMD2:=GAMMAD*GAMMAD;
          ARGV:=(VGSX-VBIN)/ETA+PHI-VBS;
          if ARGV > 0.0 then
            ARG:=SQRT(1.0+4.0*ARGV/GAMMD2);
            VDSAT:=(VGSX-VBIN)/ETA+GAMMD2*(1.0-ARG)/2.0;
            if VDSAT < 0.0 then
              VDSAT:=0.0;
            end if;
          else
            VDSAT:=0.0;
            VPOF:=VTH;
            VDSAT1:=0.0;
            DSDVGS:=0.0;
            DSDVBS:=0.0;
          end if;
          DSDVGS:=(1.0-1.0/ARG)/ETA;
          DSDVBS:=(GAMMAD*(1.0-ARG)+2.0*ARGV/(GAMMAD*ARG))/ETA*DGDVBS
            +1.0/ARG+FACTOR*DSDVGS;
        end if;
--|
--|  STORE VDSAT AS ABOVE IN VPOF (PINCH-OFF)
--|
        if VMAX /= 0.0 then
          VDSAT_VMAX(GAMMAD,ETA,UEFF,L,VGSX,VBIN,VBS,PHI,
            SARG3,VMAX,VDSAT);
        end if;
--|
--|  EVALUATE EFFECTIVE CHANNEL LENGTH AND ITS DERIVATIVES
--|
        if VDS = 0.0 then
          DLDVGS:=0.0;
          DLDVDS:=0.0;
          DLDVBS:=0.0;
        else
          GAMMAD:=GAMASD;
          if VBS-VDSAT <= 0.0 then
            BSARG:=SQRT(VDSAT-VBS+PHI);
            DBSRDB:=-0.5/BSARG;
          else
            BSARG:=SPHI/(1.0+0.5*(VBS-VDSAT)/PHI);
            DBSRDB:=-0.5*BSARG*BSARG/SPHI3;
          end if;
          BODYS:=BSARG*BSARG*BSARG-SARG3;
          GDBDVS:=2.0*GAMMAD*(BSARG*BSARG*DBSRDB-SARG*SARG*DSRGDB);
          if VMAX > 0.0 then
            ARGV:=(VGSX-VBIN)/ETA-VDSAT;
            XDV:=XD/SQRT(NEFF);
            XLV:=VMAX*XDV/(2.0*UEFF);
            VQCHAN:=ARGV-GAMMAD*BSARG;
            DQDSAT:=-1.0+GAMMAD*DBSRDB;
            VL:=VMAX*L;
            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 NSUB /= 0.0 and LAMDA <= 0.0 then
              ARGV:=VDS-VDSAT;
              if ARGV < 0.0 then
                ARGV:=0.0;
              end if;
              XLS:=SQRT(XLV*XLV+ARGV);
              DLDSAT:=XDV/(2.0*XLS);
              XLFACT:=XDV/(L*VDS);
              LAMDA:=XLFACT*(XLS-XLV);
              DLDSAT:=DLDSAT/L;
              DLDVGS:=DLDSAT*DSDVGS;
              DLDVDS:=-LAMDA+DLDSAT;
              DLDVBS:=DLDSAT*DSDVBS;
            else
              DLDVGS:=0.0;
              DLDVDS:=0.0;
              DLDVBS:=0.0;
            end if;
          elsif NSUB /= 0.0 and LAMDA <= 0.0 then
            ARGV:=(VDS-VDSAT)/4.0;
            SARGV:=SQRT(1.0+ARGV*ARGV);
            ARG:=SQRT(ARGV+SARGV);
            XLFACT:=XD/(L*VDS);
            LAMDA:=XLFACT*ARG;
            DLDSAT:=VDS*XLFACT*ARG/(8.0*SARGV);
            DLDVGS:=DLDSAT*DSDVGS;
            DLDVDS:=-LAMDA+DLDSAT;
            DLDVBS:=DLDSAT*DSDVBS;
          elsif NSUB = 0.0 or LAMDA > 0.0 then
            DLDVGS:=0.0;
            DLDVDS:=0.0;
            DLDVBS:=0.0;
          end if;
        end if;
--|
--|  LIMIT CHANNEL SHORTENING AT PUNCH-THROUGH
--|
        WB:=XD*SBIARG;
        LD:=L-WB;
        CLFACT:=1.0-LAMDA*VDS;
        DLDVDS:=-LAMDA-DLDVDS;
        LEFF:=L*CLFACT;
        DELTAL:=LAMDA*VDS*L;
        if NSUB = 0.0 then
          WB:=0.25e-6;
        end if;
        if LEFF < WB then
          LEFF:=WB/(1.0+(DELTAL-LD)/WB);
          CLFACT:=LEFF/L;
          DFACT:=LEFF*LEFF/(WB*WB);
          DLDVGS:=DFACT*DLDVGS;
          DLDVDS:=DFACT*DLDVDS;
          DLDVBS:=DFACT*DLDVBS;
        end if;
--|
--| EVALUATE EFFECTIVE BETA (EFFECTIVE KP)
--|
        BETA1:=BETA*UFACT/CLFACT;
--|
--| TEST FOR MODE OF OPERATION AND BRANCH APPROPRIATELY
--|
        GAMMAD:=GAMASD;
        DGDVBS:=DGDDVB;
        if VDS > 1.0e-8 then
          if VGS <= VON then
--|
--| SUBTHRESHOLD REGION
--|
            if VDSAT > 0.0 then
              VDSON:=VDSAT;
              if VDSON > VDS then
                VDSON := VDS;
              end if;
              IF VDS > VDSAT then
                BARG:=BSARG;
                DBRGDB:=DBSRDB;
                BODY1:=BODYS;
                GDBDV:=GDBDVS;
              end if;
              CDSON:=BETA1*((VON-VBIN-ETA*VDSON*0.5)*VDSON
               -GAMMAD*BODY1/1.5);
              DIDVDS:=BETA1*(VON-VBIN-ETA*VDSON-GAMMAD*BARG);
              GDSON:=-CDSON*DLDVDS/CLFACT-BETA1*DGDVDS*BODY1/1.5;
              IF VDS < VDSAT then
                GDSON:=GDSON+DIDVDS;
              end if;
              GBSON:=-CDSON*DLDVBS/CLFACT
               +BETA1*(DODVBS*VDSON+FACTOR*VDSON-DGDVBS*BODY1/1.5
               -GDBDV);
              IF VDS > VDSAT then
                GBSON:=GBSON+DIDVDS*DSDVBS;
              end if;
              EXPG:=POWER(2.7182818284590452, ARGG*(VGS-VON));
              CDRAIN:=CDSON*EXPG;
              GMW:=CDRAIN*ARGG;
              GM:=GMW;
              IF VDS > VDSAT then
                GM:=GMW+DIDVDS*DSDVGS*EXPG;
              end if;
              GDS:=GDSON*EXPG-GM*DODVDS-GMW*(VGS-VON)*DXNDVD/XN;
              GMBS:=GBSON*EXPG-GM*DODVBS-GMW*(VGS-VON)*DXNDVB/XN;
            else
              GDS:=0.0;
              if VGS <= VTH then
                CDRAIN:=0.0;
                GMBS:=0.0;
                GM:=0.0;
              end if;
            end if;
          else
            if VDS <= VDSAT then
--|
--|  LINEAR REGION
--|
              CDRAIN:=BETA1*((VGS-VBIN-ETA*VDS/2.0)*VDS
               -GAMMAD*BODY1/1.5);
              ARG:=CDRAIN*(DUDVGS/UFACT-DLDVGS/CLFACT);
              GM:=ARG+BETA1*VDS;
              ARG:=CDRAIN*(DUDVDS/UFACT-DLDVDS/CLFACT);
              GDS:=ARG+BETA1*(VGS-VBIN-ETA*VDS
               -GAMMAD*BARG-DGDVDS*BODY1/1.5);
              ARG:=CDRAIN*(DUDVBS/UFACT-DLDVBS/CLFACT);
              GMBS:=ARG-BETA1*(GDBDV+DGDVBS*BODY1/1.5-FACTOR*VDS);
            else
--|
--| SATURATION REGION
--|
              CDRAIN:=BETA1*((VGS-VBIN-ETA*VDSAT/2.0)*VDSAT
               -GAMMAD*BODYS/1.5);
              ARG:=CDRAIN*(DUDVGS/UFACT-DLDVGS/CLFACT);
              GM:=ARG+BETA1*VDSAT
               +BETA1*(VGS-VBIN-ETA*VDSAT-GAMMAD*BSARG)*DSDVGS;
              GDS:=-CDRAIN*DLDVDS/CLFACT-BETA1*DGDVDS*BODYS/1.5;
              ARG:=CDRAIN*(DUDVBS/UFACT-DLDVBS/CLFACT);
              GMBS:=ARG-BETA1*(GDBDVS+DGDVBS*BODYS/1.5-FACTOR*VDSAT)
               +BETA1*(VGS-VBIN-ETA*VDSAT-GAMMAD*BSARG)*DSDVBS;
            end if;
          end if;
        else
          if VGS > VON then
            GDS:=BETA1*(VGS-VBIN-GAMMAD*SARG);
            GM:=0.0;
            GMBS:=0.0;
            CDRAIN:=0.0;
          else
            if NFS /= 0.0 and COX /= 0.0 then
              GDS:=BETA1*(VON-VBIN-GAMMAD*SARG)
               *POWER(2.7182818284590452,ARGG*(VGS-VON));
              GM:=0.0;
              GMBS:=0.0;
              CDRAIN:=0.0;
            else
              GDS:=0.0;
              GM:=0.0;
              GMBS:=0.0;
              CDRAIN:=0.0;
            end if;
          end if;
        end if;
      end if;
      return;
    end MOSEQ2;
                  
--*******************************************************************
--*                                                                 *
--*  FETLIM                                                         * BODY
--*                                                                 *
--*******************************************************************
  procedure FETLIM(VNEW: inout real;
                   VOLD: inout real;
                   VTO:  inout real)
    is
      variable VTSTHI, VTSTLO, VTOX, DELV,VTEMP : real;
    begin

      VTSTHI:=abs(2.0*(VOLD-VTO))+2.0;
      VTSTLO:=VTSTHI/2.0 + 2.0;
      VTOX := VTO+3.5;
      DELV := VNEW-VOLD;
--|
--| OFF ...
--|
      if VOLD < VTO then
        if DELV <= 0.0 then
          if -DELV > VTSTHI then
            VNEW:=VOLD-VTSTHI;
          end if; 
        else
          VTEMP:=VTO+0.5;
          if VNEW <= VTEMP then
            if DELV > VTSTLO then
              VNEW:=VOLD+VTSTLO;
            end if;
          else
            VNEW:=VTEMP;
          end if;
        end if;
--|
--| MIDDLE REGION
--|
      elsif VOLD < VTOX then
        if DELV <= 0.0 then
          if VNEW < VTO-0.5 then
            VNEW:=VTO-0.5;
          end if;
        else
          if VNEW > VTO+4.0 then
            VNEW:=VTO+4.0; 
          end if;
        end if;
--|
--| ON ...
--|
      else 
        if DELV > 0.0 then
          if DELV >= VTSTHI then
            VNEW:=VOLD+VTSTHI;
          end if;
        else
          if VNEW < VTOX then
            if VNEW < VTO+2.0 then
              VNEW:=VTO+2.0;       
            end if;
          else
            if -DELV > VTSTLO then
              VNEW:=VOLD-VTSTLO;
            end if;
          end if;
        end if; 
      end if;
    return;
    end FETLIM;

--*******************************************************************
--*                                                                 *
--*  LIMVDS                                                         * BODY
--*                                                                 *
--*******************************************************************
  procedure LIMVDS(VNEW:inout real; VOLD: inout real)
   is
    begin
      
      if VOLD < 3.5 then
        if VNEW <= VOLD then
          if VNEW < -0.5 then
            VNEW:=-0.5;
          end if;
        else
          if VNEW > 4.0 then
            VNEW:=4.0;
          end if;
        end if;
      else
        if VNEW <= VOLD then
          if VNEW < 3.5 then
            if VNEW < 2.0 then
              VNEW:=2.0;
            end if;
          end if;
        else
          if VNEW > 3.0*VOLD+2.0 then
            VNEW:=3.0*VOLD+2.0;
          end if;
        end if;
      end if;
    return;
    end LIMVDS;
    
--*******************************************************************
--*                                                                 *
--*  PNJLIM                                                         * BODY
--*                                                                 *
--*******************************************************************
  procedure PNJLIM(VNEW: inout real;VOLD: inout real;
                   VT: inout real;VCRIT: inout real)
  is 
      file FILE2 : TEXT is out "STD_OUTPUT";
    variable VLIM,DELV,ARG: real;
    variable k : line;
  begin
      
    if VNEW > VCRIT then
      VLIM:=VT+VT;
      DELV:=VNEW-VOLD;
      if abs(DELV) > VLIM then
        if VOLD <= 0.0 then
          VNEW:=VT*2.30258509299404568401*LOG(VNEW/VT);
        else
          ARG:=1.0+DELV/VT;
          if ARG <= 0.0 then
            VNEW:=VCRIT;
          else
            VNEW:=VOLD+VT*2.30258509299404568401*LOG(ARG);
          end if;
        end if;
      end if;
    end if;
  return;
  end PNJLIM;
   
--******************************************************************
--*                                                                *
--*   VDSAT_VMAX                                                   * BODY
--*                                                                *
--******************************************************************
  procedure VDSAT_VMAX
   (GAMMAD: in REAL;
    ETA   : in REAL;
    UEFF  : in REAL;
    L     : in REAL;
    VGSX  : in REAL;
    VBIN  : in REAL;
    VBS   : in REAL;
    PHI   : in REAL;
    SARG3 : in REAL;
    VMAX  : in REAL;
    VDSAT : inout REAL)
  is
    variable V1,V2,V,A1,B1,A3,B3,C1,D1,A,B,C,RO,R,R3,S,S2,P,P0,P2,
             P3,P4,FI,Y3,DELTA4,XVALID,w0 : real;
    variable IKNT,JKNT, IVMFLG,I,J : integer:= 0;
    variable A4,B4,SIG1,SIG2 : VALUE_ARRAY(1 to 4);
    variable POLY4, X4 : VALUE_ARRAY(1 to 8);
file FILE2 : TEXT is out "STD_OUTPUT";
 variable k   : line;

  begin
    SIG1(1):=1.0;SIG1(2):=-1.0;SIG1(3):=1.0;SIG1(4):=-1.0;
    SIG2(1):=1.0;SIG2(2):=1.0;SIG2(3):=-1.0;SIG2(4):=-1.0;
    V1 := (VGSX-Vbin)/ETA + PHI - Vbs;
    V2 := PHI - Vbs;
    V  := VMAX*L/UEFF;
    A1 := GAMMAD/0.75;
    B1 := -2.0*(V1+V);
    C1 := -2.0*GAMMAD*V;
    D1 := 2.0*V1*(V2+V)-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.00;
    P0 := abs(P);
    P2 := sqrt(P0);
    if P >= 0.0 then 
      w0:=-S/2.0+P2;
      w0:=abs(w0);
      w0:=2.3025850929940457*LOG(w0)/3.0;
      P3:=POWER(2.71828182845904523536,w0);
      w0:=-S/2.0-P2;
      w0:=abs(w0);
      w0:=2.3025850929940457*LOG(w0)/3.0;
      P4:=POWER(2.71828182845904523536,w0);
      Y3:=P3+P4-A/3.0;
    else
      w0:=S2/4.0+P0;
      RO:=sqrt(w0);
      RO:=2.3025850929940457*LOG(RO)/3.0;
      RO:=POWER(2.71828182845904523536,RO);
      w0:=-2.0*P2/S;
      FI:=atan(w0);
      w0:=FI/3.0;
      Y3:=2.0*RO*cos(w0)-A/3.0;
      w0:=cos(w0);
    end if;
    IKNT:=0;
    w0:=A1*A1/4.0-B1+Y3;
    A3:=sqrt(w0);
    w0:=Y3*Y3/4.0-D1;
    B3:=sqrt(w0);
    loop1:
    for I in 1 to 4 loop 
      A4(I):=A1/2.0+SIG1(I)*A3;
      B4(I):=Y3/2.0+SIG2(I)*B3;
      DELTA4:=A4(I)*A4(I)/4.0-B4(I);
      if DELTA4 >= 0.0 then
        IKNT:=IKNT+1;
        X4(IKNT):=-A4(I)/2.0+sqrt(DELTA4);
        IKNT:=IKNT+1;
        X4(IKNT):=-A4(I)/2.0-sqrt(DELTA4);
      end if;
    end loop loop1;
    JKNT:=0;
    loop2:
    for J in 1 to IKNT loop  
      if X4(J) > 0.0 then 
        POLY4(J):=X4(J)*X4(J)*X4(J)*(X4(J)+A1);
        POLY4(J):=X4(J)*(X4(J)*(X4(J)*(X4(J)+A1)+B1)+C1)+D1;
        if abs(POLY4(J)) <= 1.0e-6 then 
          JKNT:=JKNT+1;
          if JKNT = 1 then 
            XVALID:=X4(J);
          end if;
          if X4(J) < XVALID then 
            XVALID:=X4(J);
          end if;
        end if;
      end if;
    end loop loop2; 
    if JKNT <= 0 then 
    --No root for the equation, saturation due to pinch-off algorithm
    --is used;
      IVMFLG:=IVMFLG+1;
    else
      Vdsat:=XVALID*XVALID+Vbs-PHI;
    end if;
    return;
  end VDSAT_VMAX;

--******************************************************************
--*                                                                *
--*   INICUR_COMP                                                  * BODY
--*                                                                *
--******************************************************************
  procedure INICUR_COMP
   (R     : in VALUE_ARRAY;
    NR1   : in NODE_ARRAY;
    NR2   : in NODE_ARRAY; 
    NL1   : in NODE_ARRAY;
    NL2   : in NODE_ARRAY;
    ID    : in VALUE_ARRAY;
    NI1   : in NODE_ARRAY;
    NI2   : in NODE_ARRAY;
    NV1   : in NODE_ARRAY;
    NV2   : in NODE_ARRAY;
    NVP1  : in NODE_ARRAY;
    NVP2  : in NODE_ARRAY;
    VT    : in VALUE_ARRAY;
    NOFI  : in INTEGER;
    NOFV  : in INTEGER;
    NOFPV : in INTEGER;
    NOFR  : in INTEGER;
    NOFL  : in INTEGER;
    RNUM  : in INTEGER;
    IL    : inout VALUE_ARRAY)
  is
    variable SO: INTEGER := 0;
    variable I : POSITIVE;
    variable k : POSITIVE;
  begin
    loop1:
    for k in 1 to NOFL loop
      IL(k) := 0.000000;
      if NL1(k) = 0 then
        loop2:
        for I in 1 to NOFR loop
          if NR1(I) = NL2(k) and NR2(I) /= 0 then
            IL(k) := IL(k) + (VT(NR2(I))-VT(NR1(I)))/R(I);
          elsif NR2(I) = NL2(k) and NR1(I) /= 0 then
            IL(k) := IL(k) + (VT(NR1(I))-VT(NR2(I)))/R(I);
          elsif NR1(I) = NL2(k) and NR2(I) = 0 then
            IL(k) := IL(k) - VT(NR1(I))/R(I);
          elsif NR2(I) = NL2(k) and NR1(I) = 0 then
            IL(k) := IL(k) - VT(NR2(I))/R(I);
          end if;
        end loop loop2;
        loop3:
        for I in 1 to NOFI loop
          if NI1(I) = NL2(k) then
            IL(k) := IL(k) - ID(I);
          elsif NI2(I) = NL2(k) then
            IL(k) := IL(k) + ID(I);
          end if;
        end loop loop3;
      elsif NL2(k) = 0 then
        loopA1:
        for I in 1 to NOFR loop
          if NR1(I) = NL1(k) and NR2(I) /= 0 then
            IL(k) := IL(k) + (VT(NR2(I))-VT(NR1(I)))/R(I);
          elsif NR2(I) = NL1(k) and NR1(I) /= 0 then
            IL(k) := IL(k) + (VT(NR1(I))-VT(NR2(I)))/R(I);
          elsif NR1(I) = NL1(k) and NR2(I) = 0 then
            IL(k) := IL(k) - VT(NR1(I))/R(I);
          elsif NR2(I) = NL1(k) and NR1(I) = 0 then
            IL(k) := IL(k) - VT(NR2(I))/R(I);
          end if;
        end loop loopA1;
        loopA2:
        for I in 1 to NOFI loop
          if NI1(I) = NL1(k) then
            IL(k) := IL(k) - ID(I);
          elsif NI2(I) = NL1(k) then
            IL(k) := IL(k) + ID(I);
          end if;
        end loop loopA2;
      elsif NL1(k) /= 0 and NL1(k) < NL2(k) then
        loopB1:
        for I in 1 to NOFV loop
          if NL1(k) = NV1(I) or NL1(k) = NV2(I) then
            SO := 1;
          end if;
        end loop loopB1;
        loopB2:
        for I in 1 to NOFPV loop
         if NL1(k) = NVP1(I) or NL1(k) = NVP2(I) then
           SO := 1;
         end if;
        end loop loopB2;
        if SO = 0 then
          loopB3:
          for I in 1 to NOFR loop
            if NR1(I) = NL1(k) and NR2(I) /= 0 then
              IL(k) := IL(k) + (VT(NR2(I))-VT(NR1(I)))/R(I);
            elsif NR2(I) = NL1(k) and NR1(I) /= 0 then
              IL(k) := IL(k) + (VT(NR1(I))-VT(NR2(I)))/R(I);
            elsif NR1(I) = NL1(k) and NR2(I) = 0 then
              IL(k) := IL(k) - VT(NR1(I))/R(I);
            elsif NR2(I) = NL1(k) and NR1(I) = 0 then
              IL(k) := IL(k) - VT(NR2(I))/R(I);
            end if;
          end loop loopB3;
          loopB4:
          for I in 1 to NOFI loop
            if NI1(I) = NL1(k) then
              IL(k) := IL(k) - ID(I);
            elsif NI2(I) = NL1(k) then
              IL(k) := IL(k) + ID(I);
            end if;
          end loop loopB4;
        else
          loopB5:
          for I in 1 to NOFR loop
            if NR1(I) = NL2(k) and NR2(I) /= 0 then
              IL(k) := IL(k) - (VT(NR2(I))-VT(NR1(I)))/R(I);
            elsif NR2(I) = NL2(k) and NR1(I) /= 0 then
              IL(k) := IL(k) - (VT(NR1(I))-VT(NR2(I)))/R(I);
            elsif NR1(I) = NL2(k) and NR2(I) = 0 then
              IL(k) := IL(k) + VT(NR1(I))/R(I);
            elsif NR2(I) = NL2(k) and NR1(I) = 0 then
              IL(k) := IL(k) + VT(NR2(I))/R(I);
            end if;
          end loop loopB5;
          loopB6:
          for I in 1 to NOFI loop
            if NI1(I) = NL2(k) then
              IL(k) := IL(k) + ID(I);
            elsif NI2(I) = NL2(k) then
              IL(k) := IL(k) - ID(I);
            end if;
          end loop loopB6;
          SO := 0;
        end if;
      elsif NL2(k) /= 0 and NL2(k) < NL1(k) then
        loopC1:
        for I in 1 to NOFV loop
          if NL2(k) = NV1(I) or NL2(k) = NV2(I) then
            SO := 1;
          end if;
        end loop loopC1;
        loopC2:
        for I in 1 to NOFPV loop
          if NL2(k) = NVP1(I) or NL2(k) = NVP2(I) then
            SO := 1;
          end if;
        end loop loopC2;
        if SO = 0 then 
          loopC3:
          for I in 1 to NOFR loop
            if NR1(I) = NL2(k) and NR2(I) /= 0 then
              IL(k) := IL(k) + (VT(NR2(I))-VT(NR1(I)))/R(I);
            elsif NR2(I) = NL2(k) and NR1(I) /= 0 then
              IL(k) := IL(k) + (VT(NR1(I))-VT(NR2(I)))/R(I);
            elsif NR1(I) = NL2(k) and NR2(I) = 0 then
              IL(k) := IL(k) - VT(NR1(I))/R(I);
            elsif NR2(I) = NL2(k) and NR1(I) = 0 then
              IL(k) := IL(k) - VT(NR2(I))/R(I);
            end if;
          end loop loopC3;
          loopC4:
          for I in 1 to NOFI loop
            if NI1(I) = NL2(k) then
              IL(k) := IL(k) - ID(I);
            elsif NI2(I) = NL2(k) then
              IL(k) := IL(k) + ID(I);
            end if;
          end loop loopC4;
        else
          loopC5:
          for I in 1 to NOFR loop
            if NR1(I) = NL1(k) and NR2(I) /= 0 then
              IL(k) := IL(k) + (VT(NR2(I))-VT(NR1(I)))/R(I);
            elsif NR2(I) = NL1(k) and NR1(I) /= 0 then
              IL(k) := IL(k) + (VT(NR1(I))-VT(NR2(I)))/R(I);
            elsif NR1(I) = NL1(k) and NR2(I) = 0 then
              IL(k) := IL(k) - VT(NR1(I))/R(I);
            elsif NR2(I) = NL1(k) and NR1(I) = 0 then
              IL(k) := IL(k) - VT(NR2(I))/R(I);
            end if;
          end loop loopC5;
          if NOFI /= 0 then
            loopC6:
            for I in 1 to NOFI loop
              if NI1(I) = NL1(k) then
                IL(k) := IL(k) + ID(I);
              elsif NI2(I) = NL1(k) then
                IL(k) := IL(k) - ID(I);
              end if;
            end loop loopC6;
          end if;
          SO := 0;
        end if;
      end if;
    end loop loop1;
  return;
  end INICUR_COMP; 
    
--******************************************************************
--*                                                                *
--*   TRAN_ANA                                                     * BODY
--*                                                                *    
--******************************************************************  
  procedure TRAN_ANA
   (R     : in VALUE_ARRAY;
    NR1   : in NODE_ARRAY;
    NR2   : in NODE_ARRAY;
    C     : in VALUE_ARRAY;
    NC1   : in NODE_ARRAY;
    NC2   : in NODE_ARRAY;
    L     : in VALUE_ARRAY;
    NL1   : in NODE_ARRAY;
    NL2   : in NODE_ARRAY;
    ID    : in VALUE_ARRAY;
    NI1   : in NODE_ARRAY;
    NI2   : in NODE_ARRAY;
    IP1   : in VALUE_ARRAY;
    IP2   : in VALUE_ARRAY;
    NP1   : in NODE_ARRAY;
    NP2   : in NODE_ARRAY;
    TDI   : in VALUE_ARRAY;
    TRI   : in VALUE_ARRAY;
    TFI   : in VALUE_ARRAY;
    PWI   : in VALUE_ARRAY;
    PERI  : in VALUE_ARRAY;
    VD    : in VALUE_ARRAY;
    NV1   : in NODE_ARRAY;
    NV2   : in NODE_ARRAY;
    VP1   : in VALUE_ARRAY;
    VP2   : in VALUE_ARRAY;
    NVP1  : in NODE_ARRAY;
    NVP2  : in NODE_ARRAY;  
    TDV   : in VALUE_ARRAY;
    TRV   : in VALUE_ARRAY;
    TFV   : in VALUE_ARRAY;
    PWV   : in VALUE_ARRAY;
    PERV  : in VALUE_ARRAY;
    MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    MODEL_NAME: in NAME_ARRAY;
    MODEL_TYPE: in NAME_ARRAY;
    MODEL_PARA: inout PARAM_MATRIX;
    RNUM  : in INTEGER;
    NOFR  : in INTEGER;
    NOFC  : in INTEGER;
    NOFL  : in INTEGER;
    NOFV  : in INTEGER;
    NOFI  : in INTEGER;
    NOFPV : in INTEGER;
    NOFPI : in INTEGER;
    NOFM  : in INTEGER;
    NOFMOD: in INTEGER;
    TNOM  : in REAL;
    T0    : in REAL;
    DELT  : inout REAL;
    STEPV : inout REAL;
    STEPV_2 : inout REAL;
    TSTOP : in TIME;
    TSTEP : in TIME;
    Vbi0  : in VALUE_ARRAY;
    NONCON: inout INTEGER;
    IMEM  : inout VALUE_ARRAY;
    VMEM  : inout VALUE_ARRAY;
    IV    : inout VALUE_ARRAY;
    VT    : inout VALUE_ARRAY;
    IOUT  : inout VALUE_ARRAY;
    VOUT  : inout VALUE_ARRAY;
    IOUT1 : inout VALUE_ARRAY;
    VOUT1 : inout VALUE_ARRAY;
    IOUT2 : inout VALUE_ARRAY;
    VOUT2 : inout VALUE_ARRAY;
    IC    : inout VALUE_ARRAY;
    IL    : inout VALUE_ARRAY;
    QGS   : inout CHARG_ARRAY;
    QGD   : inout CHARG_ARRAY;
    QGB   : inout CHARG_ARRAY;
    QBD   : inout CHARG_ARRAY;
    QBS   : inout CHARG_ARRAY;
    CCAPGS: inout CHARG_ARRAY;
    CCAPGD: inout CHARG_ARRAY;
    CCAPGB: inout CHARG_ARRAY;
    CQBS  : inout CHARG_ARRAY;
    CQBD  : inout CHARG_ARRAY;
    VBS0  : inout VALUE_ARRAY;
    VBD0  : inout VALUE_ARRAY;
    VGS0  : inout VALUE_ARRAY;
    VDS0  : inout VALUE_ARRAY;
    VON0  : inout VALUE_ARRAY;
    VDSAT0: inout VALUE_ARRAY;
    VBS01 : inout VALUE_ARRAY;
    VGS01 : inout VALUE_ARRAY;
    VDS01 : inout VALUE_ARRAY;
    ccap0 : inout ncap_array;
    qcap0 : inout ncap_array;
    outflg: inout INTEGER;
    ITFLG : inout INTEGER;
    MAX   : inout INTEGER;
    TAG   : inout INTEGER)
  is
    file FILE2 : TEXT is out "STD_OUTPUT";
    variable G      : AMATRIX(1 to RNUM,1 to RNUM); 
    variable G0     : AMATRIX(1 to RNUM,1 to RNUM); 
    variable IEFF   : VALUE_ARRAY(1 to RNUM);
    variable IV0    : VALUE_ARRAY(1 to RNUM);
    variable IV1    : VALUE_ARRAY(1 to RNUM);
    variable V_ITER : VALUE_ARRAY(1 to RNUM);
    variable I_ITER : VALUE_ARRAY(1 to RNUM);
    variable I0     : VALUE_ARRAY(1 to RNUM);
    variable I0_tem : VALUE_ARRAY(1 to RNUM);
    variable IL0    : VALUE_ARRAY(1 to NOFL);
    variable Il1    : VALUE_ARRAY(1 to NOFL);
    variable Il2    : VALUE_ARRAY(1 to NOFL);
    variable ceq    : VALUE_ARRAY(1 to NOFC);
    variable geq    : VALUE_ARRAY(1 to NOFC);
    variable Cgd    : VALUE_ARRAY(1 to NOFM);
    variable Cgb    : VALUE_ARRAY(1 to NOFM);
    variable Cgs    : VALUE_ARRAY(1 to NOFM);
    variable CD0    : VALUE_ARRAY(1 to NOFM);
    variable CBS0   : VALUE_ARRAY(1 to NOFM);
    variable CBD0   : VALUE_ARRAY(1 to NOFM);
    variable gm0    : VALUE_ARRAY(1 to NOFM);
    variable gds0   : VALUE_ARRAY(1 to NOFM);
    variable gmbs0  : VALUE_ARRAY(1 to NOFM);
    variable GBS0   : VALUE_ARRAY(1 to NOFM);
    variable GBD0   : VALUE_ARRAY(1 to NOFM);
    variable CONCK  : NODE_ARRAY(1 to NOFM);
    variable VBS1   : VALUE_ARRAY(1 to NOFM);
    variable VBD1   : VALUE_ARRAY(1 to NOFM);
    variable VGS1   : VALUE_ARRAY(1 to NOFM);
    variable VDS1   : VALUE_ARRAY(1 to NOFM);
    variable VON1   : VALUE_ARRAY(1 to NOFM);
    variable VDSAT1 : VALUE_ARRAY(1 to NOFM);
    variable T,x,TOUT : real;
    variable STEPV1,NEXTT,DELMAX,TEMP,DELTA,DELT1,DELT2,
             DXX0,DXX1,DXX2: REAL := 0.0;
    variable TAG0,NCOV,RIT,TFLG,IFG: INTEGER:= 0;
    variable I,J,k  : POSITIVE;
    constant ITL3   : integer:= 4;
    variable k1     : LINE;
    variable guess  : boolean := true;
  begin
    STEPV1:=TIME_TO_REAL(TSTEP);
    if DELT < STEPV1 then
      if TAG=0 then	
        if NOFL /= 0 then
          INICUR_COMP(R,NR1,NR2,NL1,NL2,ID,NI1,
            NI2,NV1,NV2,NVP1,NVP2,VT,NOFI,NOFV,
            NOFPV,NOFR,NOFL,RNUM,IL);
        end if;
        loop1:
        for I in 1 to NOFC loop
          IC(I) := 0.000000;
        end loop loop1;
      end if;
      T:=T0+DELT;                        --DELT is the difference between output
      DELT:=0.0;			 --time and iteration time. T0 is last 
      loop2:                             --output timepoint. 
      for I in 1 to RNUM loop
        IEFF(I):= 0.000000;
        I0(I)  := 0.000000;              
        IV(I)  := 0.000000;              
        if NOFI /= 0 then
          loop3:
          for k in 1 to NOFI LOOP
            if NI1(k) = I then             
              I0(I) := I0(I) - ID(k);      
            elsif NI2(k) = I then    
              I0(I) := I0(I) + ID(k);         
            end if;                         
          end loop loop3;               
        end if; 
      end loop loop2; 
      if TAG = 0 then                   --First timepoint in trasient analysis 
        DELMAX:=TIME_TO_REAL(TSTOP)/50.0;
        if NOFC /= 0 and NOFM = 0 then
          DELMAX:=DELMAX/4.0;
        end if;
        if NOFC/=0 and NOFM/=0 then
          DELMAX := DELMAX/5.0;
        end if;
        TEMP:=DELMAX/10.0;
        if TEMP < STEPV1 then
          DELTA:=TEMP;
        else
          DELTA:=STEPV1;
        end if;
        DELTA:=DELTA/10.0;
        STEPV:=DELTA;
        ITFLG:=0;
      end if;
      if MAX = 0 then                     --Last time point = TD+TR or TD+TR+PW
        DELTA:=STEPV;
      else
        DELTA:=STEPV_2/10.0;              --after output step
      end if; 
      loop44:                             --output loop;
      loop
        loop4:                            --convergence loop;
        loop
          IEFF:= I0;
          loopA2:
          for I in 1 to NOFL loop
            IL0(I) := IL(I);
          end loop loopA2;
          loopdd: 
          for I in 1 to RNUM loop
            V_ITER(I):=VT(I);
          end loop loopdd;
          DELMAX:=TIME_TO_REAL(TSTOP)/50.0;
          if NOFC /= 0 and NOFM = 0 then
            DELMAX:=DELMAX/4.0;
          end if;
          if NOFC/=0 and NOFM/=0 then
            DELMAX:=DELMAX/5.0;
          end if;
          TEMP:=DELMAX/10.0;
          if NONCON < ITL3 and TAG > 1 then
            DELTA:=DELTA*2.0;
            if DELMAX < DELTA then
              DELTA:=DELMAX;
            end if;
            if MAX = 0 then
              ITFLG:=1;                    --Chose iteration method;
            else
              ITFLG:=0;
            end if;
          end if;
          MAX := 0;
          looppuls:
          for I in 1 to NOFPV loop
            if abs(T-TDV(I)-TRV(I)-PWV(I)) <= 1.0e-4 
              or abs(T-TDV(I)-TRV(I)) <= 1.0e-4 then
              if DELTA > TEMP then
                DELTA:=TEMP;
                ITFLG:=0;                   --Gear Method;
              end if;
            end if;
          end loop looppuls;
          looppuls1:
          for I in 1 to NOFPV loop
            if T+DELTA > TDV(I)+TRV(I) and 
             abs(TDV(I)+TRV(I)-T0-STEPV1)<=1.0e-5 then
              DELTA:=TDV(I)+TRV(I)-T;
              DELT:=0.0;
              MAX:=1;
            elsif T+DELTA > TDV(I)+TRV(I)+PWV(I) and
             abs(TDV(I)+TRV(I)+PWV(I)-T0-STEPV1) <= 1.0e-5 then
              DELTA:=TDV(I)+TRV(I)+PWV(I)-T;
              DELT:=0.0;
              MAX:=1;
            end if; 
          end loop looppuls1;
          if T+DELTA > TIME_TO_REAL(TSTOP) then   
            DELTA := TIME_TO_REAL(TSTOP)-T;
            DELT:=0.0;
          end if;
          NONCON := 0;
          IEFF  := I0;         
          if NOFPI /= 0 then
            NEXTT:=T+DELTA;         
            PULSE(NEXTT,TDI,TRI,TFI,PWI,PERI,IP1,IP2,NP1,NP2,NOFI,NOFPI,IEFF);
          end if;
          loopA4:
          for I in 1 to G'HIGH loop
            loopB5:
    	    for J in 1 to G'HIGH loop
    	      G(I,J) := 0.000000;      
    	    end loop loopB5;     
          end loop loopA4;
          loopA5:
          for I in 1 to G'HIGH loop
            loopB6:		
            for k in 1 to NOFR loop    
    	      if NR1(k)=I  then     
    	        G(I,I) := G(I,I) + 1.0/R(k);          
    	      elsif NR2(k)=I  then   
    	        G(I,I) := G(I,I) + 1.0/R(k);
    	      end if;
       	    end loop loopB6;
          end loop loopA5;
          loopA6:
          for I in 1 to G'HIGH loop
            loopB7:    
            for J in I+1 to G'HIGH loop         
              loopC1:  
              for k in 1 to NOFR loop 
                if NR1(k)=I and NR2(k)=J then      
    	          G(I,J) := G(I,J) - 1.0/R(k);    
    	        elsif NR1(k)=J and NR2(k)=I then   
    	          G(I,J) := G(I,J) - 1.0/R(k);
    	        end if;
                G(J,I) := G(I,J);
    	      end loop loopC1;
    	    end loop loopB7;
          end loop loopA6;

          if NOFC /= 0 then
            guess := true;
            IFG:=ITFLG; 
            capac(VT,NC1,NC2,C,qcap0,ccap0,DELTA,TAG0,TAG,
             IFG,NOFC,guess,ceq,geq);
            
            loopac:
            for I in 1 to NOFC loop
              if NC1(I)/=0 and NC2(I)/=0 then
                G(NC1(I),NC1(I)):=G(NC1(I),NC1(I))+geq(I);
                G(NC2(I),NC2(I)):=G(NC2(I),NC2(I))+geq(I);
                G(NC1(I),NC2(I)):=G(NC1(I),NC2(I))-geq(I);
                G(NC2(I),NC1(I)):=G(NC2(I),NC1(I))-geq(I);
                IEFF(NC1(I)):=IEFF(NC1(I))-ceq(I);
                IEFF(NC2(I)):=IEFF(NC2(I))+ceq(I);
              elsif NC1(I)=0 then
                G(NC2(I),NC2(I)):=G(NC2(I),NC2(I))+geq(I);
                IEFF(NC2(I)):=IEFF(NC2(I))+ceq(I);
              elsif NC2(I) = 0 then
                G(NC1(I),NC1(I)):=G(NC1(I),NC1(I))+geq(I);
                IEFF(NC1(I)):=IEFF(NC1(I))-ceq(I);
              end if;
            end loop loopac;  
          end if;
          if NOFL /= 0 then 
          loopA7:
          for I in 1 to RNUM loop
            loopB9:
            for k in 1 to NOFL loop
    	    if NL1(k) = I and NL2(k)=0 then
    	      G(I,I) := G(I,I) + DELTA/(2.0*L(k));
    	      IL0(k) := IL0(k) + STEPV*VT(I)/L(k);
                  --|Current source value IL0 for inductor;
    	      IEFF(I):= IEFF(I) - IL0(k);
    	    elsif NL2(k) = I and NL1(k)=0 then
    	      G(I,I) := G(I,I) + DELTA/(2.0*L(k));
    	      IL0(k) := IL0(k) + STEPV*VT(I)/L(k);
                  --|Current source value IL0 for inductor;
    	      IEFF(I):= IEFF(I) + IL0(k);
    	    end if;
    	  end loop loopB9;
          end loop loopA7;
          loopA8:
          for I in 1 to RNUM loop
            loopB10:
    	    for J in I+1 to RNUM loop
              loopC3:
    	      for k in 1 to NOFL loop
    	      if NL1(k)=I and NL2(k)=J then
    	        G(I,J) := G(I,J) - DELTA/(2.0*L(k));
    	        G(J,I) := G(J,I) - DELTA/(2.0*L(k));
    	        G(I,I) := G(I,I) + DELTA/(2.0*L(k));
    	        G(J,J) := G(J,J) + DELTA/(2.0*L(k));
    	        IL0(k) := IL0(k) + STEPV*(VT(I)-VT(J))/L(k);
    	        IEFF(I):= IEFF(I) - IL0(k);
    	        IEFF(J):= IEFF(J) + IL0(k);
    	      elsif NL1(k)=J and NL2(k)=I then
    	        G(I,J) := G(I,J) - DELTA/(2.0*L(k));
    	        G(J,I) := G(J,I) - DELTA/(2.0*L(k));
    	        G(I,I) := G(I,I) + DELTA/(2.0*L(k));
    	        G(J,J) := G(J,J) + DELTA/(2.0*L(k));
    	        IL0(k) := IL0(k) + STEPV*(VT(J)-VT(I))/L(k);
    	        IEFF(J):= IEFF(J) - IL0(k);
    	        IEFF(I):= IEFF(I) + IL0(k);
    	      end if;
    	      end loop loopC3;
            end loop loopB10;
          end loop loopA8;
    	  end if;

          if RIT /=1 then
            loopss0:
            for I in 1 to NOFM loop
              VBS1(I):=VBS0(I);
              VBD1(I):=VBD0(I);
              VGS1(I):=VGS0(I);
              VDS1(I):=VDS0(I);
              VON1(I):=VON0(I);
              VDSAT1(I):=VDSAT0(I);
            end loop loopss0;
          end if;
          G0 := G;
          IV1:=IEFF;
          loopM1:
          loop
            if NOFM /= 0 then
              G := G0;
              IEFF := IV1;
              MOSFET_TRAN(MNAME,ND,NG,NS1,NB,CHANNEL_L,CHANNEL_W,AD,AS,PD,
                PS,NRD,NRS,OFF,IC_TRAN,MODEL_NAME,MODEL_TYPE,TNOM,CONCK,NOFMOD,
                NOFM,DELTA,STEPV,V_ITER,ITFLG,Vbi0,TAG0,MODEL_PARA,Cgd,Cgb,Cgs,
                QGS,QGD,QGB,QBD,QBS,CCAPGS,CCAPGD,CCAPGB,CQBS,
                CQBD,NONCON,VBS0,VBD0,VGS0,VDS0,VON0,VDSAT0,VBS01,VGS01,VDS01,
                VBS1,VBD1,VGS1,VDS1,VON1,VDSAT1,RIT,
                CD0,CBS0,CBD0,gm0,gds0,gmbs0,GBS0,GBD0,G,IEFF,TAG);
    
              NCOV:=0;
              loopck:
              for I in 1 to NOFM loop
                if CONCK(I)=1 then
                  NCOV:=NCOV+1;
                end if;
              end loop loopck;
            end if;
            IV0 := IEFF;
            if NOFV /= 0 then    
              loopA9:
              for k in 1 to NOFV loop
                if NV1(k) /= 0 then
        	  IEFF(k) := VD(k);
      	        elsif NV2(k) /= 0 then
      	           IEFF(k) := -VD(k);
      	        end if;
      	      end loop loopA9;
            end if;
            if NOFPV /= 0 then
              NEXTT:=T+DELTA;
              PULSE(NEXTT,TDV,TRV,TFV,PWV,PERV,VP1,VP2,NVP1,NVP2,
              NOFV,NOFPV,IEFF);
            end if;
            if NOFM /= 0 and NCOV/=NOFM then
              NONCON:=NONCON+1;
              if NONCON > 10 then
                DELTA := DELTA/8.0;
                if DELTA < 1.0e-6 then
                  DELTA:=1.0e-6;
                end if;
                RIT:=1;
                ITFLG:=0;
                exit loopM1;
              end if; 
              RIT:=0;
            elsif NCOV = NOFM or NOFM = 0 then
              T:=T+DELTA;
              if abs(T-T0-STEPV1) <= 1.0e-6 then
                DELT:=0.0;
                TFLG:=1;
              elsif T > T0+STEPV1 then
                DELT:=T-T0-STEPV1;
                TFLG:=1;
              end if;
              RIT:=0;
              if NOFM /= 0 then
                exit loopM1;
              end if;
            end if;
    
            LINEQUA_COMP(RNUM,NOFV,NOFPV,G,IV0,IEFF);
    
            V_ITER:= IEFF;
            I_ITER:= IV0;
            if NOFC /= 0 then   --ic;
              guess := false;
              capac(V_ITER,NC1,NC2,C,qcap0,ccap0,DELTA,TAG0,
               TAG,IFG,NOFC,guess,ceq,geq);
            end if;
            if NOFM = 0 then
              exit loopM1;
            end if;
          end loop loopM1;
          TAG0 := 0;
          if RIT /= 1 then                        --Iteration success
            exit loop4;
          end if;
        end loop loop4;
    
        STEPV_2:=STEPV;
        STEPV:=DELTA;
--        ITFLG:=0;
        TAG  :=TAG+1;
        loop22:
        for I in 1 to NOFM loop
          VBS01(I):=VBS1(I);
          VDS01(I):=VDS1(I);
          VGS01(I):=VGS1(I);
        end loop loop22;
        loopmm0:
        for I in 1 to RNUM loop
          IV(I):=I_ITER(I);
          VT(I):=V_ITER(I);
        end loop loopmm0;
        if TFLG = 1 then 
          loopMM1:
          for I in 1 to RNUM loop
            IOUT(I):=IMEM(I)+(IV(I)-IMEM(I))*(DELTA-DELT)/DELTA;
            VOUT(I):=VMEM(I)+(VT(I)-VMEM(I))*(DELTA-DELT)/DELTA;
          end loop loopMM1;
          if NOFV /=0 then
            loopMM11:
            for I in 1 to NOFV loop
              VOUT(I):=V_ITER(I);
            end loop loopMM11;
          end if;
          if NOFPV /= 0 then
            TOUT:=T-DELT;
            PULSE(TOUT,TDV,TRV,TFV,PWV,PERV,VP1,VP2,NVP1,NVP2,NOFV,NOFPV,VOUT);
          end if;
        end if;
        if DELT < STEPV1 then
          loopnn1:
          for I in 1 to RNUM loop
            IMEM(I):=IV(I);
            VMEM(I):=VT(I);
          end loop loopnn1;
        end if;
        if NOFL /= 0 then
          loop9:
          for I in 1 to NOFL loop
            IL(I) := IL0(I);
          end loop loop9;
        end if;
        if TFLG =1 then
          exit loop44;
        end if;
      end loop loop44;
    else
      DELT:=DELT-STEPV1;
      loopMM01:
      for I in 1 to RNUM loop
        IOUT(I):=IMEM(I)+(IV(I)-IMEM(I))*(STEPV-DELT)/STEPV;
        VOUT(I):=VMEM(I)+(VT(I)-VMEM(I))*(STEPV-DELT)/STEPV;
      end loop loopMM01;
      if NOFPV /= 0 then
        TOUT:=T0+STEPV1;
        PULSE(TOUT,TDV,TRV,TFV,PWV,PERV,VP1,VP2,NVP1,NVP2,NOFV,NOFPV,VOUT);
      end if;
      if DELT < STEPV1 then
        loopnn2:
        for I in 1 to RNUM loop
          IMEM(I):=IV(I);
          VMEM(I):=VT(I);
        end loop loopnn2;
      end if;
    end if; 
    return;       
  end TRAN_ANA;

--******************************************************************
--*                                                                *
--*  capac					                   * 
--*                                                                *
--******************************************************************
  procedure capac( Vc : in value_array;NC1 : in node_array;
                  NC2 : in node_array;C : in value_array;
                  qcap0 : inout ncap_array; ccap0 : inout ncap_array; 
                  DELTA : in real; TAG,TAGT,ITFLG,NOFC: in integer; 
                  guess : in boolean;ceq,geq: inout value_array
                  )
  is
    file FILE2   :TEXT is out "STD_OUTPUT";
    variable k   : line;
    variable vcap : real := 0.0;
    variable ccap, qcap : ncap_elem;
    variable I : integer;
  begin
    ccap(1):=0.0; ccap(2):=0.0; qcap(1):=0.0; qcap(2):=0.0;
    loopca:
    for I in 1 to NOFC loop
      ccap:=ccap0(I);
      qcap:=qcap0(I);
      if NC1(I)/=0 and NC2(I)/=0 then
        vcap := Vc(NC1(I))-Vc(NC2(I));
      elsif NC1(I) /= 0 and NC2(I) = 0 then
        vcap := Vc(NC1(I));
      elsif NC2(I) /= 0 and NC1(I) = 0 then
        vcap := -Vc(NC2(I));   
      end if;
      if TAG = 0 and TAGT = 0 then
      --|first timestep in transient analysis
        qcap(1):= C(I)*vcap;
        qcap(2):= qcap(1);
        ccap(1):= qcap(1)/DELTA - qcap(2)/DELTA;
        ceq(I) := ccap(1)-qcap(1)/DELTA;
        geq(I) := C(I)/DELTA;
        ccap(2):= ccap(1);
      elsif guess = true then
        qcap(1):=qcap(2);
        if ITFLG=0 then               --| Gear method;
          ccap(1):= qcap(1)/DELTA - qcap(2)/DELTA;
          ceq(I) := ccap(1)-qcap(1)/DELTA; 
          geq(I) := C(I)/DELTA;
        else                          --| Tranpzoid method;
          ccap(1):= -ccap(2) + 2.0*(qcap(1)-qcap(2))/DELTA; 
          ceq(I) := ccap(1)-2.0*qcap(1)/DELTA; 
          geq(I) := 2.0*C(I)/DELTA;
        end if;
      elsif guess = false then
        qcap(1):= C(I)*vcap;
        if ITFLG=0 then
          ccap(1):= qcap(1)/DELTA - qcap(2)/DELTA;
          ceq(I) := ccap(1)-qcap(1)/DELTA; 
          geq(I) := C(I)/DELTA;
        else
          ccap(1):= -ccap(2) + 2.0*(qcap(1)-qcap(2))/DELTA;
          ceq(I) := ccap(1)-2.0*qcap(1)/DELTA; 
          geq(I) := 2.0*C(I)/DELTA;
        end if;
        ccap(2):=ccap(1);
        qcap(2):=qcap(1);
      end if; 
      ccap0(I):=ccap;
      qcap0(I):=qcap;
    end loop loopca;
    return;
  end capac;    
   
--******************************************************************
--*                                                                *
--*  PULSE                                                         *
--*                                                                *
--******************************************************************
  procedure PULSE(T : inout REAL;TDV : in VALUE_ARRAY;
                  TRV : in VALUE_ARRAY;TFV : in VALUE_ARRAY;
                  PWV : in VALUE_ARRAY;PERV: in VALUE_ARRAY;
                  VP1 : in VALUE_ARRAY;VP2 : in VALUE_ARRAY;
                  NVP1: in NODE_ARRAY;NVP2 : in NODE_ARRAY;
                  NOFV: in INTEGER;NOFPV: in INTEGER;
                  VOUT: inout VALUE_ARRAY)
  is
    file FILE2   :TEXT is out "STD_OUTPUT";
    variable k1   : line;
    variable k : integer :=0;
  begin
    loopA10:
    for k in 1 to NOFPV loop
      loopB11:
      loop
        if T > PERV(k) + TDV(k) then
          T := T - PERV(k);
        else
          exit loopB11;
        end if;
      end loop loopB11;
      if T <= TDV(k) then
        if NVP1(k) /= 0 then
          VOUT(k+NOFV) := VP1(k);
        elsif NVP2(k) /= 0 then
          VOUT(k+NOFV) := -VP1(k);
        end if;
      elsif T  > TDV(k) and
        T < TDV(k) + TRV(k) then
        if NVP1(k) /= 0 then
          VOUT(k+NOFV):=(VP2(k)-VP1(k))*((T - TDV(k))/TRV(k))+VP1(k);
        elsif NVP2(k) /= 0 then
          VOUT(k+NOFV):=-(VP2(k)-VP1(k))*((T - TDV(k))/TRV(k))-VP1(k);
        end if;
      elsif T >= TDV(k) + TRV(k) and
        T <= TDV(k) + TRV(k) + PWV(k) then
        if NVP1(k) /= 0 then
          VOUT(k+NOFV) := VP2(k);
        elsif NVP2(k) /= 0 then
          VOUT(k+NOFV) := -VP2(k);
        end if;
      elsif T > TDV(k) + TRV(k) + PWV(k) and
        T < TDV(k) + TRV(k) + PWV(k) + TFV(k) then
        if NVP1(k) /= 0 then
          VOUT(k+NOFV):=(VP2(k)-VP1(k))*((TDV(k)+TRV(k)+PWV(k)
           +TFV(k)-T)/TFV(k))+VP1(k);
        elsif NVP2(k) /= 0 then
          VOUT(k+NOFV):=-(VP2(k)-VP1(k))*((TDV(k)+TRV(k)+PWV(k)
           +TFV(k)-T)/TFV(k))-VP1(k);
        end if;
      elsif T >= TDV(k)+TRV(k)+PWV(k)+TFV(k) then
        if NVP1(k) /= 0 then
          VOUT(k+NOFV) := VP1(k);
        elsif NVP2(k) /= 0 then
          VOUT(k+NOFV) := -VP1(k);
        end if;
      end if;
    end loop loopA10;
    return;
  end PULSE;

--******************************************************************
--*                                                                *
--*  MOSFET_TRAN                                                   *
--*                                                                *
--******************************************************************
  procedure MOSFET_TRAN
   (MNAME     : in NAME_ARRAY;
    ND        : in NODE_ARRAY;
    NG        : in NODE_ARRAY;
    NS1       : in NODE_ARRAY;
    NB        : in NODE_ARRAY;
    CHANNEL_L : in VALUE_ARRAY;
    CHANNEL_W : in VALUE_ARRAY;
    AD        : in VALUE_ARRAY;
    AS        : in VALUE_ARRAY;
    PD        : in VALUE_ARRAY;
    PS        : in VALUE_ARRAY;
    NRD       : in VALUE_ARRAY;
    NRS       : in VALUE_ARRAY;
    OFF       : in VALUE_ARRAY;
    IC_TRAN   : in VALUE_ARRAY;
    NAME      : in NAME_ARRAY;
    T_TYPE    : in NAME_ARRAY;
    TNOM      : in REAL;
    CONCK     : inout NODE_ARRAY;
    MODCOUNT  : in INTEGER;
    MCOUNT    : in INTEGER;
    DELTA     : in REAL;
    STEPV     : in REAL;
    V_ITER    : in VALUE_ARRAY;
    ITFLG     : in INTEGER;
    Vbi0      : in VALUE_ARRAY;
    TAG       : inout INTEGER;
    PARA      : inout PARAM_MATRIX;
    Cgd0      : inout VALUE_ARRAY;
    Cgb0      : inout VALUE_ARRAY;
    Cgs0      : inout VALUE_ARRAY;
    QGS0      : inout CHARG_ARRAY;
    QGD0      : inout CHARG_ARRAY;
    QGB0      : inout CHARG_ARRAY;
    QBD0      : inout CHARG_ARRAY;
    QBS0      : inout CHARG_ARRAY;
    CCAPGS0   : inout CHARG_ARRAY;
    CCAPGD0   : inout CHARG_ARRAY;
    CCAPGB0   : inout CHARG_ARRAY;
    CQBS0     : inout CHARG_ARRAY; 
    CQBD0     : inout CHARG_ARRAY; 
    NONCON    : inout INTEGER;
    VBS0      : inout VALUE_ARRAY;
    VBD0      : inout VALUE_ARRAY;
    VGS0      : inout VALUE_ARRAY;
    VDS0      : inout VALUE_ARRAY;
    VON0      : inout VALUE_ARRAY;
    VDSAT0    : inout VALUE_ARRAY;
    VBS01     : inout VALUE_ARRAY;
    VGS01     : inout VALUE_ARRAY;
    VDS01     : inout VALUE_ARRAY;
    VBS10     : inout VALUE_ARRAY;
    VBD10     : inout VALUE_ARRAY;
    VGS10     : inout VALUE_ARRAY;
    VDS10     : inout VALUE_ARRAY;
    VON10     : inout VALUE_ARRAY;
    VDSAT10   : inout VALUE_ARRAY;
    RIT       : inout INTEGER;
    CD0       : inout VALUE_ARRAY;
    CBS0      : inout VALUE_ARRAY;
    CBD0      : inout VALUE_ARRAY;
    gm0       : inout VALUE_ARRAY;
    gds0      : inout VALUE_ARRAY;
    gmbs0     : inout VALUE_ARRAY;
    GBS0      : inout VALUE_ARRAY;
    GBD0      : inout VALUE_ARRAY;
    G         : inout AMATRIX;
    I0        : inout VALUE_ARRAY;
    TAGT      : inout INTEGER)
  is
    file FILE2   :TEXT is out "STD_OUTPUT";
    variable k   : line;
    variable VTH,VON,VBI,x,y,TYPET,Cgso,Cgdo,Cgbo,BETA,CD,A1,COX1,Vbs,	 
             Vgs,Vgd,Vds,Vgb,Vbd,gmbs,gds,gm,GBD,GBS,GCBDB,GCBSB,
             COX,Eg,L,Cgs,Cgb,Cgd,VT0,VGD10,VGB10,VGST,BETAP,VDSAT,
             CBD,CBS,GCDSB,GCSDB,GCGDB,GCGSB,GCBGB,GCDGB,GCSGB,GCSSB,GCDDB,
             GCGGB,IEQGS,IEQGD,IEQGB,IQG,IQD,IQB,CZBD,CZBS,CZBDSW,CZBSSW,
             PB,XM,FC,FCPB,FCPB2,XFC,F0,F2,F3,CZSF2,CZSWF2,CZDF2,CZDWF2,
             ARG,SARG,SARGSW,CEQBD,CEQBS,GCGS,GCGD,GCGB,XFACT,CAPBS,CAPBD,
             VBS1,VBD1,VGS1,VGD1,VGB1,VDS1,CDRAIN,CDREQ,CDHAT,CBHAT,TOL,
             VCRIT,VTEM,VTEM0,DELVBS,DELVBD,DELVGS,DELVDS,DELVGD,DEVMOD,
             F1,VGD0,XREV,XNRM,VGS2,VGD2,VGB2,Cgs1,Cgd1,Cgb1,VGS11,VGD11,
             VGB11,VBS11,VDS11,VONS,VDBSAT,VDB11,VGBT,PHI,PHIB,EPSSIL,TWOPI,
             FNARRW,XJ,GAMMA,NSUB,LAMDA,NFS,VBP,UEXP,UO,VMAX,NEFF,CHARGE,
             VDDIF,VDDIF1,XD,
             VDDIF2,VDS2,VBS2,VBD2,CTEP : REAL;
    variable QGS,QGD,QGB,QBD,QBS,CCAPGS,CCAPGD,CCAPGB,CQBD,CQBS:
             CHARG_ELEM;
    variable type0 : ELEMENT_NAME;
    variable I,J,INDAX : positive;
    constant RELTOL: real := 0.001;
    constant VNTOL : real := 1.0e-6;
    constant ABSTOL: real := 1.0e-12;
  begin
--    VT0:=(8.6170869e-5)*TNOM; 
    VT0:= 0.25864186384551e-01; 
    Eg:=1.16-7.02e-4*TNOM*TNOM/(1108.0+TNOM);
    loopA1:
    for I in 1 to MCOUNT loop 
      loopB1: 
      for J in 1 to MODCOUNT loop
        if MNAME(I) = NAME(J) then
          type0:=T_TYPE(J);
          if type0(1)='N' and type0(2)='M' and type0(3)='O'
            and type0(4)='S' then
            TYPET:=1.0;
            CONCK(I):=0;
          elsif type0(1)='P' and type0(2)='M' and type0(3)='O'
            and type0(4)='S' then
            CONCK(I):=0;
            TYPET:=-1.0;
          end if;
          QGS:=QGS0(I);QGD:=QGD0(I);QGB:=QGB0(I);QBD:=QBD0(I);QBS:=QBS0(I);
          CCAPGS:=CCAPGS0(I);CCAPGD:=CCAPGD0(I);CCAPGB:=CCAPGB0(I);
          CQBD:=CQBD0(I); CQBS:=CQBS0(I);
          PHI:=PARA(5,J);
          PHIB:=PARA(12,J);
          EPSSIL:=1.0359431399070e-10;
          TWOPI:= 6.2831853071795864769;
          FNARRW:=PARA(39,J);
          XJ:=PARA(27,J);
          GAMMA:=PARA(4,J);
          NSUB:=PARA(23,J);
          LAMDA:=PARA(6,J);
          NFS:=PARA(25,J);
          VBP:=PARA(30,J)*EPSSIL*PARA(22,J)/3.45314379969e-11;
          UEXP:=PARA(31,J);
          UO:=PARA(29,J);
          VMAX:= PARA(33,J);
          NEFF:= PARA(34,J);
          CHARGE:=1.6021918000000e-19;
--|
          if TAGT=0 and TAG = 0 then
            Vgs:=VGS10(I);
            Vds:=VDS10(I);
            Vbs:=VBS10(I);
          elsif TAGT /= 0 and TAG = 0 then
            XFACT:=DELTA/STEPV;
            Vgs:=(1.0+XFACT)*VGS10(I)-XFACT*VGS01(I); 
            Vbs:=(1.0+XFACT)*VBS10(I)-XFACT*VBS01(I); 
            Vds:=(1.0+XFACT)*VDS10(I)-XFACT*VDS01(I); 
          else
            if NB(I)/=0 and NS1(I)/=0 and NB(I)/=NS1(I) then
              Vbs:= TYPET*(V_ITER(NB(I))-V_ITER(NS1(I)));
            elsif NB(I)=0 and NS1(I)/=0 then
              Vbs:= -TYPET*V_ITER(NS1(I));
            elsif NB(I)/=0 and NS1(I)=0 then
              Vbs:= TYPET*V_ITER(NB(I));
            elsif NB(I)=NS1(I) then
              Vbs:= 0.0;
            end if;
            if NG(I)/=0 and NS1(I)/=0 and NG(I)/=NS1(I) then
              Vgs:= TYPET*(V_ITER(NG(I))-V_ITER(NS1(I)));
            elsif NG(I)=0 and NS1(I)/=0 then
              Vgs:= - TYPET*V_ITER(NS1(I));
            elsif NG(I)/=0 and NS1(I)=0 then
              Vgs:= TYPET*V_ITER(NG(I));
            elsif NG(I)=NS1(I) then
              Vgs:= 0.0;
            end if;
            if ND(I)/=0 and NS1(I)/=0 and ND(I)/=NS1(I) then
              Vds:= TYPET*(V_ITER(ND(I))-V_ITER(NS1(I)));
            elsif ND(I)=0 and NS1(I)/=0 then
              Vds:= - TYPET*V_ITER(NS1(I));
            elsif ND(I)/=0 and NS1(I)=0 then
              Vds:= TYPET*V_ITER(ND(I));
            elsif ND(I)=NS1(I) then
              Vds:= 0.0;
            end if;
          end if;
          Vgd := Vgs - Vds;
          Vbd := Vbs - Vds;
          Vgb := Vgs - Vbs;
          VGD10:= VGS10(I)-VDS10(I);
          VGB10:= VGS10(I)-VBS10(I);
          VBD10(I):= VBS10(I)-VDS10(I);
--|
--| DEVICE WORKING MODE CHECK
--|
          if VDS0(I) < 0.0 then
            DEVMOD:=-1.0;
          else
            DEVMOD:=1.0;
          end if;
          CONCK(I):=0;
--|
--| Compute the new and old branch voltage difference;
--|
          VON:=VON0(I);
          VGD0:=VGS0(I)-VDS0(I);
          if TAG /= 0 then
            DELVBS:=Vbs-VBS0(I);
            DELVBD:=Vbd-VBD0(I);
            DELVGS:=Vgs-VGS0(I);
            DELVDS:=Vds-VDS0(I);
            DELVGD:=Vgd-VGD0;
            CDHAT:=CD0(I)-GBD0(I)*DELVBD+gmbs0(I)*DELVBS
             +gm0(I)*DELVGS+gds0(I)*DELVDS;
            if DEVMOD = -1.0 then
              CDHAT:=CD0(I)-(GBD0(I)-gmbs0(I))*DELVBD
               -gm0(I)*DELVGD+gds0(I)*DELVDS;
            end if;
            CBHAT:=CBS0(I)+CBD0(I)+GBD0(I)*DELVBD
              +GBS0(I)*DELVBS;
--|
--| Check the voltage limits;
--|
            TOL:=RELTOL*abs(Vbs) + VNTOL;
            if abs(Vbs) < abs(VBS0(I)) then
              TOL:=RELTOL*abs(VBS0(I)) + VNTOL;
            end if;
            if abs(DELVBS) <= TOL then
              TOL:=RELTOL*abs(Vbd) + VNTOL;
              if abs(Vbd) < abs(VBD0(I)) then
                TOL:=RELTOL*abs(VBD0(I)) + VNTOL;
              end if;
              if abs(DELVBD) <= TOL then
                TOL:=RELTOL*abs(Vgs) + VNTOL;
                if abs(Vgs) < abs(VGS0(I)) then
                  TOL:=RELTOL*abs(VGS0(I)) + VNTOL;
                end if;
                if abs(DELVGS) <= TOL then
                  TOL:=RELTOL*abs(Vds) + VNTOL;
                  if abs(vds) < abs(VDS0(I)) then
                    TOL:=RELTOL*abs(VDS0(I)) + VNTOL;
                  end if;
                  if abs(DELVDS) <= TOL then
                    TOL:=RELTOL*abs(CDHAT) + ABSTOL;
                    if abs(CDHAT) < CD0(I) then
                      TOL:=RELTOL*abs(CD0(I)) + ABSTOL;
                    end if;
                    if abs(CDHAT-CD0(I)) <= TOL then
                      TOL:=RELTOL*abs(CBHAT) + ABSTOL;
                      if abs(CBHAT) < abs(CBS0(I)+CBD0(I)) then
                        TOL:=RELTOL*abs(CBS0(I)+CBD0(I)) + ABSTOL;
                      end if;
                      if abs(CBHAT-(CBS0(I)+CBD0(I))) <= TOL then
                        Vbs:=VBS0(I);
                        Vbd:=VBD0(I);
                        Vgs:=VGS0(I);
                        Vds:=VDS0(I);
                        Vgd:=Vgs-Vds;
                        Vgb:=Vgs-Vbs;
                        CD :=CD0(I);
                        CBS:=CBS0(I);
                        CBD:=CBD0(I);
                        CDRAIN:=DEVMOD*(CD+CBD);
                        gm:=gm0(I);
                        gds:=gds0(I);
                        gmbs:=gmbs0(I);
                        GBS:=GBS0(I);
                        GBD:=GBD0(I);
                        Cgb:=Cgb0(I);
                        Cgd:=Cgd0(I);
                        Cgs:=Cgs0(I);
                        CONCK(I):=1;
                      end if;
                    end if;
                  end if;
                end if;
              end if;
            end if;
          end if;
          if CONCK(I) /= 1 then
            if VDS0(I) >= 0.0 then
              FETLIM(Vgs,VGS0(I),VON);
              Vds:=Vgs-Vgd;
              LIMVDS(Vds,VDS0(I));
              Vgd:=Vgs-Vds;
            else
              FETLIM(Vgd,VGD0,VON);
              Vds:=Vgs-Vgd;
              VTEM:=-Vds;
              VTEM0:=-VDS0(I);
              LIMVDS(VTEM,VTEM0);
              Vgs:=Vgd+Vds;
            end if;
            if Vds >= 0.0 then
              VCRIT:=VT0*2.3025850929940457
                *LOG(VT0/(1.414213562373*PARA(11,J)));
              PNJLIM(Vbs,VBS0(I),VT0,VCRIT);
              Vbd:=Vbs-Vds;
            else
              VCRIT:=VT0*2.3025850929940457
               *LOG(VT0/(1.414213562373*PARA(11,J)));
              PNJLIM(Vbd,VBD0(I),VT0,VCRIT);
              Vbs:=Vbd+Vds;
            end if;
            Vbd:=Vbs-Vds;
            Vgd:=Vgs-Vds;
            Vgb:=Vgs-Vbs;
          end if;
--|
--| Check New Device Working Mode
--|
          if Vds < 0.0 then
            DEVMOD := -1.0;
          else
            DEVMOD := 1.0;
          end if;
--|
--|
          if DEVMOD = -1.0 then
            VDS1:=-Vds;
            VGS1:=Vgd;
            VBS1:=Vbd;
            VDS2:=-VDS10(I);
            VGS2:=VGD10;
            VBS2:=VBD10(I);
          else
            VDS1:=Vds;
            VGS1:=Vgs;
            VBS1:=Vbs;
            VDS2:=VDS10(I);
            VGS2:=VGS10(I);
            VBS2:=VBS10(I);
          end if;
          if TAGT=0 and TAG=0 then
            VDS2:=VDS1;
            VGS2:=VGS1;
            VBS2:=VBS1;
          end if;
          VBD1:=VBS1-VDS1;
          VGB1:=VGS1-VBS1;
          VGD1:=VGS1-VDS1;
          VBD2:=VBS2-VDS2;
          VGB2:=VGS2-VBS2;
          VGD2:=VGS2-VDS2;
--|
--| DETERMING DC CURRENT & DERIVATIVES
--|
          if CONCK(I) /= 1 then
            if Vbs > 0.0 then
              x := Vbs/VT0;
              GBS := PARA(11,J)*power(2.7182818284590452, x)/VT0+1.0e-12;
              CBS:= PARA(11,J)*(power(2.7182818284590452, x)-1.0);
            else
              GBS :=PARA(11,J)/VT0;
              CBS := GBS*Vbs;
              GBS :=GBS+1.0e-12;
            end if;
            if Vbd > 0.0 then
              x := Vbd/VT0;
              GBD := PARA(11,J)*power(2.7182818284590452, x)/VT0+1.0e-12;
              CBD := PARA(11,J)*(power(2.7182818284590452,x)-1.0);
            else
              GBD := PARA(11,J)/VT0;
              CBD := GBD*Vbd;
              GBD := GBD + 1.0e-12;
            end if;
--|
            L:=CHANNEL_L(I)-2.0*PARA(28,J);
            COX:= 3.45314379969e-11/PARA(22,J);  
            COX1:=COX*CHANNEL_W(I)*L;
            x :=1.0e-6*(EPSSIL+EPSSIL)/1.6021918000000e-19;
            XD := sqrt(x/NSUB);
            BETA:= CHANNEL_W(I)*PARA(3,J)/L;
            VBI:=TYPET*Vbi0(I);
            if PARA(1,J) = 1.0 then
              MOSEQ1(VDS1,VBS1,VGS1,PHI,VBI,GAMMA,LAMDA,BETA,
                VON,VDSAT,CDRAIN,GM,GDS,GMBS);
            elsif PARA(1,J)=2.0 then
              MOSEQ2(VDS1,VBS1,VGS1,PHI,VBI,GAMMA,LAMDA,BETA,
                FNARRW,TWOPI,EPSSIL,COX1,CHANNEL_W(I),NSUB,XD,
                XJ,L,NFS,VT0,UO,VBP,UEXP,VMAX,NEFF,VON,VDSAT,
                CDRAIN,GM,GDS,GMBS,CHARGE);
            end if;
            CD := DEVMOD*CDRAIN-CBD;
--|
--| Calculate Junction capacitances
--|
            if RIT /= 1 then
              if TAG = 0 and TAGT/=0 then
                QBS(2) := QBS(1);
                QBD(2) := QBD(1);
                CQBS(2):=CQBS(1); CQBD(2):=CQBD(1);
                --|Shift charge in memory;
              end if; 
            end if;
            CZBD:=0.0;
            CZBS:=0.0;
            CZBDSW:=0.0;
            CZBSSW:=0.0;
            if PARA(9,J) /= 0.0 and PARA(10,J) /= 0.0 then
              CZBD:=PARA(9,J);
              CZBS:=PARA(10,J);
            else
              if PARA(17,J) /= 0.0 then
                CZBD:=PARA(17,J)*AD(I);
                CZBS:=PARA(17,J)*AS(I);
              end if;
            end if;
            if PARA(19,J) /= 0.0 then
              CZBDSW:=PARA(19,J)*PD(I);
              CZBSSW:=PARA(19,J)*PS(I);
            end if;
            PB:=PARA(12,J);
            XM:=0.5;
            FC:=PARA(38,J);
            FCPB:=FC*PB;
            FCPB2:=FCPB*FCPB;
            XFC:=2.3025850929940457*LOG(1.0-FC);
            x:=(1.0-XM)*XFC;
            x:=POWER(2.7182818284590452,x);
            F1:=PB*(1.0-x)/(1.0-XM);
            x:=(1.0+XM)*XFC;
            F2:=POWER(2.7182818284590452,x);
            F3:=1.0-FC*(1.0+XM);
            CZSF2:=CZBS/F2;
            CZSWF2:=CZBSSW/F2;
            CZDF2:=CZBD/F2;
            CZDWF2:=CZBDSW/F2;
            if Vbs < FCPB then
            --|reverse bias;
              ARG:=1.0-Vbs/PARA(12,J);
              x:=-PARA(18,J)*2.3025850929940457*LOG(ARG);
              SARG:=POWER(2.7182818284590452,x);
              x:=-PARA(20,J)*2.3025850929940457*LOG(ARG);
              SARGSW:=POWER(2.7182818284590452,x);
              QBS(1):=PARA(12,J)*(CZBS*(1.0-ARG*SARG)/(1.0-PARA(18,J))
                   +CZBSSW*(1.0-ARG*SARGSW)/(1.0-PARA(20,J)));
              CAPBS:=CZBS*SARG+CZBSSW*SARGSW;
              --|CAPBS is the total bulk and source junction
              --|capacitances;
            else
            --|forward bias;
              QBS(1):=F1*(CZBS+CZBSSW)+F3*(Vbs-FCPB)*(CZSF2+CZSWF2)
                +(Vbs*Vbs-FCPB2)*(CZSF2*PARA(18,J)+CZSWF2*PARA(20,J));
              CAPBS:=F3*(CZSF2+CZSWF2)+Vbs/PARA(12,J)*(CZSF2*PARA(18,J)
                +CZSWF2*PARA(20,J));
            end if;
            if  Vbd < FCPB then
            --|reverse bias;
              ARG:=1.0-Vbd/PARA(12,J);
              x:=-PARA(18,J)*2.3025850929940457*LOG(ARG);
              SARG:=POWER(2.7182818284590452,x);
              x:=-PARA(20,J)*2.3025850929940457*LOG(ARG);
              SARGSW:=POWER(2.718281828459,x);
              QBD(1):=PARA(12,J)*(CZBD*(1.0-ARG*SARG)/(1.0-PARA(18,J))
                   +CZBDSW*(1.0-ARG*SARGSW)/(1.0-PARA(20,J)));
              CAPBD:=CZBD*SARG+CZBDSW*SARGSW;
              --|CAPBD is the total bulk and source junction
              --|capacitances;
            else
            --|forward bias;
              QBD(1):=F1*(CZBD+CZBDSW)+F3*(Vbd-FCPB)*(CZDF2+CZDWF2)
                +(Vbd*Vbd-FCPB2)*(CZDF2*PARA(18,J)
                +CZDWF2*PARA(20,J));
              CAPBD:=F3*(CZDF2+CZDWF2)+Vbd/PARA(12,J)*(CZDF2*PARA(18,J)
                +CZDWF2*PARA(20,J));
            end if;
--|
--| CALCULATE EQUIVALENT CONDUCTANCES & CURRENTS FOR 
--| DEPLETION CAPACITORS;
--|
            if TAG = 0 and TAGT =0 then
            --|FIRST ITERATION
              QBS(2) := QBS(1);
              QBD(2) := QBD(1);
              CQBS(2):=CQBS(1); CQBD(2):=CQBD(1);
              --|Shift charge in memory;
            end if; 
            if ITFLG = 0 then
            --| Gear Methode
              CQBS(1):= 1.0e+9*QBS(1)/DELTA -1.0e+9*QBS(2)/DELTA;
              CQBD(1):= 1.0e+9*QBD(1)/DELTA -1.0e+9*QBD(2)/DELTA;
              GBS := GBS + 1.0e+9*CAPBS/DELTA;
              CBS := CBS + CQBS(1);
              GBD := GBD + 1.0e+9*CAPBD/DELTA;
              CBD := CBD + CQBD(1);
            else
            --| Trapzoide
              CQBS(1) := -CQBS(2) + 2.0e+9*(QBS(1)-QBS(2))/DELTA;
              CQBD(1) := -CQBD(2) + 2.0e+9*(QBD(1)-QBD(2))/DELTA;
              GBS := GBS + 2.0e+9*CAPBS/DELTA;
              CBS := CBS + CQBS(1);
              GBD := GBD + 2.0e+9*CAPBD/DELTA;
              CBD := CBD + CQBD(1);
            end if;
            CD:=CD-CQBD(1);
--|
--|  Check convergence;
--|
            if TAG /= 0 then
              TOL:=RELTOL*abs(CDHAT)+ABSTOL;
              if abs(CDHAT) < abs(CD) then
                TOL:=RELTOL*abs(CD)+ABSTOL;
              end if;
              if abs(CDHAT-CD) <= TOL then
                TOL:=RELTOL*abs(CBHAT)+ABSTOL;
                if abs(CBHAT) < abs(CBS+CBD) then
                  TOL:=RELTOL*abs(CBS+CBD)+ABSTOL;
                end if;
                if abs(CBHAT-(CBS+CBD)) <= TOL then
                  CONCK(I):=1;
                end if;
              end if;
            end if;
            VBS0(I):=Vbs;
            VBD0(I):=Vbd;
            VGS0(I):=Vgs;
            VDS0(I):=Vds;
            CD0(I) :=CD;
            CBS0(I):=CBS;
            CBD0(I):=CBD;
            gm0(I) :=gm;
            gds0(I):=gds;
            gmbs0(I):=gmbs;
            GBS0(I):=GBS;
            GBD0(I):=GBD;
            VON0(I):=VON;
            VDSAT0(I):=VDSAT;
            if TAGT=0 and TAG=0 then
              VDSAT10(I):=VDSAT;
              VON10(I):=VON;
            end if;
--|
--| Calculate MEYER's capacitance;
--|
            Cgso := PARA(13,J)*CHANNEL_W(I);
            Cgdo := PARA(14,J)*CHANNEL_W(I);
            Cgbo := PARA(15,J)*L;
            --|Cgso,Cgdo,and Cgbo are overlap capacitances;
            INDAX:=1;
            VGS11:=VGS1;
            VGD11:=VGD1;
            VGB11:=VGB1;
            VONS :=VON;
            VBS11:=VGS11-VGB11;
            VDBSAT:=VDSAT-VBS11;
            VDB11:=VGB11-VGD11;
            PHI:=PARA(5,J);
            loopCA:
            loop
              VDS11:=VGS11-VGD11;
              VGBT:=VGS11-VONS; 
              if VGBT > 0.0  and VDBSAT <= VDB11 then 
                CGB:= Cgbo;
                CGS:= Cgso + COX1/1.5;
                CGD:= Cgdo;
              elsif VDBSAT > VDB11 then
              --|triode regime;
                VDDIF:=2.0*VDBSAT-VDB11;
                VDDIF1:=VDBSAT-VDB11-1.0e-12;
                VDDIF2:=VDDIF*VDDIF;
                CGD:=COX1*(1.0-VDBSAT*VDBSAT/VDDIF2)/1.5+Cgdo; 
                CGS:=COX1*(1.0-VDDIF1*VDDIF1/VDDIF2)/1.5+Cgso; 
                CGB:=Cgbo; 
              elsif VGBT <= 0.0 and VGBT > -PHI*0.5 then
                CGB:=-VGBT*COX1/PHI+Cgbo; 
                CGD:=Cgdo;  
                CGS:=COX1/(7.5e-1*PHI)*VGBT+COX1/1.5+Cgso;
              elsif VGBT > -PHI and VGBT <=-PHI/2.0 then
                CGB:=-VGBT*COX1/PHI+Cgbo;
                CGS:= Cgso;
                CGD:= Cgdo;
              elsif VGBT <= -PHI then
                CGB:= COX1 + Cgbo;
                CGD:= Cgdo;
                CGS:= Cgso;
              end if;
              if INDAX=1 then
                CGS1:=CGS;
                CGD1:=CGD;
                CGB1:=CGB;
                VGS11:=VGS2; 
                VGD11:=VGD2;
                VGB11:=VGB2;
                VONS:= VON10(I);
                VDBSAT:=VDSAT10(I)-VBS2;
                VDB11:=VGB11-VGD11;
                INDAX:=2;
              elsif INDAX=2 then
                INDAX:=1;
                exit loopCA;
              end if;
            end loop loopCA;
            INDAX:=1;
            Cgd:= (Cgd+Cgd1)/2.0;
            Cgs:= (Cgs+Cgs1)/2.0;
            Cgb:= (Cgb+Cgb1)/2.0;
            if DEVMOD = -1.0 then
              CTEP:=Cgs;
              Cgs:=Cgd;
              Cgd:=CTEP;
            end if;
          end if;
          Cgd0(I):=Cgd;
          Cgs0(I):=Cgs;
          Cgb0(I):=Cgb;
--|
--| Mapping Meyer's capacitance model into charge oriented model
--|

            if TAGT=0 and TAG = 0 then
            --|FIRST ITERATION
              QGS(1) := Cgs*Vgs;
              QGD(1) := Cgd*Vgd;
              QGB(1) := Cgb*Vgb;
              QGS(2) := QGS(1);
              QGD(2) := QGD(1);
              QGB(2) := QGB(1);
            elsif TAGT/=0 and TAG = 0 then
              QGS(3) := QGS(2); QGS(2) := QGS(1);
              QGD(3) := QGD(2); QGD(2) := QGD(1);
              QGB(3) := QGB(2); QGB(2) := QGB(1);
              CCAPGS(2):=CCAPGS(1);
              CCAPGD(2):=CCAPGD(1);
              CCAPGB(2):=CCAPGB(1);
              --|Shift charge in memory;
              XFACT := DELTA/STEPV;
              QGS(1) := (1.0 + XFACT)*QGS(2) - XFACT*QGS(3);
              QGD(1) := (1.0 + XFACT)*QGD(2) - XFACT*QGD(3);
              QGB(1) := (1.0 + XFACT)*QGB(2) - XFACT*QGB(3);
            else
              QGS(1) := (Vgs-Vgs10(I))*Cgs;
              QGD(1) := (Vgd-Vgd10)*Cgd;
              QGB(1) := (Vgb-Vgb10)*Cgb;
              QGS(1) := QGS(1) + QGS(2);
              QGD(1) := QGD(1) + QGD(2);
              QGB(1) := QGB(1) + QGB(2);
            end if;
            if TAGT=0 and TAG=0 then
              GCGS := 0.0;
              IEQGS:= 0.0;
              GCGD := 0.0;
              IEQGD:= 0.0;
              GCGB := 0.0;
              IEQGB:= 0.0;
            else
              if ITFLG=0 then                  --Gear Method
                CCAPGS(1):=1.0e+9*QGS(1)/DELTA -1.0e+9*QGS(2)/DELTA; 
                CCAPGD(1):=1.0e+9*QGD(1)/DELTA -1.0e+9*QGD(2)/DELTA; 
                CCAPGB(1):=1.0e+9*QGB(1)/DELTA -1.0e+9*QGB(2)/DELTA; 
                GCGS  := 1.0e+9*Cgs/DELTA;
                GCGD  := 1.0e+9*Cgd/DELTA;
                GCGB := 1.0e+9*Cgb/DELTA;
              else                             --Trapzoid
                GCGS  := 2.0e+9*Cgs/DELTA;
                CCAPGS(1):= - CCAPGS(2) 
                 + 2.0e+9*(QGS(1)-QGS(2))/DELTA;
                GCGD  := 2.0e+9*Cgd/DELTA;
                CCAPGD(1):= - CCAPGD(2) 
                 + 2.0e+9*(QGD(1)-QGD(2))/DELTA;
                GCGB := 2.0e+9*Cgb/DELTA;
                CCAPGB(1):= - CCAPGB(2) 
                 + 2.0e+9*(QGB(1)-QGB(2))/DELTA;
              end if;
              IEQGS := CCAPGS(1) - GCGS*Vgs;
              IEQGD := CCAPGD(1) - GCGD*Vgd;
              IEQGB := CCAPGB(1) - GCGB*Vgb;
            end if;
            
--|
--| Equivalent current source and conductances; 
--|
--          CEQBS:= TYPET*(CBS - (GBS-1.0e-12)*Vbs);
--          CEQBD:= TYPET*(CBD - (GBD-1.0e-12)*Vbd);
          CEQBS:=TYPET*(CBS*1.0e+12-GBS*1.0e+12*Vbs+Vbs)*1.0e-12;
          CEQBD:=TYPET*(CBD*1.0e+12-GBD*1.0e+12*Vbd+Vbd)*1.0e-12;
          IQG := TYPET*(IEQGS + IEQGD + IEQGB);
          IQB := TYPET*(-IEQGB);
          IQD := TYPET*(-IEQGD);
          GCBDB := 0.0; 
          GCBSB := 0.0; 
          GCDSB := 0.0; 
          GCSDB := 0.0; 
          GCGDB := -GCGD; 
          GCGSB := -GCGS; 
          GCBGB := -GCGB; 
          GCDGB := -GCGD; 
          GCSGB := -GCGS; 
          GCSSB := GCGS; 
          GCDDB := GCGD; 
          GCGGB := GCGS + GCGD + GCGB; 
        
          if DEVMOD = 1.0 then
            XNRM:=1.0;
            XREV:=0.0;
          else
            XNRM:=0.0;
            XREV:=1.0;
          end if;
          CDREQ:= DEVMOD*TYPET*(CDRAIN-gmbs*VBS1-gm*VGS1-gds*VDS1);
--|
--| Load current vector & nodal admittance matrix;
--|
          if NG(I) /= 0 then
            G(NG(I),NG(I)):= G(NG(I),NG(I))+GCGGB;
            I0(NG(I)):=I0(NG(I))-IQG;
            if ND(I)/=0 then
              G(NG(I),ND(I)):= G(NG(I),ND(I))+GCGDB;
            end if;
            if NS1(I)/=0 then
              G(NG(I),NS1(I)):= G(NG(I),NS1(I))+GCGSB;
            end if;
            if NB(I)/=0 then
              G(NG(I),NB(I)):= G(NG(I),NB(I))-GCGGB-GCGDB-GCGSB;
            end if;
          end if;
          if ND(I)/=0 then
            G(ND(I),ND(I)) := G(ND(I),ND(I))+gds+GBD+GCDDB+XREV*(gm+gmbs); 
            I0(ND(I)) := I0(ND(I))+CEQBD-CDREQ-IQD;
            if NG(I)/=0 then
              G(ND(I),NG(I)):= G(ND(I),NG(I))+(XNRM-XREV)*gm+GCDGB;
            end if;
            if NS1(I)/=0 then
              G(ND(I),NS1(I)) := G(ND(I),NS1(I))-gds-XNRM*(gmbs+gm)+GCDSB;
            end if;
            if NB(I)/=0 then
              G(ND(I),NB(I)) := G(ND(I),NB(I))+(XNRM-XREV)*gmbs-GBD-GCDGB
               -GCDDB-GCDSB;
            end if;
          end if;
          if NS1(I)/= 0 then
            G(NS1(I),NS1(I)) := G(NS1(I),NS1(I))+gds+GBS+XNRM*(gmbs+gm)
              + GCSSB;
            I0(NS1(I)) := I0(NS1(I))+CDREQ+IQB+IQD+IQG+CEQBS;
            if NG(I)/=0 then
              G(NS1(I),NG(I)):= G(NS1(I),NG(I))-(XNRM-XREV)*gm+GCSGB;
            end if;
            if ND(I)/= 0 then
              G(NS1(I),ND(I)):= G(NS1(I),ND(I))-gds-XREV*(gm+gmbs)+GCSDB;
            end if;
            if NB(I)/= 0 then
              G(NS1(I),NB(I)):= G(NS1(I),NB(I))-GBS-(XNRM-XREV)*gmbs-GCSGB
               -GCSDB-GCSSB;
            end if;
          end if;
          if NB(I)/=0 then
            G(NB(I),NB(I)) := G(NB(I),NB(I))+GBS+GBD-GCBGB-GCBDB-GCBSB; 
            I0(NB(I)) := I0(NB(I))-IQB-CEQBS-CEQBD;
            if ND(I)/= 0 then
              G(NB(I),ND(I)) := G(NB(I),ND(I))-GBD + GCBDB;
            end if;
            if NS1(I)/=0 then
              G(NB(I),NS1(I)):=G(NB(I),NS1(I))-GBS + GCBSB;
            end if;
            if NG(I)/=0 then
              G(NB(I),NG(I)) := G(NB(I),NG(I))+GCBGB;
            end if;
          end if;
          QGS0(I):=QGS;QGD0(I):=QGD;QGB0(I):=QGB;QBD0(I):=QBD;QBS0(I):=QBS;
          CCAPGS0(I):=CCAPGS;CCAPGD0(I):=CCAPGD;CCAPGB0(I):=CCAPGB;
          CQBD0(I):=CQBD; CQBS0(I):=CQBS;
        end if;
      end loop loopB1;
    end loop loopA1;
    TAG := TAG+1;
  return;
  end MOSFET_TRAN;

--******************************************************************
--*                                                                *
--*   TIME_TO_REAL                                                 * BODY
--*                                                                *
--******************************************************************
  Function TIME_TO_REAL(A: in TIME) return REAL
  is
    variable x : Time;
    variable y : Time; 
    variable B : integer := 0;
    variable R : real := 0.00000;
    variable F : real := 1.00000;
    variable T_REAL : real := 0.00000;
    variable FACT: real:=1.0;
variable k : line;
file FILE2 : TEXT is out "STD_OUTPUT";
  begin
	
    x := A;                               --Input  Time   value   A 
    y := A;                               --Input  Time   value   A
    if x >= 10 ns then
      FACT := 1.0;
    elsif x >= 1 ns and x < 10 ns then
      FACT:=0.01;
      x := 100.0 * x;
      y := 100.0 * y;
    elsif x < 1 ns and x >= 0.1 ns then
      FACT:=0.001;
      x := 1000 * x;
      y := 1000 * y;
    elsif x < 0.1 ns and x >= 0.001 ns then
      FACT:=0.0001;
      x := 10000 * x;
      y := 10000 * y;
    elsif x < 0.001 ns and x >= 0.000001 ns then
      FACT:=0.000001;
      x := 1000000 * x;
      y := 1000000 * y;
    end if;
    loop0:
    loop
      x := (x/10 ns) * 1 ns;            --Gelet the last bit of x.
      if x = 0 ns and y = 0 ns then     --No more bit left.
	exit loop0;
      end if;
      B := (y - x * 10) / 1 ns ;        --Extract the GeleteG bit
      y := (y/10 ns) * 1 ns;	          --Gelet the last bit  for
      if B = 0 then                     --CSTEPVange  integer  bit  B 
        R := 	0.00000; 
      elsif B = 1 then
        R :=  1.00000; 
      elsif B = 2 then 
        R :=  2.00000; 
      elsif B = 3 then	
        R :=  3.00000; 
      elsif B = 4 then	
        R :=  4.00000; 
      elsif B = 5 then	
        R :=  5.00000; 
      elsif B = 6 then	
        R :=  6.00000; 
      elsif B = 7 then	
        R :=  7.00000; 
      elsif B = 8 then	
        R :=  8.00000; 
      elsif B = 9 then	
        R :=  9.00000; 
      end if;
      T_REAL := T_REAL + R * F;         --Get back the input time
      F := F * 10.00000;                --value but is a floating  
    end loop loop0;                         --STEPV 
    T_REAL := FACT*T_REAL;                 --unit on it.	
  return T_REAL;
  end TIME_TO_REAL;
 
--******************************************************************
--*                                                                *
--*   LOG                                                          * BODY
--*                                                                *
--******************************************************************
  function LOG(x: in REAL) return REAL
  is
    variable j   : integer := 0; 
    variable n, k: real := 0.0; 
    variable a,y,z,l,z0,f0: real := 0.0; 
    variable k1 : line;
file FILE2 : TEXT is out "STD_OUTPUT";
  begin
    
    z := x;
    loop1:
    loop 
      if z < 1.0 then
        z := z*10.0; 
        n := n+1.0;
      elsif z >= 10.0 then
        z := z/10.0;
        k := k+1.0; 
      end if;
      exit loop1 when z < 10.0 and z >= 1.0;
    end loop loop1;     
    loop2:
    loop
      j := j + 1;
      l := l + 1.0;
      if z >=1.0 and z < 2.0 then
        z0 := 1.0;
        f0 := 0.0;
      elsif z >= 2.0 and z < 3.0 then
        z0 := 2.0;
        f0 := 0.69314718055994530941;
      elsif z >= 3.0 and z < 4.0 then
        z0 := 3.0;
        f0 := 1.09861228866810969139;
      elsif z >= 4.0 and z < 5.0 then
        z0 := 4.0;
        f0 := 1.38629436111989061883;
      elsif z >= 5.0 and z < 6.0 then
        z0 := 5.0;
        f0 := 1.60943791243410037460;
      elsif z >= 6.0 and z < 7.0 then
        z0 := 6.0;
        f0 := 1.79175946922805500081;
      elsif z >= 7.0 and z < 8.0 then
        z0 := 7.0;
        f0 := 1.94591014905531330510;
      elsif z >= 8.0 and z < 9.0 then
        z0 := 8.0;
        f0 := 2.07944154167983592825;
      elsif z >= 8.0 and z < 10.0 then
        z0 := 9.0;
        f0 := 2.19722457733621938279;
      end if;
        a := a + ((-1.0)**(j-1))*(((z/z0)-1.0)**j)/l;
        y := ((z/z0)-1.0)**(j+1)*((-1.0)**j)/(l+1.0);   
      exit loop2 when abs(y) < 1.0e-14;
    end loop loop2;
    a := a + f0;
    a := a*0.43429448190325182765;
    if n /= 0.0 then
      a := a - n ;
    elsif k /= 0.0 then
      a := a + k;
    end if;
  return a;
  end LOG;

--*****************************************************************
--*                                                               *
--*   POWER                                                       * BODY
--*                                                               *
--*****************************************************************
  function POWER(x: in real; y: in real) return real 
  is
file FILE2 :TEXT is out "STD_OUTPUT";
variable k : line;
    variable a,b,c,l: real := 1.0; 
    variable j : real := 0.0;
    variable n : INTEGER := 0; 
    variable m : integer := 1;
  begin
    b := 2.30258509299404568401*y*LOG(x);
    if abs(b) >=1.0 then
      loop0:
      loop
        b:=b/10.0;
        m:=m*10;
        exit loop0 when abs(b) < 1.0;
      end loop loop0;
    end if;
    if b > 0.0 then
      loop1:
      loop
        n := n+1;
        j := j+1.0;
        l := FACTORIAL(j);
        a := a + (b**n)/l;
        c := (b**(n+1))/(l*(j+1.0));
        exit loop1 when c < 1.0e-14;
      end loop loop1;
    elsif b < 0.0 then
      b := -b;
      loop2:
      loop
        n := n+1;
        j := j+1.0;
        a := a + (b**n)/FACTORIAL(j);
        c := (b**(n+1))/FACTORIAL(j+1.0);
        exit loop2 when c < 1.0e-14;
      end loop loop2;
      a := 1.0/a;
    elsif b = 0.0 then
      a:=1.0;
    end if;
    a:=a**m;
  return a;
  end POWER; 
        
--*****************************************************************
--*                                                               *
--*   FACTORIAL                                                   * BODY
--*                                                               *
--*****************************************************************
  function FACTORIAL(x: in real) return real is
    variable a,j: real := 1.0;
  begin
    loop1:
    loop 
      a := a*j;
      exit loop1 when j = x;
      j := j + 1.0;
    end loop loop1;
  return a;
  end FACTORIAL;
    
--*****************************************************************
--*                                                               *
--*   sqrt                                                        * BODY
--*                                                               *
--*****************************************************************
  function sqrt(x: in real) return real is
    variable a: real;
    constant error: real:=1.0e-12;
file FILE2 : text is out "STD_OUTPUT";
variable k : line;
    
  begin
    a := 1.0;
    while abs(a-x/a) > error loop
      a := (a+x/a)/2.0;
    end loop;
    return a;
  end sqrt;

--******************************************************************
--*                                                                *
--*  cos                                                           * BODY
--*                                                                *
--******************************************************************
  function cos(x: in real) return real is
   constant EPSILON : real := 1.0e-14;
   constant TWOPI : real := 6.283185307179586476925286766559005768;
   variable x1,a, fact, yold, ynew, n, sign, term : real;
  begin
    x1 := x;
    if x1 > TWOPI then
      loop1:
      loop
        x1 := x1 - TWOPI;
        exit loop1 when x1 < TWOPI;
      end loop loop1;
    elsif x1 < -TWOPI then
      loop2:
      loop
        x1 := x1 + TWOPI;
        exit loop2 when x1 > -TWOPI;
      end loop loop2;
    end if;
    ynew := 1.0;
    n := 0.0;
    sign := 1.0;
    term := 1.0;
    fact := 1.0;
    loop3:
    loop
      yold := ynew;
      sign := -sign;
      fact := fact * (n + 1.0) * (n + 2.0);
      n := n + 2.0;
      term := term * x1 * x1;
      ynew := yold + sign * term / fact;
      a := ynew-yold;
      exit loop3 when abs(a) < EPSILON;
    end loop loop3;
    return ynew;
  end cos;

--********************************************************************
--*                                                                  *
--*  atan                                                            * BODY
--*                                                                  *
--********************************************************************
  function atan (x: in  real ) return real is
    constant EPSILON : real := 1.0e-14;
    constant PI2     : real := 1.5707963267948966192313216916397514420000;
    variable n,a, ynew, yold, term, sign, y : real;
file FILE2 : text is out "STD_OUTPUT";
variable k : line;
  begin
    if abs(x) < 1.0 then
      y := 1.0;
      n := 1.0;
      sign := 1.0;
      ynew := x;
      term := x;
      yold := EPSILON + 1.0 + ynew;
      a := ynew - yold;
      loop1:
      while abs(a) > EPSILON loop
        yold := ynew;
        sign := -sign;
        term := term * x * x;
        n := n + 2.0;
        ynew := yold + sign * term / n;
        a := ynew - yold;
      end loop loop1;
    elsif abs(x) > 1.0 then
      if x > 0.0 then 
        ynew := PI2;
      else
        ynew := -PI2;
      end if; 
      term := x;
      sign := -1.0;
      n := 1.0;
      ynew := ynew - 1.0 / x;
      yold := EPSILON + 1.0 + ynew;
      a := ynew-yold;
      loop2:
      while abs(a) > EPSILON loop 
        yold := ynew;
        sign := -sign;
        term := term * x * x;
        n := n + 2.0;
        ynew := yold + sign / term / n;
        a := ynew-yold;
      end loop loop2;
    elsif x = 1.0 then
      ynew := PI2/2.0;
    else
      ynew := -PI2/2.0;
    end if;
    return ynew;
  end atan;

end COMPUTE_PACK;

<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>