<?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">

<!-- expression//function: mapping verilog-name == C-name of function -->
<admst:template match="fname">
  <admst:choose>
    <admst:when test="[name='div']"><admst:return name="fname" value="_f_div1"/></admst:when>
    <admst:when test="[name='abs']"><admst:return name="fname" value="fabs"/></admst:when>
    <admst:when test="[name='\$shrinkl']"><admst:return name="fname" value="shrinkl"/></admst:when>
    <admst:when test="[name='\$shrinka']"><admst:return name="fname" value="shrinka"/></admst:when>
    <admst:when test="[name='log']"><admst:return name="fname" value="log10"/></admst:when>
    <admst:when test="[name='ln']"><admst:return name="fname" value="log"/></admst:when>
    <admst:when test="[name='limexp']"><admst:return name="fname" value="limexp"/></admst:when>
    <admst:when test="[name='\$limexp']"><admst:return name="fname" value="limexp"/></admst:when>
    <admst:when test="[name='\$model']"><admst:return name="fname" value="_modelname"/></admst:when>
    <admst:when test="[name='\$instance']"><admst:return name="fname" value="_instancename"/></admst:when>
    <admst:when test="[name='\$temperature']"><admst:return name="fname" value="_circuit_temp"/></admst:when>
    <admst:when test="[name='cos' or name='sin' or name='tan' or
                      name='cosh' or name='sinh' or name='tanh' or
                      name='acos' or name='asin' or name='atan' or name='atan2' or
                      name='acosh' or name='asinh' or name='atanh' or
                      name='ln' or name='log' or name='exp' or name='sqrt' or name='abs' or name='limexp' or
                      name='div' or name='pow' or name='hypot' or name='min' or name='max' or name='\$vt' or
                      name='floor' or name='ceil']">
      <admst:return name="fname" value="%(name)"/>
    </admst:when>
    <admst:otherwise><admst:return name="fname" value="$(module)_%(name)"/></admst:otherwise>
  </admst:choose>
</admst:template>

<admst:template match="function">
  <admst:choose>
    <admst:when test="[name='\$port_connected']">
      <admst:message format="ZZ 11!! port_connected, this one\n"/>
      <admst:for-each select="arguments[position(.)=1]">
        <admst:value-to select="/simulator/tmp" value="(here->%(.)Node_connected /* port_connected 13 */)"/>
      </admst:for-each>
    </admst:when>
    <admst:otherwise>
  <admst:variable name="function" select="%(name)"/>
  <admst:variable name="args" select=""/>
  <admst:for-each select="arguments">
    <admst:variable test="[$args='']" name="args" select="$args,"/>
    <admst:apply-templates select="." match="subexpression:stringify:noprobe"/>
    <admst:variable name="args" select="$args%s"/>
  </admst:for-each>
  <admst:choose>
    <admst:when test="[name='\$simparam']">
      <admst:apply-templates select="." match="function:simparam"/>
    </admst:when>
    <admst:when test="[name='analysis']">
      <admst:apply-templates select="." match="function:analysis"/>
    </admst:when>
    <admst:when test="[name='\$given' or name='\$param_given']">
      <admst:for-each select="arguments[position(.)=1]">
        <admst:assert test="[datatypename='variable' and input='yes']" format="%(../name)(%(../arguments[1])): argument is not a parameter\n"/>
        <admst:choose>
          <admst:when test="[parametertype='model']">
            <admst:value-of select="name"/>
            <admst:value-to select="/simulator/tmp" value="model->%s_Given"/>
          </admst:when>
          <admst:when test="[parametertype='instance']">
            <admst:value-of select="name"/>
            <admst:value-to select="/simulator/tmp" value="here->%s_Given"/>
          </admst:when>
          <admst:otherwise>
            <admst:error format="%(../name)(%(../arguments[1])): should not be reached\n"/>
          </admst:otherwise>
        </admst:choose>
      </admst:for-each>
    </admst:when>
    <!-- fixme, seems to be necessairy only because dependency detection does not drop an unneeded expression requiring $vt -->
    <admst:when test="[name='\$vt']">
      <admst:choose>
        <admst:when test="[nilled(arguments)]">
          <admst:value-to select="/simulator/tmp" value="((BOLTZMANN/ELECTRON_CHARGE)*ckt->CKTtemp)"/>
        </admst:when>
        <admst:when test="arguments[count(.)=1]">
          <admst:value-to select="/simulator/tmp" value="((BOLTZMANN/ELECTRON_CHARGE)*(%(arguments[1])))"/>
        </admst:when>
      </admst:choose>
    </admst:when>
    <admst:otherwise>
      <admst:variable name="mycode" select=""/>
      <admst:if test="[exists(arguments)]">
        <admst:for-each select="arguments">
          <admst:apply-templates select="." match="subexpression:stringify:noprobe"/>
          <admst:choose>
            <admst:when test="[$mycode='']">
              <admst:variable name="mycode" select="%s"/>
            </admst:when>
            <admst:otherwise>
              <admst:variable name="mycode" select="$mycode,%s"/>
            </admst:otherwise>
          </admst:choose>
        </admst:for-each>
        <admst:variable name="mycode" select="($mycode)"/>
      </admst:if>
      <admst:variable name="mycode" select="%(fname(.)/[name='fname']/value)$mycode"/>
      <admst:value-to select="/simulator/tmp" value="$mycode"/>
    </admst:otherwise>
  </admst:choose>
    </admst:otherwise>
  </admst:choose>
</admst:template>

<admst:template match="evaluatetopology">
  <admst:choose>
    <admst:when test="[datatypename='callfunction']"/>
    <admst:when test="[datatypename='whileloop']">
      <admst:apply-templates select="whileblock" match="evaluatetopology"/>
      <admst:apply-templates select="while" match="evaluatetopology"/>
    </admst:when>
    <admst:when test="[datatypename='conditional']">
      <admst:if test="if[nilled(variable[OPdependent='yes'])]">
        <admst:apply-templates select="if" match="evaluatetopology"/>
        <admst:choose>
          <admst:when test="if/math[dependency='constant']">
            <admst:apply-templates select="if" match="expression:stringify:noprobe"/>
            <admst:text format="if\n(%s)\n"/>
            <admst:text format="{\n"/>
            <admst:apply-templates select="then" match="evaluatetopology"/>
            <admst:text format="}\n"/>
            <admst:if test="[exists(else)]">
              <admst:text format="else\n"/>
              <admst:text format="{\n"/>
              <admst:apply-templates select="else" match="evaluatetopology"/>
              <admst:text format="}\n"/>
            </admst:if>
          </admst:when>
          <admst:otherwise>
            <admst:apply-templates select="then" match="evaluatetopology"/>
            <admst:apply-templates select="else" match="evaluatetopology"/>
          </admst:otherwise>
        </admst:choose>
      </admst:if>
    </admst:when>
    <admst:when test="[datatypename='case']">
      <admst:text format="/* -- CASE BEGIN -- */;\n"/>
      <admst:variable name="casecondition" path="case"/>
      <admst:variable name="havedefault" string="no"/>
      <!-- check for default -->
      <admst:for-each select="caseitem/[defaultcase='yes']">
        <admst:variable name="havedefault" string="yes"/>
      </admst:for-each>
      <admst:for-each select="caseitem/[defaultcase='no']">
          <admst:text format="/* CASE ITEM */\n"/>
          <admst:text format="if\n("/>
          <admst:join select="condition" separator="||">
            <admst:apply-templates select="$(casecondition)" match="expression:stringify:noprobe"/>
            <admst:text format="((%s)==(%(.)))"/>
          </admst:join>
          <admst:text format=")\n"/>
          <admst:text format="{\n"/>
          <admst:apply-templates select="code" match="evaluatetopology"/>
          <admst:text format="}\n"/>
          <admst:text format="else\n"/>
      </admst:for-each>
      <admst:text select="[$havedefault='no']" format="{ /* no default */ }\n"/>
      <admst:for-each select="caseitem/[defaultcase='yes']">
          <admst:text format="/* CASE DEFAULT */\n"/>
          <admst:text format="{\n"/>
          <admst:apply-templates select="code" match="evaluatetopology"/>
          <admst:text format="}\n"/>
      </admst:for-each>
      <admst:text format="/* -- CASE END -- */;\n"/>
    </admst:when>
    <admst:when test="[datatypename='contribution']">
      <admst:if test="lhs[discipline/potential=nature]">
        <admst:choose>
          <admst:when test="lhs/branch[grounded='no']">
            <admst:text test="lhs/branch/nnode[location='internal']"
              format="here->%(lhs/branch/nnode/name)Node = here->%(lhs/branch/pnode/name)Node; /* nnode collapsed */\n  here->%(lhs/branch/nnode/name)Node_mine = 0;\n"/>
            <admst:text test="lhs/branch/pnode[location='internal']"
              format="here->%(lhs/branch/pnode/name)Node = here->%(lhs/branch/nnode/name)Node; /* pnode collapsed */\n  here->%(lhs/branch/pnode/name)Node_mine = 0;\n"/>
          </admst:when>
          <admst:otherwise>
            <admst:text format="here->%(lhs/branch/pnode/name)Node = 0; /* pnode collapsed to GND */ \n  here->%(lhs/branch/pnode/name)Node_mine = 0;\n"/>
          </admst:otherwise>
        </admst:choose>
      </admst:if>
      <admst:variable name="contribution" select="%(.)"/>
      <admst:variable name="psource" select="%(lhs/branch/pnode)"/>
      <admst:variable name="nsource" select="%(lhs/branch/nnode)"/>
      <admst:for-each select="rhs/probe">
        <admst:variable name="pprobe" select="%(branch/pnode)"/>
        <admst:variable name="nprobe" select="%(branch/nnode)"/>
        <admst:choose>
          <admst:when test="$contribution[static='yes']"> <admst:text format="  static_"/> </admst:when>
          <admst:when test="$contribution[dynamic='yes']"> <admst:text format="  dynamic_"/> </admst:when>
          <admst:when test="$contribution[whitenoise='yes']"> <admst:text format="  whitenoise_"/> </admst:when>
          <admst:when test="$contribution[flickernoise='yes']"> <admst:text format="  flickernoise_"/> </admst:when>
        </admst:choose>
        <admst:choose>
          <admst:when test="[($nprobe/grounded='no')and($nsource/grounded='no')]">
            <admst:text format="jacobian4(%($psource/name),%($nsource/name),%($pprobe/name),%($nprobe/name))\n"/>
          </admst:when>
          <admst:when test="[($nprobe/grounded='no')and($nsource/grounded='yes')]">
            <admst:text format="jacobian2p(%($psource/name),%($pprobe/name),%($nprobe/name))\n"/>
          </admst:when>
          <admst:when test="[$nsource/grounded='no']">
            <admst:text format="jacobian2s(%($psource/name),%($nsource/name),%($pprobe/name))\n"/>
          </admst:when>
          <admst:when test="[$nsource/grounded='yes']">
            <admst:text format="jacobian1(%($psource/name),%($pprobe/name))\n"/>
          </admst:when>
        </admst:choose>
      </admst:for-each>
    </admst:when>
    <admst:when test="[datatypename='assignment']">
      <admst:if test="[(lhs/insource='yes') and (lhs/OPdependent='no')]">
        <admst:apply-templates select="lhs" match="variable:lhs"/>
        <admst:text format="="/>
        <admst:apply-templates select="rhs" match="expression:stringify:noprobe"/>
        <admst:text format="%s;\n"/>
      </admst:if>
    </admst:when>
    <admst:when test="[datatypename='block']">
      <admst:apply-templates select="item" match="evaluatetopology"/>
    </admst:when>
    <admst:when test="[datatypename='expression']"/>
    <admst:when test="[datatypename='probe']"/>
    <admst:when test="[datatypename='variable']"/>
    <admst:when test="[datatypename='mapply_unary']"/>
    <admst:when test="[datatypename='mapply_binary']"/>
    <admst:when test="[datatypename='mapply_ternary']"/>
    <admst:when test="[datatypename='function']"/>
    <admst:when test="[datatypename='number']"/>
    <admst:when test="[datatypename='string']"/>
    <admst:when test="[datatypename='nilled']"/>
    <admst:when test="[datatypename='blockvariable']"/>
    <admst:otherwise>
      <admst:fatal format="%(datatypename): adms element not implemented\n"/>
    </admst:otherwise>
  </admst:choose>
</admst:template>

<admst:template match="code">

#include &quot;ngspice/ngspice.h&quot;
#include &quot;ngspice/cktdefs.h&quot;
#include &quot;ngspice/smpdefs.h&quot;
#include &quot;$(module)defs.h&quot;
#include &quot;ngspice/const.h&quot;
#include &quot;ngspice/sperror.h&quot;
#include &quot;ngspice/ifsim.h&quot;
#include &quot;ngspice/suffix.h&quot;

#define  ELECTRON_CHARGE        1.602191770e-19         /* C */
#define  BOLTZMANN              1.38062259e-23          /* J/oK */

#define jacobian(a,b) here-&gt;PTR_J_##a##_##b##_required=1;
#define static_jacobian4(p,q,r,s)  jacobian(p,r) jacobian(p,s) jacobian(q,r) jacobian(q,s)
#define static_jacobian2s(p,q,r)   jacobian(p,r) jacobian(q,r)
#define static_jacobian2p(p,r,s)   jacobian(p,r) jacobian(p,s)
#define static_jacobian1(p,r)      jacobian(p,r)
#define dynamic_jacobian4(p,q,r,s) jacobian(p,r) jacobian(p,s) jacobian(q,r) jacobian(q,s)
#define dynamic_jacobian2s(p,q,r)  jacobian(p,r) jacobian(q,r)
#define dynamic_jacobian2p(p,r,s)  jacobian(p,r) jacobian(p,s)
#define dynamic_jacobian1(p,r)     jacobian(p,r)
#define whitenoise_jacobian4(p,q,r,s)
#define whitenoise_jacobian2s(p,q,r)
#define whitenoise_jacobian2p(p,r,s)
#define whitenoise_jacobian1(p)
#define flickernoise_jacobian4(p,q,r,s)
#define flickernoise_jacobian2s(p,q,r)
#define flickernoise_jacobian2p(p,r,s)
#define flickernoise_jacobian1(p)


int $(module)guesstopology (SMPmatrix *matrix, CKTcircuit *ckt, $(module)model *model, $(module)instance *here)
     /* guess topology */
{
  NG_IGNOREABLE(matrix);
  NG_IGNOREABLE(ckt);

<admst:template match="evaluate.localvariables">
  <admst:choose>
    <admst:when test="[datatypename='assignment']">
      <admst:if test="[(lhs/insource='yes') and (lhs/OPdependent='no')]">
        <admst:push select="lhs[scope='local']" into="$localvariables" onduplicate="ignore"/>
      </admst:if>
    </admst:when>
    <admst:when test="[datatypename='block']">
      <admst:apply-templates select="item" match="evaluate.localvariables"/>
    </admst:when>
    <admst:when test="[datatypename='conditional']">
      <admst:push select="if/variable[scope='local' and OPdependent='no']" into="$localvariables" onduplicate="ignore"/>
      <admst:apply-templates select="then" match="evaluate.localvariables"/>
      <admst:apply-templates select="else" match="evaluate.localvariables"/>
    </admst:when>
    <admst:when test="[datatypename='whileloop']">
      <admst:apply-templates select="whileblock" match="evaluate.localvariables"/>
    </admst:when>
    <admst:when test="[datatypename='case']">
      <admst:apply-templates select="caseitem/code" match="evaluate.localvariables"/>
    </admst:when>
    <admst:when test="[datatypename='contribution']"/>
    <admst:when test="[datatypename='nilled']"/>
    <admst:when test="[datatypename='callfunction']"/>
    <admst:when test="[datatypename='blockvariable']"/>
    <admst:otherwise>
      <admst:error format="'%(datatypename): should not be reached\n"/>
    </admst:otherwise>
  </admst:choose>
</admst:template>
  <admst:for-each select="analog/code[datatypename='block']/item">
    <admst:if test="[(datatypename!='block') or (datatypename='block'
         and name!='initial_model' and name!='initializeModel' and name!='initial_instance' and name!='initializeInstance')]">
      <admst:apply-templates select="." match="evaluate.localvariables"/>
    </admst:if>
  </admst:for-each>
  <admst:for-each select="$localvariables">
    <admst:if test="[type='integer']">int %(name);\n</admst:if>
    <admst:if test="[type='real']">double %(name)=0.0/0.0;\n</admst:if>
    <admst:if test="[type='string']">char* %(name);\n</admst:if>
  </admst:for-each>
  <admst:for-each select="analog/code[datatypename='block']/item">
    <admst:if test="[(datatypename!='block') or (datatypename='block'
         and name!='initial_model' and name!='initializeModel' and name!='initial_instance' and name!='initializeInstance')]">
      <admst:apply-templates select="." match="evaluatetopology"/>
    </admst:if>
  </admst:for-each>
  return(OK);
}

</admst:template>

<admst:variable name="localvariables"/>
<admst:for-each select="/module">
  <!-- fixme, this $(module) variable diverts from other usage pattern -->
  <admst:variable name="module" select="%(attribute[name='ngspicename']/value)"/>
  <admst:open file="$(module)guesstopology.c">
    <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:message format="$(module)guesstopology.c: file created\n"/>
</admst:for-each>

</admst>
