//======================================================================================
//======================================================================================
// Filename: JUNCAP200_macrodefs.include
//======================================================================================
//======================================================================================
//
//  (c) Copyright 2007, All Rights Reserved, NXP Semiconductors
//
//
//  Version: 102.1 (PSP), 200.2 (JUNCAP), April 2007 (Simkit 2.5)
//
//======================================================================================
//======================================================================================
//
// Further information can be found in the file readme.txt
//

///////////////////////////////////////////
//
// Macros and constants used in JUNCAP2 
//
///////////////////////////////////////////

// Other constants
`define MINTEMP          -250                               
`define vbilow            0.050                             
`define a                 2                                 
`define epsch             0.1
`define dvbi              0.050                               
`define epsav             1E-6                              
`define vbrmax            1000                              
`define alphaav           0.999                             
`define vmaxlarge         1E8
`define aerfc             0.29214664
`define twothirds         0.666666666666667


// Clipping values
`define levelnumber        200
`define AB_cliplow         0
`define LS_cliplow         0
`define LG_cliplow         0
`define MULT_cliplow       0
`define TRJ_cliplow        `MINTEMP
`define IMAX_cliplow       1E-12
`define CJORBOT_cliplow    1E-12
`define CJORSTI_cliplow    1E-18    
`define CJORGAT_cliplow    1E-18    
`define VBIR_cliplow       `vbilow
`define P_cliplow          0.05
`define P_cliphigh         0.95
`define IDSATR_cliplow     0
`define CSRH_cliplow       0
`define XJUN_cliplow       1E-9
`define CTAT_cliplow       0
`define MEFFTAT_cliplow    0.01
`define CBBT_cliplow       0
`define VBR_cliplow        0.1
`define PBR_cliplow        0.1


/////////////////////////////////////////////////////////////////////////////
//
//  Macro definitions.
//
//  Note that because at present locally scoped variables
//  can only be in named blocks, the intermediate variables
//  used in the macros below must be explicitly declared
//  as variables.
//
/////////////////////////////////////////////////////////////////////////////

// Instance parameter dependent initialization

`define JuncapInitInstance(AB_i, LS_i, LG_i, VMAX, vbimin, vch, vfmin, vbbtlim) \
if (idsatbot * AB_i > 0) begin \
    vmaxbot = phitd * ln(IMAX_i / (idsatbot * AB_i) + 1); \
end else begin \
    vmaxbot = `vmaxlarge; \
end \
if (idsatsti * LS_i > 0) begin \
    vmaxsti = phitd * ln(IMAX_i / (idsatsti * LS_i) + 1);  \
end else begin \
    vmaxsti = `vmaxlarge; \
end \
if (idsatgat * LG_i > 0) begin \
    vmaxgat = phitd * ln(IMAX_i / (idsatgat * LG_i) + 1); \
end else begin \
    vmaxgat = `vmaxlarge; \
end \
VMAX = min(min(vmaxbot, vmaxsti), vmaxgat); \
 \
/* determination of minimum value of the relevant built-in voltages */ \
vbibot2 = vbibot; \
vbisti2 = vbisti; \
vbigat2 = vbigat; \
if (AB_i == 0) begin vbibot2 = vbisti + vbigat; end \
if (LS_i == 0) begin vbisti2 = vbibot + vbigat; end \
if (LG_i == 0) begin vbigat2 = vbibot + vbisti; end \
vbimin = min(min(vbibot2, vbisti2), vbigat2); \
vch = vbimin * `epsch; \
if (vbimin == vbibot) begin vfmin = vbibot * (1 - (pow(`a, (-1.0 / PBOT_i)))); end \
if (vbimin == vbisti) begin vfmin = vbisti * (1 - (pow(`a, (-1.0 / PSTI_i)))); end \
if (vbimin == vbigat) begin vfmin = vbigat * (1 - (pow(`a, (-1.0 / PGAT_i)))); end \
 \
/* determination of limiting value of conditioned voltage for BBT calculation */ \
vbibot2r = VBIRBOT_i; \
vbisti2r = VBIRSTI_i; \
vbigat2r = VBIRGAT_i; \
if (AB_i == 0) begin vbibot2r = VBIRSTI_i + VBIRGAT_i; end \
if (LS_i == 0) begin vbisti2r = VBIRBOT_i + VBIRGAT_i; end \
if (LG_i == 0) begin vbigat2r = VBIRBOT_i + VBIRSTI_i; end \
vbbtlim = min(min(vbibot2r, vbisti2r), vbigat2r) - `dvbi; \


// Special power-functions

`define mypower(x,power,result) \
if (power == 0.5) begin \
    result = sqrt(x); \
end else begin \
    result = pow(x, power); \
end

`define mypower2(x,power,result) \
if (power == -1) begin \
    result = 1 / (x); \
end else begin \
    result = pow(x, power); \
end

`define mypower3(x,power,result) \
if (power == 4) begin \
    result = (x) * (x) * (x) * (x); \
end else begin \
    result = pow(x, power); \
end


// Smoothing functions

`define hypfunction2(x,x0,eps,hyp2) \
hyp2 = 0.5 * ((x) + (x0) - sqrt(((x) - (x0)) * ((x) - (x0)) + 4 * (eps) * (eps))); 

`define hypfunction5(x,x0,eps,hyp5) \
h1   = 4.0 * (eps) * (eps); \
h2   = (eps) / (x0); \
h2d  = (x) + (eps) * h2; \
h3   = (x0) + h2d; \
h4   = (x0) - h2d; \
h5   = sqrt(h4 * h4 + h1); \
hyp5 = 2.0 * ((x) * (x0) / (h3 + h5)); 


// A special function used to calculate TAT-currents,
// including an approximation of the erfc-function

`define calcerfcexpmtat(y,m,result) \
ysq = y * y; \
if (y > 0) begin \
    terfc = 1 / (1 + perfc * y); \
end else begin \
    terfc = 1 / (1 - perfc * y); \
end \
`expl_low(-ysq + m, tmp) \
erfcpos = (`aerfc * terfc + berfc * (terfc * terfc) + cerfc * (terfc * terfc * terfc)) * tmp; \
if (y > 0) begin \
    result = erfcpos; \
end else begin\
    `expl_low(m, tmp) \
    result = 2 * tmp - erfcpos; \
end


// This is the main function of the JUNCAP2-model. It returns the current and charge
// for a single diode

`define juncapfunction(qpref,qpref2,vbiinv,one_minus_P,idsat,CSRH,CTAT,vbi,wdepnulr,VBIRinv,P,ftd,btatpart,atat,one_over_one_minus_P,CBBT,VBIR,wdepnulrinv,fbbt,VBR,VBRinv,PBR,fstop,slope,Ijprime,Qjprime) \
`mypower((1 - vj * vbiinv), one_minus_P, tmp) \
Qjprime = qpref * (1 - tmp) + qpref2 * (VAK - vj); \
id    = idsat * idmult; \
if ((CSRH == 0) && (CTAT == 0)) begin \
    isrh = 0; \
end else begin \
    vbi_minus_vjsrh = vbi-vjsrh; \
    wsrhstep = 1 - sqrt(1 - two_psistar / vbi_minus_vjsrh); \
    if (P == 0.5) begin \
        dwsrh = 0; \
    end else begin \
        dwsrh = ((wsrhstep * wsrhstep * ln(wsrhstep) / (1 - wsrhstep)) + wsrhstep) * (1 - 2 * P); \
    end \
    wsrh  = wsrhstep + dwsrh; \
    `mypower(vbi_minus_vjsrh * VBIRinv, P, tmp) \
    wdep  = wdepnulr * tmp; \
    asrh  = ftd * ((zinv - 1) * wdep); \
    isrh  = CSRH * (asrh * wsrh); \
end \
if (CTAT == 0) begin \
    itat = 0; \
end else begin \
    btat  = btatpart * ((wdep * one_minus_P) / vbi_minus_vjsrh); \
    twoatatoverthreebtat = (`twothirds * atat) / btat; \
    umaxbeforelimiting = twoatatoverthreebtat * twoatatoverthreebtat; \
    umax  = sqrt(umaxbeforelimiting * umaxbeforelimiting / (umaxbeforelimiting * umaxbeforelimiting + 1)); \
    sqrtumax = sqrt(abs(umax)); \
    umaxpoweronepointfive = umax * sqrtumax; \
    `mypower2((1 + btat * umaxpoweronepointfive), (-P * one_over_one_minus_P), wgamma) \
    wtat  = wsrh * wgamma / (wsrh + wgamma); \
    ktat  = sqrt(0.375 * (btat / sqrtumax)); \
    ltat  = 2 * (twoatatoverthreebtat * sqrtumax) - umax; \
    mtat  = atat * twoatatoverthreebtat * sqrtumax - atat * umax + 0.5 * (btat * umaxpoweronepointfive); \
    xerfc = (ltat - 1) * ktat; \
    `calcerfcexpmtat(xerfc, mtat, erfctimesexpmtat) \
    gammamax = `SQRTPI * 0.5 * (atat * erfctimesexpmtat  / ktat); \
    itat  = CTAT * (asrh * gammamax * wtat); \
end \
if (CBBT == 0) begin \
   ibbt = 0; \
end else begin \
   `mypower(((VBIR - vbbt) * VBIRinv), P, tmp) \
   Fmaxr = one_over_one_minus_P * ((VBIR - vbbt) * wdepnulrinv / tmp); \
   `expl(-fbbt / Fmaxr, tmp) \
   ibbt  = CBBT * (VAK * Fmaxr * Fmaxr * tmp); \
end \
if (VBR > `vbrmax) begin \
   fbreakdown = 1; \
end else begin \
   if (vav > -`alphaav * VBR) begin \
      `mypower3(abs(vav * VBRinv), PBR, tmp) \
      fbreakdown = 1 / (1 - tmp); \
   end else begin \
      fbreakdown = fstop + (vav + `alphaav * VBR) * slope; \
   end \
end \
Ijprime = (id + isrh + itat + ibbt) * fbreakdown; 


// The following code is written as a macro because the naming of the instance parameters is
// different for JUNCAP2 stand-alone and JUNCAP2-in-PSP: AB, LS, LG for JUNCAP2 stand-alone,
// ABSOURCE, LSSOURCE, LGSOURCE for source junction in PSP and ABDRAIN, LSDRAIN, LGDRAIN for
// drain junction in PSP

`define juncapcommon(AB_i,LS_i,LG_i,ijunbot,qjunbot,ijunsti,qjunsti,ijungat,qjungat) \
vbbt = 0.0; \
two_psistar = 0.0; \
if ( !( ((AB_i) == 0) && ((LS_i) == 0) && ((LG_i) == 0) ) ) begin \
    `hypfunction5(VAK, vfmin, vch, vj) \
    if (VAK < VMAX)  begin \
        `expl(0.5 * (VAK * phitdinv), zinv) \
        idmult = zinv * zinv; \
    end else begin \
        `expl(VMAX * phitdinv, exp_VMAX_over_phitd) \
        idmult = (1 + (VAK - VMAX) * phitdinv) * exp_VMAX_over_phitd; \
        zinv   = sqrt(idmult); \
    end \
    idmult = idmult - 1.0; \
    z      = 1 / zinv; \
    if (VAK > 0) begin \
        two_psistar = 2.0 * (phitd * ln(2.0 + z + sqrt((z + 1.0) * (z + 3.0)))); \
    end else begin \
        two_psistar = -VAK + 2.0 * (phitd * ln(2 * zinv + 1 + sqrt((1 + zinv) * (1 + 3 * zinv)))); \
    end \
    vjlim = vbimin - two_psistar; \
    `hypfunction2(VAK, vjlim, phitd, vjsrh) \
    `hypfunction2(VAK, vbbtlim, phitr, vbbt) \
    `hypfunction2(VAK, 0, `epsav, vav) \
end \
if ((AB_i) == 0) begin \
    ijunbot = 0; \
    qjunbot = 0; \
end else begin \
    `juncapfunction(qprefbot,qpref2bot,vbiinvbot,one_minus_PBOT,idsatbot,CSRHBOT_i,CTATBOT_i,vbibot,wdepnulrbot,VBIRBOTinv,PBOT_i,ftdbot,btatpartbot,atatbot,one_over_one_minus_PBOT,CBBTBOT_i,VBIRBOT_i,wdepnulrinvbot,fbbtbot,VBRBOT_i,VBRinvbot,PBRBOT_i,fstopbot,slopebot,ijunbot, qjunbot) \
end \
if ((LS_i) == 0) begin \
    ijunsti = 0; \
    qjunsti = 0; \
end else begin \
   `juncapfunction(qprefsti,qpref2sti,vbiinvsti,one_minus_PSTI,idsatsti,CSRHSTI_i,CTATSTI_i,vbisti,wdepnulrsti,VBIRSTIinv,PSTI_i,ftdsti,btatpartsti,atatsti,one_over_one_minus_PSTI,CBBTSTI_i,VBIRSTI_i,wdepnulrinvsti,fbbtsti,VBRSTI_i,VBRinvsti,PBRSTI_i,fstopsti,slopesti,ijunsti, qjunsti) \
end \
if ((LG_i) == 0) begin \
    ijungat = 0; \
    qjungat = 0; \
end else begin \
    `juncapfunction(qprefgat,qpref2gat,vbiinvgat,one_minus_PGAT,idsatgat,CSRHGAT_i,CTATGAT_i,vbigat,wdepnulrgat,VBIRGATinv,PGAT_i,ftdgat,btatpartgat,atatgat,one_over_one_minus_PGAT,CBBTGAT_i,VBIRGAT_i,wdepnulrinvgat,fbbtgat,VBRGAT_i,VBRinvgat,PBRGAT_i,fstopgat,slopegat,ijungat, qjungat) \
end
