You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
873 lines
30 KiB
873 lines
30 KiB
/**********
|
|
License : 3-clause BSD
|
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher
|
|
Model Author : 1990 Michael Schröter TU Dresden
|
|
**********/
|
|
|
|
/*
|
|
* This routine should only be called when circuit topology
|
|
* changes, since its computations do not depend on most
|
|
* device or model parameters, only on topology (as
|
|
* affected by emitter, collector, and base resistances)
|
|
*/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "ngspice/smpdefs.h"
|
|
#include "hicum2defs.h"
|
|
#include "ngspice/const.h"
|
|
#include "ngspice/sperror.h"
|
|
#include "ngspice/ifsim.h"
|
|
#include "ngspice/suffix.h"
|
|
|
|
int
|
|
HICUMsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|
/* load the HICUM structure with those pointers needed later
|
|
* for fast matrix loading
|
|
*/
|
|
{
|
|
HICUMmodel *model = (HICUMmodel*)inModel;
|
|
HICUMinstance *here;
|
|
int error;
|
|
CKTnode *tmp;
|
|
|
|
/* loop through all the transistor models */
|
|
for( ; model != NULL; model = HICUMnextModel(model)) {
|
|
|
|
//Circuit simulator specific parameters
|
|
if(model->HICUMtype != NPN && model->HICUMtype != PNP)
|
|
model->HICUMtype = NPN;
|
|
|
|
if(!model->HICUMtnomGiven)
|
|
model->HICUMtnom = ckt->CKTnomTemp;
|
|
|
|
if (!model->HICUMversionGiven)
|
|
model->HICUMversion = copy("2.4.0");
|
|
|
|
//Transfer current
|
|
if(!model->HICUMc10Given)
|
|
model->HICUMc10 = 2e-30;
|
|
|
|
if(!model->HICUMqp0Given)
|
|
model->HICUMqp0 = 2e-14;
|
|
|
|
if(!model->HICUMichGiven)
|
|
model->HICUMich = 0.0;
|
|
|
|
if(!model->HICUMhf0Given)
|
|
model->HICUMhf0 = 1.0;
|
|
|
|
if(!model->HICUMhfeGiven)
|
|
model->HICUMhfe = 1.0;
|
|
|
|
if(!model->HICUMhfcGiven)
|
|
model->HICUMhfc = 1.0;
|
|
|
|
if(!model->HICUMhjeiGiven)
|
|
model->HICUMhjei = 1.0;
|
|
|
|
if(!model->HICUMahjeiGiven)
|
|
model->HICUMahjei = 0.0;
|
|
|
|
if(!model->HICUMrhjeiGiven)
|
|
model->HICUMrhjei = 1.0;
|
|
|
|
if(!model->HICUMhjciGiven)
|
|
model->HICUMhjci = 1.0;
|
|
|
|
//Base-Emitter diode;
|
|
if(!model->HICUMibeisGiven)
|
|
model->HICUMibeis = 1e-18;
|
|
|
|
if(!model->HICUMmbeiGiven)
|
|
model->HICUMmbei = 1.0;
|
|
|
|
if(!model->HICUMireisGiven)
|
|
model->HICUMireis = 0.0;
|
|
|
|
if(!model->HICUMmreiGiven)
|
|
model->HICUMmrei = 2.0;
|
|
|
|
if(!model->HICUMibepsGiven)
|
|
model->HICUMibeps = 0.0;
|
|
|
|
if(!model->HICUMmbepGiven)
|
|
model->HICUMmbep = 1.0;
|
|
|
|
if(!model->HICUMirepsGiven)
|
|
model->HICUMireps = 0.0;
|
|
|
|
if(!model->HICUMmrepGiven)
|
|
model->HICUMmrep = 2.0;
|
|
|
|
if(!model->HICUMmcfGiven)
|
|
model->HICUMmcf = 1.0;
|
|
|
|
//Transit time for excess recombination current at b-c barrier
|
|
if(!model->HICUMtbhrecGiven)
|
|
model->HICUMtbhrec = 0.0;
|
|
|
|
//Base-Collector diode currents
|
|
if(!model->HICUMibcisGiven)
|
|
model->HICUMibcis = 1e-16;
|
|
|
|
if(!model->HICUMmbciGiven)
|
|
model->HICUMmbci = 1.0;
|
|
|
|
if(!model->HICUMibcxsGiven)
|
|
model->HICUMibcxs = 0.0;
|
|
|
|
if(!model->HICUMmbcxGiven)
|
|
model->HICUMmbcx = 1.0;
|
|
|
|
//Base-Emitter tunneling current
|
|
if(!model->HICUMibetsGiven)
|
|
model->HICUMibets = 0.0;
|
|
|
|
if(!model->HICUMabetGiven)
|
|
model->HICUMabet = 40.0;
|
|
|
|
if(!model->HICUMtunodeGiven)
|
|
model->HICUMtunode = 1;
|
|
|
|
//Base-Collector avalanche current
|
|
if(!model->HICUMfavlGiven)
|
|
model->HICUMfavl = 0.0;
|
|
|
|
if(!model->HICUMqavlGiven)
|
|
model->HICUMqavl = 0.0;
|
|
|
|
if(!model->HICUMkavlGiven)
|
|
model->HICUMkavl = 0.0;
|
|
|
|
if(!model->HICUMalfavGiven)
|
|
model->HICUMalfav = 0.0;
|
|
|
|
if(!model->HICUMalqavGiven)
|
|
model->HICUMalqav = 0.0;
|
|
|
|
if(!model->HICUMalkavGiven)
|
|
model->HICUMalkav = 0.0;
|
|
|
|
//Series resistances
|
|
if(!model->HICUMrbi0Given)
|
|
model->HICUMrbi0 = 0.0;
|
|
|
|
if(!model->HICUMrbxGiven)
|
|
model->HICUMrbx = 0.0;
|
|
|
|
if(!model->HICUMfgeoGiven)
|
|
model->HICUMfgeo = 0.6557;
|
|
|
|
if(!model->HICUMfdqr0Given)
|
|
model->HICUMfdqr0 = 0.0;
|
|
|
|
if(!model->HICUMfcrbiGiven)
|
|
model->HICUMfcrbi = 0.0;
|
|
|
|
if(!model->HICUMfqiGiven)
|
|
model->HICUMfqi = 1.0;
|
|
|
|
if(!model->HICUMreGiven)
|
|
model->HICUMre = 0.0;
|
|
|
|
if(!model->HICUMrcxGiven)
|
|
model->HICUMrcx = 0.0;
|
|
|
|
//Substrate transistor
|
|
if(!model->HICUMitssGiven)
|
|
model->HICUMitss = 0.0;
|
|
|
|
if(!model->HICUMmsfGiven)
|
|
model->HICUMmsf = 1.0;
|
|
|
|
if(!model->HICUMiscsGiven)
|
|
model->HICUMiscs = 0.0;
|
|
|
|
if(!model->HICUMmscGiven)
|
|
model->HICUMmsc = 1.0;
|
|
|
|
if(!model->HICUMtsfGiven)
|
|
model->HICUMtsf = 0.0;
|
|
|
|
//Intra-device substrate coupling
|
|
if(!model->HICUMrsuGiven)
|
|
model->HICUMrsu = 0.0;
|
|
|
|
if(!model->HICUMcsuGiven)
|
|
model->HICUMcsu = 0.0;
|
|
|
|
//Depletion Capacitances
|
|
if(!model->HICUMcjei0Given)
|
|
model->HICUMcjei0 = 1.0e-20;
|
|
|
|
if(!model->HICUMvdeiGiven)
|
|
model->HICUMvdei = 0.9;
|
|
|
|
if(!model->HICUMzeiGiven)
|
|
model->HICUMzei = 0.5;
|
|
|
|
if(!model->HICUMajeiGiven)
|
|
model->HICUMajei = 2.5;
|
|
|
|
if(!model->HICUMcjep0Given)
|
|
model->HICUMcjep0 = 1.0e-20;
|
|
|
|
if(!model->HICUMvdepGiven)
|
|
model->HICUMvdep = 0.9;
|
|
|
|
if(!model->HICUMzepGiven)
|
|
model->HICUMzep = 0.5;
|
|
|
|
if(!model->HICUMajepGiven)
|
|
model->HICUMajep = 2.5;
|
|
|
|
if(!model->HICUMcjci0Given)
|
|
model->HICUMcjci0 = 1.0e-20;
|
|
|
|
if(!model->HICUMvdciGiven)
|
|
model->HICUMvdci = 0.7;
|
|
|
|
if(!model->HICUMzciGiven)
|
|
model->HICUMzci = 0.4;
|
|
|
|
if(!model->HICUMvptciGiven)
|
|
model->HICUMvptci = 100.0;
|
|
|
|
if(!model->HICUMcjcx0Given)
|
|
model->HICUMcjcx0 = 1.0e-20;
|
|
|
|
if(!model->HICUMvdcxGiven)
|
|
model->HICUMvdcx = 0.7;
|
|
|
|
if(!model->HICUMzcxGiven)
|
|
model->HICUMzcx = 0.4;
|
|
|
|
if(!model->HICUMvptcxGiven)
|
|
model->HICUMvptcx = 100.0;
|
|
|
|
if(!model->HICUMfbcparGiven)
|
|
model->HICUMfbcpar = 0.0;
|
|
|
|
if(!model->HICUMfbeparGiven)
|
|
model->HICUMfbepar = 1.0;
|
|
|
|
if(!model->HICUMcjs0Given)
|
|
model->HICUMcjs0 = 0.0;
|
|
|
|
if(!model->HICUMvdsGiven)
|
|
model->HICUMvds = 0.6;
|
|
|
|
if(!model->HICUMzsGiven)
|
|
model->HICUMzs = 0.5;
|
|
|
|
if(!model->HICUMvptsGiven)
|
|
model->HICUMvpts = 100.0;
|
|
|
|
if(!model->HICUMcscp0Given)
|
|
model->HICUMcscp0 = 0.0;
|
|
|
|
if(!model->HICUMvdspGiven)
|
|
model->HICUMvdsp = 0.6;
|
|
|
|
if(!model->HICUMzspGiven)
|
|
model->HICUMzsp = 0.5;
|
|
|
|
if(!model->HICUMvptspGiven)
|
|
model->HICUMvptsp = 100.0;
|
|
|
|
//Diffusion Capacitances
|
|
if(!model->HICUMt0Given)
|
|
model->HICUMt0 = 0.0;
|
|
|
|
if(!model->HICUMdt0hGiven)
|
|
model->HICUMdt0h = 0.0;
|
|
|
|
if(!model->HICUMtbvlGiven)
|
|
model->HICUMtbvl = 0.0;
|
|
|
|
if(!model->HICUMtef0Given)
|
|
model->HICUMtef0 = 0.0;
|
|
|
|
if(!model->HICUMgtfeGiven)
|
|
model->HICUMgtfe = 1.0;
|
|
|
|
if(!model->HICUMthcsGiven)
|
|
model->HICUMthcs = 0.0;
|
|
|
|
if(!model->HICUMahcGiven)
|
|
model->HICUMahc = 0.1;
|
|
|
|
if(!model->HICUMfthcGiven)
|
|
model->HICUMfthc = 0.0;
|
|
|
|
if(!model->HICUMrci0Given)
|
|
model->HICUMrci0 = 150;
|
|
|
|
if(!model->HICUMvlimGiven)
|
|
model->HICUMvlim = 0.5;
|
|
|
|
if(!model->HICUMvcesGiven)
|
|
model->HICUMvces = 0.1;
|
|
|
|
if(!model->HICUMvptGiven)
|
|
model->HICUMvpt = 100.0;
|
|
|
|
if(!model->HICUMaickGiven)
|
|
model->HICUMaick = 1.0e-03;
|
|
|
|
if(!model->HICUMdelckGiven)
|
|
model->HICUMdelck = 2.0;
|
|
|
|
if(!model->HICUMtrGiven)
|
|
model->HICUMtr = 0.0;
|
|
|
|
if(!model->HICUMvcbarGiven)
|
|
model->HICUMvcbar = 0.0;
|
|
|
|
if(!model->HICUMicbarGiven)
|
|
model->HICUMicbar = 0.0;
|
|
|
|
if(!model->HICUMacbarGiven)
|
|
model->HICUMacbar = 0.01;
|
|
|
|
//Isolation Capacitances
|
|
if(!model->HICUMcbeparGiven)
|
|
model->HICUMcbepar = 0.0;
|
|
|
|
if(!model->HICUMcbcparGiven)
|
|
model->HICUMcbcpar = 0.0;
|
|
|
|
//Non-quasi-static Effect
|
|
if(!model->HICUMalqfGiven)
|
|
model->HICUMalqf = 0.167;
|
|
|
|
if(!model->HICUMalitGiven)
|
|
model->HICUMalit = 0.333;
|
|
|
|
if(!model->HICUMflnqsGiven)
|
|
model->HICUMflnqs = 0;
|
|
|
|
//Noise
|
|
if(!model->HICUMkfGiven)
|
|
model->HICUMkf = 0.0;
|
|
|
|
if(!model->HICUMafGiven)
|
|
model->HICUMaf = 2.0;
|
|
|
|
if(!model->HICUMcfbeGiven)
|
|
model->HICUMcfbe = -1;
|
|
|
|
if(!model->HICUMflconoGiven)
|
|
model->HICUMflcono = 0;
|
|
|
|
if(!model->HICUMkfreGiven)
|
|
model->HICUMkfre = 0.0;
|
|
|
|
if(!model->HICUMafreGiven)
|
|
model->HICUMafre = 2.0;
|
|
|
|
//Lateral Geometry Scaling (at high current densities)
|
|
if(!model->HICUMlatbGiven)
|
|
model->HICUMlatb = 0.0;
|
|
|
|
if(!model->HICUMlatlGiven)
|
|
model->HICUMlatl = 0.0;
|
|
|
|
//Temperature dependence
|
|
if(!model->HICUMvgbGiven)
|
|
model->HICUMvgb = 1.17;
|
|
|
|
if(!model->HICUMalt0Given)
|
|
model->HICUMalt0 = 0.0;
|
|
|
|
if(!model->HICUMkt0Given)
|
|
model->HICUMkt0 = 0.0;
|
|
|
|
if(!model->HICUMzetaciGiven)
|
|
model->HICUMzetaci = 0.0;
|
|
|
|
if(!model->HICUMalvsGiven)
|
|
model->HICUMalvs = 0.0;
|
|
|
|
if(!model->HICUMalcesGiven)
|
|
model->HICUMalces = 0.0;
|
|
|
|
if(!model->HICUMzetarbiGiven)
|
|
model->HICUMzetarbi = 0.0;
|
|
|
|
if(!model->HICUMzetarbxGiven)
|
|
model->HICUMzetarbx = 0.0;
|
|
|
|
if(!model->HICUMzetarcxGiven)
|
|
model->HICUMzetarcx = 0.0;
|
|
|
|
if(!model->HICUMzetareGiven)
|
|
model->HICUMzetare = 0.0;
|
|
|
|
if(!model->HICUMzetacxGiven)
|
|
model->HICUMzetacx = 1.0;
|
|
|
|
if(!model->HICUMvgeGiven)
|
|
model->HICUMvge = 1.17;
|
|
|
|
if(!model->HICUMvgcGiven)
|
|
model->HICUMvgc = 1.17;
|
|
|
|
if(!model->HICUMvgsGiven)
|
|
model->HICUMvgs = 1.17;
|
|
|
|
if(!model->HICUMf1vgGiven)
|
|
model->HICUMf1vg = -1.02377e-4;
|
|
|
|
if(!model->HICUMf2vgGiven)
|
|
model->HICUMf2vg = 4.3215e-4;
|
|
|
|
if(!model->HICUMzetactGiven)
|
|
model->HICUMzetact = 3.0;
|
|
|
|
if(!model->HICUMzetabetGiven)
|
|
model->HICUMzetabet = 3.5;
|
|
|
|
if(!model->HICUMalbGiven)
|
|
model->HICUMalb = 0.0;
|
|
|
|
if(!model->HICUMdvgbeGiven)
|
|
model->HICUMdvgbe = 0.0;
|
|
|
|
if(!model->HICUMzetahjeiGiven)
|
|
model->HICUMzetahjei = 1.0;
|
|
|
|
if(!model->HICUMzetavgbeGiven)
|
|
model->HICUMzetavgbe = 1.0;
|
|
|
|
//Self-Heating
|
|
if(!model->HICUMflshGiven)
|
|
model->HICUMflsh = 0;
|
|
|
|
if(!model->HICUMrthGiven)
|
|
model->HICUMrth = 0.0;
|
|
|
|
if(!model->HICUMzetarthGiven)
|
|
model->HICUMzetarth = 0.0;
|
|
|
|
if(!model->HICUMalrthGiven)
|
|
model->HICUMalrth = 0.0;
|
|
|
|
if(!model->HICUMcthGiven)
|
|
model->HICUMcth = 0.0;
|
|
|
|
if((model->HICUMrthGiven) && (model->HICUMcth < 1e-12))
|
|
model->HICUMcth = 1e-12;
|
|
|
|
//Compatibility with V2.1
|
|
if(!model->HICUMflcompGiven)
|
|
model->HICUMflcomp = 0.0;
|
|
|
|
if(!model->HICUMvbeMaxGiven)
|
|
model->HICUMvbeMax = 1e99;
|
|
|
|
if(!model->HICUMvbcMaxGiven)
|
|
model->HICUMvbcMax = 1e99;
|
|
|
|
if(!model->HICUMvceMaxGiven)
|
|
model->HICUMvceMax = 1e99;
|
|
|
|
int selfheat = (((model->HICUMflsh == 1) || (model->HICUMflsh == 2)) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0));
|
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0));
|
|
|
|
/* loop through all the instances of the model */
|
|
for (here = HICUMinstances(model); here != NULL ;
|
|
here=HICUMnextInstance(here)) {
|
|
CKTnode *tmpNode;
|
|
IFuid tmpName;
|
|
|
|
if(!here->HICUMareaGiven) {
|
|
here->HICUMarea = 1.0;
|
|
}
|
|
if(!here->HICUMmGiven) {
|
|
here->HICUMm = 1.0;
|
|
}
|
|
if(!here->HICUMdtempGiven) {
|
|
here->HICUMdtemp = 0.0;
|
|
}
|
|
|
|
// Warning:
|
|
// The scaling with HICUMm and HICUMarea is done here from model to here variables in order to save memory.
|
|
// Classical spice scaling with "area" is implemented, but it is not recommended to be used. If you want
|
|
// scaling, more sophisticated expressions should be used. Those can be found in modern PDKs or should be
|
|
// provided by modeling engineers.
|
|
// For discrete devices, the multiplication factor "m" should give reasonable results.
|
|
//
|
|
// The HICUMm device multiplicaton factor can be exected to give good results.
|
|
// The following variables need scaling in HICUM:
|
|
// IT : qp0 ~ (area m)**2 qp0 ~ area m icbar ~ area m
|
|
// BE junction: cjei0 ~ area m cjep0 ~ m
|
|
// ibeis ~ area m ibeps ~ m
|
|
// cbepar ~ m -> area scaling not reasonable
|
|
// BC junction: cjci0 ~ area m cjcx0 ~ m
|
|
// ibcis ~ area m ibcxs ~ m
|
|
// ireis ~ area m ireps ~ m
|
|
// cbcpar ~ m -> area scaling not reasonable
|
|
// qavl ~ area m
|
|
// re ~1/(area*m)
|
|
// rci0 ~1/(area*m)
|
|
// rbx ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase
|
|
// rcx ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase
|
|
// rbi0 ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase
|
|
// rth ~1/(area*m) -> bad assumption, but more transistor geometry needs to be known for accurate scaling
|
|
// cth ~ area*m -> bad assumption, but more transistor geometry needs to be known for accurate scaling
|
|
// Substrate related parameters not scaled on purpose. This is very geometry dependent?
|
|
|
|
double area_times_m = here->HICUMm*here->HICUMarea;
|
|
//IT
|
|
here->HICUMqp0_scaled = model->HICUMqp0 * area_times_m;
|
|
here->HICUMc10_scaled = model->HICUMc10 * area_times_m*area_times_m;
|
|
here->HICUMicbar_scaled = model->HICUMicbar * area_times_m;
|
|
here->HICUMrth_scaled = model->HICUMrth / area_times_m; //very poor assumption
|
|
here->HICUMcth_scaled = model->HICUMcth * area_times_m; //very poor assumption
|
|
//BE junction
|
|
here->HICUMcjei0_scaled = model->HICUMcjei0 * area_times_m;
|
|
here->HICUMibeis_scaled = model->HICUMibeis * area_times_m;
|
|
here->HICUMireis_scaled = model->HICUMireis * area_times_m;
|
|
here->HICUMibeps_scaled = model->HICUMibeps * here->HICUMm;
|
|
here->HICUMireps_scaled = model->HICUMireps * here->HICUMm;
|
|
here->HICUMcjep0_scaled = model->HICUMcjep0 * here->HICUMm;
|
|
here->HICUMcbepar_scaled = model->HICUMcbepar * here->HICUMm;
|
|
here->HICUMibets_scaled = model->HICUMibets * area_times_m;
|
|
//BC junction
|
|
here->HICUMibcis_scaled = model->HICUMibcis * area_times_m;
|
|
here->HICUMcjci0_scaled = model->HICUMcjci0 * area_times_m;
|
|
here->HICUMcjcx0_scaled = model->HICUMcjcx0 * here->HICUMm;
|
|
here->HICUMcbcpar_scaled = model->HICUMcbcpar * here->HICUMm;
|
|
here->HICUMibcxs_scaled = model->HICUMibcxs * here->HICUMm;
|
|
here->HICUMqavl_scaled = model->HICUMqavl * area_times_m;
|
|
//resistances
|
|
here->HICUMre_scaled = model->HICUMre / area_times_m;
|
|
here->HICUMrci0_scaled = model->HICUMrci0 / area_times_m;
|
|
here->HICUMrbx_scaled = model->HICUMrbx / area_times_m;
|
|
here->HICUMrcx_scaled = model->HICUMrcx / area_times_m;
|
|
here->HICUMrbi0_scaled = model->HICUMrbi0 / area_times_m;
|
|
//noise
|
|
here->HICUMkf_scaled = model->HICUMkf * pow(here->HICUMm, (1-model->HICUMaf));
|
|
here->HICUMkfre_scaled = model->HICUMkfre * pow(here->HICUMm, (1-model->HICUMafre));
|
|
|
|
here->HICUMstate = *states;
|
|
*states += HICUMnumStates;
|
|
|
|
if(model->HICUMrcx == 0) {
|
|
here->HICUMcollCINode = here->HICUMcollNode;
|
|
} else if(here->HICUMcollCINode == 0) {
|
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname,"collCI");
|
|
if(error) return(error);
|
|
here->HICUMcollCINode = tmp->number;
|
|
if (ckt->CKTcopyNodesets) {
|
|
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) {
|
|
if (tmpNode->nsGiven) {
|
|
tmp->nodeset=tmpNode->nodeset;
|
|
tmp->nsGiven=tmpNode->nsGiven;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(model->HICUMrbx == 0) {
|
|
here->HICUMbaseBPNode = here->HICUMbaseNode;
|
|
} else if(here->HICUMbaseBPNode == 0){
|
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "baseBP");
|
|
if(error) return(error);
|
|
here->HICUMbaseBPNode = tmp->number;
|
|
if (ckt->CKTcopyNodesets) {
|
|
if (CKTinst2Node(ckt,here,2,&tmpNode,&tmpName)==OK) {
|
|
if (tmpNode->nsGiven) {
|
|
tmp->nodeset=tmpNode->nodeset;
|
|
tmp->nsGiven=tmpNode->nsGiven;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(model->HICUMre == 0) {
|
|
here->HICUMemitEINode = here->HICUMemitNode;
|
|
} else if(here->HICUMemitEINode == 0) {
|
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "emitEI");
|
|
if(error) return(error);
|
|
here->HICUMemitEINode = tmp->number;
|
|
if (ckt->CKTcopyNodesets) {
|
|
if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) {
|
|
if (tmpNode->nsGiven) {
|
|
tmp->nodeset=tmpNode->nodeset;
|
|
tmp->nsGiven=tmpNode->nsGiven;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(model->HICUMrsu == 0) {
|
|
here->HICUMsubsSINode = here->HICUMsubsNode;
|
|
} else if(here->HICUMsubsSINode == 0) {
|
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "subsSI");
|
|
if(error) return(error);
|
|
here->HICUMsubsSINode = tmp->number;
|
|
if (ckt->CKTcopyNodesets) {
|
|
if (CKTinst2Node(ckt,here,4,&tmpNode,&tmpName)==OK) {
|
|
if (tmpNode->nsGiven) {
|
|
tmp->nodeset=tmpNode->nodeset;
|
|
tmp->nsGiven=tmpNode->nsGiven;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(model->HICUMrbi0 == 0) {
|
|
here->HICUMbaseBINode = here->HICUMbaseBPNode;
|
|
} else if(here->HICUMbaseBINode == 0) {
|
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "baseBI");
|
|
if(error) return(error);
|
|
here->HICUMbaseBINode = tmp->number;
|
|
if (ckt->CKTcopyNodesets) {
|
|
if (CKTinst2Node(ckt,here,5,&tmpNode,&tmpName)==OK) {
|
|
if (tmpNode->nsGiven) {
|
|
tmp->nodeset=tmpNode->nodeset;
|
|
tmp->nsGiven=tmpNode->nsGiven;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selfheat) {
|
|
if (here->HICUMtempNode == 0) { // no external node for temperature
|
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname,"dT"); // create internal node
|
|
if (error) return(error);
|
|
here->HICUMtempNode = tmp->number;
|
|
}
|
|
} else {
|
|
if (here->HICUMtempNode > 0) { // external temp node is given, but no she parameter
|
|
here->HICUMtempNode = 0;
|
|
}
|
|
}
|
|
|
|
if (nqs) {
|
|
if(here->HICUMxfNode == 0) {
|
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf");
|
|
if(error) return(error);
|
|
here->HICUMxfNode = tmp->number;
|
|
}
|
|
if(here->HICUMxf1Node == 0) {
|
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf1");
|
|
if(error) return(error);
|
|
here->HICUMxf1Node = tmp->number;
|
|
}
|
|
if(here->HICUMxf2Node == 0) {
|
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf2");
|
|
if(error) return(error);
|
|
here->HICUMxf2Node = tmp->number;
|
|
}
|
|
} else {
|
|
here->HICUMxfNode = 0;
|
|
here->HICUMxf1Node = 0;
|
|
here->HICUMxf2Node = 0;
|
|
}
|
|
|
|
/* macro to make elements with built in test for out of memory */
|
|
#define TSTALLOC(ptr,first,second) \
|
|
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|
return(E_NOMEM);\
|
|
} } while(0)
|
|
TSTALLOC(HICUMcollCollPtr,HICUMcollNode,HICUMcollNode);
|
|
TSTALLOC(HICUMbaseBasePtr,HICUMbaseNode,HICUMbaseNode);
|
|
TSTALLOC(HICUMemitEmitPtr,HICUMemitNode,HICUMemitNode);
|
|
TSTALLOC(HICUMsubsSubsPtr,HICUMsubsNode,HICUMsubsNode);
|
|
|
|
TSTALLOC(HICUMcollCICollCIPtr,HICUMcollCINode,HICUMcollCINode);
|
|
TSTALLOC(HICUMbaseBIBaseBIPtr,HICUMbaseBINode,HICUMbaseBINode);
|
|
TSTALLOC(HICUMemitEIEmitEIPtr,HICUMemitEINode,HICUMemitEINode);
|
|
TSTALLOC(HICUMbaseBPBaseBPPtr,HICUMbaseBPNode,HICUMbaseBPNode);
|
|
TSTALLOC(HICUMsubsSISubsSIPtr,HICUMsubsSINode,HICUMsubsSINode);
|
|
|
|
TSTALLOC(HICUMbaseEmitPtr,HICUMbaseNode,HICUMemitNode); //b-e
|
|
TSTALLOC(HICUMemitBasePtr,HICUMemitNode,HICUMbaseNode); //e-b
|
|
|
|
TSTALLOC(HICUMbaseBaseBPPtr,HICUMbaseNode,HICUMbaseBPNode); //b-bp
|
|
TSTALLOC(HICUMbaseBPBasePtr,HICUMbaseBPNode,HICUMbaseNode); //bp-b
|
|
TSTALLOC(HICUMemitEmitEIPtr,HICUMemitNode,HICUMemitEINode); //e-ei
|
|
TSTALLOC(HICUMemitEIEmitPtr,HICUMemitEINode,HICUMemitNode); //ei-e
|
|
|
|
TSTALLOC(HICUMsubsSubsSIPtr,HICUMsubsNode,HICUMsubsSINode); //s-si
|
|
TSTALLOC(HICUMsubsSISubsPtr,HICUMsubsSINode,HICUMsubsNode); //si-s
|
|
|
|
TSTALLOC(HICUMcollCIBasePtr,HICUMcollCINode,HICUMbaseNode); //b-ci
|
|
TSTALLOC(HICUMbaseCollCIPtr,HICUMbaseNode,HICUMcollCINode); //ci-b
|
|
|
|
TSTALLOC(HICUMcollCIEmitEIPtr,HICUMcollCINode,HICUMemitEINode); //ci-ei
|
|
TSTALLOC(HICUMemitEICollCIPtr,HICUMemitEINode,HICUMcollCINode); //ei-ci
|
|
|
|
TSTALLOC(HICUMbaseBPBaseBIPtr,HICUMbaseBPNode,HICUMbaseBINode); //bp-bi
|
|
TSTALLOC(HICUMbaseBIBaseBPPtr,HICUMbaseBINode,HICUMbaseBPNode); //bi-bp
|
|
|
|
TSTALLOC(HICUMbaseBPEmitEIPtr,HICUMbaseBPNode,HICUMemitEINode); //bp-ei
|
|
TSTALLOC(HICUMemitEIBaseBPPtr,HICUMemitEINode,HICUMbaseBPNode); //ei-bp
|
|
|
|
TSTALLOC(HICUMbaseBPEmitPtr,HICUMbaseBPNode,HICUMemitNode); //bp-e
|
|
TSTALLOC(HICUMemitBaseBPPtr,HICUMemitNode,HICUMbaseBPNode); //e-bp
|
|
|
|
TSTALLOC(HICUMbaseBPSubsSIPtr,HICUMbaseBPNode,HICUMsubsSINode); //bp-si
|
|
TSTALLOC(HICUMsubsSIBaseBPPtr,HICUMsubsSINode,HICUMbaseBPNode); //si-bp
|
|
|
|
TSTALLOC(HICUMbaseBIEmitEIPtr,HICUMbaseBINode,HICUMemitEINode); //ei-bi
|
|
TSTALLOC(HICUMemitEIBaseBIPtr,HICUMemitEINode,HICUMbaseBINode); //bi-ei
|
|
if (nqs) {
|
|
TSTALLOC(HICUMbaseBIXfPtr ,HICUMbaseBINode,HICUMxfNode); //bi - xf
|
|
TSTALLOC(HICUMemitEIXfPtr ,HICUMemitEINode,HICUMxfNode); //ei - xf
|
|
}
|
|
|
|
TSTALLOC(HICUMbaseBICollCIPtr,HICUMbaseBINode,HICUMcollCINode); //ci-bi
|
|
TSTALLOC(HICUMcollCIBaseBIPtr,HICUMcollCINode,HICUMbaseBINode); //bi-ci
|
|
|
|
TSTALLOC(HICUMbaseBPCollCIPtr,HICUMbaseBPNode,HICUMcollCINode); //bp-ci
|
|
TSTALLOC(HICUMcollCIBaseBPPtr,HICUMcollCINode,HICUMbaseBPNode); //ci-bp
|
|
|
|
TSTALLOC(HICUMsubsSICollCIPtr,HICUMsubsSINode,HICUMcollCINode); //si-ci
|
|
TSTALLOC(HICUMcollCISubsSIPtr,HICUMcollCINode,HICUMsubsSINode); //ci-si
|
|
|
|
TSTALLOC(HICUMcollCICollPtr,HICUMcollCINode,HICUMcollNode); //ci-c
|
|
TSTALLOC(HICUMcollCollCIPtr,HICUMcollNode,HICUMcollCINode); //c-ci
|
|
|
|
TSTALLOC(HICUMsubsCollPtr,HICUMsubsNode,HICUMcollNode); //s-c
|
|
TSTALLOC(HICUMcollSubsPtr,HICUMcollNode,HICUMsubsNode); //c-s
|
|
|
|
if (nqs) {
|
|
TSTALLOC(HICUMxf1Xf1Ptr ,HICUMxf1Node ,HICUMxf1Node);
|
|
TSTALLOC(HICUMxf1BaseBIPtr,HICUMxf1Node ,HICUMbaseBINode);
|
|
TSTALLOC(HICUMxf1EmitEIPtr,HICUMxf1Node ,HICUMemitEINode);
|
|
TSTALLOC(HICUMxf1CollCIPtr,HICUMxf1Node ,HICUMcollCINode);
|
|
TSTALLOC(HICUMxf1Xf2Ptr ,HICUMxf1Node ,HICUMxf2Node);
|
|
|
|
TSTALLOC(HICUMxf2Xf1Ptr ,HICUMxf2Node ,HICUMxf1Node);
|
|
TSTALLOC(HICUMxf2BaseBIPtr,HICUMxf2Node ,HICUMbaseBINode);
|
|
TSTALLOC(HICUMxf2EmitEIPtr,HICUMxf2Node ,HICUMemitEINode);
|
|
TSTALLOC(HICUMxf2CollCIPtr,HICUMxf2Node ,HICUMcollCINode);
|
|
TSTALLOC(HICUMxf2Xf2Ptr ,HICUMxf2Node ,HICUMxf2Node);
|
|
TSTALLOC(HICUMemitEIXf2Ptr,HICUMemitEINode,HICUMxf2Node);
|
|
TSTALLOC(HICUMcollCIXf2Ptr,HICUMcollCINode,HICUMxf2Node);
|
|
|
|
TSTALLOC(HICUMxfXfPtr ,HICUMxfNode,HICUMxfNode);
|
|
TSTALLOC(HICUMxfEmitEIPtr ,HICUMxfNode,HICUMemitEINode);
|
|
TSTALLOC(HICUMxfCollCIPtr ,HICUMxfNode,HICUMcollCINode);
|
|
TSTALLOC(HICUMxfBaseBIPtr ,HICUMxfNode,HICUMbaseBINode);
|
|
|
|
}
|
|
|
|
TSTALLOC(HICUMbaseBPSubsSIPtr ,HICUMbaseBPNode,HICUMsubsSINode);
|
|
TSTALLOC(HICUMsubsSIBaseBPPtr ,HICUMsubsSINode,HICUMbaseBPNode);
|
|
|
|
if (selfheat) {
|
|
TSTALLOC(HICUMcollTempPtr, HICUMcollNode, HICUMtempNode);
|
|
TSTALLOC(HICUMbaseTempPtr,HICUMbaseNode,HICUMtempNode);
|
|
TSTALLOC(HICUMemitTempPtr,HICUMemitNode,HICUMtempNode);
|
|
|
|
TSTALLOC(HICUMcollCItempPtr,HICUMcollCINode,HICUMtempNode);
|
|
TSTALLOC(HICUMbaseBItempPtr,HICUMbaseBINode,HICUMtempNode);
|
|
TSTALLOC(HICUMbaseBPtempPtr,HICUMbaseBPNode,HICUMtempNode);
|
|
TSTALLOC(HICUMemitEItempPtr,HICUMemitEINode,HICUMtempNode);
|
|
TSTALLOC(HICUMsubsSItempPtr,HICUMsubsSINode,HICUMtempNode);
|
|
TSTALLOC(HICUMsubsTempPtr ,HICUMsubsNode ,HICUMtempNode);
|
|
TSTALLOC(HICUMcollTempPtr ,HICUMcollNode ,HICUMtempNode);
|
|
|
|
TSTALLOC(HICUMtempCollPtr,HICUMtempNode,HICUMcollNode);
|
|
TSTALLOC(HICUMtempBasePtr,HICUMtempNode,HICUMbaseNode);
|
|
TSTALLOC(HICUMtempEmitPtr,HICUMtempNode,HICUMemitNode);
|
|
|
|
TSTALLOC(HICUMtempCollCIPtr,HICUMtempNode,HICUMcollCINode);
|
|
TSTALLOC(HICUMtempBaseBIPtr,HICUMtempNode,HICUMbaseBINode);
|
|
TSTALLOC(HICUMtempBaseBPPtr,HICUMtempNode,HICUMbaseBPNode);
|
|
TSTALLOC(HICUMtempEmitEIPtr,HICUMtempNode,HICUMemitEINode);
|
|
TSTALLOC(HICUMtempSubsSIPtr,HICUMtempNode,HICUMsubsSINode);
|
|
|
|
TSTALLOC(HICUMtempTempPtr,HICUMtempNode,HICUMtempNode);
|
|
|
|
if (nqs) {
|
|
TSTALLOC(HICUMxfTempPtr ,HICUMxfNode,HICUMtempNode);
|
|
TSTALLOC(HICUMxf2TempPtr ,HICUMxf2Node ,HICUMtempNode);
|
|
TSTALLOC(HICUMxf1TempPtr ,HICUMxf1Node ,HICUMtempNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(OK);
|
|
}
|
|
|
|
int
|
|
HICUMunsetup(
|
|
GENmodel *inModel,
|
|
CKTcircuit *ckt)
|
|
{
|
|
HICUMmodel *model;
|
|
HICUMinstance *here;
|
|
|
|
for (model = (HICUMmodel *)inModel; model != NULL;
|
|
model = HICUMnextModel(model))
|
|
{
|
|
int selfheat = (((model->HICUMflsh == 1) || (model->HICUMflsh == 2)) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0));
|
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0));
|
|
|
|
for (here = HICUMinstances(model); here != NULL;
|
|
here=HICUMnextInstance(here))
|
|
{
|
|
if (here->HICUMcollCINode > 0
|
|
&& here->HICUMcollCINode != here->HICUMcollNode)
|
|
CKTdltNNum(ckt, here->HICUMcollCINode);
|
|
here->HICUMcollCINode = 0;
|
|
|
|
if (here->HICUMbaseBINode > 0
|
|
&& here->HICUMbaseBPNode != here->HICUMbaseBINode)
|
|
CKTdltNNum(ckt, here->HICUMbaseBINode);
|
|
here->HICUMbaseBINode = 0;
|
|
|
|
if (here->HICUMbaseBPNode > 0
|
|
&& here->HICUMbaseBPNode != here->HICUMbaseNode)
|
|
CKTdltNNum(ckt, here->HICUMbaseBPNode);
|
|
here->HICUMbaseBPNode = 0;
|
|
|
|
if (here->HICUMemitEINode > 0
|
|
&& here->HICUMemitEINode != here->HICUMemitNode)
|
|
CKTdltNNum(ckt, here->HICUMemitEINode);
|
|
here->HICUMemitEINode = 0;
|
|
|
|
if (here->HICUMsubsSINode > 0
|
|
&& here->HICUMsubsSINode != here->HICUMsubsNode)
|
|
CKTdltNNum(ckt, here->HICUMsubsSINode);
|
|
here->HICUMsubsSINode = 0;
|
|
|
|
if (selfheat) {
|
|
if (here->HICUMtempNode > 6) { // it is an internal node
|
|
CKTdltNNum(ckt, here->HICUMtempNode);
|
|
here->HICUMtempNode = 0;
|
|
}
|
|
}
|
|
|
|
if (nqs) {
|
|
|
|
if(here->HICUMxfNode > 0)
|
|
CKTdltNNum(ckt, here->HICUMxfNode);
|
|
here->HICUMxfNode = 0;
|
|
|
|
if(here->HICUMxf1Node > 0)
|
|
CKTdltNNum(ckt, here->HICUMxf1Node);
|
|
here->HICUMxf1Node = 0;
|
|
|
|
if(here->HICUMxf2Node > 0)
|
|
CKTdltNNum(ckt, here->HICUMxf2Node);
|
|
here->HICUMxf2Node = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
int
|
|
HICUMmDelete(GENmodel* gen_model)
|
|
{
|
|
HICUMmodel* model = (HICUMmodel*)gen_model;
|
|
|
|
FREE(model->HICUMversion);
|
|
|
|
return OK;
|
|
}
|