Qucs-core  0.0.19
qucs_producer.cpp
Go to the documentation of this file.
00001 /*
00002  * qucs_producer.cpp - the Qucs netlist producer
00003  *
00004  * Copyright (C) 2004-2011 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  * 
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.  
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <time.h>
00032 #include <string.h>
00033 #include <ctype.h>
00034 
00035 #include "object.h"
00036 #include "complex.h"
00037 #include "vector.h"
00038 #include "dataset.h"
00039 #include "netdefs.h"
00040 #include "check_spice.h"
00041 #include "check_vcd.h"
00042 #include "hash.h"
00043 
00044 /* Global variables. */
00045 FILE * qucs_out = NULL;
00046 int    qucs_actions = 1;
00047 const char * qucs_gnd = "gnd";
00048 
00049 qucs::hash<struct node_t> qucs_nodes;
00050 
00051 /* Looks through the given list if there is such a node already in the
00052    list and returns non-zero if so, otherwise the function returns
00053    zero. */
00054 int qucs_find_node (struct node_t * root, char * node) {
00055   for (struct node_t * n = root; n; n = n->next) {
00056     if (!strcmp (node, n->node)) return 1;
00057   }
00058   return 0;
00059 }
00060 
00061 /* Adds the given node list to the overall node list without
00062    duplicating the nodes. */
00063 void qucs_add_nodes (struct node_t * node) {
00064   while (node) {
00065     if (!qucs_nodes.get (node->node))
00066       qucs_nodes.put (node->node, node);
00067     node = node->next;
00068   }
00069 }
00070 
00071 /* Deletes the given node list. */
00072 void qucs_free_nodes (struct node_t * node) {
00073   struct node_t * n;
00074   for ( ; node; node = n) {
00075     n = node->next;
00076     free (node->node);
00077     free (node);
00078   }
00079 }
00080 
00081 /* The function deletes the collected qucs nodes. */
00082 static void qucs_delete_nodes (void) {
00083   qucs_nodes.clear ();
00084 }
00085 
00086 /* Collects all nodes within the given definition root. */
00087 static void qucs_collect_nodes (struct definition_t * root) {
00088   while (root) {
00089     qucs_add_nodes (root->nodes);
00090     root = root->next;
00091   }
00092 }
00093 
00094 /* Prints value representation. */
00095 static void netlist_list_value (struct value_t * value) {
00096   if (value == NULL)
00097     fprintf (qucs_out, "[]");
00098   else if (value->ident)
00099     fprintf (qucs_out, "%s", value->ident);
00100   else if (value->next) {
00101     fprintf (qucs_out, "[");
00102     for (; value != NULL; value = value->next)
00103       fprintf (qucs_out, "%g%s", value->value, value->next ? ";" : "");
00104     fprintf (qucs_out, "]");
00105   } else {
00106     fprintf (qucs_out, "%g", value->value);
00107     if (value->scale)
00108       fprintf (qucs_out, "%s", value->scale);
00109     if (value->unit)
00110       fprintf (qucs_out, "%s", value->unit);
00111   }
00112 }
00113 
00114 /* Returns a static string for an instance identifier usable in
00115    netlists based upon the given identifier. */
00116 static char * netlist_instance (const char * instance) {
00117   static char ret[256];
00118   sprintf (ret, "%s%s", isdigit (instance[0]) ? "X" : "", instance);
00119   return ret;
00120 }
00121 
00122 /* Prints a single definition on a single line. */
00123 static void netlist_list_def (struct definition_t * def, const char * prefix) {
00124   struct node_t * node;
00125   struct pair_t * pair;
00126   if (def->define == NULL) {
00127     if (def->text != NULL)
00128       fprintf (qucs_out, "%s# %s\n", prefix, def->text);
00129   }
00130   else {
00131     if (!qucs_actions) {
00132       // skip specific actions if required
00133       if (def->action && strcmp (def->type, "Def")) return;
00134     }
00135     fprintf (qucs_out, "%s%s%s:%s", prefix, def->action ? "." : "",
00136              def->type, netlist_instance (def->instance));
00137     for (node = def->nodes; node != NULL; node = node->next)
00138       fprintf (qucs_out, " %s", node->node);
00139     for (pair = def->pairs; pair != NULL; pair = pair->next) {
00140       fprintf (qucs_out, " %s=\"", pair->key);
00141       netlist_list_value (pair->value);
00142       fprintf (qucs_out, "\"");
00143     }
00144     fprintf (qucs_out, "\n");
00145   }
00146 }
00147 
00148 /* Prints definition list representation. */
00149 static void netlist_lister (struct definition_t * root, const char * prefix) {
00150   struct definition_t * def;
00151   for (def = root; def != NULL; def = def->next) {
00152     if (def->sub != NULL) {
00153       netlist_list_def (def, prefix);
00154       netlist_lister (def->sub, "  ");
00155       fprintf (qucs_out, ".Def:End\n");
00156     }
00157     else {
00158       netlist_list_def (def, prefix);
00159     }
00160   }
00161 }
00162 
00163 /* Goes recursively through the netlist and applies additional
00164    reference node modifications to subcircuits and their instances. */
00165 static void netlist_fix_reference (struct definition_t * root) {
00166   struct definition_t * def;
00167   struct node_t * n;
00168 
00169   // go through definitions
00170   for (def = root; def != NULL; def = def->next) {
00171     if (!strcmp (def->type, "Sub")) { // subcircuit instances
00172       n = create_node ();
00173       n->node = strdup (qucs_gnd);
00174       n->next = def->nodes;
00175       def->nodes = n;
00176     }
00177     else if (def->sub != NULL) {     // subcircuit definitions
00178       n = create_node ();
00179       n->node = strdup (qucs_gnd);
00180       n->next = def->nodes;
00181       def->nodes = n;
00182       netlist_fix_reference (def->sub);
00183     }
00184   }
00185 }
00186 
00187 /* Applies reference node modifications if necessary. */
00188 static void netlist_reference_ground (void) {
00189   struct definition_t * def;
00190 
00191   // return if nothing todo
00192   if (qucs_gnd && !strcmp (qucs_gnd, "gnd")) return;
00193 
00194   netlist_fix_reference (definition_root);
00195   // go through subcircuits
00196   for (def = subcircuit_root; def != NULL; def = def->next) {
00197     netlist_fix_reference (def->sub);
00198   }
00199 }
00200 
00201 /* Look for a single subcircuit definition in a netlist. */
00202 static struct definition_t *
00203 netlist_get_single_subcircuit (struct definition_t * root) {
00204   int count = 0;
00205   struct definition_t * ret = NULL;
00206   for (struct definition_t * def = root; def != NULL; def = def->next) {
00207     if (!def->action) {
00208       count++;
00209     } else if (def->sub) {
00210       count++;
00211       ret = def;
00212     }
00213   }
00214   return (count == 1) ? ret : NULL;
00215 }
00216 
00217 /* Prints the overall netlist representation. */
00218 static void netlist_list (void) {
00219   struct node_t * n;
00220   struct definition_t * def;
00221   time_t t = time (NULL);
00222   fprintf (qucs_out, "# converted Qucs netlist processed at %s\n", ctime (&t));
00223   if (spice_title != NULL) {
00224     fprintf (qucs_out, "#\n# %s#\n\n", spice_title);
00225   }
00226   netlist_lister (definition_root, "");
00227   for (def = subcircuit_root; def != NULL; def = def->next) {
00228     fprintf (qucs_out, ".Def:%s\n", netlist_instance (def->instance));
00229     netlist_lister (def->sub, "  ");
00230     fprintf (qucs_out, ".Def:End\n");
00231   }
00232   /* Instantiate subcircuit if there is just a single definition. */
00233   if (definition_root != NULL && subcircuit_root == NULL &&
00234       (def = netlist_get_single_subcircuit (definition_root)) != NULL) {
00235     fprintf (qucs_out, "\n# no instance of subcircuit \"%s\" found, "
00236              "creating it\n", netlist_instance (def->instance));
00237     fprintf (qucs_out, "Sub:X1");
00238     for (n = def->nodes; n; n = n->next) fprintf (qucs_out, " %s", n->node);
00239     fprintf (qucs_out, " Type=\"%s\"\n", netlist_instance (def->instance));
00240   }
00241   /* Print overall (toplevel only) node list. */
00242   qucs_collect_nodes (definition_root);
00243   fprintf (qucs_out, "\n### TOPLEVEL NODELIST BEGIN\n");
00244   for (qucs::hashiterator<struct node_t> it (qucs_nodes); *it; ++it) {
00245     n = it.currentVal ();
00246     fprintf (qucs_out, "# %s\n", n->node);
00247   }
00248   qucs_delete_nodes ();
00249   fprintf (qucs_out, "### TOPLEVEL NODELIST END\n");
00250   /* Print potential external node list. */
00251   fprintf (qucs_out, "\n### SPICE OUTPUT NODELIST BEGIN\n");
00252   for (n = spice_nodes; n; n = n->next) {
00253     fprintf (qucs_out, "# %s\n", n->node);
00254   }
00255   fprintf (qucs_out, "### SPICE OUTPUT NODELIST END\n");
00256 }
00257 
00258 /* This function is the overall Qucs netlist producer. */
00259 void qucs_producer (void) {
00260   if (qucs_out != NULL) {
00261     netlist_reference_ground ();
00262     netlist_list ();
00263   }
00264 }
00265 
00266 // Structure defining Qucs schematic entries of device models.
00267 struct device_t {
00268   const char * ntype;      // netlist type
00269   const char * ltype;      // schematic type
00270   const char * stype;      // spice type
00271   int nodes;               // number of nodes
00272   const char * props[128]; // list of properties in schematic order
00273   const char * symbol;     // symbol text
00274   const char * coords;     // coordinates and other text
00275   const char * ports;      // subcircuit ports
00276 }
00277 qucs_devices[] = {
00278   /* diode */
00279   { "Diode", "Diode", "D", 2,
00280     {"Is", "N", "Cj0", "M", "Vj", "Fc", "Cp", "Isr", "Nr", "Rs", "Tt", "Ikf",
00281      "Kf", "Af", "Ffe", "Bv", "Ibv",  "Temp", "Xti", "Eg", "Tbv", "Trs",
00282      "Ttt1", "Ttt2", "Tm1", "Tm2", "Tnom", "Area", NULL },
00283     NULL,
00284     "1 0 0 -26 13 0 0",
00285     NULL
00286   },
00287   /* bipolar transistor */
00288   { "BJT", "_BJT", "Q", 4,
00289     { "Type", "Is", "Nf", "Nr", "Ikf", "Ikr", "Vaf", "Var", "Ise", "Ne", "Isc",
00290       "Nc", "Bf", "Br", "Rbm", "Irb", "Rc", "Re", "Rb", "Cje", "Vje", "Mje",
00291       "Cjc", "Vjc", "Mjc", "Xcjc", "Cjs", "Vjs", "Mjs", "Fc", "Tf", "Xtf",
00292       "Vtf", "Itf", "Tr", "Temp", "Kf", "Af", "Ffe", "Kb", "Ab", "Fb", "Ptf",
00293       "Xtb", "Xti", "Eg", "Tnom", "Area", NULL },
00294     NULL,
00295     "1 0 0 8 -26 0 0",
00296     NULL
00297   },
00298   /* hicum/l0 bipolar transistor */
00299   { "hic0_full", "hic0_full", "Q", 5,
00300     { "Type", "is", "mcf", "mcr", "vef", "iqf", "iqr", "iqfh", "tfh", "ibes",
00301       "mbe", "ires", "mre", "ibcs", "mbc", "cje0", "vde", "ze", "aje", "t0",
00302       "dt0h", "tbvl", "tef0", "gte", "thcs", "ahc", "tr", "rci0", "vlim",
00303       "vpt", "vces", "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx",
00304       "vptcx", "fbc", "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re",
00305       "itss", "msf", "iscs", "msc", "cjs0", "vds", "zs", "vpts", "cbcpar",
00306       "cbepar", "eavl", "kavl", "kf", "af", "vgb", "vge", "vgc", "vgs",
00307       "f1vg", "f2vg", "alt0", "kt0", "zetact", "zetabet", "zetaci", "alvs",
00308       "alces", "zetarbi", "zetarbx", "zetarcx", "zetare", "alkav", "aleav",
00309       "flsh", "rth", "cth", "tnom", "dt", "Temp", NULL },
00310     NULL,
00311     "1 0 0 8 -26 0 0",
00312     NULL
00313   },
00314   /* hicum/l0 v1.2 bipolar transistor */
00315   { "hicumL0V1p2", "hicumL0V1p2", "Q", 5,
00316     { "Type", "is", "mcf", "mcr", "vef", "ver", "iqf", "fiqf", "iqr", "iqfh",
00317       "tfh", "ahq", "ibes", "mbe", "ires", "mre", "ibcs", "mbc", "cje0", "vde",
00318       "ze", "aje", "vdedc", "zedc", "ajedc", "t0", "dt0h", "tbvl", "tef0",
00319       "gte", "thcs", "ahc", "tr", "rci0", "vlim", "vpt", "vces", "cjci0",
00320       "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc", "rbi0",
00321       "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re", "itss", "msf", "iscs", "msc",
00322       "cjs0", "vds", "zs", "vpts", "cbcpar", "cbepar", "eavl", "kavl", "kf",
00323       "af", "vgb", "vge", "vgc", "vgs", "f1vg", "f2vg", "alt0", "kt0",
00324       "zetact", "zetabet", "zetaci", "alvs", "alces", "zetarbi", "zetarbx",
00325       "zetarcx", "zetare", "zetaiqf", "alkav", "aleav", "zetarth", "flsh",
00326       "rth", "cth", "tnom", "dt", "Temp", NULL },
00327     NULL,
00328     "1 0 0 8 -26 0 0",
00329     NULL
00330   },
00331   /* hicum/l0 v1.2g bipolar transistor */
00332   { "hicumL0V1p2g", "hicumL0V1p2g", "Q", 5,
00333     { "Type", "is", "mcf", "mcr", "vef", "ver", "iqf", "fiqf", "iqr", "iqfh",
00334       "iqfe", "ahq", "ibes", "mbe", "ires", "mre", "ibcs", "mbc", "cje0",
00335       "vde", "ze", "aje", "vdedc", "zedc", "ajedc", "t0", "dt0h", "tbvl",
00336       "tef0", "gte", "thcs", "ahc", "tr", "rci0", "vlim", "vpt", "vces",
00337       "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc",
00338       "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re", "itss", "msf",
00339       "iscs", "msc", "cjs0", "vds", "zs", "vpts", "cbcpar", "cbepar", "eavl",
00340       "kavl", "kf", "af", "vgb", "vge", "vgc", "vgs", "f1vg", "f2vg", "alt0",
00341       "kt0", "zetact", "zetabet", "zetaci", "alvs", "alces", "zetarbi",
00342       "zetarbx", "zetarcx", "zetare", "zetaiqf", "alkav", "aleav", "flsh",
00343       "rth", "zetarth", "cth", "tnom", "dt", "delte", "deltc", "zetaver",
00344       "zetavef", "ibhrec", "Temp", NULL },
00345     NULL,
00346     "1 0 0 8 -26 0 0",
00347     NULL
00348   },
00349   /* hicum/l0 v1.3 bipolar transistor */
00350   { "hicumL0V1p3", "hicumL0V1p3", "Q", 5,
00351     { "Type", "is", "it_mod", "mcf", "mcr", "vef", "ver", "aver", "iqf",
00352       "fiqf", "iqr", "iqfh", "tfh", "ahq", "ibes", "mbe", "ires", "mre",
00353       "ibcs", "mbc", "cje0", "vde", "ze", "aje", "vdedc", "zedc", "ajedc",
00354       "t0", "dt0h", "tbvl", "tef0", "gte", "thcs", "ahc", "tr", "rci0",
00355       "vlim", "vpt", "vces", "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx",
00356       "zcx", "vptcx", "fbc", "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx",
00357       "re", "itss", "msf", "iscs", "msc", "cjs0", "vds", "zs", "vpts",
00358       "cbcpar", "cbepar", "eavl", "kavl", "kf", "af", "vgb", "vge", "vgc",
00359       "vgs", "f1vg", "f2vg", "alt0", "kt0", "zetact", "zetabet", "zetaci",
00360       "alvs", "alces", "zetarbi", "zetarbx", "zetarcx", "zetare", "zetaiqf",
00361       "alkav", "aleav", "zetarth", "tef_temp", "zetaver", "zetavgbe", "dvgbe",
00362       "aliqfh", "kiqfh", "flsh", "rth", "cth", "tnom", "dt", "Temp", NULL },
00363     NULL,
00364     "1 0 0 8 -26 0 0",
00365     NULL
00366   },
00367   /* hicum/l2 v2.22 bipolar transistor */
00368   { "hic2_full", "hic2_full", "Q", 5,
00369     { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
00370       "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
00371       "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
00372       "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
00373       "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
00374       "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
00375       "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
00376       "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
00377       "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
00378       "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
00379       "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
00380       "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
00381       "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
00382       "flcomp", "tnom", "dt", "Temp", NULL },
00383     NULL,
00384     "1 0 0 8 -26 0 0",
00385     NULL
00386   },
00387   /* hicum/l2 v2.1 bipolar transistor */
00388   { "hicumL2V2p1", "hicumL2V2p1", "Q", 5,
00389     { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis",
00390       "mbei", "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf",
00391       "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "favl", "qavl",
00392       "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi", "fqi", "re",
00393       "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu", "cjei0",
00394       "vdei", "zei", "aljei", "cjep0", "vdep", "zep", "aljep", "cjci0",
00395       "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc", "cjs0",
00396       "vds", "zs", "vpts", "t0", "dt0h", "tbvl", "tef0", "gtfe", "thcs",
00397       "alhc", "fthc", "rci0", "vlim", "vces", "vpt", "tr", "ceox", "ccox",
00398       "alqf", "alit", "kf", "af", "krbi", "latb", "latl", "vgb", "alt0",
00399       "kt0", "zetaci", "zetacx", "alvs", "alces", "zetarbi", "zetarbx",
00400       "zetarcx", "zetare", "alb", "rth", "cth", "tnom", "dt", "Temp", NULL },
00401     NULL,
00402     "1 0 0 8 -26 0 0",
00403     NULL
00404   },
00405   /* hicum/l2 v2.23 bipolar transistor */
00406   { "hicumL2V2p23", "hicumL2V2p23", "Q", 5,
00407     { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
00408       "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
00409       "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
00410       "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
00411       "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
00412       "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
00413       "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
00414       "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
00415       "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
00416       "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
00417       "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
00418       "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
00419       "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
00420       "flcomp", "tnom", "dt", "Temp", NULL },
00421     NULL,
00422     "1 0 0 8 -26 0 0",
00423     NULL
00424   },
00425   /* hicum/l2 v2.24 bipolar transistor */
00426   { "hicumL2V2p24", "hicumL2V2p24", "Q", 5,
00427     { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
00428       "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
00429       "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
00430       "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
00431       "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
00432       "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
00433       "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
00434       "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
00435       "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
00436       "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
00437       "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
00438       "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
00439       "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
00440       "flcomp", "tnom", "dt", "Temp", NULL },
00441     NULL,
00442     "1 0 0 8 -26 0 0",
00443     NULL
00444   },
00445   /* junction FET */
00446   { "JFET", "JFET", "J", 3,
00447     { "Type", "Vt0", "Beta", "Lambda", "Rd", "Rs", "Is", "N", "Isr", "Nr",
00448       "Cgs", "Cgd", "Pb", "Fc", "M", "Kf", "Af", "Ffe", "Temp", "Xti",
00449       "Vt0tc", "Betatce", "Tnom", "Area", NULL },
00450     NULL,
00451     "1 190 140 30 -49 0 0",
00452     NULL
00453   },
00454   /* MOSFET */
00455   { "MOSFET", "_MOSFET", "M", 4,
00456     { "Type", "Vt0", "Kp", "Gamma", "Phi", "Lambda", "Rd", "Rs", "Rg", "Is",
00457       "N", "W", "L", "Ld", "Tox", "Cgso", "Cgdo", "Cgbo", "Cbd", "Cbs", "Pb",
00458       "Mj", "Fc", "Cjsw", "Mjsw", "Tt", "Nsub", "Nss", "Tpg", "Uo", "Rsh",
00459       "Nrd", "Nrs", "Cj", "Js", "Ad", "As", "Pd", "Ps", "Kf", "Af", "Ffe",
00460       "Temp", "Tnom", NULL },
00461     NULL,
00462     "1 0 0 8 -26 0 0",
00463     NULL
00464   },
00465   { NULL, NULL, NULL, 0, { NULL }, NULL, NULL, NULL }
00466 };
00467 
00468 /* Looks through the list of available Qucs devices.  Returns NULL if
00469    there is no such device. */
00470 static struct device_t * qucslib_find_device (char * type) {
00471   struct device_t * dev;
00472   for (dev = qucs_devices; dev->ntype; dev++) {
00473     if (!strcmp (dev->ntype, type))
00474       return dev;
00475   }
00476   return NULL;
00477 }
00478 
00479 /* This function tries to find the given property in the key/value
00480    pairs of the given netlist entry and returns NULL if there is no
00481    such property. */
00482 static struct pair_t *
00483 qucslib_find_prop (struct definition_t * def, const char * key) {
00484   struct pair_t * pair;
00485   for (pair = def->pairs; pair; pair = pair->next) {
00486     if (!strcmp (pair->key, key))
00487       return pair;
00488   }
00489   return NULL;
00490 }
00491 
00492 /* The function outputs a device library entry in the Qucs schematic
00493    data format. */
00494 static void qucslib_list_device (struct definition_t * def) {
00495   struct device_t * dev;
00496   if (!(dev = qucslib_find_device (def->type))) return;
00497   struct pair_t * pair;
00498   char txt[1024];
00499   
00500   sprintf (txt, "\n<Component %s>\n", def->instance[0] == dev->stype[0] ?
00501            &def->instance[1] : def->instance);
00502   fprintf (qucs_out, "%s", txt);
00503   fprintf (qucs_out, "  <Description>\n");
00504   fprintf (qucs_out, "  </Description>\n");
00505   fprintf (qucs_out, "  <Model>\n");
00506   fprintf (qucs_out, "    <%s %s_ %s", dev->ltype,
00507            netlist_instance (def->instance), dev->coords);
00508   for (int i = 0; dev->props[i]; i++) {
00509     if ((pair = qucslib_find_prop (def, dev->props[i])) != NULL) {
00510       fprintf (qucs_out, " \"");
00511       netlist_list_value (pair->value);
00512       fprintf (qucs_out, "\" 0");
00513     }
00514   }
00515   fprintf (qucs_out, ">\n");
00516   fprintf (qucs_out, "  </Model>\n");
00517   fprintf (qucs_out, "</Component>\n");
00518 }
00519 
00520 /* This function is the overall Qucs library producer. */
00521 void qucslib_producer (void) {
00522   struct definition_t * def;
00523   fprintf (qucs_out, "<Qucs Library " PACKAGE_VERSION " \"Generic\">\n");
00524   for (def = device_root; def; def = def->next) {
00525     qucslib_list_device (def);
00526   }
00527 }
00528 
00529 /* This function is the Qucs dataset producer for VCD files. */
00530 void qucsdata_producer_vcd (void) {
00531   struct dataset_variable * ds;
00532   struct dataset_value * dv;
00533   fprintf (qucs_out, "<Qucs Dataset " PACKAGE_VERSION ">\n");
00534   for (ds = dataset_root; ds; ds = ds->next) {
00535     if (!ds->output || ds->type == DATA_UNKNOWN)
00536       continue;
00537     if (ds->type == DATA_INDEPENDENT)
00538       fprintf (qucs_out, "<indep %s %d>\n", ds->ident, ds->size);
00539     else if (ds->type == DATA_DEPENDENT)
00540       fprintf (qucs_out, "<dep %s.%s %s>\n", ds->ident, ds->isreal ? "R" : "X",
00541                ds->dependencies);
00542     for (dv = ds->values; dv; dv = dv->next) {
00543       fprintf (qucs_out, "  %s\n", dv->value);
00544     }
00545     if (ds->type == DATA_INDEPENDENT)
00546       fprintf (qucs_out, "</indep>\n");
00547     else if (ds->type == DATA_DEPENDENT)
00548       fprintf (qucs_out, "</dep>\n");
00549   }
00550 }
00551 
00552 /* This function is the Qucs dataset producer. */
00553 void qucsdata_producer (dataset * data) {
00554   data->print ();
00555 }