--******************************************************************* --* :::::::::::: * --* 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;