diff --git a/ChangeLog b/ChangeLog index da76e25de..71b4b0605 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,13 @@ + +2010-06-28 Holger Vogt + * bsim3/b3set.c b3ld.c bsim3def.h: new preproc flag USE_OMP3 + * bsim4/b4set.c b4ld.c bsim4def.h: OpenMP support for BSIM4 model + 2010-06-27 Robert Larice * src/xspice/enh/enhtrans.c: drop useless cast of a copy() return value -2010-06-23 Holger Vogt +2010-06-27 Holger Vogt * numparam.h: short replaced by int 2010-06-27 Robert Larice diff --git a/src/spicelib/devices/bsim3/b3ld.c b/src/spicelib/devices/bsim3/b3ld.c index d9585f92b..acbe51c16 100644 --- a/src/spicelib/devices/bsim3/b3ld.c +++ b/src/spicelib/devices/bsim3/b3ld.c @@ -1,4 +1,5 @@ /**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ /********** * Copyright 2004 Regents of the University of California. All rights reserved. @@ -31,7 +32,7 @@ #define DELTA_3 0.02 #define DELTA_4 0.02 -#ifdef USE_OMP +#ifdef USE_OMP3 int BSIM3LoadOMP(BSIM3instance *here, CKTcircuit *ckt); void BSIM3LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt); extern int nthreads; @@ -43,7 +44,7 @@ BSIM3load( GENmodel *inModel, CKTcircuit *ckt) { -#ifdef USE_OMP +#ifdef USE_OMP3 int idx; BSIM3model *model = (BSIM3model*)inModel; int good = 0; @@ -166,7 +167,7 @@ struct bsim3SizeDependParam *pParam; int ByPass, Check, ChargeComputationNeeded, error; /* double junk[50]; */ -#ifdef USE_OMP +#ifdef USE_OMP3 model = here->BSIM3modPtr; #endif @@ -175,7 +176,7 @@ ChargeComputationNeeded = ((ckt->CKTmode & (MODEAC | MODETRAN | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? 1 : 0; -#ifndef USE_OMP +#ifndef USE_OMP3 for (; model != NULL; model = model->BSIM3nextModel) { for (here = model->BSIM3instances; here != NULL; here = here->BSIM3nextInstance) @@ -2925,7 +2926,7 @@ line900: } m = here->BSIM3m; -#ifdef USE_OMP +#ifdef USE_OMP3 here->BSIM3rhsG = m * ceqqg; here->BSIM3rhsB = m * (ceqbs + ceqbd + ceqqb); here->BSIM3rhsD = m * (ceqbd - cdreq - ceqqd); @@ -2947,7 +2948,7 @@ line900: */ T1 = qdef * here->BSIM3gtau; -#ifdef USE_OMP +#ifdef USE_OMP3 here->BSIM3DdPt = m * here->BSIM3drainConductance; here->BSIM3GgPt = m * (gcggb - ggtg); here->BSIM3SsPt = m * here->BSIM3sourceConductance; @@ -3051,14 +3052,14 @@ line900: } #endif line1000: ; -#ifndef USE_OMP +#ifndef USE_OMP3 } /* End of Mosfet Instance */ } /* End of Model Instance */ #endif return(OK); } -#ifdef USE_OMP +#ifdef USE_OMP3 void BSIM3LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) { unsigned int InstCount, idx; diff --git a/src/spicelib/devices/bsim3/b3set.c b/src/spicelib/devices/bsim3/b3set.c index 3c8665f84..bc30d5fc8 100644 --- a/src/spicelib/devices/bsim3/b3set.c +++ b/src/spicelib/devices/bsim3/b3set.c @@ -1,4 +1,5 @@ /**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ /********** * Copyright 2004 Regents of the University of California. All rights reserved. @@ -15,7 +16,7 @@ #include "const.h" #include "sperror.h" #include "suffix.h" -#ifdef USE_OMP +#ifdef USE_OMP3 int nthreads; extern bool cp_getvar(char *name, int type, void *retval); #define VT_NUM 1 @@ -45,7 +46,7 @@ CKTnode *tmp; CKTnode *tmpNode; IFuid tmpName; -#ifdef USE_OMP +#ifdef USE_OMP3 unsigned int idx, InstCount; BSIM3instance **InstArray; int nthreads; @@ -1009,9 +1010,9 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ } } -#ifdef USE_OMP +#ifdef USE_OMP3 if (!cp_getvar("num_threads", VT_NUM, (char *) &nthreads)) - nthreads = 4; + nthreads = 2; omp_set_num_threads(nthreads); if (nthreads == 1) diff --git a/src/spicelib/devices/bsim3/bsim3def.h b/src/spicelib/devices/bsim3/bsim3def.h index fa7912ff2..beb4164e6 100644 --- a/src/spicelib/devices/bsim3/bsim3def.h +++ b/src/spicelib/devices/bsim3/bsim3def.h @@ -3,6 +3,7 @@ Copyright 2004 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. Author: 2001- Xuemei Xi +**** OpenMP support for ngspice by Holger Vogt 06/28/2010 **** File: bsim3def.h **********/ @@ -15,9 +16,11 @@ File: bsim3def.h #include "complex.h" #include "noisedef.h" -//#define USE_OMP - #ifdef USE_OMP +#define USE_OMP3 +#endif + +#ifdef USE_OMP3 #include #endif @@ -169,7 +172,7 @@ typedef struct sBSIM3instance double *BSIM3SPqPtr; double *BSIM3BqPtr; -#ifdef USE_OMP +#ifdef USE_OMP3 /* per instance storage of results, to update matrix at a later stge */ double BSIM3rhsG; double BSIM3rhsB; @@ -844,7 +847,7 @@ typedef struct sBSIM3model struct bsim3SizeDependParam *pSizeDependParamKnot; -#ifdef USE_OMP +#ifdef USE_OMP3 int BSIM3InstCount; struct sBSIM3instance **BSIM3InstanceArray; #endif diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index 9b388a854..b11ef34c2 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -1,5 +1,6 @@ /**** BSIM4.6.2 Released by Wenwei Yang 07/31/2008****/ /**** BSIM4.6.5 Update ngspice 09/22/2009 ****/ +/**** OpenMP support ngspice 06/28/2010 ****/ /********** * Copyright 2006 Regents of the University of California. All rights reserved. * File: b4ld.c of BSIM4.6.2. @@ -29,6 +30,7 @@ #include "sperror.h" #include "devdefs.h" #include "suffix.h" + /* #define MAX_EXP 2.688117142e+43 #define MIN_EXP 3.720075976e-44 @@ -58,6 +60,13 @@ } \ } + +#ifdef USE_OMP4 +int BSIM4LoadOMP(BSIM4instance *here, CKTcircuit *ckt); +void BSIM4LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt); +extern int nthreads; +#endif + int BSIM4polyDepletion(double phi, double ngate,double epsgate, double coxe, double Vgs, double *Vgs_eff, double *dVgs_eff_dVg); int @@ -65,9 +74,32 @@ BSIM4load( GENmodel *inModel, CKTcircuit *ckt) { +#ifdef USE_OMP4 + int idx; + BSIM4model *model = (BSIM4model*)inModel; + int good = 0; + BSIM4instance *here; + BSIM4instance **InstArray; + InstArray = model->BSIM4InstanceArray; + +#pragma omp parallel for num_threads(nthreads) private(here) + for (idx = 0; idx < model->BSIM4InstCount; idx++) { + here = InstArray[idx]; + good = BSIM4LoadOMP(here, ckt); + } + + BSIM4LoadRhsMat(inModel, ckt); + + return good; +} + + +int BSIM4LoadOMP(BSIM4instance *here, CKTcircuit *ckt) { +BSIM4model *model; +#else BSIM4model *model = (BSIM4model*)inModel; BSIM4instance *here; - +#endif double ceqgstot, dgstot_dvd, dgstot_dvg, dgstot_dvs, dgstot_dvb; double ceqgdtot, dgdtot_dvd, dgdtot_dvg, dgdtot_dvs, dgdtot_dvb; double gstot, gstotd, gstotg, gstots, gstotb, gspr, Rs, Rd; @@ -206,16 +238,23 @@ int ByPass, ChargeComputationNeeded, error, Check, Check1, Check2; double m; +#ifdef USE_OMP4 +model = here->BSIM4modPtr; +#endif + ScalingFactor = 1.0e-9; ChargeComputationNeeded = ((ckt->CKTmode & (MODEAC | MODETRAN | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? 1 : 0; +#ifndef USE_OMP4 for (; model != NULL; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here != NULL; here = here->BSIM4nextInstance) { if (here->BSIM4owner != ARCHme) continue; +#endif + Check = Check1 = Check2 = 1; ByPass = 0; pParam = here->pParam; @@ -4685,7 +4724,7 @@ line900: ceqqg = -ceqqg; ceqqd = -ceqqd; ceqqb = -ceqqb; - ceqgcrg = -ceqgcrg; + ceqgcrg = -ceqgcrg; if (here->BSIM4trnqsMod) { cqdef = -cqdef; @@ -4708,60 +4747,253 @@ line900: m = here->BSIM4m; - (*(ckt->CKTrhs + here->BSIM4dNodePrime) += m * (ceqjd - ceqbd + ceqgdtot +#ifdef USE_OMP4 + here->BSIM4rhsdPrime = m * (ceqjd - ceqbd + ceqgdtot + - ceqdrn - ceqqd + Idtoteq); + here->BSIM4rhsgPrime = m * (ceqqg - ceqgcrg + Igtoteq); + + if (here->BSIM4rgateMod == 2) + here->BSIM4rhsgExt = m * ceqgcrg; + else if (here->BSIM4rgateMod == 3) + here->BSIM4grhsMid = m * (ceqqgmid + ceqgcrg); + + if (!here->BSIM4rbodyMod) + { here->BSIM4rhsbPrime = m * (ceqbd + ceqbs - ceqjd + - ceqjs - ceqqb + Ibtoteq); + here->BSIM4rhssPrime = m * (ceqdrn - ceqbs + ceqjs + + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq); + } + else + { here->BSIM4rhsdb = m * (ceqjd + ceqqjd); + here->BSIM4rhsbPrime = m * (ceqbd + ceqbs - ceqqb + Ibtoteq); + here->BSIM4rhssb = m * (ceqjs + ceqqjs); + here->BSIM4rhssPrime = m * (ceqdrn - ceqbs + ceqjs + ceqqd + + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq); + } + + if (model->BSIM4rdsMod) + { here->BSIM4rhsd = m * ceqgdtot; + here->BSIM4rhss = m * ceqgstot; + } + + if (here->BSIM4trnqsMod) + here->BSIM4rhsq = m * (cqcheq - cqdef); +#else + (*(ckt->CKTrhs + here->BSIM4dNodePrime) += m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq)); - (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= m * (ceqqg - ceqgcrg + Igtoteq)); + (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= m * (ceqqg - ceqgcrg + Igtoteq)); - if (here->BSIM4rgateMod == 2) - (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= m * ceqgcrg); - else if (here->BSIM4rgateMod == 3) - (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= m * (ceqqgmid + ceqgcrg)); + if (here->BSIM4rgateMod == 2) + (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= m * ceqgcrg); + else if (here->BSIM4rgateMod == 3) + (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= m * (ceqqgmid + ceqgcrg)); - if (!here->BSIM4rbodyMod) - { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqjd + if (!here->BSIM4rbodyMod) + { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq)); - } - else - { (*(ckt->CKTrhs + here->BSIM4dbNode) -= m * (ceqjd + ceqqjd)); - (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqqb + Ibtoteq)); - (*(ckt->CKTrhs + here->BSIM4sbNode) -= m * (ceqjs + ceqqjs)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqd + } + + else + { (*(ckt->CKTrhs + here->BSIM4dbNode) -= m * (ceqjd + ceqqjd)); + (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqqb + Ibtoteq)); + (*(ckt->CKTrhs + here->BSIM4sbNode) -= m * (ceqjs + ceqqjs)); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq)); - } + } - if (model->BSIM4rdsMod) - { (*(ckt->CKTrhs + here->BSIM4dNode) -= m * ceqgdtot); - (*(ckt->CKTrhs + here->BSIM4sNode) += m * ceqgstot); - } + if (model->BSIM4rdsMod) + { (*(ckt->CKTrhs + here->BSIM4dNode) -= m * ceqgdtot); + (*(ckt->CKTrhs + here->BSIM4sNode) += m * ceqgstot); + } - if (here->BSIM4trnqsMod) - *(ckt->CKTrhs + here->BSIM4qNode) += m * (cqcheq - cqdef); + if (here->BSIM4trnqsMod) + *(ckt->CKTrhs + here->BSIM4qNode) += m * (cqcheq - cqdef); +#endif - - /* - * Loading matrix - */ + /* + * Loading matrix + */ if (!here->BSIM4rbodyMod) { gjbd = here->BSIM4gbd; gjbs = here->BSIM4gbs; } - else - gjbd = gjbs = 0.0; + else + gjbd = gjbs = 0.0; - if (!model->BSIM4rdsMod) - { gdpr = here->BSIM4drainConductance; - gspr = here->BSIM4sourceConductance; + if (!model->BSIM4rdsMod) + { gdpr = here->BSIM4drainConductance; + gspr = here->BSIM4sourceConductance; + } + else + gdpr = gspr = 0.0; + + geltd = here->BSIM4grgeltd; + + T1 = qdef * here->BSIM4gtau; +#ifdef USE_OMP4 + if (here->BSIM4rgateMod == 1) + { here->BSIM4_1 = m * geltd; + here->BSIM4_2 = m * geltd; + here->BSIM4_3 = m * geltd; + here->BSIM4_4 = m * (gcggb + geltd - ggtg + gIgtotg); + here->BSIM4_5 = m * (gcgdb - ggtd + gIgtotd); + here->BSIM4_6 = m * (gcgsb - ggts + gIgtots); + here->BSIM4_7 = m * (gcgbb - ggtb + gIgtotb); + } /* WDLiu: gcrg already subtracted from all gcrgg below */ + else if (here->BSIM4rgateMod == 2) + { here->BSIM4_8 = m * gcrg; + here->BSIM4_9 = m * gcrgg; + here->BSIM4_10 = m * gcrgd; + here->BSIM4_11 = m * gcrgs; + here->BSIM4_12 = m * gcrgb; + + here->BSIM4_13 = m * gcrg; + here->BSIM4_14 = m * (gcggb - gcrgg - ggtg + gIgtotg); + here->BSIM4_15 = m * (gcgdb - gcrgd - ggtd + gIgtotd); + here->BSIM4_16 = m * (gcgsb - gcrgs - ggts + gIgtots); + here->BSIM4_17 = m * (gcgbb - gcrgb - ggtb + gIgtotb); + } + else if (here->BSIM4rgateMod == 3) + { here->BSIM4_18 = m * geltd; + here->BSIM4_19 = m * geltd; + here->BSIM4_20 = m * geltd; + here->BSIM4_21 = m * (geltd + gcrg + gcgmgmb); + + here->BSIM4_22 = m * (gcrgd + gcgmdb); + here->BSIM4_23 = m * gcrgg; + here->BSIM4_24 = m * (gcrgs + gcgmsb); + here->BSIM4_25 = m * (gcrgb + gcgmbb); + + here->BSIM4_26 = m * gcdgmb; + here->BSIM4_26 = m * gcrg; + here->BSIM4_28 = m * gcsgmb; + here->BSIM4_29 = m * gcbgmb; + + here->BSIM4_30 = m * (gcggb - gcrgg - ggtg + gIgtotg); + here->BSIM4_31 = m * (gcgdb - gcrgd - ggtd + gIgtotd); + here->BSIM4_32 = m * (gcgsb - gcrgs - ggts + gIgtots); + here->BSIM4_33 = m * (gcgbb - gcrgb - ggtb + gIgtotb); + } + + else + { here->BSIM4_34 = m * (gcggb - ggtg + gIgtotg); + here->BSIM4_35 = m * (gcgdb - ggtd + gIgtotd); + here->BSIM4_36 = m * (gcgsb - ggts + gIgtots); + here->BSIM4_37 = m * (gcgbb - ggtb + gIgtotb); + } + + if (model->BSIM4rdsMod) + { here->BSIM4_38 = m * gdtotg; + here->BSIM4_39 = m * gdtots; + here->BSIM4_40 = m * gdtotb; + here->BSIM4_41 = m * gstotd; + here->BSIM4_42 = m * gstotg; + here->BSIM4_43 = m * gstotb; + } + + here->BSIM4_44 = m * (gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd + - gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd); + here->BSIM4_45 = m * (gdpr + gdtot); + + here->BSIM4_46 = m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + + dxpart * ggtg + T1 * ddxpart_dVg); + here->BSIM4_47 = m * (here->BSIM4gds + gdtots - dxpart * ggts + gIdtots + - T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp); + here->BSIM4_48 = m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb + - T1 * ddxpart_dVb - dxpart * ggtb); + + here->BSIM4_49 = m * (gdpr - gdtotd); + here->BSIM4_50 = m * (gdpr + gdtot); + + here->BSIM4_51 = m * (here->BSIM4gds + gstotd + RevSum - gcsdb - gbspdp + - T1 * dsxpart_dVd - sxpart * ggtd + gIstotd); + here->BSIM4_52 = m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + + T1 * dsxpart_dVg - gIstotg); + here->BSIM4_53 = m * (gspr + here->BSIM4gds + here->BSIM4gbs + T1 * dsxpart_dVs + - gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots); + here->BSIM4_54 = m * (gspr + gstot); + here->BSIM4_55 = m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb + - T1 * dsxpart_dVb + gIstotb); + + here->BSIM4_56 = m * (gspr - gstots); + here->BSIM4_57 = m * (gspr + gstot); + + here->BSIM4_58 = m * (gcbdb - gjbd + gbbdp - gIbtotd); + here->BSIM4_59 = m * (gcbgb - here->BSIM4gbgs - gIbtotg); + here->BSIM4_60 = m * (gcbsb - gjbs + gbbsp - gIbtots); + here->BSIM4_61 = m * (gjbd + gjbs + gcbbb - here->BSIM4gbbs - gIbtotb); + + ggidld = here->BSIM4ggidld; + ggidlg = here->BSIM4ggidlg; + ggidlb = here->BSIM4ggidlb; + ggislg = here->BSIM4ggislg; + ggisls = here->BSIM4ggisls; + ggislb = here->BSIM4ggislb; + + /* stamp gidl */ + here->BSIM4_62 = m * ggidld; + here->BSIM4_63 = m * ggidlg; + here->BSIM4_64 = m * (ggidlg + ggidld + ggidlb); + here->BSIM4_65 = m * ggidlb; + here->BSIM4_66 = m * ggidld; + here->BSIM4_67 = m * ggidlg; + here->BSIM4_68 = m * (ggidlg + ggidld + ggidlb); + here->BSIM4_69 = m * ggidlb; + /* stamp gisl */ + here->BSIM4_70 = m * (ggisls + ggislg + ggislb); + here->BSIM4_71 = m * ggislg; + here->BSIM4_72 = m * ggisls; + here->BSIM4_73 = m * ggislb; + here->BSIM4_74 = m * (ggislg + ggisls + ggislb); + here->BSIM4_75 = m * ggislg; + here->BSIM4_76 = m * ggisls; + here->BSIM4_77 = m * ggislb; + + if (here->BSIM4rbodyMod) + { here->BSIM4_78 = m * (gcdbdb - here->BSIM4gbd); + here->BSIM4_79 = m * (here->BSIM4gbs - gcsbsb); + + here->BSIM4_80 = m * (gcdbdb - here->BSIM4gbd); + here->BSIM4_81 = m * (here->BSIM4gbd - gcdbdb + + here->BSIM4grbpd + here->BSIM4grbdb); + here->BSIM4_82 = m * here->BSIM4grbpd; + here->BSIM4_83 = m * here->BSIM4grbdb; + + here->BSIM4_84 = m * here->BSIM4grbpd; + here->BSIM4_85 = m * here->BSIM4grbpb; + here->BSIM4_86 = m * here->BSIM4grbps; + here->BSIM4_87 = m * (here->BSIM4grbpd + here->BSIM4grbps + + here->BSIM4grbpb); + /* WDLiu: (gcbbb - here->BSIM4gbbs) already added to BPbpPtr */ + + here->BSIM4_88 = m * (gcsbsb - here->BSIM4gbs); + here->BSIM4_89 = m * here->BSIM4grbps; + here->BSIM4_90 = m * here->BSIM4grbsb; + here->BSIM4_91 = m * (here->BSIM4gbs - gcsbsb + + here->BSIM4grbps + here->BSIM4grbsb); + + here->BSIM4_92 = m * here->BSIM4grbdb; + here->BSIM4_93 = m * here->BSIM4grbpb; + here->BSIM4_94 = m * here->BSIM4grbsb; + here->BSIM4_95 = m * (here->BSIM4grbsb + here->BSIM4grbdb + + here->BSIM4grbpb); } - else - gdpr = gspr = 0.0; - geltd = here->BSIM4grgeltd; - - T1 = qdef * here->BSIM4gtau; + if (here->BSIM4trnqsMod) + { here->BSIM4_96 = m * (gqdef + here->BSIM4gtau); + here->BSIM4_97 = m * (ggtg - gcqgb); + here->BSIM4_98 = m * (ggtd - gcqdb); + here->BSIM4_99 = m * (ggts - gcqsb); + here->BSIM4_100 = m * (ggtb - gcqbb); + here->BSIM4_101 = m * dxpart * here->BSIM4gtau; + here->BSIM4_102 = m * sxpart * here->BSIM4gtau; + here->BSIM4_103 = m * here->BSIM4gtau; + } +#else if (here->BSIM4rgateMod == 1) { (*(here->BSIM4GEgePtr) += m * geltd); (*(here->BSIM4GPgePtr) -= m * geltd); @@ -4772,11 +5004,11 @@ line900: (*(here->BSIM4GPbpPtr) += m * (gcgbb - ggtb + gIgtotb)); } /* WDLiu: gcrg already subtracted from all gcrgg below */ else if (here->BSIM4rgateMod == 2) - { (*(here->BSIM4GEgePtr) += m * gcrg); + { (*(here->BSIM4GEgePtr) += m * gcrg); (*(here->BSIM4GEgpPtr) += m * gcrgg); (*(here->BSIM4GEdpPtr) += m * gcrgd); (*(here->BSIM4GEspPtr) += m * gcrgs); - (*(here->BSIM4GEbpPtr) += m * gcrgb); + (*(here->BSIM4GEbpPtr) += m * gcrgb); (*(here->BSIM4GPgePtr) -= m * gcrg); (*(here->BSIM4GPgpPtr) += m * (gcggb - gcrgg - ggtg + gIgtotg)); @@ -4821,7 +5053,7 @@ line900: (*(here->BSIM4SbpPtr) += m * gstotb); } - (*(here->BSIM4DPdpPtr) += m * (gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd + (*(here->BSIM4DPdpPtr) = m * (gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd - gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd)); (*(here->BSIM4DPdPtr) -= m * (gdpr + gdtot)); (*(here->BSIM4DPgpPtr) += m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg @@ -4921,11 +5153,14 @@ line900: (*(here->BSIM4SPqPtr) += m * sxpart * here->BSIM4gtau); (*(here->BSIM4GPqPtr) -= m * here->BSIM4gtau); } +#endif line1000: ; +#ifndef USE_OMP4 } /* End of MOSFET Instance */ } /* End of Model Instance */ +#endif return(OK); } @@ -4963,3 +5198,192 @@ int BSIM4polyDepletion( } return(0); } + +#ifdef USE_OMP4 +void BSIM4LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) +{ + unsigned int InstCount, idx; + BSIM4instance **InstArray; + BSIM4instance *here; + BSIM4model *model = (BSIM4model*)inModel; + + InstArray = model->BSIM4InstanceArray; + InstCount = model->BSIM4InstCount; + + for(idx = 0; idx < InstCount; idx++) { + here = InstArray[idx]; + /* Update b for Ax = b */ + (*(ckt->CKTrhs + here->BSIM4dNodePrime) += here->BSIM4rhsdPrime); + (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= here->BSIM4rhsgPrime); + + if (here->BSIM4rgateMod == 2) + (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= here->BSIM4rhsgExt); + else if (here->BSIM4rgateMod == 3) + (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= here->BSIM4grhsMid); + + if (!here->BSIM4rbodyMod) + { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += here->BSIM4rhsbPrime); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += here->BSIM4rhssPrime); + } + else + { (*(ckt->CKTrhs + here->BSIM4dbNode) -= here->BSIM4rhsdb); + (*(ckt->CKTrhs + here->BSIM4bNodePrime) += here->BSIM4rhsbPrime); + (*(ckt->CKTrhs + here->BSIM4sbNode) -= here->BSIM4rhssb); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += here->BSIM4rhssPrime); + } + + if (model->BSIM4rdsMod) + { (*(ckt->CKTrhs + here->BSIM4dNode) -= here->BSIM4rhsd); + (*(ckt->CKTrhs + here->BSIM4sNode) += here->BSIM4rhss); + } + + if (here->BSIM4trnqsMod) + *(ckt->CKTrhs + here->BSIM4qNode) += here->BSIM4rhsq; + + + /* Update A for Ax = b */ + if (here->BSIM4rgateMod == 1) + { (*(here->BSIM4GEgePtr) += here->BSIM4_1); + (*(here->BSIM4GPgePtr) -= here->BSIM4_2); + (*(here->BSIM4GEgpPtr) -= here->BSIM4_3); + (*(here->BSIM4GPgpPtr) += here->BSIM4_4); + (*(here->BSIM4GPdpPtr) += here->BSIM4_5); + (*(here->BSIM4GPspPtr) += here->BSIM4_6); + (*(here->BSIM4GPbpPtr) += here->BSIM4_7); + } + else if (here->BSIM4rgateMod == 2) + { (*(here->BSIM4GEgePtr) += here->BSIM4_8); + (*(here->BSIM4GEgpPtr) += here->BSIM4_9); + (*(here->BSIM4GEdpPtr) += here->BSIM4_10); + (*(here->BSIM4GEspPtr) += here->BSIM4_11); + (*(here->BSIM4GEbpPtr) += here->BSIM4_12); + + (*(here->BSIM4GPgePtr) -= here->BSIM4_13); + (*(here->BSIM4GPgpPtr) += here->BSIM4_14); + (*(here->BSIM4GPdpPtr) += here->BSIM4_15); + (*(here->BSIM4GPspPtr) += here->BSIM4_16); + (*(here->BSIM4GPbpPtr) += here->BSIM4_17); + } + else if (here->BSIM4rgateMod == 3) + { (*(here->BSIM4GEgePtr) += here->BSIM4_18); + (*(here->BSIM4GEgmPtr) -= here->BSIM4_19); + (*(here->BSIM4GMgePtr) -= here->BSIM4_20); + (*(here->BSIM4GMgmPtr) += here->BSIM4_21); + + (*(here->BSIM4GMdpPtr) += here->BSIM4_22); + (*(here->BSIM4GMgpPtr) += here->BSIM4_23); + (*(here->BSIM4GMspPtr) += here->BSIM4_24); + (*(here->BSIM4GMbpPtr) += here->BSIM4_25); + + (*(here->BSIM4DPgmPtr) += here->BSIM4_26); + (*(here->BSIM4GPgmPtr) -= here->BSIM4_27); + (*(here->BSIM4SPgmPtr) += here->BSIM4_28); + (*(here->BSIM4BPgmPtr) += here->BSIM4_29); + + (*(here->BSIM4GPgpPtr) += here->BSIM4_30); + (*(here->BSIM4GPdpPtr) += here->BSIM4_31); + (*(here->BSIM4GPspPtr) += here->BSIM4_32); + (*(here->BSIM4GPbpPtr) += here->BSIM4_33); + } + + + else + { (*(here->BSIM4GPgpPtr) += here->BSIM4_34); + (*(here->BSIM4GPdpPtr) += here->BSIM4_35); + (*(here->BSIM4GPspPtr) += here->BSIM4_36); + (*(here->BSIM4GPbpPtr) += here->BSIM4_37); + } + + + if (model->BSIM4rdsMod) + { (*(here->BSIM4DgpPtr) += here->BSIM4_38); + (*(here->BSIM4DspPtr) += here->BSIM4_39); + (*(here->BSIM4DbpPtr) += here->BSIM4_40); + (*(here->BSIM4SdpPtr) += here->BSIM4_41); + (*(here->BSIM4SgpPtr) += here->BSIM4_42); + (*(here->BSIM4SbpPtr) += here->BSIM4_43); + } + + (*(here->BSIM4DPdpPtr) += here->BSIM4_44); + (*(here->BSIM4DPdPtr) -= here->BSIM4_45); + (*(here->BSIM4DPgpPtr) += here->BSIM4_46); + (*(here->BSIM4DPspPtr) -= here->BSIM4_47); + (*(here->BSIM4DPbpPtr) -= here->BSIM4_48); + + (*(here->BSIM4DdpPtr) -= here->BSIM4_49); + (*(here->BSIM4DdPtr) += here->BSIM4_50); + + (*(here->BSIM4SPdpPtr) -= here->BSIM4_51); + (*(here->BSIM4SPgpPtr) += here->BSIM4_52); + (*(here->BSIM4SPspPtr) += here->BSIM4_53); + (*(here->BSIM4SPsPtr) -= here->BSIM4_54); + (*(here->BSIM4SPbpPtr) -= here->BSIM4_55); + + (*(here->BSIM4SspPtr) -= here->BSIM4_56); + (*(here->BSIM4SsPtr) += here->BSIM4_57); + + (*(here->BSIM4BPdpPtr) += here->BSIM4_58); + (*(here->BSIM4BPgpPtr) += here->BSIM4_59); + (*(here->BSIM4BPspPtr) += here->BSIM4_60); + (*(here->BSIM4BPbpPtr) += here->BSIM4_61); + + /* stamp gidl */ + (*(here->BSIM4DPdpPtr) += here->BSIM4_62); + (*(here->BSIM4DPgpPtr) += here->BSIM4_63); + (*(here->BSIM4DPspPtr) -= here->BSIM4_64); + (*(here->BSIM4DPbpPtr) += here->BSIM4_65); + (*(here->BSIM4BPdpPtr) -= here->BSIM4_66); + (*(here->BSIM4BPgpPtr) -= here->BSIM4_67); + (*(here->BSIM4BPspPtr) += here->BSIM4_68); + (*(here->BSIM4BPbpPtr) -= here->BSIM4_69); + /* stamp gisl */ + (*(here->BSIM4SPdpPtr) -= here->BSIM4_70); + (*(here->BSIM4SPgpPtr) += here->BSIM4_71); + (*(here->BSIM4SPspPtr) += here->BSIM4_72); + (*(here->BSIM4SPbpPtr) += here->BSIM4_73); + (*(here->BSIM4BPdpPtr) += here->BSIM4_74); + (*(here->BSIM4BPgpPtr) -= here->BSIM4_75); + (*(here->BSIM4BPspPtr) -= here->BSIM4_76); + (*(here->BSIM4BPbpPtr) -= here->BSIM4_77); + + + if (here->BSIM4rbodyMod) + { (*(here->BSIM4DPdbPtr) += here->BSIM4_78); + (*(here->BSIM4SPsbPtr) -= here->BSIM4_79); + + (*(here->BSIM4DBdpPtr) += here->BSIM4_80); + (*(here->BSIM4DBdbPtr) += here->BSIM4_81); + (*(here->BSIM4DBbpPtr) -= here->BSIM4_82); + (*(here->BSIM4DBbPtr) -= here->BSIM4_83); + + (*(here->BSIM4BPdbPtr) -= here->BSIM4_84); + (*(here->BSIM4BPbPtr) -= here->BSIM4_85); + (*(here->BSIM4BPsbPtr) -= here->BSIM4_86); + (*(here->BSIM4BPbpPtr) += here->BSIM4_87); + + (*(here->BSIM4SBspPtr) += here->BSIM4_88); + (*(here->BSIM4SBbpPtr) -= here->BSIM4_89); + (*(here->BSIM4SBbPtr) -= here->BSIM4_90); + (*(here->BSIM4SBsbPtr) += here->BSIM4_91); + + (*(here->BSIM4BdbPtr) -= here->BSIM4_92); + (*(here->BSIM4BbpPtr) -= here->BSIM4_93); + (*(here->BSIM4BsbPtr) -= here->BSIM4_94); + (*(here->BSIM4BbPtr) += here->BSIM4_95); + } + + if (here->BSIM4trnqsMod) + { (*(here->BSIM4QqPtr) += here->BSIM4_96); + (*(here->BSIM4QgpPtr) += here->BSIM4_97); + (*(here->BSIM4QdpPtr) += here->BSIM4_98); + (*(here->BSIM4QspPtr) += here->BSIM4_99); + (*(here->BSIM4QbpPtr) += here->BSIM4_100); + + (*(here->BSIM4DPqPtr) += here->BSIM4_101); + (*(here->BSIM4SPqPtr) += here->BSIM4_102); + (*(here->BSIM4GPqPtr) -= here->BSIM4_103); + } + } +} + +#endif diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 9c0a2bed5..8c77e5d40 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -1,5 +1,6 @@ /**** BSIM4.6.2 Released by Wenwei Yang 07/31/2008 ****/ /**** BSIM4.6.4 Update ngspice 08/22/2009 ****/ +/**** OpenMP support ngspice 06/28/2010 ****/ /********** * Copyright 2006 Regents of the University of California. All rights reserved. * File: b4set.c of BSIM4.6.2. @@ -30,6 +31,12 @@ #include "sperror.h" #include "suffix.h" +#ifdef USE_OMP4 +int nthreads; +extern bool cp_getvar(char *name, int type, void *retval); +#define VT_NUM 1 +#endif + #define MAX_EXP 5.834617425e14 #define MIN_EXP 1.713908431e-15 #define EXP_THRESHOLD 34.0 @@ -58,6 +65,13 @@ int noiseAnalGiven = 0, createNode; /* Criteria for new node creation */ double Rtot, DMCGeff, DMCIeff, DMDGeff; JOB *job; + +#ifdef USE_OMP4 +unsigned int idx, InstCount; +BSIM4instance **InstArray; +int nthreads; +#endif + /* Search for a noise analysis request */ for (job = ((TSKtask *)ft_curckt->ci_curTask)->jobs;job;job = job->JOBnextJob) { if(strcmp(job->JOBname,"Noise Analysis")==0) { @@ -2325,9 +2339,9 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ { TSTALLOC(BSIM4GEgePtr, BSIM4gNodeExt, BSIM4gNodeExt) TSTALLOC(BSIM4GEgpPtr, BSIM4gNodeExt, BSIM4gNodePrime) TSTALLOC(BSIM4GPgePtr, BSIM4gNodePrime, BSIM4gNodeExt) - TSTALLOC(BSIM4GEdpPtr, BSIM4gNodeExt, BSIM4dNodePrime) - TSTALLOC(BSIM4GEspPtr, BSIM4gNodeExt, BSIM4sNodePrime) - TSTALLOC(BSIM4GEbpPtr, BSIM4gNodeExt, BSIM4bNodePrime) + TSTALLOC(BSIM4GEdpPtr, BSIM4gNodeExt, BSIM4dNodePrime) + TSTALLOC(BSIM4GEspPtr, BSIM4gNodeExt, BSIM4sNodePrime) + TSTALLOC(BSIM4GEbpPtr, BSIM4gNodeExt, BSIM4bNodePrime) TSTALLOC(BSIM4GMdpPtr, BSIM4gNodeMid, BSIM4dNodePrime) TSTALLOC(BSIM4GMgpPtr, BSIM4gNodeMid, BSIM4gNodePrime) @@ -2363,19 +2377,61 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ TSTALLOC(BSIM4BdbPtr, BSIM4bNode, BSIM4dbNode) TSTALLOC(BSIM4BbpPtr, BSIM4bNode, BSIM4bNodePrime) TSTALLOC(BSIM4BsbPtr, BSIM4bNode, BSIM4sbNode) - TSTALLOC(BSIM4BbPtr, BSIM4bNode, BSIM4bNode) - } + TSTALLOC(BSIM4BbPtr, BSIM4bNode, BSIM4bNode) + } if (model->BSIM4rdsMod) { TSTALLOC(BSIM4DgpPtr, BSIM4dNode, BSIM4gNodePrime) - TSTALLOC(BSIM4DspPtr, BSIM4dNode, BSIM4sNodePrime) + TSTALLOC(BSIM4DspPtr, BSIM4dNode, BSIM4sNodePrime) TSTALLOC(BSIM4DbpPtr, BSIM4dNode, BSIM4bNodePrime) TSTALLOC(BSIM4SdpPtr, BSIM4sNode, BSIM4dNodePrime) TSTALLOC(BSIM4SgpPtr, BSIM4sNode, BSIM4gNodePrime) TSTALLOC(BSIM4SbpPtr, BSIM4sNode, BSIM4bNodePrime) } } + } /* end of loop through all the BSIM4 device models */ + +#ifdef USE_OMP4 + if (!cp_getvar("num_threads", VT_NUM, (char *) &nthreads)) + nthreads = 2; + + omp_set_num_threads(nthreads); + if (nthreads == 1) + printf("OpenMP: %d thread is requested in BSIM4\n", nthreads); + else + printf("OpenMP: %d threads are requested in BSIM4\n", nthreads); + InstCount = 0; + model = (BSIM4model*)inModel; + /* loop through all the BSIM4 device models + to count the number of instances */ + + for( ; model != NULL; model = model->BSIM4nextModel ) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4instances; here != NULL ; + here=here->BSIM4nextInstance) + { + InstCount++; + } } + InstArray = (BSIM4instance**)tmalloc(InstCount*sizeof(BSIM4instance**)); + model = (BSIM4model*)inModel; + idx = 0; + for( ; model != NULL; model = model->BSIM4nextModel ) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4instances; here != NULL ; + here=here->BSIM4nextInstance) + { + InstArray[idx] = here; + idx++; + } + /* set the array pointer and instance count into each model */ + model->BSIM4InstCount = InstCount; + model->BSIM4InstanceArray = InstArray; + } +#endif + return(OK); } diff --git a/src/spicelib/devices/bsim4/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index cad624166..ae8b46107 100644 --- a/src/spicelib/devices/bsim4/bsim4def.h +++ b/src/spicelib/devices/bsim4/bsim4def.h @@ -1,5 +1,5 @@ /**** BSIM4.6.2 Released by Wenwei Yang 07/31/2008 ****/ - +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ /********** Copyright 2006 Regents of the University of California. All rights reserved. File: bsim4def.h @@ -27,6 +27,15 @@ Modified by Wenwei Yang, 07/31/2008. #include "complex.h" #include "noisedef.h" +#ifdef USE_OMP +#define USE_OMP4 +#endif + + +#ifdef USE_OMP4 +#include +#endif + typedef struct sBSIM4instance { struct sBSIM4model *BSIM4modPtr; @@ -386,6 +395,125 @@ typedef struct sBSIM4instance double *BSIM4GPqPtr; double *BSIM4SPqPtr; +#ifdef USE_OMP4 + /* per instance storage of results, to update matrix at a later stge */ + double BSIM4rhsdPrime; + double BSIM4rhsgPrime; + double BSIM4rhsgExt; + double BSIM4grhsMid; + double BSIM4rhsbPrime; + double BSIM4rhssPrime; + double BSIM4rhsdb; + double BSIM4rhssb; + double BSIM4rhsd; + double BSIM4rhss; + double BSIM4rhsq; + + double BSIM4_1; + double BSIM4_2; + double BSIM4_3; + double BSIM4_4; + double BSIM4_5; + double BSIM4_6; + double BSIM4_7; + double BSIM4_8; + double BSIM4_9; + double BSIM4_10; + double BSIM4_11; + double BSIM4_12; + double BSIM4_13; + double BSIM4_14; + double BSIM4_15; + double BSIM4_16; + double BSIM4_17; + double BSIM4_18; + double BSIM4_19; + double BSIM4_20; + double BSIM4_21; + double BSIM4_22; + double BSIM4_23; + double BSIM4_24; + double BSIM4_25; + double BSIM4_26; + double BSIM4_27; + double BSIM4_28; + double BSIM4_29; + double BSIM4_30; + double BSIM4_31; + double BSIM4_32; + double BSIM4_33; + double BSIM4_34; + double BSIM4_35; + double BSIM4_36; + double BSIM4_37; + double BSIM4_38; + double BSIM4_39; + double BSIM4_40; + double BSIM4_41; + double BSIM4_42; + double BSIM4_43; + double BSIM4_44; + double BSIM4_45; + double BSIM4_46; + double BSIM4_47; + double BSIM4_48; + double BSIM4_49; + double BSIM4_50; + double BSIM4_51; + double BSIM4_52; + double BSIM4_53; + double BSIM4_54; + double BSIM4_55; + double BSIM4_56; + double BSIM4_57; + double BSIM4_58; + double BSIM4_59; + double BSIM4_60; + double BSIM4_61; + double BSIM4_62; + double BSIM4_63; + double BSIM4_64; + double BSIM4_65; + double BSIM4_66; + double BSIM4_67; + double BSIM4_68; + double BSIM4_69; + double BSIM4_70; + double BSIM4_71; + double BSIM4_72; + double BSIM4_73; + double BSIM4_74; + double BSIM4_75; + double BSIM4_76; + double BSIM4_77; + double BSIM4_78; + double BSIM4_79; + double BSIM4_80; + double BSIM4_81; + double BSIM4_82; + double BSIM4_83; + double BSIM4_84; + double BSIM4_85; + double BSIM4_86; + double BSIM4_87; + double BSIM4_88; + double BSIM4_89; + double BSIM4_90; + double BSIM4_91; + double BSIM4_92; + double BSIM4_93; + double BSIM4_94; + double BSIM4_95; + double BSIM4_96; + double BSIM4_97; + double BSIM4_98; + double BSIM4_99; + double BSIM4_100; + double BSIM4_101; + double BSIM4_102; + double BSIM4_103; + +#endif #define BSIM4vbd BSIM4states+ 0 #define BSIM4vbs BSIM4states+ 1 @@ -1575,6 +1703,12 @@ typedef struct sBSIM4model struct bsim4SizeDependParam *pSizeDependParamKnot; + +#ifdef USE_OMP4 + int BSIM4InstCount; + struct sBSIM4instance **BSIM4InstanceArray; +#endif + /* Flags */ unsigned BSIM4mobModGiven :1; unsigned BSIM4binUnitGiven :1;