<?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="_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:otherwise><admst:return name="fname" value="%(name)"/></admst:otherwise>
  </admst:choose>
</admst:template>

<admst:template match="function">
  <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']">
      <admst:for-each select="arguments[position(.)=1]">
        <admst:if test="[datatypename!='variable']">
          <admst:error format="$given: argument is not a variable\n"/>
        </admst:if>
        <admst:if test="[input='no']">
          <admst:value-of select="name"/>
          <admst:error format="$given(%s): argument is not a parameter\n"/>
        </admst:if>
        <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="$given(%s): should not be reached\n"/>
          </admst:otherwise>
        </admst:choose>
      </admst:for-each>
    </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: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='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"/>
            <admst:text test="lhs/branch/pnode[location='internal']"
              format="here->%(lhs/branch/pnode/name)Node = here->%(lhs/branch/nnode/name)Node; /* pnode collapsed */ \n"/>
          </admst:when>
          <admst:otherwise>
            <admst:text format="here->%(lhs/branch/pnode/name)Node = 0; /* pnode collapsed to GND */ \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 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">
  <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) - %(/simulator/currentdate) ***/\n"/>
    <admst:apply-templates select="." match="code"/>
  </admst:open>
  <admst:message format="$(module)guesstopology.c: file created\n"/>
</admst:for-each>

</admst>
