// Model generated by Verilog-A Distiller.
// (c)2026 Arpad Buermen. All rights reserved.
// SPDX-License-Identifier: AGPL-3.0-or-later
// 
// SPICE flavour: ngspice
// Version      : ngspice-45-116-gf11f4594e
// Origin       : https://sourceforge.net/u/arpadbuermen/ngspice/ci/vadng-pre-46/tree/
// Date         : 2026-02-02 07:38:10 UTC
// Module name  : sp_diode
// Model variant: sn
// 
// Notes:
//   Parameter m was replaced with builtin Verilog-A parameter $mfactor.
//
//   All parameters and output variables refer to a single parallel instance,
//   even if $mfactor>1.
//
//   Parameter off was removed. Bypassing is not available in Verilog-A. 
//   
//   Model parameters area, pj, lm, lp, wm, and wp were renamed to 
//   model_area, model_pj, model_lm, model_lp, model_wm, and model_wp 
//   due to name conflicts with instance parameters. 
//   
//   Parameter ic was removed. Initial conditions should be set via the 
//   simulator's initial conditions mechanism. 
//   
//   Instance parameter thermal and model parameters rth0 and cth0 were 
//   removed because the model does not support self-heating. 
//   
//   Output variable alias c was removed due to a conflict with a 
//   terminal name.
//
//   Simplified noise model used (ignores capacitive current).
//   Appropriate only for small-signal noise analysis.
//
// SPICE variable mapping
//   scale -> $simparam("scale", 1)
//
// CKTcircuit member mapping
//    CKTepsmin -> ('epsmin', '$simparam("epsmin", 1e-28)')
//      CKTgmin -> ('gmin', '$simparam("gmin", 1e-12)')
//   CKTnomTemp -> ('tnom', '($simparam("tnom", 27)+273.15)')
//    CKTreltol -> ('reltol', '$simparam("reltol", 1e-3)', 'const')
//      CKTtemp -> (None, '$temperature')
//
// Source files and copyright information:
//   dio/diodefs.h
//   dio/dio.c
//   dio/dioparam.c
//   dio/diompar.c
//   dio/dioask.c
//   dio/diomask.c
//     Copyright 1990 Regents of the University of California.  All rights reserved.
//     Author: 1985 Thomas L. Quarles
//     Modified by Paolo Nenzi 2003 and Dietmar Warning 2012
//   dio/diosetup.c
//   dio/diotemp.c
//   dio/dioload.c
//     Copyright 1990 Regents of the University of California.  All rights reserved.
//     Author: 1985 Thomas L. Quarles
//     Modified: 2000 AlansFixes
//     Modified by Paolo Nenzi 2003 and Dietmar Warning 2012
//   dio/dionoise.c
//     Copyright 1990 Regents of the University of California.  All rights reserved.
//     Author: 1987 Gary W. Ng
//     Modified by Dietmar Warning 2003

`include "constants.vams"
`include "disciplines.vams"

module sp_diode(a, c);
  inout a, c;
  electrical a, c, a_int, sw_int;

  // Instance parameters
  (* desc = "Instance temperature", type = "instance" *) parameter real temp = 0;
  (* desc = "Instance delta temperature", type = "instance" *) parameter real dtemp = 0.0;
  (* desc = "Area factor", type = "instance" *) parameter real area = 0;
  (* desc = "Perimeter factor", type = "instance" *) parameter real pj = 0;
  aliasparam perim = pj;
  (* desc = "Diode width", type = "instance" *) parameter real w = 0;
  (* desc = "Diode length", type = "instance" *) parameter real l = 0;
  (* desc = "Length of metal capacitor (level=3)", type = "instance" *) parameter real lm = 0;
  (* desc = "Length of polysilicon capacitor (level=3)", type = "instance" *) parameter real lp = 0;
  (* desc = "Width of metal capacitor (level=3)", type = "instance" *) parameter real wm = 0;
  (* desc = "Width of polysilicon capacitor (level=3)", type = "instance" *) parameter real wp = 0;

  // Model parameters
  (* desc = "Diode level selector" *) parameter integer level = 1;
  (* desc = "Saturation current" *) parameter real is = 1e-14;
  aliasparam js = is;
  (* desc = "Sidewall Saturation current" *) parameter real jsw = 0.0;
  aliasparam isw = jsw;
  (* desc = "Parameter measurement temperature" *) parameter real tnom = 0;
  aliasparam tref = tnom;
  (* desc = "Ohmic resistance" *) parameter real rs = 0;
  (* desc = "Ohmic resistance sidewall" *) parameter real rsw = 0;
  (* desc = "Ohmic resistance 1st order temp. coeff." *) parameter real trs = 0.0;
  aliasparam trs1 = trs;
  (* desc = "Ohmic resistance 2nd order temp. coeff." *) parameter real trs2 = 0.0;
  (* desc = "Emission Coefficient" *) parameter real n = 1;
  (* desc = "Sidewall emission Coefficient" *) parameter real ns = 1;
  (* desc = "Transit Time" *) parameter real tt = 0;
  (* desc = "Transit Time 1st order temp. coeff." *) parameter real ttt1 = 0.0;
  (* desc = "Transit Time 2nd order temp. coeff." *) parameter real ttt2 = 0.0;
  (* desc = "Junction capacitance" *) parameter real cjo = 0.0;
  aliasparam cj0 = cjo;
  aliasparam cj = cjo;
  (* desc = "Junction potential" *) parameter real vj = 1;
  aliasparam pb = vj;
  (* desc = "Grading coefficient" *) parameter real m = 0.5;
  aliasparam mj = m;
  (* desc = "Grading coefficient 1st temp. coeff." *) parameter real tm1 = 0.0;
  (* desc = "Grading coefficient 2nd temp. coeff." *) parameter real tm2 = 0.0;
  (* desc = "Sidewall junction capacitance" *) parameter real cjp = 0;
  aliasparam cjsw = cjp;
  (* desc = "Sidewall junction potential" *) parameter real php = 1;
  aliasparam vjsw = php;
  (* desc = "Sidewall Grading coefficient" *) parameter real mjsw = 0.33;
  (* desc = "Forward Knee current" *) parameter real ikf = 0;
  aliasparam ik = ikf;
  (* desc = "Reverse Knee current" *) parameter real ikr = 0;
  (* desc = "Forward Sw Knee current" *) parameter real ikp = 0;
  (* desc = "Breakdown Emission Coefficient" *) parameter real nbv = 0;
  aliasparam nz = nbv;
  (* desc = "Area factor" *) parameter real model_area = 1.0;
  (* desc = "Perimeter factor" *) parameter real model_pj = 0.0;
  (* desc = "Diode temperature equation selector" *) parameter integer tlev = 0;
  (* desc = "Diode temperature equation selector" *) parameter integer tlevc = 0;
  (* desc = "Activation energy" *) parameter real eg = 0;
  (* desc = "First bandgap correction factor" *) parameter real gap1 = 0.000702;
  (* desc = "Second bandgap correction factor" *) parameter real gap2 = 1108.0;
  (* desc = "Saturation current temperature exp." *) parameter real xti = 3;
  (* desc = "Area junction temperature coefficient" *) parameter real cta = 0.0;
  aliasparam ctc = cta;
  (* desc = "Perimeter junction capacitance temperature coefficient" *) parameter real ctp = 0.0;
  (* desc = "Area junction potential temperature coefficient" *) parameter real tpb = 0.0;
  aliasparam tvj = tpb;
  (* desc = "Perimeter junction potential temperature coefficient" *) parameter real tphp = 0.0;
  (* desc = "Tunneling saturation current" *) parameter real jtun = 0.0;
  (* desc = "Tunneling sidewall saturation current" *) parameter real jtunsw = 0.0;
  (* desc = "Tunneling emission coefficient" *) parameter real ntun = 30.0;
  (* desc = "Tunneling saturation current exponential" *) parameter real xtitun = 3.0;
  (* desc = "EG correction factor for tunneling" *) parameter real keg = 1.0;
  (* desc = "flicker noise coefficient" *) parameter real kf = 0.0;
  (* desc = "flicker noise exponent" *) parameter real af = 1.0;
  (* desc = "Forward bias junction fit parameter" *) parameter real fc = 0.5;
  (* desc = "Forward bias sidewall junction fit parameter" *) parameter real fcs = 0.5;
  (* desc = "Reverse breakdown voltage" *) parameter real bv = 0;
  aliasparam vb = bv;
  aliasparam vrb = bv;
  aliasparam var = bv;
  (* desc = "Current at reverse breakdown voltage" *) parameter real ibv = 0.001;
  aliasparam ib = ibv;
  (* desc = "Reverse breakdown voltage temperature coefficient" *) parameter real tcv = 0.0;
  aliasparam tbv1 = tcv;
  (* desc = "Recombination saturation current" *) parameter real isr = 1e-14;
  (* desc = "Recombination current emission coefficient" *) parameter real nr = 2;
  (* desc = "maximum voltage in forward direction" *) parameter real fv_max = 1e+99;
  (* desc = "maximum voltage in reverse direction" *) parameter real bv_max = 1e+99;
  (* desc = "maximum current" *) parameter real id_max = 1e+99;
  (* desc = "temperature" *) parameter real te_max = 1e+99;
  (* desc = "maximum power dissipation" *) parameter real pd_max = 1e+99;
  (* desc = "Length of metal capacitor (level=3)" *) parameter real model_lm = 0.0;
  (* desc = "Length of polysilicon capacitor (level=3)" *) parameter real model_lp = 0.0;
  (* desc = "Width of metal capacitor (level=3)" *) parameter real model_wm = 0.0;
  (* desc = "Width of polysilicon capacitor (level=3)" *) parameter real model_wp = 0.0;
  (* desc = "Thickness of the metal to bulk oxide (level=3)" *) parameter real xom = 10000.0;
  (* desc = "Thickness of the polysilicon to bulk oxide (level=3)" *) parameter real xoi = 10000.0;
  (* desc = "Masking and etching effects in metal (level=3)" *) parameter real xm = 0.0;
  (* desc = "Masking and etching effects in polysilicon (level=3)" *) parameter real xp = 0.0;
  (* desc = "Masking and etching effects (level=3)" *) parameter real xw = 0.0;

  // Instance output variables
  (* desc = "Diode voltage" *) real vd;
  (* desc = "Diode conductance" *) real gd;
  (* desc = "Diode capacitance" *) real cd;
  (* desc = "Diode capacitor charge" *) real charge;

  // Model output variables
  (* desc = "Ohmic conductance" *) real cond;

  // Instance fields
  integer DIOtempNode = 0;
  real DIOcap = 0;
  real DIOcapSW = 0;
  real i_DIOarea = 0;
  real i_DIOpj = 0;
  real DIOtemp = 0;
  real DIOtJctPot = 0;
  real DIOtJctCap = 0;
  real DIOtJctSWPot = 0;
  real DIOtJctSWCap = 0;
  real DIOtTransitTime = 0;
  real DIOtGradingCoeff = 0;
  real DIOtConductance = 0;
  real DIOtConductanceSW = 0;
  real DIOtDepCap = 0;
  real DIOtDepSWCap = 0;
  real DIOtSatCur = 0;
  real DIOtSatSWCur = 0;
  real DIOtTunSatCur = 0;
  real DIOtTunSatSWCur = 0;
  real DIOtVcrit = 0;
  real DIOtVcritSW = 0;
  real DIOtF1 = 0;
  real DIOtBrkdwnV = 0;
  real DIOtF2 = 0;
  real DIOtF3 = 0;
  real DIOtF2SW = 0;
  real DIOtF3SW = 0;
  real i_DIOforwardKneeCurrent = 0;
  real i_DIOreverseKneeCurrent = 0;
  real i_DIOforwardSWKneeCurrent = 0;
  real i_DIOjunctionCap = 0;
  real i_DIOjunctionSWCap = 0;
  real DIOtRecSatCur = 0;
  real DIOdIth_dVrssw = 0;
  real DIOgcTt = 0;
  real DIOcmetal = 0;
  real DIOcpoly = 0;
  real DIOdcCurrent = 0;
  integer DIOtempGiven = 0;

  // Model fields
  real DIOsatCur = 0;
  real DIOconductance = 0;
  real DIOconductanceSW = 0;
  real DIObrkdEmissionCoeff = 0;
  real DIOactivationEnergy = 0;
  real DIOnomTemp = 0;
  real DIOmetalOxideThick = 0;
  real DIOpolyOxideThick = 0;
  integer DIOnomTempGiven = 0;
  integer DIOforwardKneeCurrentGiven = 0;
  integer DIOreverseKneeCurrentGiven = 0;
  integer DIOforwardSWKneeCurrentGiven = 0;
  integer DIOmetalOxideThickGiven = 0;
  integer DIOpolyOxideThickGiven = 0;

  // States
  real DIOvoltage = 0;
  real DIOcurrent = 0;
  real DIOconduct = 0;
  real DIOvoltageSW = 0;
  real DIOcurrentSW = 0;
  real DIOconductSW = 0;
  real DIOcapCharge = 0;
  real DIOcapCurrent = 0;
  real DIOcapChargeSW = 0;
  real DIOcapCurrentSW = 0;

  // Model parameter access locals

  // Instance parameter access locals

  // Device setup locals
  real scale = 0;
  real setup_wm = 0;
  real setup_lm = 0;
  real setup_wp = 0;
  real setup_lp = 0;

  // Device temperature dependence locals
  real xfc = 0;
  real xfcs = 0;
  real vt = 0;
  real vte = 0;
  real vts = 0;
  real vtt = 0;
  real vtr = 0;
  real cbv = 0;
  real xbv = 0;
  real xcbv = 0;
  real tol = 0;
  real vtnom = 0;
  integer iter = 0;
  real dt = 0;
  real factor = 0;
  real tBreakdownVoltage = 0;
  real totalSatCur = 0;
  real egfet1 = 0;
  real arg1 = 0;
  real fact1 = 0;
  real pbfact1 = 0;
  real pbo = 0;
  real gmaold = 0;
  real pboSW = 0;
  real gmaSWold = 0;
  real fact2 = 0;
  real pbfact = 0;
  real arg = 0;
  real egfet = 0;
  real gmanew = 0;
  real gmaSWnew = 0;
  real arg2 = 0;
  real lnTRatio = 0;
  real arg0 = 0;

  // Device load locals
  integer limited = 0;
  real load_arg = 0;
  real argsw = 0;
  real capd = 0;
  real capdsw = 0;
  real load_cd = 0;
  real cdb = 0;
  real cdsw = 0;
  real cdeq = 0;
  real ceq = 0;
  real csat = 0;
  real csatsw = 0;
  real czero = 0;
  real czof2 = 0;
  real argSW = 0;
  real czeroSW = 0;
  real czof2SW = 0;
  real sargSW = 0;
  real sqrt_ikx = 0;
  real delvd = 0;
  real delvdsw = 0;
  real evd = 0;
  real evrev = 0;
  real load_gd = 0;
  real gdb = 0;
  real gdsw = 0;
  real gen_fac = 0;
  real gen_fac_vd = 0;
  real t1 = 0;
  real evd_rec = 0;
  real cdb_rec = 0;
  real gdb_rec = 0;
  real geq = 0;
  real gspr = 0;
  real gsprsw = 0;
  real sarg = 0;
  real load_vd = 0;
  real vdsw = 0;
  real vdtemp = 0;
  real load_vt = 0;
  real load_vte = 0;
  real vtesw = 0;
  real vtetun = 0;
  real vtebrk = 0;
  real vterec = 0;
  real diffcharge = 0;
  real deplcharge = 0;
  real deplchargeSW = 0;
  real diffcap = 0;
  real deplcap = 0;
  real deplcapSW = 0;
  real delTemp = 0;
  real Temp = 0;
  real ceqqth = 0;
  real Ith = 0;
  real gcTt = 0;
  real vrs = 0;
  real vrssw = 0;
  real dIth_dVdio = 0;
  real dIth_dVrs = 0;
  real dIth_dVdioSw = 0;
  real dIth_dVrssw = 0;
  real vds = 0;
  real ikf_area_m = 0;
  real ikr_area_m = 0;
  real ikp_peri_m = 0;
  real vdx = 0;
  real cdeqsw = 0;

  // Device noise locals
  real noise_dtemp = 0;

  // Global constants
  real CONSTroot2 = sqrt(2.0);
  real CONSTvt0 = 1.38064852e-23*(27+273.15)/1.6021766208e-19;
  real CONSTKoverQ = 1.38064852e-23/1.6021766208e-19;
  real CONSTe = exp(1.0);
  real VACONSTcharge = 1.6021766208e-19;
  real VACONSTboltz = 1.38064852e-23;
  real epsmin = $simparam("epsmin", 1e-28);
  real VACONST_tnom = ($simparam("tnom", 27)+273.15);
  real reltol = $simparam("reltol", 1e-3);
  real cpscale = $simparam("scale", 1);

  // Evaluation constants
  real gmin = 0;

  // Translated function definitions

  // Verbatim analog functions
  analog function integer initialize_limiting;
    integer il;
    begin
      il = $simparam("iniLim", -1);
      if (il<0) begin
        // iniLim not available, use heuristics
        initialize_limiting = 
          $simparam("iteration", 10)==1 && 
          (analysis("dc") || analysis("static")) && 
          analysis("nodeset");
      end else begin
        initialize_limiting = il;
      end
    end
  endfunction

  analog function real DEVlimitOldGet;
    input vnew, vold;
    real vnew, vold, result;
    begin
      DEVlimitOldGet = vold;
    end
  endfunction

  analog function real DEVlimitNewSet;
    input vnew, vold, new_value, limited;
    real vnew, vold, new_value;
    integer limited;
    begin
      DEVlimitNewSet = new_value;
      if (limited) begin
        $discontinuity(-1);
      end
    end
  endfunction

  analog function real DEVpnjlim;
    input vnew, vold, vt, vcrit;
    inout limiting_applied;
    real vnew, vold, vt, vcrit, limited, arg;
    integer limiting_applied;
    
    begin
      limited = vnew;
      if ((vnew > vcrit) && (abs(vnew - vold) > (vt + vt))) begin
        // Positive vnew above vcrit, change greater than 2*vt
        if(vold > 0) begin
          arg = (vnew - vold) / vt;
          if(arg > 0) begin
            limited = vold + vt * (2+ln(arg-2));
            limiting_applied = 1;
          end else begin
            limited = vold - vt * (2+ln(2-arg));
            limiting_applied = 1;
          end
        end else begin
          limited = vt *ln(vnew/vt);
          limiting_applied = 1;
        end
      end else if (vnew<0) begin
        // Negative vnew, use ngspice limiting
        if (vold > 0) begin
          arg = -1*vold-1; 
        end else begin
          arg = 2*vold-1;
        end
        if (vnew<arg) begin
          limited = arg;
          limiting_applied = 1;
        end
      end 
      DEVpnjlim = limited;
    end
  endfunction

  // Analog block
  analog begin

    // Instance field assignments
    if ($param_given(temp)) begin
      DIOtemp = temp+273.15;
      DIOtempGiven = 1;
    end
    if ($param_given(area)) begin
      i_DIOarea = area;
    end
    if ($param_given(pj)) begin
      i_DIOpj = pj;
    end

    // Model field assignments
    if ($param_given(is)) begin
      DIOsatCur = is;
    end
    if ($param_given(tnom)) begin
      DIOnomTemp = tnom+273.15;
      DIOnomTempGiven = 1;
    end
    if ($param_given(nbv)) begin
      DIObrkdEmissionCoeff = nbv;
    end
    if ($param_given(eg)) begin
      DIOactivationEnergy = eg;
    end
    if ($param_given(xom)) begin
      DIOmetalOxideThick = xom*1e-10;
      DIOmetalOxideThickGiven = 1;
    end
    if ($param_given(xoi)) begin
      DIOpolyOxideThick = xoi*1e-10;
      DIOpolyOxideThickGiven = 1;
    end

    // Evaluation constants
    gmin = $simparam("gmin", 1e-12);

    // Tag: setup, function: DIOsetup
    scale = cpscale;
    if (!$param_given(is)) begin
      DIOsatCur = 1e-14;
    end
    if (DIOforwardKneeCurrentGiven) begin
      if (ikf<epsmin) begin
        DIOforwardKneeCurrentGiven = 0;
        $warning("IKF too small - model effect disabled!");
      end
    end
    if (DIOreverseKneeCurrentGiven) begin
      if (ikr<epsmin) begin
        DIOreverseKneeCurrentGiven = 0;
        $warning("IKR too small - model effect disabled!");
      end
    end
    if (DIOforwardSWKneeCurrentGiven) begin
      if (ikp<epsmin) begin
        DIOforwardSWKneeCurrentGiven = 0;
        $warning("IKP too small - model effect disabled!");
      end
    end
    if (!$param_given(nbv)) begin
      DIObrkdEmissionCoeff = n;
    end
    if (!$param_given(eg)) begin
      if (tlev==2) begin
        DIOactivationEnergy = 1.16;
      end else begin
        DIOactivationEnergy = 1.11;
      end
    end
    if (DIOsatCur<epsmin) begin
      DIOsatCur = epsmin;
    end
    if (!DIOnomTempGiven) begin
      DIOnomTemp = VACONST_tnom;
    end
    if (!$param_given(rs)||rs==0) begin
      DIOconductance = 0.0;
    end else begin
      DIOconductance = 1/rs;
    end
    if (!$param_given(rsw)||rsw==0) begin
      DIOconductanceSW = 0.0;
    end else begin
      DIOconductanceSW = 1/rsw;
    end
    if (!DIOmetalOxideThickGiven) begin
      DIOmetalOxideThick = 1e4;
    end
    if (!DIOpolyOxideThickGiven) begin
      DIOpolyOxideThick = 1e4;
    end
    if (!$param_given(area)) begin
      if (!$param_given(w)&&!$param_given(l)) begin
        i_DIOarea = model_area;
      end else begin
        i_DIOarea = 1;
      end
    end
    if (!$param_given(pj)) begin
      if (!$param_given(w)&&!$param_given(l)) begin
        i_DIOpj = model_pj;
      end else begin
        i_DIOpj = 0;
      end
    end
    DIOcmetal = 0.0;
    DIOcpoly = 0.0;
    if (level==3) begin
      if ($param_given(w)&&$param_given(l)) begin
        i_DIOarea = (w+xw)*(l+xw)*scale*scale;
        i_DIOpj = (2*(w+xw)+2*(l+xw))*scale;
      end
      if ($param_given(wm)) begin
        setup_wm = wm;
      end else begin
        setup_wm = model_wm;
      end
      if ($param_given(lm)) begin
        setup_lm = lm;
      end else begin
        setup_lm = model_lm;
      end
      if ($param_given(wp)) begin
        setup_wp = wp;
      end else begin
        setup_wp = model_wp;
      end
      if ($param_given(lp)) begin
        setup_lp = lp;
      end else begin
        setup_lp = model_lp;
      end
      DIOcmetal = 3.9*(1.0/(4.0*3.1415926535897932384626433832795*1E-7*299792458*299792458))/DIOmetalOxideThick*(setup_wm*scale+xm)*(setup_lm*scale+xm);
      DIOcpoly = 3.9*(1.0/(4.0*3.1415926535897932384626433832795*1E-7*299792458*299792458))/DIOpolyOxideThick*(setup_wp*scale+xp)*(setup_lp*scale+xp);
    end
    i_DIOforwardKneeCurrent = ikf*i_DIOarea;
    i_DIOreverseKneeCurrent = ikr*i_DIOarea;
    i_DIOforwardSWKneeCurrent = ikp*i_DIOpj;
    i_DIOjunctionCap = cjo*i_DIOarea;
    i_DIOjunctionSWCap = cjp*i_DIOpj;
    if (rs==0) begin
      V(a_int, a) <+ 0;
    end
    if (!$param_given(rsw)) begin
      V(sw_int, a_int) <+ 0;
    end

    // Tag: temp, function: DIOtemp
    if (!DIOtempGiven) begin
      DIOtemp = $temperature+dtemp;
    end
    // inlined: DIOtempUpdate(model, here, here->DIOtemp, ckt)
    vt = CONSTKoverQ*DIOtemp;
    vte = n*vt;
    vts = ns*vt;
    vtt = ntun*vt;
    vtr = nr*vt;
    vtnom = CONSTKoverQ*DIOnomTemp;
    dt = DIOtemp-DIOnomTemp;
    lnTRatio = ln(DIOtemp/DIOnomTemp);
    factor = 1.0+tm1*dt+tm2*dt*dt;
    DIOtGradingCoeff = m*factor;
    if (tlev==0||tlev==1) begin
      egfet = 1.16-7.02e-4*DIOtemp*DIOtemp/(DIOtemp+1108);
      egfet1 = 1.16-7.02e-4*DIOnomTemp*DIOnomTemp/(DIOnomTemp+1108);
    end else begin
      egfet = DIOactivationEnergy-gap1*DIOtemp*DIOtemp/(DIOtemp+gap2);
      egfet1 = DIOactivationEnergy-gap1*DIOnomTemp*DIOnomTemp/(DIOnomTemp+gap2);
    end
    fact2 = DIOtemp/(27.0+273.15);
    arg = -egfet/(2*1.38064852e-23*DIOtemp)+1.1150877/(1.38064852e-23*(27.0+273.15+(27.0+273.15)));
    pbfact = -2*vt*(1.5*ln(fact2)+1.6021766208e-19*arg);
    arg1 = -egfet1/(1.38064852e-23*2*DIOnomTemp)+1.1150877/(2*1.38064852e-23*(27.0+273.15));
    fact1 = DIOnomTemp/(27.0+273.15);
    pbfact1 = -2*vtnom*(1.5*ln(fact1)+1.6021766208e-19*arg1);
    if (tlevc==0) begin
      pbo = (vj-pbfact1)/fact1;
      gmaold = (vj-pbo)/pbo;
      DIOtJctCap = i_DIOjunctionCap/(1+DIOtGradingCoeff*(400e-6*(DIOnomTemp-(27.0+273.15))-gmaold));
      DIOtJctPot = pbfact+fact2*pbo;
      gmanew = (DIOtJctPot-pbo)/pbo;
      DIOtJctCap = DIOtJctCap * (1+DIOtGradingCoeff*(400e-6*(DIOtemp-(27.0+273.15))-gmanew));
    end else if (tlevc==1) begin
      DIOtJctPot = vj-tpb*(DIOtemp-(27.0+273.15));
      DIOtJctCap = i_DIOjunctionCap*(1+cta*(DIOtemp-(27.0+273.15)));
    end
    if (tlevc==0) begin
      pboSW = (php-pbfact1)/fact1;
      gmaSWold = (php-pboSW)/pboSW;
      DIOtJctSWCap = i_DIOjunctionSWCap/(1+mjsw*(400e-6*(DIOnomTemp-(27.0+273.15))-gmaSWold));
      DIOtJctSWPot = pbfact+fact2*pboSW;
      gmaSWnew = (DIOtJctSWPot-pboSW)/pboSW;
      DIOtJctSWCap = DIOtJctSWCap * (1+mjsw*(400e-6*(DIOtemp-(27.0+273.15))-gmaSWnew));
    end else if (tlevc==1) begin
      DIOtJctSWPot = php-tphp*(DIOtemp-(27.0+273.15));
      DIOtJctSWCap = i_DIOjunctionSWCap*(1+ctp*(DIOtemp-(27.0+273.15)));
    end
    if (tlev==0||tlev==1) begin
      arg1 = (DIOtemp/DIOnomTemp-1)*DIOactivationEnergy/vte;
      arg2 = xti/n*lnTRatio;
      DIOtSatCur = DIOsatCur*i_DIOarea*exp(arg1+arg2);
      arg1 = (DIOtemp/DIOnomTemp-1)*DIOactivationEnergy/vts;
      arg2 = xti/ns*lnTRatio;
      DIOtSatSWCur = jsw*i_DIOpj*exp(arg1+arg2);
      arg1 = (DIOtemp/DIOnomTemp-1)*keg*DIOactivationEnergy/vtt;
      arg2 = xtitun/ntun*lnTRatio;
      DIOtTunSatCur = jtun*i_DIOarea*exp(arg1+arg2);
      DIOtTunSatSWCur = jtunsw*i_DIOpj*exp(arg1+arg2);
      arg1 = (DIOtemp/DIOnomTemp-1)*DIOactivationEnergy/vtr;
      arg2 = xti/nr*lnTRatio;
      DIOtRecSatCur = isr*i_DIOarea*exp(arg1+arg2);
    end else begin
      arg0 = egfet1/(n*vtnom);
      arg1 = egfet/vte;
      arg2 = xti/n*lnTRatio;
      DIOtSatCur = DIOsatCur*i_DIOarea*exp(arg0-arg1+arg2);
      arg0 = egfet1/(ns*vtnom);
      arg1 = egfet/vts;
      arg2 = xti/ns*lnTRatio;
      DIOtSatSWCur = jsw*i_DIOpj*exp(arg0-arg1+arg2);
      arg0 = keg*egfet1/(ntun*vtnom);
      arg1 = keg*egfet/vtt;
      arg2 = xtitun/ntun*lnTRatio;
      DIOtTunSatCur = jtun*i_DIOarea*exp(arg0-arg1+arg2);
      DIOtTunSatSWCur = jtunsw*i_DIOpj*exp(arg0-arg1+arg2);
      arg0 = egfet1/(nr*vtnom);
      arg1 = egfet/vtr;
      arg2 = xti/nr*lnTRatio;
      DIOtRecSatCur = isr*i_DIOarea*exp(arg0-arg1+arg2);
    end
    xfc = ln(1-fc);
    xfcs = ln(1-fcs);
    DIOtF1 = DIOtJctPot*(1-exp((1-DIOtGradingCoeff)*xfc))/(1-DIOtGradingCoeff);
    DIOtDepCap = fc*DIOtJctPot;
    DIOtDepSWCap = fcs*DIOtJctSWPot;
    totalSatCur = DIOtSatCur+DIOtSatSWCur;
    if ($param_given(rsw)) begin
      DIOtVcrit = vte*ln(vte/(CONSTroot2*DIOtSatCur));
      DIOtVcritSW = vts*ln(vts/(CONSTroot2*DIOtSatSWCur));
    end else begin
      DIOtVcrit = vte*ln(vte/(CONSTroot2*totalSatCur));
      DIOtVcritSW = vts*ln(vts/(CONSTroot2*DIOtSatSWCur));
    end
    if ($param_given(bv)) begin
      if (tlev==0) begin
        tBreakdownVoltage = bv-tcv*dt;
      end else begin
        tBreakdownVoltage = bv*(1-tcv*dt);
      end
      if (level==1) begin
        cbv = ibv;
      end else begin
        cbv = ibv*i_DIOarea;
      end
      if (cbv<totalSatCur*tBreakdownVoltage/vt) begin
        xbv = tBreakdownVoltage;
      end else begin
        tol = reltol*cbv;
        xbv = tBreakdownVoltage-DIObrkdEmissionCoeff*vt*ln(1+cbv/totalSatCur);
        for(iter = 0; iter<25; iter = iter+1) begin
          xbv = tBreakdownVoltage-DIObrkdEmissionCoeff*vt*ln(cbv/totalSatCur+1-xbv/vt);
          xcbv = totalSatCur*(exp((tBreakdownVoltage-xbv)/(DIObrkdEmissionCoeff*vt))-1+xbv/vt);
          if (abs(xcbv-cbv)<=tol) begin
            iter = 25;
          end
        end
        if (!(abs(xcbv-cbv)<tol)) begin
          $warning("unable to match forward and reverse diode regions: bv = %g, ibv = %g", xbv, xcbv);
        end
      end
      DIOtBrkdwnV = xbv;
    end
    factor = 1.0+ttt1*dt+ttt2*dt*dt;
    DIOtTransitTime = tt*factor;
    DIOtConductance = DIOconductance*i_DIOarea;
    if ($param_given(rs)&&rs!=0.0) begin
      factor = 1.0+trs*dt+trs2*dt*dt;
      DIOtConductance = DIOconductance*i_DIOarea/factor;
    end
    DIOtConductanceSW = DIOconductanceSW*i_DIOpj;
    if ($param_given(rsw)&&rsw!=0.0) begin
      factor = 1.0+trs*dt+trs2*dt*dt;
      DIOtConductanceSW = DIOconductanceSW*i_DIOpj/factor;
    end
    DIOtF2 = exp((1+DIOtGradingCoeff)*xfc);
    DIOtF3 = 1-fc*(1+DIOtGradingCoeff);
    DIOtF2SW = exp((1+mjsw)*xfcs);
    DIOtF3SW = 1-fcs*(1+mjsw);
    // end of inlined: DIOtempUpdate(model, here, here->DIOtemp, ckt)

    // Tag: load, function: DIOload
    capdsw = 0.0;
    delvdsw = 0.0;
    vdsw = 0.0;
    ceqqth = 0.0;
    Ith = 0.0;
    gcTt = 0.0;
    vrs = 0.0;
    vrssw = 0.0;
    dIth_dVdio = 0.0;
    dIth_dVrs = 0.0;
    dIth_dVdioSw = 0.0;
    dIth_dVrssw = 0.0;
    cdsw = 0.0;
    gdsw = 0.0;
    delTemp = 0.0;
    load_vt = CONSTKoverQ*DIOtemp;
    load_vte = n*load_vt;
    vtesw = ns*load_vt;
    vtebrk = DIObrkdEmissionCoeff*load_vt;
    vterec = nr*load_vt;
    gspr = DIOtConductance;
    gsprsw = DIOtConductanceSW;
    limited = 0;
    DIOvoltage = $limit(V(a_int,c), DEVlimitOldGet);
    DIOvoltageSW = $limit(V(sw_int,c), DEVlimitOldGet);
    load_vd = V(a_int, c);
    if ($param_given(rsw)) begin
      vdsw = V(sw_int, c);
    end
    delTemp = 0.0;
    delvd = load_vd-DIOvoltage;
    if ($param_given(rsw)) begin
      delvdsw = vdsw-DIOvoltageSW;
    end
    if ($param_given(bv)&&load_vd<((0<-DIOtBrkdwnV+10*vtebrk) ? (0) : (-DIOtBrkdwnV+10*vtebrk))) begin
      vdtemp = -(load_vd+DIOtBrkdwnV);
      vdtemp = DEVpnjlim(vdtemp, -(DIOvoltage+DIOtBrkdwnV), vtebrk, DIOtVcrit, limited);
      load_vd = -(vdtemp+DIOtBrkdwnV);
    end else begin
      load_vd = DEVpnjlim(load_vd, DIOvoltage, load_vte, DIOtVcrit, limited);
    end
    if ($param_given(rsw)) begin
      if ($param_given(bv)&&vdsw<((0<-DIOtBrkdwnV+10*vtebrk) ? (0) : (-DIOtBrkdwnV+10*vtebrk))) begin
        vdtemp = -(vdsw+DIOtBrkdwnV);
        vdtemp = DEVpnjlim(vdtemp, -(DIOvoltageSW+DIOtBrkdwnV), vtebrk, DIOtVcritSW, limited);
        vdsw = -(vdtemp+DIOtBrkdwnV);
      end else begin
        vdsw = DEVpnjlim(vdsw, DIOvoltageSW, vtesw, DIOtVcritSW, limited);
      end
    end
    delTemp = 0.0;
    if (initialize_limiting()) begin
        load_vd = DIOtVcrit;
        vdsw = DIOtVcritSW;
    end
    load_vd = $limit(V(a_int,c), DEVlimitNewSet, load_vd, limited);
    vdsw = $limit(V(sw_int,c), DEVlimitNewSet, vdsw, limited);
    Temp = DIOtemp;
    csat = DIOtSatCur;
    csatsw = DIOtSatSWCur;
    gspr = DIOtConductance;
    gsprsw = DIOtConductanceSW;
    if ($param_given(jsw)) begin
      if ($param_given(rsw)) begin
        vds = vdsw;
      end else begin
        vds = load_vd;
      end
      if ($param_given(ns)) begin
        if (vds>=-3*vtesw) begin
          evd = exp(vds/vtesw);
          cdsw = csatsw*(evd-1);
          gdsw = csatsw*evd/vtesw;
        end else if (!$param_given(bv)||vds>=-DIOtBrkdwnV) begin
          argsw = 3*vtesw/(vds*CONSTe);
          argsw = argsw*argsw*argsw;
          cdsw = -csatsw*(1+argsw);
          gdsw = csatsw*3*argsw/vds;
        end else if (!$param_given(rsw)) begin
          evrev = exp(-(DIOtBrkdwnV+vds)/vtebrk);
          cdsw = -csatsw*evrev;
          gdsw = csatsw*evrev/vtebrk;
        end
      end
    end
    if (load_vd>=-3*load_vte) begin
      evd = exp(load_vd/load_vte);
      cdb = csat*(evd-1);
      gdb = csat*evd/load_vte;
      if ($param_given(jsw)&&!$param_given(ns)) begin
        cdsw = csatsw*(evd-1);
        gdsw = csatsw*evd/load_vte;
      end
      if ($param_given(isr)) begin
        evd_rec = exp(load_vd/vterec);
        cdb_rec = DIOtRecSatCur*(evd_rec-1);
        gdb_rec = DIOtRecSatCur*evd_rec/vterec;
        t1 = pow(1-load_vd/DIOtJctPot, 2)+0.005;
        gen_fac = pow(t1, DIOtGradingCoeff/2);
        gen_fac_vd = -DIOtGradingCoeff*(1-load_vd/DIOtJctPot)*pow(t1, DIOtGradingCoeff/2-1);
        cdb_rec = cdb_rec*gen_fac;
        gdb_rec = gdb_rec*gen_fac+cdb_rec*gen_fac_vd;
        cdb = cdb+cdb_rec;
        gdb = gdb+gdb_rec;
      end
    end else if (!$param_given(bv)||load_vd>=-DIOtBrkdwnV) begin
      load_arg = 3*load_vte/(load_vd*CONSTe);
      load_arg = load_arg*load_arg*load_arg;
      if ($param_given(isr)) begin
        evd_rec = exp(-3*load_vte/vterec);
        cdb_rec = DIOtRecSatCur*(evd_rec-1);
        t1 = pow(1--3*load_vte/DIOtJctPot, 2)+0.005;
        gen_fac = pow(t1, DIOtGradingCoeff/2);
        cdb = -csat*(1+load_arg)+gen_fac*cdb_rec;
      end else begin
        cdb = -csat*(1+load_arg);
      end
      gdb = csat*3*load_arg/load_vd;
      if ($param_given(jsw)&&!$param_given(ns)) begin
        cdsw = -csatsw*(1+load_arg);
        gdsw = csatsw*3*load_arg/load_vd;
      end
    end else begin
      evrev = exp(-(DIOtBrkdwnV+load_vd)/vtebrk);
      if ($param_given(isr)) begin
        evd_rec = exp(-3*load_vte/vterec);
        cdb_rec = DIOtRecSatCur*(evd_rec-1);
        t1 = pow(1--3*load_vte/DIOtJctPot, 2)+0.005;
        gen_fac = pow(t1, DIOtGradingCoeff/2);
        cdb = -csat*evrev+gen_fac*cdb_rec;
      end else begin
        cdb = -csat*evrev;
      end
      gdb = csat*evrev/vtebrk;
      if ($param_given(jsw)&&!$param_given(ns)&&!$param_given(rsw)) begin
        evrev = exp(-(DIOtBrkdwnV+vdsw)/vtebrk);
        cdsw = -csatsw*evrev;
        gdsw = csatsw*evrev/vtebrk;
      end
    end
    if ($param_given(jtunsw)) begin
      vtetun = ntun*load_vt;
      evd = exp(-load_vd/vtetun);
      cdsw = cdsw-DIOtTunSatSWCur*(evd-1);
      gdsw = gdsw+DIOtTunSatSWCur*evd/vtetun;
    end
    if ($param_given(jtun)) begin
      vtetun = ntun*load_vt;
      evd = exp(-load_vd/vtetun);
      cdb = cdb-DIOtTunSatCur*(evd-1);
      gdb = gdb+DIOtTunSatCur*evd/vtetun;
    end
    if (load_vd>=-3*load_vte) begin
      if (DIOforwardKneeCurrentGiven&&cdb>1.0e-18) begin
        ikf_area_m = i_DIOforwardKneeCurrent;
        sqrt_ikx = sqrt(cdb/ikf_area_m);
        gdb = ((1+sqrt_ikx)*gdb-cdb*gdb/(2*sqrt_ikx*ikf_area_m))/(1+2*sqrt_ikx+cdb/ikf_area_m);
        cdb = cdb/(1+sqrt_ikx);
      end
    end else if (DIOreverseKneeCurrentGiven&&cdb<-1.0e-18) begin
      ikr_area_m = i_DIOreverseKneeCurrent;
      sqrt_ikx = sqrt(cdb/-ikr_area_m);
      gdb = ((1+sqrt_ikx)*gdb+cdb*gdb/(2*sqrt_ikx*ikr_area_m))/(1+2*sqrt_ikx-cdb/ikr_area_m);
      cdb = cdb/(1+sqrt_ikx);
    end
    if (DIOforwardSWKneeCurrentGiven&&cdsw>1.0e-18) begin
      ikp_peri_m = i_DIOforwardSWKneeCurrent;
      sqrt_ikx = sqrt(cdsw/ikp_peri_m);
      gdsw = ((1+sqrt_ikx)*gdsw-cdsw*gdsw/(2*sqrt_ikx*ikp_peri_m))/(1+2*sqrt_ikx+cdsw/ikp_peri_m);
      cdsw = cdsw/(1+sqrt_ikx);
    end
    if (!$param_given(rsw)) begin
      load_cd = cdb+cdsw+gmin*load_vd;
      load_gd = gdb+gdsw+gmin;
    end else begin
      load_cd = cdb+gmin*load_vd;
      load_gd = gdb+gmin;
      cdsw = cdsw+gmin*vdsw;
      gdsw = gdsw+gmin;
    end
    czero = DIOtJctCap;
    if (load_vd<DIOtDepCap) begin
      load_arg = 1-load_vd/DIOtJctPot;
      sarg = exp(-DIOtGradingCoeff*ln(load_arg));
      deplcharge = DIOtJctPot*czero*(1-load_arg*sarg)/(1-DIOtGradingCoeff);
      deplcap = czero*sarg;
    end else begin
      czof2 = czero/DIOtF2;
      deplcharge = czero*DIOtF1+czof2*(DIOtF3*(load_vd-DIOtDepCap)+DIOtGradingCoeff/(DIOtJctPot+DIOtJctPot)*(load_vd*load_vd-DIOtDepCap*DIOtDepCap));
      deplcap = czof2*(DIOtF3+DIOtGradingCoeff*load_vd/DIOtJctPot);
    end
    czeroSW = DIOtJctSWCap;
    if ($param_given(rsw)) begin
      vdx = vdsw;
    end else begin
      vdx = load_vd;
    end
    if (vdx<DIOtDepSWCap) begin
      argSW = 1-vdx/DIOtJctSWPot;
      sargSW = exp(-mjsw*ln(argSW));
      deplchargeSW = DIOtJctSWPot*czeroSW*(1-argSW*sargSW)/(1-mjsw);
      deplcapSW = czeroSW*sargSW;
    end else begin
      czof2SW = czeroSW/DIOtF2SW;
      deplchargeSW = czeroSW*DIOtF1+czof2SW*(DIOtF3SW*(vdx-DIOtDepSWCap)+mjsw/(DIOtJctSWPot+DIOtJctSWPot)*(vdx*vdx-DIOtDepSWCap*DIOtDepSWCap));
      deplcapSW = czof2SW*(DIOtF3SW+mjsw*vdx/DIOtJctSWPot);
    end
    diffcharge = DIOtTransitTime*load_cd;
    diffcap = DIOtTransitTime*load_gd;
    if (!$param_given(rsw)) begin
      DIOcapCharge = diffcharge+deplcharge+deplchargeSW+(DIOcmetal+DIOcpoly)*load_vd;
      capd = diffcap+deplcap+deplcapSW+DIOcmetal+DIOcpoly;
      DIOcap = capd;
    end else begin
      DIOcapCharge = diffcharge+deplcharge+(DIOcmetal+DIOcpoly)*load_vd;
      capd = diffcap+deplcap+DIOcmetal+DIOcpoly;
      DIOcap = capd;
      DIOcapChargeSW = deplcapSW;
      capdsw = deplcapSW;
      DIOcapSW = capdsw;
    end
    geq = 0;
    DIOcapCurrent = ddt(DIOcapCharge);
    ceq = DIOcapCurrent;
    load_gd = load_gd+geq;
    DIOdcCurrent = load_cd;
    load_cd = load_cd+DIOcapCurrent;
    if ($param_given(rsw)) begin
      geq = 0;
      DIOcapCurrentSW = ddt(DIOcapChargeSW);
      ceq = DIOcapCurrentSW;
      gdsw = gdsw+geq;
      cdsw = cdsw+DIOcapCurrentSW;
    end
    load_gd = load_gd - gmin + gmin / $mfactor;
    load_cd = load_cd - gmin * load_vd + gmin / $mfactor * load_vd;
    DIOvoltage = load_vd;
    DIOcurrent = load_cd;
    DIOconduct = load_gd;
    if ($param_given(rsw)) begin
      DIOvoltageSW = vdsw;
      DIOcurrentSW = cdsw;
      DIOconductSW = gdsw;
    end
    cdeq = load_cd;
    if ($param_given(rsw)) begin
      cdeqsw = cdsw;
    end
    
    // Residuals
    I(a) <+ gspr*V(a, a_int)+gsprsw*V(a, sw_int);
    I(c) <+ -cdeq+-cdeqsw;
    I(a_int) <+ gspr*V(a_int, a)+cdeq;
    I(sw_int) <+ gsprsw*V(sw_int, a)+cdeqsw;

    // Tag: noise, function: DIOnoise
    if (DIOtempGiven) begin
      noise_dtemp = DIOtemp-$temperature+(DIOnomTemp-273.15);
    end else begin
      noise_dtemp = dtemp;
    end
    I(a_int, a) <+ white_noise(4*(VACONSTboltz*(($temperature+noise_dtemp)*DIOtConductance)), "rs");
    I(a_int, c) <+ white_noise(2*(VACONSTcharge*DIOdcCurrent), "id");
    I(a_int, c) <+ flicker_noise(((DIOdcCurrent>=0) ? (1) : (-1))*(kf*exp(af*ln(((abs(DIOdcCurrent)>1E-38) ? (abs(DIOdcCurrent)) : (1E-38))))), 1, "flicker");
    if ($param_given(rsw)) begin
      I(sw_int, a) <+ white_noise(4*(VACONSTboltz*(($temperature+noise_dtemp)*DIOtConductanceSW)), "rsw");
      I(sw_int, c) <+ white_noise(2*(VACONSTcharge*DIOcurrentSW), "idsw");
      I(sw_int, c) <+ flicker_noise(((DIOcurrentSW>=0) ? (1) : (-1))*(kf*exp(af*ln(((abs(DIOcurrentSW)>1E-38) ? (abs(DIOcurrentSW)) : (1E-38))))), 1, "flickersw");
    end

    // Instance output variable computation
    vd = DIOvoltage;
    gd = DIOconduct;
    cd = DIOcap;
    charge = DIOcapCharge;

    // Model output variable computation

  end
endmodule
