<?xml version="1.0" encoding="ISO-8859-1"?>

<!--
     Written by Laurent Lemaitre - r29173@users.sourceforge.net
     Documentation:
       http://sourceforge.net/docman/display_doc.php?docid=18993&group_id=84289
     Target Interface: ngspice
     Supported by adms-1.x.x
     This file is used by adms - http://sourceforge.net/projects/mot-adms.
     adms is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
     adms is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
     You should have received a copy of the GNU General Public License
     along with adms; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-->

<!DOCTYPE admst SYSTEM "admst.dtd">
<admst version="2.3.0" xmlns:admst="http://mot-adms.sourceforge.net/xml-files/admst">

<admst:template match="dectype">
  <admst:choose>
    <admst:when test="[type='real']">
      <admst:text format="  double "/>
    </admst:when>
    <admst:when test="[type='integer']">
      <admst:text format="  int "/>
    </admst:when>
    <admst:otherwise>
      <admst:text format="  char* "/>
    </admst:otherwise>
  </admst:choose>
</admst:template>

<admst:template match="code">
<admst:value-of select="attribute[name='ngspicename']/value"/>
<admst:variable name="module" select="%s"/>

#ifndef $(module)
#define $(module)

#include &quot;ngspice/cktdefs.h&quot;
#include &quot;ngspice/ifsim.h&quot;
#include &quot;ngspice/gendefs.h&quot;
#include &quot;ngspice/complex.h&quot;
#include &quot;ngspice/noisedef.h&quot;

<admst:for-each select="variable">
<admst:value-of select="name"/>
<admst:variable name="variable" select="%s"/>
#ifdef $(variable)
  #warning conflict: $(variable) is declared as a variable of module '$(module)'.
  #warning conflict: However in the API of ngspice '$(variable)' is also defined as a pragma.
  #warning conflict: Pragma '$(variable)' will be undefined.
  #warning conflict: You can solve the confict by renaming variable '$(variable)' in module '$(module)'.
  #undef $(variable)
#endif
</admst:for-each>
<admst:for-each select="node">
<admst:value-of select="name"/>
<admst:variable name="node" select="%s"/>
#ifdef $(variable)
  #warning conflict: $(node) is declared as a node of module '$(module)'.
  #warning conflict: However in the API of ngspice '$(node)' is also defined as a pragma.
  #warning conflict: Pragma '$(node)' will be undefined.
  #warning conflict: You can solve the confict by renaming variable '$(node)' in module '$(module)'.
  #undef $(variable)
#endif
</admst:for-each>

#ifdef NGSPICE_DEBUG_OK
#define NGSPICE_DEBUG \\
{ \\
  if(getenv(&quot;ngspice_debug&quot;)) \\
    $(module)debug(ckt,model,here); \\
  else \\
  { \\
    printf(&quot;  To get more info run your simulation after setting shell variable ngspice_debug to 1\\n&quot;); \\
    printf(&quot;  For example in sh shell just type: export ngspice_debug=1\\n&quot;); \\
  } \\
}
#else
#define NGSPICE_DEBUG
#endif

#define EXIT_IF_ISNAN(var) \\
{ \\
}

static inline double max(double x,double y)  { return ((x)&gt;(y))?(x):(y); }
static inline double min(double x,double y)  { return ((x)&lt;(y))?(x):(y); }

/* ngspice \$simparam variables
    gdev                (1/Ohms): Additional conductance to be added to nonlinear branches for conductance homotopy convergence algorithm.
    gmin                (1/Ohms): Minimum conductance placed in parallel with nonlinear branches.
    imax                (Amps)  : Branch current threshold above which the constitutive relation of a nonlinear branch should be linearized.
    imelt               (Amps)  : Branch current threshold indicating device failure.
    iteration                   : Iteration number of the analog solver.
    scale                       : Scale factor for device instance geometry parameters.
    shrink                      : Optical linear shrink factor.
    simulatorSubversion         : The simulator sub-version.
    simulatorVersion            : The simulator version.
    sourceScaleFactor           : Multiplicative factor for independent sources for source stepping homotopy convergence algorithm.
    tnom degrees       (Celsius): Default value of temperature at which model parameters were extracted.
*/

#define _circuit_gdev                ckt-&gt;CKTgmin
#define _circuit_gmin                ((ckt-&gt;CKTgmin)&gt;(ckt-&gt;CKTdiagGmin))?(ckt-&gt;CKTgmin):(ckt-&gt;CKTdiagGmin)
#define _circuit_imax                1.0
#define _circuit_imelt               1.0
#define _circuit_iteration           1.0
#define _circuit_scale               1.0
#define _circuit_shrink              1.0
#define _circuit_simulatorSubversion 0
#define _circuit_simulatorVersion    3.5
#define _circuit_sourceScaleFactor   1.0
#define _circuit_tnom                ckt-&gt;CKTnomTemp

#define _circuit_temp      ckt-&gt;CKTtemp
#define _scale             1.0

#define _f_cos(val,arg)          val = cos(arg);
#define _d_cos(val,dval,arg)     val = cos(arg);     dval = (-sin(arg));
#define _f_sin(val,arg)          val = sin(arg);
#define _d_sin(val,dval,arg)     val = sin(arg);     dval = (cos(arg));
#define _f_tan(val,arg)          val = tan(arg);
#define _d_tan(val,dval,arg)     val = tan(arg);     dval = (1.0/cos(arg)/cos(arg));
#define _f_asinh(val,arg)        val = asinh(arg);
#define _d_asinh(val,dval,arg)   val = asinh(arg);   dval = (1.0/sqrt(arg*arg + 1));
#define _f_hypot(xy,x,y)         xy = sqrt((x)*(x)+(y)*(y));
#define _dx_hypot(dx,xy,x,y)     dx = (x)/(xy);
#define _dy_hypot(dy,xy,x,y)     dy = (y)/(xy);
#define _f_max(xy,x,y)           xy = ((x)&gt;(y))?(x):(y);
#define _dx_max(dx,xy,x,y)       dx = ((x)&gt;(y))?1.0:0.0;
#define _dy_max(dy,xy,x,y)       dy = ((x)&gt;(y))?0.0:1.0;
#define _f_min(xy,x,y)           xy = ((x)&lt;(y))?(x):(y);
#define _dx_min(dx,xy,x,y)       dx = ((x)&lt;(y))?1.0:0.0;
#define _dy_min(dy,xy,x,y)       dy = ((x)&lt;(y))?0.0:1.0;
#define _f_cosh(val,arg)         val = cosh(arg);
#define _d_cosh(val,dval,arg)    val = cosh(arg);    dval = (sinh(arg));
#define _f_sinh(val,arg)         val = sinh(arg);
#define _d_sinh(val,dval,arg)    val = sinh(arg);    dval = (cosh(arg));
#define _f_tanh(val,arg)         val = tanh(arg);
#define _d_tanh(val,dval,arg)    val = tanh(arg);    dval = (1.0/cosh(arg)/cosh(arg));
#define _f_acos(val,arg)         val = acos(arg);
#define _d_acos(val,dval,arg)    val = acos(arg);    dval = (-1.0/sqrt(1-arg*arg));
#define _f_asin(val,arg)         val = asin(arg);
#define _d_asin(val,dval,arg)    val = asin(arg);    dval = (+1.0/sqrt(1-arg*arg));
#define _f_atan(val,arg)         val = atan(arg);
#define _d_atan(val,dval,arg)    val = atan(arg);    dval = (+1.0/(1+arg*arg));
#define _f_logE(val,arg)         val = log(arg);
#define _d_logE(val,dval,arg)    val = log(arg);     dval = (1.0/arg);
#define _f_log10(val,arg)        val = log10(arg);
#define _d_log10(val,dval,arg)   val = log10(arg);   dval = (1.0/arg/log(10));
#define _f_exp(val,arg)          val = exp(arg);
#define _d_exp(val,dval,arg)     val = exp(arg);     dval = val;
#define _f_sqrt(val,arg)         val = sqrt(arg);
#define _d_sqrt(val,dval,arg)    val = sqrt(arg);    dval = (1.0/val/2.0);
#define _f_pow(xy,x,y)           xy = pow(x,y);
#define _dx_pow(dx,xy,x,y)       dx = (x==0.0)?0.0:((y/x)*xy);
#define _dy_pow(dy,xy,x,y)       dy = (x==0.0)?0.0:((log(x)/exp(0.0))*xy);

#define _f_atan2(xy,x,y)         xy = atan2(x,y);
#define _dx_atan2(dx,x,y)        dx = -(y)/((x)*(x)+(y)*(y));
#define _dy_atan2(dy,x,y)        dy = (x)/((x)*(x)+(y)*(y));

#define _f_div1(x,y)             ((x)/(y))
#define _f_div0(xy,x,y)          xy=(x)/(y);
#define _f_div(xy,dx,x,y)        dx=1/(y); xy=(x)*dx;
#define _dx_div(dx,xy,x,y)
#define _dy_div(dy,dx,xy,x,y)    dy = -xy*dx;

#define _f_limexp(val,arg)       val = ((arg)&lt;(90)) ? (exp(arg)) : (exp(90)*(1.0+(arg-90)));
#define _d_limexp(val,dval,arg)  val = ((arg)&lt;(90)) ? (exp(arg)) : (exp(90)*(1.0+(arg-90))); dval = val;
#define _f_fabs(val,arg)         val = fabs(arg);
#define _d_fabs(val,dval,arg)    val = fabs(arg);    dval = (((val)&gt;=0)?(+1.0):(-1.0));
#define _f_abs(val)              ((val)&lt;(0) ? (-(val)):(val))
#define _f_floor(val,arg)        val = floor(arg);
#define _f_ceil(val,arg)         val = ceil(arg);

/* declarations for $(module) MOSFETs */

/* information needed for each instance */
typedef struct s$(module)instance {

    struct GENinstance gen;

#define $(module)modPtr(inst) (($(module)model *)((inst)-&gt;gen.GENmodPtr))
#define $(module)nextInstance(inst) (($(module)instance *)((inst)-&gt;gen.GENnextInstance))
#define $(module)name gen.GENname
#define $(module)states gen.GENstate

  /* node */
<admst:for-each select="node[grounded='no']">
  <admst:value-of select="name"/>
  <admst:text format="  int %sNode;"/>
  <admst:if test="attribute[name='info']">
    <admst:value-of select="."/>
    <admst:text format="  /*%s*/"/>
  </admst:if>
  <admst:text format="\n"/>
</admst:for-each>
<admst:for-each select="node[grounded='no']">
  <admst:choose>
    <admst:when test="[location='internal']">
      <admst:text format="  unsigned %(name)Node_mine :1;\n"/>
    </admst:when>
    <admst:otherwise>
      <admst:text format="  unsigned %(name)Node_mine :1;\n"/>
      <admst:text format="  unsigned %(name)Node_connected :1;\n"/>
    </admst:otherwise>
  </admst:choose>
</admst:for-each>
  /* instance parameters */
<admst:for-each select="variable[parametertype='instance' and input='yes']">
  <admst:value-of select="name"/>
  <admst:value-of select="name"/>
  <admst:apply-templates select="." match="dectype"/>
  <admst:text format="%s;\n"/>
  <admst:text format="  unsigned %s_Given  :1;"/>
  <admst:if test="attribute[name='info']">
    <admst:value-of select="."/>
    <admst:text format="  /*%s*/"/>
  </admst:if>
  <admst:text format="\n"/>
</admst:for-each>
 // noise\n
  <admst:text select="$fnoise/item" format="  double fpnoise%(index($fnoise/item,.)), fenoise%(index($fnoise/item,.));\n"/>
  <admst:text select="$tnoise/item" format="  double tnoise%(index($tnoise/item,.));\n"/>
  <admst:text select="$wnoise/item" format="  double wnoise%(index($wnoise/item,.));\n"/>

  /* variables */
<admst:for-each select="variable[input='no' and scope='global_instance']">
  <admst:value-of select="name"/>
  <admst:apply-templates select="." match="dectype"/>
  <admst:text format="%s;\n"/>
  <admst:for-each select="attribute[name='info']">
    <admst:value-of select="."/>
    <admst:text format="  /*%s*/"/>
  </admst:for-each>
</admst:for-each>
  /* states */
<admst:for-each select="source[dynamic='yes']">
  <admst:value-of select="branch/nnode/name"/>
  <admst:value-of select="branch/pnode/name"/>
  <admst:text format="  int state_%s_%s;\n"/>
</admst:for-each>
  /* pointer to sparse matrix (+ values)*/
<admst:for-each select="jacobian">
  <admst:value-of select="column/name"/>
  <admst:value-of select="row/name"/>
  <admst:text format="  double *PTR_J_%s_%s;\n"/>
  <admst:value-of select="column/name"/>
  <admst:value-of select="row/name"/>
  <admst:text format="    int PTR_J_%s_%s_required;\n"/>
  <admst:if test="[static='yes']">
    <admst:value-of select="column/name"/>
    <admst:value-of select="row/name"/>
    <admst:text format="    double JSVAL_%s_%s;\n"/>
  </admst:if>
  <admst:if test="[dynamic='yes']">
    <admst:value-of select="column/name"/>
    <admst:value-of select="row/name"/>
    <admst:text format="    double JDVAL_%s_%s;\n"/>
  </admst:if>
</admst:for-each>

} $(module)instance ;

enum {
<admst:for-each select="variable">
  <admst:if test="attribute[name='desc']">
    <admst:if test="[not((input='yes' and (parametertype='model' or parametertype='instance')) or (input='np' and (scope='global_model' or scope='global_instance')))]">
      hide_%(name),
#define %(name) ((struct hides *)hide_%(name))
    </admst:if>
  </admst:if>
</admst:for-each>
    $(module)numStates
};

/* per model data */

typedef struct s$(module)model {         /* model structure */
  struct GENmodel gen;

#define $(module)modType            gen.GENmodType
#define $(module)nextModel(inst)    (($(module)model*)((inst)->gen.GENnextModel))
#define $(module)instances(inst)    (($(module)instance*)((inst)->gen.GENinstances))
#define $(module)modName            gen.GENmodName

  /* model parameters */
  <admst:for-each select="variable[parametertype='model' and input='yes']">
    <admst:value-of select="name"/>
    <admst:value-of select="name"/>
    <admst:apply-templates select="." match="dectype"/>
    <admst:text format="%s;\n"/>
    <admst:text format="  unsigned %s_Given  :1;"/>
    <admst:if test="attribute[name='info']">
      <admst:value-of select="."/>
      <admst:text format="  /*%s*/"/>
    </admst:if>
    <admst:text format="\n"/>
  </admst:for-each>
  /* variable */
  <admst:for-each select="variable[input='no' and scope='global_model']">
    <admst:value-of select="name"/>
    <admst:apply-templates select="." match="dectype"/>
    <admst:text format="%s;\n"/>
    <admst:for-each select="attribute[name='info']">
      <admst:value-of select="."/>
      <admst:text format="  /*%s*/"/>
    </admst:for-each>
  </admst:for-each>

} $(module)model;

  <admst:text format="  /* flags */\n"/>
  <admst:text format="typedef enum {\n"/>
  <admst:for-each select="variable[parametertype='model' and input='yes']">
    <admst:value-of select="name"/>
    <admst:text format="  $(module)_model_%s,\n"/>
  </admst:for-each>
    <admst:text format="  DUMMY_MODEL"/>
  <admst:text format="\n} e_$(module)_model;\n"/>
  <admst:text format="typedef enum {\n"/>
  <admst:for-each select="variable[parametertype='instance' and input='yes']">
    <admst:value-of select="name"/>
    <admst:text format="  $(module)_instance_%s,\n"/>
  </admst:for-each>
  <admst:for-each select="variable">
    <admst:if test="attribute[name='desc']">
      <admst:if test="[not((input='yes' and (parametertype='model' or parametertype='instance')) or (input='np' and (scope='global_model' or scope='global_instance')))]">
        $(module)_ask_%(name),
      </admst:if>
    </admst:if>
  </admst:for-each>
  <admst:text format="  DUMMY_INSTANCE"/>
  <admst:text format="\n} e_$(module)_instance;\n"/>

<admst:value-of select="attribute[name='ngspicename']/value"/>
<admst:variable name="module" select="%s"/>

#include &quot;$(module)ext.h&quot;
<admst:if test="[not(nilled(analogfunction))]">
#include &quot;$(module).analogfunction.h&quot;
</admst:if>

#endif /*$(module)*/

</admst:template>

<admst:for-each select="/module">
  <admst:value-of select="attribute[name='ngspicename']/value"/>
  <admst:open file="%sdefs.h">
    <admst:text format="/***\n*** Interface: %(/simulator/package_string)\n"/>
    <admst:text format=" *** created by: %(/simulator/fullname) ***/\n"/>
    <admst:apply-templates select="." match="code"/>
  </admst:open>
  <admst:value-of select="attribute[name='ngspicename']/value"/>
  <admst:message format="%sdefs.h: file created\n"/>
</admst:for-each>

</admst>
