My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
qucs_producer.cpp
Go to the documentation of this file.
1 /*
2  * qucs_producer.cpp - the Qucs netlist producer
3  *
4  * Copyright (C) 2004-2011 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: qucs_producer.cpp 1826 2011-03-12 01:00:56Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include "object.h"
36 #include "complex.h"
37 #include "vector.h"
38 #include "dataset.h"
39 #include "netdefs.h"
40 #include "check_spice.h"
41 #include "check_vcd.h"
42 #include "hash.h"
43 
44 /* Global variables. */
45 FILE * qucs_out = NULL;
46 int qucs_actions = 1;
47 const char * qucs_gnd = "gnd";
48 
50 
51 /* Looks through the given list if there is such a node already in the
52  list and returns non-zero if so, otherwise the function returns
53  zero. */
54 int qucs_find_node (struct node_t * root, char * node) {
55  for (struct node_t * n = root; n; n = n->next) {
56  if (!strcmp (node, n->node)) return 1;
57  }
58  return 0;
59 }
60 
61 /* Adds the given node list to the overall node list without
62  duplicating the nodes. */
63 void qucs_add_nodes (struct node_t * node) {
64  while (node) {
65  if (!qucs_nodes.get (node->node))
66  qucs_nodes.put (node->node, node);
67  node = node->next;
68  }
69 }
70 
71 /* Deletes the given node list. */
72 void qucs_free_nodes (struct node_t * node) {
73  struct node_t * n;
74  for ( ; node; node = n) {
75  n = node->next;
76  if (node->node) free (node->node);
77  free (node);
78  }
79 }
80 
81 /* The function deletes the collected qucs nodes. */
82 static void qucs_delete_nodes (void) {
83  qucs_nodes.clear ();
84 }
85 
86 /* Collects all nodes within the given definition root. */
87 static void qucs_collect_nodes (struct definition_t * root) {
88  while (root) {
89  qucs_add_nodes (root->nodes);
90  root = root->next;
91  }
92 }
93 
94 /* Prints value representation. */
95 static void netlist_list_value (struct value_t * value) {
96  if (value == NULL)
97  fprintf (qucs_out, "[]");
98  else if (value->ident)
99  fprintf (qucs_out, "%s", value->ident);
100  else if (value->next) {
101  fprintf (qucs_out, "[");
102  for (; value != NULL; value = value->next)
103  fprintf (qucs_out, "%g%s", value->value, value->next ? ";" : "");
104  fprintf (qucs_out, "]");
105  } else {
106  fprintf (qucs_out, "%g", value->value);
107  if (value->scale)
108  fprintf (qucs_out, "%s", value->scale);
109  if (value->unit)
110  fprintf (qucs_out, "%s", value->unit);
111  }
112 }
113 
114 /* Returns a static string for an instance identifier usable in
115  netlists based upon the given identifier. */
116 static char * netlist_instance (const char * instance) {
117  static char ret[256];
118  sprintf (ret, "%s%s", isdigit (instance[0]) ? "X" : "", instance);
119  return ret;
120 }
121 
122 /* Prints a single definition on a single line. */
123 static void netlist_list_def (struct definition_t * def, const char * prefix) {
124  struct node_t * node;
125  struct pair_t * pair;
126  if (def->define == NULL) {
127  if (def->text != NULL)
128  fprintf (qucs_out, "%s# %s\n", prefix, def->text);
129  }
130  else {
131  if (!qucs_actions) {
132  // skip specific actions if required
133  if (def->action && strcmp (def->type, "Def")) return;
134  }
135  fprintf (qucs_out, "%s%s%s:%s", prefix, def->action ? "." : "",
136  def->type, netlist_instance (def->instance));
137  for (node = def->nodes; node != NULL; node = node->next)
138  fprintf (qucs_out, " %s", node->node);
139  for (pair = def->pairs; pair != NULL; pair = pair->next) {
140  fprintf (qucs_out, " %s=\"", pair->key);
141  netlist_list_value (pair->value);
142  fprintf (qucs_out, "\"");
143  }
144  fprintf (qucs_out, "\n");
145  }
146 }
147 
148 /* Prints definition list representation. */
149 static void netlist_lister (struct definition_t * root, const char * prefix) {
150  struct definition_t * def;
151  for (def = root; def != NULL; def = def->next) {
152  if (def->sub != NULL) {
153  netlist_list_def (def, prefix);
154  netlist_lister (def->sub, " ");
155  fprintf (qucs_out, ".Def:End\n");
156  }
157  else {
158  netlist_list_def (def, prefix);
159  }
160  }
161 }
162 
163 /* Goes recursively through the netlist and applies additional
164  reference node modifications to subcircuits and their instances. */
165 static void netlist_fix_reference (struct definition_t * root) {
166  struct definition_t * def;
167  struct node_t * n;
168 
169  // go through definitions
170  for (def = root; def != NULL; def = def->next) {
171  if (!strcmp (def->type, "Sub")) { // subcircuit instances
172  n = create_node ();
173  n->node = strdup (qucs_gnd);
174  n->next = def->nodes;
175  def->nodes = n;
176  }
177  else if (def->sub != NULL) { // subcircuit definitions
178  n = create_node ();
179  n->node = strdup (qucs_gnd);
180  n->next = def->nodes;
181  def->nodes = n;
182  netlist_fix_reference (def->sub);
183  }
184  }
185 }
186 
187 /* Applies reference node modifications if necessary. */
188 static void netlist_reference_ground (void) {
189  struct definition_t * def;
190 
191  // return if nothing todo
192  if (qucs_gnd && !strcmp (qucs_gnd, "gnd")) return;
193 
194  netlist_fix_reference (definition_root);
195  // go through subcircuits
196  for (def = subcircuit_root; def != NULL; def = def->next) {
197  netlist_fix_reference (def->sub);
198  }
199 }
200 
201 /* Look for a single subcircuit definition in a netlist. */
202 static struct definition_t *
203 netlist_get_single_subcircuit (struct definition_t * root) {
204  int count = 0;
205  struct definition_t * ret = NULL;
206  for (struct definition_t * def = root; def != NULL; def = def->next) {
207  if (!def->action) {
208  count++;
209  } else if (def->sub) {
210  count++;
211  ret = def;
212  }
213  }
214  return (count == 1) ? ret : NULL;
215 }
216 
217 /* Prints the overall netlist representation. */
218 static void netlist_list (void) {
219  struct node_t * n;
220  struct definition_t * def;
221  time_t t = time (NULL);
222  fprintf (qucs_out, "# converted Qucs netlist processed at %s\n", ctime (&t));
223  if (spice_title != NULL) {
224  fprintf (qucs_out, "#\n# %s#\n\n", spice_title);
225  }
226  netlist_lister (definition_root, "");
227  for (def = subcircuit_root; def != NULL; def = def->next) {
228  fprintf (qucs_out, ".Def:%s\n", netlist_instance (def->instance));
229  netlist_lister (def->sub, " ");
230  fprintf (qucs_out, ".Def:End\n");
231  }
232  /* Instantiate subcircuit if there is just a single definition. */
233  if (definition_root != NULL && subcircuit_root == NULL &&
234  (def = netlist_get_single_subcircuit (definition_root)) != NULL) {
235  fprintf (qucs_out, "\n# no instance of subcircuit \"%s\" found, "
236  "creating it\n", netlist_instance (def->instance));
237  fprintf (qucs_out, "Sub:X1");
238  for (n = def->nodes; n; n = n->next) fprintf (qucs_out, " %s", n->node);
239  fprintf (qucs_out, " Type=\"%s\"\n", netlist_instance (def->instance));
240  }
241  /* Print overall (toplevel only) node list. */
242  qucs_collect_nodes (definition_root);
243  fprintf (qucs_out, "\n### TOPLEVEL NODELIST BEGIN\n");
244  for (qucs::hashiterator<struct node_t> it (qucs_nodes); *it; ++it) {
245  n = it.currentVal ();
246  fprintf (qucs_out, "# %s\n", n->node);
247  }
248  qucs_delete_nodes ();
249  fprintf (qucs_out, "### TOPLEVEL NODELIST END\n");
250  /* Print potential external node list. */
251  fprintf (qucs_out, "\n### SPICE OUTPUT NODELIST BEGIN\n");
252  for (n = spice_nodes; n; n = n->next) {
253  fprintf (qucs_out, "# %s\n", n->node);
254  }
255  fprintf (qucs_out, "### SPICE OUTPUT NODELIST END\n");
256 }
257 
258 /* This function is the overall Qucs netlist producer. */
259 void qucs_producer (void) {
260  if (qucs_out != NULL) {
261  netlist_reference_ground ();
262  netlist_list ();
263  }
264 }
265 
266 // Structure defining Qucs schematic entries of device models.
267 struct device_t {
268  const char * ntype; // netlist type
269  const char * ltype; // schematic type
270  const char * stype; // spice type
271  int nodes; // number of nodes
272  const char * props[128]; // list of properties in schematic order
273  const char * symbol; // symbol text
274  const char * coords; // coordinates and other text
275  const char * ports; // subcircuit ports
276 }
277 qucs_devices[] = {
278  /* diode */
279  { "Diode", "Diode", "D", 2,
280  {"Is", "N", "Cj0", "M", "Vj", "Fc", "Cp", "Isr", "Nr", "Rs", "Tt", "Ikf",
281  "Kf", "Af", "Ffe", "Bv", "Ibv", "Temp", "Xti", "Eg", "Tbv", "Trs",
282  "Ttt1", "Ttt2", "Tm1", "Tm2", "Tnom", "Area", NULL },
283  NULL,
284  "1 0 0 -26 13 0 0",
285  NULL
286  },
287  /* bipolar transistor */
288  { "BJT", "_BJT", "Q", 4,
289  { "Type", "Is", "Nf", "Nr", "Ikf", "Ikr", "Vaf", "Var", "Ise", "Ne", "Isc",
290  "Nc", "Bf", "Br", "Rbm", "Irb", "Rc", "Re", "Rb", "Cje", "Vje", "Mje",
291  "Cjc", "Vjc", "Mjc", "Xcjc", "Cjs", "Vjs", "Mjs", "Fc", "Tf", "Xtf",
292  "Vtf", "Itf", "Tr", "Temp", "Kf", "Af", "Ffe", "Kb", "Ab", "Fb", "Ptf",
293  "Xtb", "Xti", "Eg", "Tnom", "Area", NULL },
294  NULL,
295  "1 0 0 8 -26 0 0",
296  NULL
297  },
298  /* hicum/l0 bipolar transistor */
299  { "hic0_full", "hic0_full", "Q", 5,
300  { "Type", "is", "mcf", "mcr", "vef", "iqf", "iqr", "iqfh", "tfh", "ibes",
301  "mbe", "ires", "mre", "ibcs", "mbc", "cje0", "vde", "ze", "aje", "t0",
302  "dt0h", "tbvl", "tef0", "gte", "thcs", "ahc", "tr", "rci0", "vlim",
303  "vpt", "vces", "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx",
304  "vptcx", "fbc", "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re",
305  "itss", "msf", "iscs", "msc", "cjs0", "vds", "zs", "vpts", "cbcpar",
306  "cbepar", "eavl", "kavl", "kf", "af", "vgb", "vge", "vgc", "vgs",
307  "f1vg", "f2vg", "alt0", "kt0", "zetact", "zetabet", "zetaci", "alvs",
308  "alces", "zetarbi", "zetarbx", "zetarcx", "zetare", "alkav", "aleav",
309  "flsh", "rth", "cth", "tnom", "dt", "Temp", NULL },
310  NULL,
311  "1 0 0 8 -26 0 0",
312  NULL
313  },
314  /* hicum/l0 v1.2 bipolar transistor */
315  { "hicumL0V1p2", "hicumL0V1p2", "Q", 5,
316  { "Type", "is", "mcf", "mcr", "vef", "ver", "iqf", "fiqf", "iqr", "iqfh",
317  "tfh", "ahq", "ibes", "mbe", "ires", "mre", "ibcs", "mbc", "cje0", "vde",
318  "ze", "aje", "vdedc", "zedc", "ajedc", "t0", "dt0h", "tbvl", "tef0",
319  "gte", "thcs", "ahc", "tr", "rci0", "vlim", "vpt", "vces", "cjci0",
320  "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc", "rbi0",
321  "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re", "itss", "msf", "iscs", "msc",
322  "cjs0", "vds", "zs", "vpts", "cbcpar", "cbepar", "eavl", "kavl", "kf",
323  "af", "vgb", "vge", "vgc", "vgs", "f1vg", "f2vg", "alt0", "kt0",
324  "zetact", "zetabet", "zetaci", "alvs", "alces", "zetarbi", "zetarbx",
325  "zetarcx", "zetare", "zetaiqf", "alkav", "aleav", "zetarth", "flsh",
326  "rth", "cth", "tnom", "dt", "Temp", NULL },
327  NULL,
328  "1 0 0 8 -26 0 0",
329  NULL
330  },
331  /* hicum/l0 v1.2g bipolar transistor */
332  { "hicumL0V1p2g", "hicumL0V1p2g", "Q", 5,
333  { "Type", "is", "mcf", "mcr", "vef", "ver", "iqf", "fiqf", "iqr", "iqfh",
334  "iqfe", "ahq", "ibes", "mbe", "ires", "mre", "ibcs", "mbc", "cje0",
335  "vde", "ze", "aje", "vdedc", "zedc", "ajedc", "t0", "dt0h", "tbvl",
336  "tef0", "gte", "thcs", "ahc", "tr", "rci0", "vlim", "vpt", "vces",
337  "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc",
338  "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx", "re", "itss", "msf",
339  "iscs", "msc", "cjs0", "vds", "zs", "vpts", "cbcpar", "cbepar", "eavl",
340  "kavl", "kf", "af", "vgb", "vge", "vgc", "vgs", "f1vg", "f2vg", "alt0",
341  "kt0", "zetact", "zetabet", "zetaci", "alvs", "alces", "zetarbi",
342  "zetarbx", "zetarcx", "zetare", "zetaiqf", "alkav", "aleav", "flsh",
343  "rth", "zetarth", "cth", "tnom", "dt", "delte", "deltc", "zetaver",
344  "zetavef", "ibhrec", "Temp", NULL },
345  NULL,
346  "1 0 0 8 -26 0 0",
347  NULL
348  },
349  /* hicum/l0 v1.3 bipolar transistor */
350  { "hicumL0V1p3", "hicumL0V1p3", "Q", 5,
351  { "Type", "is", "it_mod", "mcf", "mcr", "vef", "ver", "aver", "iqf",
352  "fiqf", "iqr", "iqfh", "tfh", "ahq", "ibes", "mbe", "ires", "mre",
353  "ibcs", "mbc", "cje0", "vde", "ze", "aje", "vdedc", "zedc", "ajedc",
354  "t0", "dt0h", "tbvl", "tef0", "gte", "thcs", "ahc", "tr", "rci0",
355  "vlim", "vpt", "vces", "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx",
356  "zcx", "vptcx", "fbc", "rbi0", "vr0e", "vr0c", "fgeo", "rbx", "rcx",
357  "re", "itss", "msf", "iscs", "msc", "cjs0", "vds", "zs", "vpts",
358  "cbcpar", "cbepar", "eavl", "kavl", "kf", "af", "vgb", "vge", "vgc",
359  "vgs", "f1vg", "f2vg", "alt0", "kt0", "zetact", "zetabet", "zetaci",
360  "alvs", "alces", "zetarbi", "zetarbx", "zetarcx", "zetare", "zetaiqf",
361  "alkav", "aleav", "zetarth", "tef_temp", "zetaver", "zetavgbe", "dvgbe",
362  "aliqfh", "kiqfh", "flsh", "rth", "cth", "tnom", "dt", "Temp", NULL },
363  NULL,
364  "1 0 0 8 -26 0 0",
365  NULL
366  },
367  /* hicum/l2 v2.22 bipolar transistor */
368  { "hic2_full", "hic2_full", "Q", 5,
369  { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
370  "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
371  "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
372  "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
373  "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
374  "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
375  "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
376  "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
377  "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
378  "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
379  "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
380  "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
381  "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
382  "flcomp", "tnom", "dt", "Temp", NULL },
383  NULL,
384  "1 0 0 8 -26 0 0",
385  NULL
386  },
387  /* hicum/l2 v2.1 bipolar transistor */
388  { "hicumL2V2p1", "hicumL2V2p1", "Q", 5,
389  { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis",
390  "mbei", "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf",
391  "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "favl", "qavl",
392  "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi", "fqi", "re",
393  "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu", "cjei0",
394  "vdei", "zei", "aljei", "cjep0", "vdep", "zep", "aljep", "cjci0",
395  "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx", "fbc", "cjs0",
396  "vds", "zs", "vpts", "t0", "dt0h", "tbvl", "tef0", "gtfe", "thcs",
397  "alhc", "fthc", "rci0", "vlim", "vces", "vpt", "tr", "ceox", "ccox",
398  "alqf", "alit", "kf", "af", "krbi", "latb", "latl", "vgb", "alt0",
399  "kt0", "zetaci", "zetacx", "alvs", "alces", "zetarbi", "zetarbx",
400  "zetarcx", "zetare", "alb", "rth", "cth", "tnom", "dt", "Temp", NULL },
401  NULL,
402  "1 0 0 8 -26 0 0",
403  NULL
404  },
405  /* hicum/l2 v2.23 bipolar transistor */
406  { "hicumL2V2p23", "hicumL2V2p23", "Q", 5,
407  { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
408  "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
409  "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
410  "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
411  "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
412  "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
413  "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
414  "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
415  "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
416  "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
417  "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
418  "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
419  "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
420  "flcomp", "tnom", "dt", "Temp", NULL },
421  NULL,
422  "1 0 0 8 -26 0 0",
423  NULL
424  },
425  /* hicum/l2 v2.24 bipolar transistor */
426  { "hicumL2V2p24", "hicumL2V2p24", "Q", 5,
427  { "c10", "qp0", "ich", "hfe", "hfc", "hjei", "hjci", "ibeis", "mbei",
428  "ireis", "mrei", "ibeps", "mbep", "ireps", "mrep", "mcf", "tbhrec",
429  "ibcis", "mbci", "ibcxs", "mbcx", "ibets", "abet", "tunode", "favl",
430  "qavl", "alfav", "alqav", "rbi0", "rbx", "fgeo", "fdqr0", "fcrbi",
431  "fqi", "re", "rcx", "itss", "msf", "iscs", "msc", "tsf", "rsu", "csu",
432  "cjei0", "vdei", "zei", "ajei", "cjep0", "vdep", "zep", "ajep",
433  "cjci0", "vdci", "zci", "vptci", "cjcx0", "vdcx", "zcx", "vptcx",
434  "fbcpar", "fbepar", "cjs0", "vds", "zs", "vpts", "t0", "dt0h", "tbvl",
435  "tef0", "gtfe", "thcs", "ahc", "fthc", "rci0", "vlim", "vces", "vpt",
436  "tr", "cbepar", "cbcpar", "alqf", "alit", "flnqs", "kf", "af", "cfbe",
437  "latb", "latl", "vgb", "alt0", "kt0", "zetaci", "alvs", "alces",
438  "zetarbi", "zetarbx", "zetarcx", "zetare", "zetacx", "vge", "vgc",
439  "vgs", "f1vg", "f2vg", "zetact", "zetabet", "alb", "flsh", "rth", "cth",
440  "flcomp", "tnom", "dt", "Temp", NULL },
441  NULL,
442  "1 0 0 8 -26 0 0",
443  NULL
444  },
445  /* junction FET */
446  { "JFET", "JFET", "J", 3,
447  { "Type", "Vt0", "Beta", "Lambda", "Rd", "Rs", "Is", "N", "Isr", "Nr",
448  "Cgs", "Cgd", "Pb", "Fc", "M", "Kf", "Af", "Ffe", "Temp", "Xti",
449  "Vt0tc", "Betatce", "Tnom", "Area", NULL },
450  NULL,
451  "1 190 140 30 -49 0 0",
452  NULL
453  },
454  /* MOSFET */
455  { "MOSFET", "_MOSFET", "M", 4,
456  { "Type", "Vt0", "Kp", "Gamma", "Phi", "Lambda", "Rd", "Rs", "Rg", "Is",
457  "N", "W", "L", "Ld", "Tox", "Cgso", "Cgdo", "Cgbo", "Cbd", "Cbs", "Pb",
458  "Mj", "Fc", "Cjsw", "Mjsw", "Tt", "Nsub", "Nss", "Tpg", "Uo", "Rsh",
459  "Nrd", "Nrs", "Cj", "Js", "Ad", "As", "Pd", "Ps", "Kf", "Af", "Ffe",
460  "Temp", "Tnom", NULL },
461  NULL,
462  "1 0 0 8 -26 0 0",
463  NULL
464  },
465  { NULL, NULL, NULL, 0, { NULL }, NULL, NULL, NULL }
466 };
467 
468 /* Looks through the list of available Qucs devices. Returns NULL if
469  there is no such device. */
470 static struct device_t * qucslib_find_device (char * type) {
471  struct device_t * dev;
472  for (dev = qucs_devices; dev->ntype; dev++) {
473  if (!strcmp (dev->ntype, type))
474  return dev;
475  }
476  return NULL;
477 }
478 
479 /* This function tries to find the given property in the key/value
480  pairs of the given netlist entry and returns NULL if there is no
481  such property. */
482 static struct pair_t *
483 qucslib_find_prop (struct definition_t * def, const char * key) {
484  struct pair_t * pair;
485  for (pair = def->pairs; pair; pair = pair->next) {
486  if (!strcmp (pair->key, key))
487  return pair;
488  }
489  return NULL;
490 }
491 
492 /* The function outputs a device library entry in the Qucs schematic
493  data format. */
494 static void qucslib_list_device (struct definition_t * def) {
495  struct device_t * dev;
496  if (!(dev = qucslib_find_device (def->type))) return;
497  struct pair_t * pair;
498  char txt[1024];
499 
500  sprintf (txt, "\n<Component %s>\n", def->instance[0] == dev->stype[0] ?
501  &def->instance[1] : def->instance);
502  fprintf (qucs_out, txt);
503  fprintf (qucs_out, " <Description>\n");
504  fprintf (qucs_out, " </Description>\n");
505  fprintf (qucs_out, " <Model>\n");
506  fprintf (qucs_out, " <%s %s_ %s", dev->ltype,
507  netlist_instance (def->instance), dev->coords);
508  for (int i = 0; dev->props[i]; i++) {
509  if ((pair = qucslib_find_prop (def, dev->props[i])) != NULL) {
510  fprintf (qucs_out, " \"");
511  netlist_list_value (pair->value);
512  fprintf (qucs_out, "\" 0");
513  }
514  }
515  fprintf (qucs_out, ">\n");
516  fprintf (qucs_out, " </Model>\n");
517  fprintf (qucs_out, "</Component>\n");
518 }
519 
520 /* This function is the overall Qucs library producer. */
521 void qucslib_producer (void) {
522  struct definition_t * def;
523  fprintf (qucs_out, "<Qucs Library " PACKAGE_VERSION " \"Generic\">\n");
524  for (def = device_root; def; def = def->next) {
525  qucslib_list_device (def);
526  }
527 }
528 
529 /* This function is the Qucs dataset producer for VCD files. */
531  struct dataset_variable * ds;
532  struct dataset_value * dv;
533  fprintf (qucs_out, "<Qucs Dataset " PACKAGE_VERSION ">\n");
534  for (ds = dataset_root; ds; ds = ds->next) {
535  if (!ds->output || ds->type == DATA_UNKNOWN)
536  continue;
537  if (ds->type == DATA_INDEPENDENT)
538  fprintf (qucs_out, "<indep %s %d>\n", ds->ident, ds->size);
539  else if (ds->type == DATA_DEPENDENT)
540  fprintf (qucs_out, "<dep %s.%s %s>\n", ds->ident, ds->isreal ? "R" : "X",
541  ds->dependencies);
542  for (dv = ds->values; dv; dv = dv->next) {
543  fprintf (qucs_out, " %s\n", dv->value);
544  }
545  if (ds->type == DATA_INDEPENDENT)
546  fprintf (qucs_out, "</indep>\n");
547  else if (ds->type == DATA_DEPENDENT)
548  fprintf (qucs_out, "</dep>\n");
549  }
550 }
551 
552 /* This function is the Qucs dataset producer. */
554  data->print ();
555 }