Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
check_spice.cpp
Go to the documentation of this file.
1 /*
2  * check_spice.cpp - checker for a Spice netlist
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$
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 <string.h>
32 #include <cmath>
33 #include <assert.h>
34 #include <float.h>
35 #include <ctype.h>
36 
37 #if defined(_WIN32) & not defined(__MINGW32__)
38 #define strcasecmp stricmp
39 #endif
40 
41 #include "constants.h"
42 #include "check_spice.h"
43 #include "qucs_producer.h"
44 #include "hash.h"
45 
46 /* Global definitions for parser and checker. */
47 struct definition_t * definition_root = NULL;
48 struct definition_t * subcircuit_root = NULL;
49 struct definition_t * device_root = NULL;
50 int spice_errors = 0;
51 char * spice_title = NULL;
52 
53 // List of available Spice component properties.
54 static struct property_t spice_noprops[] = { PROP_NO_PROP };
55 
56 static struct property_t req_spice_R[] = {
57  { "R", PROP_REAL, { 50, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
58 static struct property_t opt_spice_R[] = {
59  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
60  PROP_NO_PROP };
61 
62 static struct property_t req_spice_L[] = {
63  { "L", PROP_REAL, { 1e-9, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
64 
65 static struct property_t req_spice_C[] = {
66  { "C", PROP_REAL, { 1e-12, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
67 
68 static struct property_t req_spice_V[] = {
69  { "U", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
70 
71 static struct property_t req_spice_I[] = {
72  { "I", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
73 
74 static struct property_t req_spice_G[] = {
75  { "G", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
76 
77 static struct property_t req_spice_E[] = {
78  { "G", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
79 
80 static struct property_t req_spice_F[] = {
81  { "G", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
82 
83 static struct property_t req_spice_H[] = {
84  { "G", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
85 
86 static struct property_t req_spice_T[] = {
87  { "Z0", PROP_REAL, { 50, PROP_NO_STR }, PROP_POS_RANGE }, PROP_NO_PROP };
88 
89 static struct property_t req_spice_NODESET[] = {
90  { "U", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
91 
92 static struct property_t req_spice_IC[] = {
93  { "U", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP };
94 
95 // List of available Spice components.
97 {
98  /* resistor */
100  req_spice_R, opt_spice_R },
101  /* inductor */
103  req_spice_L, spice_noprops },
104  /* capacitor */
106  req_spice_C, spice_noprops },
107  /* voltage sources */
109  req_spice_V, spice_noprops },
110  /* current sources */
112  req_spice_I, spice_noprops },
113  /* voltage-controlled current source */
115  req_spice_G, spice_noprops },
116  /* voltage-controlled voltage source */
118  req_spice_E, spice_noprops },
119  /* current-controlled current source */
121  req_spice_F, spice_noprops },
122  /* current-controlled voltage source */
124  req_spice_H, spice_noprops },
125  /* transformer (mutual inductors) */
127  spice_noprops, spice_noprops },
128  /* BJT device */
130  spice_noprops, spice_noprops },
131  /* MOS device */
133  spice_noprops, spice_noprops },
134  /* JFET device */
136  spice_noprops, spice_noprops },
137  /* diodes */
139  spice_noprops, spice_noprops },
140  /* relais */
142  spice_noprops, spice_noprops },
143  /* lossless transmission line */
145  req_spice_T, spice_noprops },
146  /* transient analysis */
148  spice_noprops, spice_noprops },
149  /* AC analysis */
151  spice_noprops, spice_noprops },
152  /* DC analysis */
154  spice_noprops, spice_noprops },
155  /* operating point analysis */
157  spice_noprops, spice_noprops },
158  /* subcircuit instance */
160  spice_noprops, spice_noprops },
161  /* subcircuit definition */
163  spice_noprops, spice_noprops },
164  /* nodeset functionality */
165  { "NODESET", 1, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR,
166  req_spice_NODESET, spice_noprops },
167  /* nodeset functionality */
169  req_spice_IC, spice_noprops },
170 
171  /* end of list */
172  { NULL, 0, 0, 0, 0, spice_noprops, spice_noprops },
173 };
174 
175 // Include also the (generated) Qucs definitions.
176 #include "qucsdefs.h"
177 
178 // Short definition for iterating a list of values.
179 #define foreach_value(values,val) \
180  for ((val) = (values); (val) != NULL; (val) = (val)->next) \
181  if (!((val)->hint & HINT_DONE))
182 
183 /* The function reverses the order of the given value list and returns
184  the reversed list. */
186  struct value_t * root, * next;
187  for (root = NULL; values != NULL; values = next) {
188  next = values->next;
189  values->next = root;
190  root = values;
191  }
192  return root;
193 }
194 
195 /* The function reverses the order of the given pair list and returns
196  the reversed list. */
198  struct pair_t * root, * next;
199  for (root = NULL; pairs != NULL; pairs = next) {
200  next = pairs->next;
201  pairs->next = root;
202  root = pairs;
203  }
204  return root;
205 }
206 
207 /* The function reverses the order of the given node list and returns
208  the reversed list. */
210  struct node_t * root, * next;
211  for (root = NULL; nodes != NULL; nodes = next) {
212  next = nodes->next;
213  nodes->next = root;
214  root = nodes;
215  }
216  return root;
217 }
218 
219 // The function appends lists of pairs and returns the resulting list.
220 struct pair_t *
221 netlist_append_pairs (struct pair_t * p1, struct pair_t * p2) {
222  if (p1 == NULL) return p2;
223  struct pair_t * pair;
224  for (pair = p1; pair->next != NULL; pair = pair->next) ;
225  pair->next = p2;
226  return p1;
227 }
228 
229 // The function appends lists of values and returns the resulting list.
230 struct value_t *
231 netlist_append_values (struct value_t * v1, struct value_t * v2) {
232  if (v1 == NULL) return v2;
233  struct value_t * val;
234  for (val = v1; val->next != NULL; val = val->next) ;
235  val->next = v2;
236  return v1;
237 }
238 
239 // The function appends lists of nodes and returns the resulting list.
240 struct node_t *
241 netlist_append_nodes (struct node_t * n1, struct node_t * n2) {
242  if (n1 == NULL) return n2;
243  struct node_t * node;
244  for (node = n1; node->next != NULL; node = node->next) ;
245  node->next = n2;
246  return n1;
247 }
248 
249 /* This function goes through the list of available definitions and
250  checks whether the given component type can be found. */
251 static struct define_t * spice_find_definition (const char * n) {
252  struct define_t * def;
253  for (def = spice_definition_available; def->type != NULL; def++)
254  if (!strcasecmp (n, def->type)) return def;
255  return NULL;
256 }
257 
258 /* The function creates a single translated spice node. */
259 static struct node_t * spice_translate_node (char * node) {
260  struct node_t * n = create_node ();
261  if (!strcmp (node, "0")) { // translate ground node
262  n->node = strdup (qucs_gnd);
263  }
264  else { // translated other node than ground
265  n->node = (char *) malloc (5 + strlen (node));
266  strcpy (n->node, "_net");
267  strcat (n->node, node);
268  // strip off invalid characters
269  for (unsigned int i = 0; i < strlen (n->node); i++) {
270  if (!isalpha (n->node[i]) && !isdigit (n->node[i])) {
271  switch (n->node[i]) {
272  case '+': n->node[i] = 'P'; break;
273  case '-': n->node[i] = 'N'; break;
274  default : n->node[i] = '_'; break;
275  }
276  }
277  }
278  }
279  return n;
280 }
281 
282 /* The function marks the given value to be processed and free()'s
283  unnecessary memory. */
284 static void spice_value_done (struct value_t * val) {
285  if (val->ident) { free (val->ident); val->ident = NULL; }
286  if (val->unit) { free (val->unit); val->unit = NULL; }
287  if (val->scale) { free (val->scale); val->scale = NULL; }
288  val->hint |= HINT_DONE;
289 }
290 
291 /* The function creates the nodes list for the given component. */
292 static struct node_t * spice_get_nodes (struct definition_t * def) {
293 
294  // has this component actually any nodes to define?
295  int nodes = def->define->nodes;
296  if (nodes == 0) return NULL;
297 
298  // go through value list and try identifying nodes
299  struct value_t * val;
300  struct node_t * root = NULL;
301  int i = 0;
302  foreach_value (def->values, val) {
303  if (val->hint & HINT_NODE) {
304  struct node_t * n = spice_translate_node (val->ident);
305  n->next = root;
306  root = n;
307  spice_value_done (val);
308  // continue until all nodes are done
309  if (++i >= nodes && nodes != PROP_NODES) break;
310  }
311  // nodes are defined successively
312  else break;
313  }
314  // return reversed list of nodes
315  return netlist_reverse_nodes (root);
316 }
317 
318 /* Evaluates the unit scale in a property value. It adjusts the
319  actual value and omits the scale. The function returns NULL if
320  there is no valid scale found and otherwise the corrected scale.
321  The given endptr is set to the character after the last valid scale
322  character. */
323 static const char *
324 spice_evaluate_scale (char * value, char ** endptr, double * factor) {
325  const char * scale = NULL;
326  *factor = 1.0;
327  switch (*value) {
328  case 'T': case 't':
329  value++; scale = "T"; break;
330  case 'G': case 'g':
331  value++; scale = "G"; break;
332  case 'M': case 'm':
333  value++; scale = (char *) ((*value == 'M') ? "M" : "m");
334  if ((value[0] == 'i' || value[0] == 'I') &&
335  (value[1] == 'l' || value[1] == 'L')) {
336  value += 2; *factor = 2.54e-5; scale = NULL;
337  }
338  if ((value[0] == 'e' || value[0] == 'E') &&
339  (value[1] == 'g' || value[1] == 'G')) {
340  value += 2; scale = "M";
341  }
342  break;
343  case 'k': case 'K':
344  value++; scale = "k"; break;
345  case 'u': case 'U':
346  value++; scale = "u"; break;
347  case 'n': case 'N':
348  value++; scale = "n"; break;
349  case 'p': case 'P':
350  value++; scale = "p"; break;
351  case 'f': case 'F':
352  value++; scale = "f"; break;
353  }
354  *endptr = value;
355  return scale;
356 }
357 
358 /* This little function takes the given string value, converts it into
359  an appropriate real value and save optional scale and unit. */
360 static struct value_t * spice_create_value (const char * ident) {
361  struct value_t * val;
362  char * end;
363  const char * str;
364  double value = 1.0;
365  val = create_value ();
366  val->value = strtod (ident, &end);
367  if (*end) {
368  str = spice_evaluate_scale (end, &end, &value);
369  val->value *= value;
370  val->scale = str ? strdup (str) : NULL;
371  if (*end) val->unit = strdup (end);
372  }
373  return val;
374 }
375 
376 /* The function identifies key/value pairs in the value list of the
377  given definition and saves these into an appropriate list. */
378 static struct pair_t * spice_get_pairs (struct definition_t * def) {
379  struct value_t * val;
380  struct pair_t * p, * root = NULL;
381  struct property_t * prop;
382  int i = 0;
383 
384  // if there is a value given and no description (key), it is required
385  foreach_value (def->values, val) {
386  prop = &def->define->required[i];
387  // a float given ?
388  if (val->hint & HINT_NUMBER && prop->key) {
389  p = create_pair ();
390  p->key = strdup (prop->key);
391  p->value = spice_create_value (val->ident);
392  p->next = root;
393  root = p;
394  spice_value_done (val);
395  i++;
396  }
397  // skip identifier if next is a float again (F and H sources)
398  else if ((def->type[0] == 'F' || def->type[0] == 'H') &&
399  strcasecmp (val->ident, "POLY") &&
400  val->hint & HINT_NAME &&
401  val->next && val->next->hint & HINT_NUMBER)
402  continue;
403  // break it here
404  else
405  break;
406  }
407  // other key/value pairs on that line
408  foreach_value (def->values, val) {
409  if (val->hint & HINT_PAIR) {
410  p = create_pair ();
411  p->key = strdup (val->ident);
412  p->value = spice_create_value (val->unit);
413  p->next = root;
414  root = p;
415  spice_value_done (val);
416  }
417  }
418  return netlist_reverse_pairs (root);
419 }
420 
421 /* The function goes through the list of definitions and tries to find
422  the given device model. It returns NULL if there is no such
423  model. */
424 static struct definition_t *
425 spice_find_device (struct definition_t * root, char * type) {
426  for (struct definition_t * def = root; def != NULL; def = def->next) {
427  if (def->action && !strcasecmp (def->type, "MODEL") &&
428  !strcasecmp (def->instance, type)) {
429  return def;
430  }
431  }
432  return NULL;
433 }
434 
435 /* Looks for the first possible .MODEL or any other device reference
436  instance name in the given list. Returns NULL if there is no such
437  thing. */
438 static struct value_t *
440  struct value_t * val;
441  foreach_value (def->values, val) {
442  if (val->hint & HINT_NAME) return val;
443  }
444  return NULL;
445 }
446 
447 // Little helper structure for device translations.
449  const char * type; // Spice type
450  const char * trans_type; // Qucs type
451  const char * trans_type_prop; // value of 'Type' in Qucs
452 }
453 spice_devices[] = {
454  { "NPN", "BJT", "npn" },
455  { "PNP", "BJT", "pnp" },
456  { "NJF", "JFET", "nfet" },
457  { "PJF", "JFET", "pfet" },
458  { "NMOS", "MOSFET", "nfet" },
459  { "PMOS", "MOSFET", "pfet" },
460  { "D", "Diode", NULL },
461  { "SW", "Relais", NULL },
462  { "VSWITCH", "Relais", NULL },
463  { "RES", "R", NULL },
464  { "R", "R", NULL },
465  { "C", "C", NULL },
466  { NULL, NULL, NULL }
467 };
468 
469 /* The function goes through the given value list and creates an
470  appropriate list of key/value pairs stored inside .MODEL
471  specifications. */
472 static struct pair_t * spice_generate_Model_pairs (struct value_t * values) {
473  struct pair_t * root = NULL;
474  struct value_t * val;
475  foreach_value (values, val) {
476  if (val->hint & HINT_PAIR) {
477  struct pair_t * p = create_pair ();
478  p->key = strdup (val->ident);
479  p->value = spice_create_value (val->unit);
480  p->next = root;
481  root = p;
482  if (val->hint & HINT_MSTOP) break;
483  }
484  else break;
485  }
486  return netlist_reverse_pairs (root);
487 }
488 
489 /* The function goes through the property list of the given definition
490  and checks whether there is the given property stored. It returns
491  NULL if not. */
492 static struct pair_t *
493 spice_find_property (struct definition_t * def, const char * prop) {
494  struct pair_t * pair;
495  for (pair = def->pairs; pair != NULL; pair = pair->next) {
496  if (!strcmp (pair->key, prop))
497  return pair;
498  }
499  return NULL;
500 }
501 
502 /* This function is the case-insensitive version of the above. */
503 static struct pair_t *
504 spice_find_property_nocase (struct definition_t * def, const char * prop) {
505  struct pair_t * pair;
506  for (pair = def->pairs; pair != NULL; pair = pair->next) {
507  if (!strcasecmp (pair->key, prop))
508  return pair;
509  }
510  return NULL;
511 }
512 
513 /* The function starts at a given property pair and is otherwise
514  similar to the above function. */
515 static struct pair_t *
516 spice_find_property_nocase (struct pair_t * pair, const char * prop) {
517  for (; pair != NULL; pair = pair->next) {
518  if (!strcasecmp (pair->key, prop))
519  return pair;
520  }
521  return NULL;
522 }
523 
524 /* This function looks whether the given property name is stored
525  within the given list of values and returns it. If there is no
526  such name, then it returns NULL. */
527 static struct value_t *
528 spice_find_property (struct value_t * values, const char * prop) {
529  struct value_t * val;
530  foreach_value (values, val) {
531  if (!strcasecmp (prop, val->ident)) return val;
532  }
533  return NULL;
534 }
535 
536 /* The function replaces or appends the given key/value pair to the
537  list of properties of the given definition. */
538 static void
539 spice_set_property_string (struct definition_t * def, const char * key,
540  const char * val) {
541  struct pair_t * prop = spice_find_property (def, key);
542  if (prop != NULL) {
543  if (prop->value->ident) free (prop->value->ident);
544  prop->value->ident = strdup (val);
545  }
546  else {
547  prop = create_pair ();
548  prop->key = strdup (key);
549  prop->value = create_value ();
550  prop->value->ident = strdup (val);
551  def->pairs = netlist_append_pairs (prop, def->pairs);
552  }
553 }
554 
555 /* This function evaluates the already translated value (translated
556  scale value) and returns the actual value leaving it untouched. */
557 static double spice_evaluate_value (struct value_t * value) {
558  double val = value->value, factor = 1.0;
559  if (value->scale != NULL) {
560  switch (*(value->scale)) {
561  case 'T': factor = 1e12; break;
562  case 'G': factor = 1e9; break;
563  case 'M': factor = 1e6; break;
564  case 'k': factor = 1e3; break;
565  case 'm': factor = 1e-3; break;
566  case 'u': factor = 1e-6; break;
567  case 'n': factor = 1e-9; break;
568  case 'p': factor = 1e-12; break;
569  case 'f': factor = 1e-15; break;
570  }
571  }
572  return val * factor;
573 }
574 
575 /* The following function free()'s the given value. */
576 static void netlist_free_value (struct value_t * value) {
577  if (value->ident) free (value->ident);
578  if (value->unit) free (value->unit);
579  if (value->scale) free (value->scale);
580  free (value);
581 }
582 
583 /* Deletes the given value list. */
584 static void netlist_free_values (struct value_t * value) {
585  struct value_t * next;
586  for (; value != NULL; value = next) {
587  next = value->next;
588  netlist_free_value (value);
589  }
590 }
591 
592 /* Deletes the given key/value pair. */
593 void netlist_free_pair (struct pair_t * pair) {
594  if (pair->value) netlist_free_values (pair->value);
595  free (pair->key);
596  free (pair);
597 }
598 
599 /* Unchains a property pair and deletes it. */
600 struct pair_t *
601 spice_del_property (struct pair_t * root, struct pair_t * pair) {
602  struct pair_t * prev;
603  if (pair == root) {
604  root = pair->next;
605  netlist_free_pair (pair);
606  }
607  else {
608  // find previous to the candidate to be deleted
609  for (prev = root; prev != NULL && prev->next != pair; prev = prev->next) ;
610  if (prev != NULL) {
611  prev->next = pair->next;
612  netlist_free_pair (pair);
613  }
614  }
615  return root;
616 }
617 
618 /* This function adjusts the given device instance definition using
619  the the given device definition. */
620 static void spice_adjust_device (struct definition_t * def,
621  struct definition_t * trandef) {
622 
623  // first find the starting point of the definition
624  struct value_t * val, * start = NULL;
625  foreach_value (trandef->values, val) {
626  if (val->hint & HINT_MSTART) { start = val; break; }
627  }
628  if (start == NULL) {
629  foreach_value (trandef->values, val) {
630  if (val->hint & HINT_NAME) { start = val; break; }
631  }
632  }
633 
634  // second: look for an appropriate available translation
635  struct spice_device_t * tran;
636  for (tran = spice_devices; tran->type; tran++) {
637  if (!strcasecmp (tran->type, start->ident)) {
638  struct pair_t * p;
639  // append properties
640  p = spice_generate_Model_pairs (start->next);
641  def->pairs = netlist_append_pairs (def->pairs, p);
642  // adjust type of device
643  if (def->type) free (def->type);
644 
645  bool hic = false;
646  // check for HICUM transistors
647  if (!strcmp (tran->trans_type, "BJT")) {
648  struct pair_t * p1, * p2;
649  if ((p1 = spice_find_property (def, "LEVEL")) != NULL) {
650  double level = spice_evaluate_value (p1->value);
651  def->pairs = spice_del_property (def->pairs, p1);
652  if ((p2 = spice_find_property (def, "VERSION")) != NULL) {
653  double version = spice_evaluate_value (p2->value);
654  def->pairs = spice_del_property (def->pairs, p2);
655  if (level == 0) {
656  if (version >= 1.11) {
657  if (version >= 1.2e9)
658  def->type = strdup ("hicumL0V1p2g");
659  else if (version >= 1.3)
660  def->type = strdup ("hicumL0V1p3");
661  else if (version >= 1.2)
662  def->type = strdup ("hicumL0V1p2");
663  else
664  def->type = strdup ("hic0_full");
665  if (tran->trans_type_prop != NULL) {
666  spice_set_property_string (def, "Type",
667  tran->trans_type_prop);
668  }
669  hic = true;
670  }
671  }
672  else if (level == 2 && version == 2.1) {
673  def->type = strdup ("hicumL2V2p1");
674  hic = true;
675  }
676  else if (level == 2 && version >= 2.21 && version <= 2.22) {
677  def->type = strdup ("hic2_full");
678  hic = true;
679  }
680  else if (level == 2 && version == 2.23) {
681  def->type = strdup ("hicumL2V2p23");
682  hic = true;
683  }
684  else if (level == 2 && version >= 2.24) {
685  def->type = strdup ("hicumL2V2p24");
686  hic = true;
687  }
688  }
689  }
690  }
691  if (!hic) {
692  def->type = strdup (tran->trans_type);
693  // append "Type" property
694  if (tran->trans_type_prop != NULL) {
695  spice_set_property_string (def, "Type", tran->trans_type_prop);
696  }
697  }
698  break;
699  }
700  }
701 }
702 
703 /* The function translates .MODEL specifications in device (MOSFET,
704  BJT, etc.) instances. */
705 static void spice_translate_device (struct definition_t * root,
706  struct definition_t * def) {
707  struct value_t * inst = spice_find_device_instance (def);
708 
709  // return if no Model given
710  if (inst == NULL) return;
711 
712  /* first look for the Model in the local definition root, then in
713  the global definition root */
714  struct definition_t * tran;
715  if ((tran = spice_find_device (root, inst->ident)) == NULL)
716  tran = spice_find_device (definition_root, inst->ident);
717  // really translate the instance here
718  if (tran != NULL) {
719  spice_value_done (inst);
720  spice_adjust_device (def, tran);
721  }
722  else if (!strcasecmp (def->type, "C")) {
723  // can probably be skipped
724  }
725  else {
726  fprintf (stderr, "spice error, no such .MODEL `%s' found as specified in "
727  "device instance `%s'\n", inst->ident, def->instance);
728  spice_errors++;
729  }
730 }
731 
732 /* Goes through the list of available definition and returns the
733  appropriate component definition. */
734 static struct define_t *
736  struct define_t * entry;
737  for (entry = qucs_definition_available; entry->type != NULL; entry++)
738  if (!strcmp (entry->type, def->type)) return entry;
739  return NULL;
740 }
741 
742 // Helper structure for direct type translations.
744  const char * type; // Spice type
745  const char * trans; // Qucs type
746 }
747 spice_device_table[] = {
748  { "Q", "BJT" },
749  { "J", "JFET", },
750  { "M", "MOSFET" },
751  { "D", "Diode" },
752  { "V", "Vdc" },
753  { "I", "Idc" },
754  { "G", "VCCS" },
755  { "E", "VCVS" },
756  { "F", "CCCS" },
757  { "H", "CCVS" },
758  { "K", "Tr" },
759  { "S", "Relais" },
760  { "T", "TLIN4P" },
761  { NULL, NULL }
762 };
763 
764 /* This little function translates the Spice type definitions into Qucs
765  types. */
766 static int spice_translate_type (struct definition_t * def) {
767  struct spice_device_table_t * tran;
768  int found = 0;
769  for (tran = spice_device_table; tran->type && def->type; tran++) {
770  found = 1;
771  if (!strcasecmp (tran->type, def->type)) {
772  if (!spice_find_property (def->values, "POLY")) {
773  free (def->type);
774  def->type = strdup (tran->trans);
775  found++;
776  break;
777  }
778  }
779  }
780  return found;
781 }
782 
783 // Helper structure for node translations.
785  const char * type; // the type of definition
786  int pass; // pass number when the translation should be performed
787  int Mapping[6]; // node ordering
788  int Default[6]; // default nodes
789 }
790 node_translations[] = {
791  { "BJT", 0,
792  { 2, 1, 3, 4, -1 },
793  { 1, 2, 3, 0, -1 }
794  },
795  { "MOSFET", 0,
796  { 2, 1, 3, 4, -1 },
797  { 1, 2, 3, 3, -1 }
798  },
799  { "JFET", 0,
800  { 2, 1, 3, -1 },
801  { 1, 2, 3, -1 }
802  },
803  { "Diode", 0,
804  { 2, 1, -1 },
805  { 1, 2, -1 }
806  },
807  { "Iac", 0,
808  { 2, 1, -1 },
809  { 1, 2, -1 }
810  },
811  { "Idc", 0,
812  { 2, 1, -1 },
813  { 1, 2, -1 }
814  },
815  { "VCCS", 0,
816  { 3, 1, 2, 4, -1 },
817  { 1, 2, 3, 4, -1 }
818  },
819  { "VCVS", 0,
820  { 3, 1, 2, 4, -1 },
821  { 1, 2, 3, 4, -1 }
822  },
823  { "CCCS", 1,
824  { 3, 1, 2, 4, -1 },
825  { 1, 2, 3, 4, -1 }
826  },
827  { "CCVS", 1,
828  { 3, 1, 2, 4, -1 },
829  { 1, 2, 3, 4, -1 }
830  },
831  { "Tr", 1,
832  { 3, 1, 2, 4, -1 },
833  { 1, 2, 3, 4, -1 }
834  },
835  { "NodeSet", 1,
836  { 1, -1 },
837  { 1, -1 }
838  },
839  { "Relais", 0,
840  { 3, 1, 2, 4, -1 },
841  { 1, 2, 3, 4, -1 }
842  },
843  { "TLIN4P", 0,
844  { 1, 3, 4, 2, -1 },
845  { 1, 2, 3, 4, -1 }
846  },
847  { NULL, 0, { -1 }, { -1 } }
848 };
849 
850 // Counts the number of nodes stored in the given definition.
851 static int spice_count_nodes (struct definition_t * def) {
852  int res = 0;
853  for (struct node_t * node = def->nodes; node != NULL; node = node->next)
854  res++;
855  return res;
856 }
857 
858 // Deletes node list of a definition.
859 static void netlist_free_nodes (struct node_t * node) {
860  struct node_t * n;
861  for (; node != NULL; node = n) {
862  n = node->next;
863  free (node->node);
864  free (node);
865  }
866 }
867 
868 /* Deletes pair list of a definition. */
869 static void netlist_free_pairs (struct pair_t * pair) {
870  struct pair_t * n;
871  for (; pair != NULL; pair = n) {
872  n = pair->next;
873  netlist_free_pair (pair);
874  }
875 }
876 
877 // The function returns the node specified at the given position.
878 static struct node_t * spice_get_node (struct definition_t * def, int pos) {
879  struct node_t * node;
880  int i;
881  for (i = 1, node = def->nodes; node != NULL; node = node->next, i++)
882  if (i == pos) return node;
883  return NULL;
884 }
885 
886 /* This function transforms the collected node information in the
887  Spice list into the appropriate Qucs definition. */
888 static void spice_translate_nodes (struct definition_t * def, int pass) {
889  struct node_translation_t * nodes;
890  struct node_t * node;
891  // find node translator
892  for (nodes = node_translations; nodes->type != NULL; nodes++)
893  if (!strcmp (nodes->type, def->type)) break;
894  if (nodes->type == NULL || pass != nodes->pass) return;
895 
896  struct define_t * entry = spice_get_qucs_definition (def);
897  // adjust the number of nodes and append default nodes
898  if (entry->nodes > spice_count_nodes (def)) {
899  for (int n = spice_count_nodes (def); n < entry->nodes; n++) {
900  node = create_node ();
901  if (nodes->Default[n] == 0) { // default is the ground node
902  node->node = strdup (qucs_gnd);
903  }
904  else { // default is some other node
905  struct node_t * t = spice_get_node (def, nodes->Default[n]);
906  if (t != NULL)
907  node->node = strdup (t->node);
908  else {
909  // no node given, occurs in device descriptions
910  char txt[16];
911  sprintf (txt, "%s%d", "_node", n);
912  node->node = strdup (txt);
913  }
914  }
915  def->nodes = netlist_append_nodes (def->nodes, node);
916  }
917  }
918  // remap the node definitions if necessary
919  struct node_t * root = NULL;
920  for (int n = entry->nodes - 1; n >= 0; n--) {
921  struct node_t * t = spice_get_node (def, nodes->Mapping[n]);
922  node = create_node ();
923  node->node = strdup (t->node);
924  node->next = root;
925  root = node;
926  }
927  netlist_free_nodes (def->nodes);
928  def->nodes = root;
929 }
930 
931 // Helper structure for unit translations.
933  const char * key;
934  const char * trans;
935 }
936 unit_translations[] = {
937  { "OHM", "Ohm" },
938  { "OHMS", "Ohm" },
939  { "MHO", "S" },
940  { "S", "s" },
941  { "H", "H" },
942  { "F", "F" },
943  { "HZ", "Hz" },
944  { "V", "V" },
945  { "VOLT", "V" },
946  { "A", "A" },
947  { "M", "m" },
948  { NULL, NULL }
949 };
950 
951 /* This function tries to figure out units given in the Spice list and
952  translates these patterns into valid Qucs units. */
953 static void spice_translate_units (struct definition_t * def) {
954  for (struct pair_t * pair = def->pairs; pair != NULL; pair = pair->next) {
955  struct value_t * value = pair->value;
956  if (value->unit) {
957  struct unit_translation_t * unit;
958  int found = 0;
959  for (unit = unit_translations; unit->key != NULL; unit++) {
960  if (!strcasecmp (unit->key, value->unit)) {
961  free (value->unit);
962  value->unit = strdup (unit->trans);
963  found++;
964  break;
965  }
966  }
967  if (!found) { // no such unit found
968  free (value->unit);
969  value->unit = NULL;
970  }
971  }
972  }
973 }
974 
975 /* This function appends all the required Qucs properties not given in
976  the Spice netlist. */
977 static void spice_adjust_default_properties (struct definition_t * def) {
978  struct define_t * entry = spice_get_qucs_definition (def);
979  if (entry == NULL) return;
980 
981  // handle required properties only
982  for (int i = 0; PROP_IS_PROP (entry->required[i]); i++) {
983  struct property_t * prop = &entry->required[i];
984  if (spice_find_property (def, prop->key) == NULL) {
985  struct pair_t * pair = create_pair ();
986  pair->key = strdup (prop->key);
987  pair->value = create_value ();
988  if (PROP_IS_VAL (*prop)) {
989  pair->value->value = prop->defaultval.d;
990  }
991  else {
992  pair->value->ident = strdup (prop->defaultval.s);
993  }
994  def->pairs = netlist_append_pairs (def->pairs, pair);
995  }
996  }
997 }
998 
999 /* This function appends the optional Qucs properties not given in the
1000  Spice netlist. */
1002  struct define_t * entry = spice_get_qucs_definition (def);
1003  if (entry == NULL) return;
1004 
1005  // handle optional properties if requested
1006  for (int i = 0; PROP_IS_PROP (entry->optional[i]); i++) {
1007  struct property_t * prop = &entry->optional[i];
1008  if (spice_find_property (def, prop->key) == NULL) {
1009  struct pair_t * pair = create_pair ();
1010  pair->key = strdup (prop->key);
1011  pair->value = create_value ();
1012  if (PROP_IS_VAL (*prop)) {
1013  pair->value->value = prop->defaultval.d;
1014  }
1015  else {
1016  pair->value->ident = strdup (prop->defaultval.s);
1017  }
1018  def->pairs = netlist_append_pairs (def->pairs, pair);
1019  }
1020  }
1021 }
1022 
1023 // Helper structure for property translations and aliases in devices.
1025  const char * type;
1026  const char * key;
1027  const char * trans;
1028 }
1030  /* BJT device */
1031  { NULL, "CCS", "Cjs" },
1032  { NULL, "VA", "Vaf" },
1033  { NULL, "VB", "Var" },
1034  { NULL, "IK", "Ikf" },
1035  { NULL, "PE", "Vje" },
1036  { NULL, "ME", "Mje" },
1037  { NULL, "PC", "Vjc" },
1038  { NULL, "MC", "Mjc" },
1039  { NULL, "PS", "Vjs" },
1040  { NULL, "MS", "Mjs" },
1041  /* MOSFET device */
1042  { NULL, "VTO", "Vt0" },
1043  { NULL, "U0", "Uo" },
1044  /* DIODE device */
1045  { NULL, "CJO", "Cj0" },
1046  /* OTHER devices */
1047  { "C", "IC", "V" },
1048  { "L", "IC", "I" },
1049  { NULL, "Z0", "Z" },
1050  { "R", "TC", "Tc1" },
1051  /* END of list */
1052  { NULL, NULL, NULL }
1053 };
1054 
1055 /* The function translates property and aliases of devices in the list
1056  of key/value pairs of the given definition. */
1058  struct pair_t * pair) {
1060  for (; prop->key != NULL; prop++) {
1061  if (!prop->type || !strcmp (prop->type, def->type)) {
1062  if (!strcasecmp (prop->key, pair->key)) {
1063  free (pair->key);
1064  pair->key = strdup (prop->trans);
1065  }
1066  }
1067  }
1068 }
1069 
1070 /* The function goes through the pair (property) list of the given
1071  definition and adjusts the spelling of the property keys according
1072  to the Qucs definitions. */
1074  struct define_t * entry = spice_get_qucs_definition (def);
1075  if (entry) {
1076  struct pair_t * pair;
1077  for (pair = def->pairs; pair != NULL; pair = pair->next) {
1078  int i, found = 0;
1079  // handle required properties
1080  for (i = 0; PROP_IS_PROP (entry->required[i]); i++) {
1081  if (!strcasecmp (entry->required[i].key, pair->key)) {
1082  free (pair->key);
1083  pair->key = strdup (entry->required[i].key);
1084  found++;
1085  break;
1086  }
1087  }
1088  // handle optional properties
1089  for (i = 0; PROP_IS_PROP (entry->optional[i]); i++) {
1090  if (!strcasecmp (entry->optional[i].key, pair->key)) {
1091  free (pair->key);
1092  pair->key = strdup (entry->optional[i].key);
1093  found++;
1094  break;
1095  }
1096  }
1097  // some other direct translations
1098  if (!found) spice_adjust_alias_properties (def, pair);
1099  }
1100  }
1101 }
1102 
1103 /* This function appends the given key/value pair to the given
1104  definition. If the replace flag is non-zero the pair gets
1105  replaced. If the replace flag is zero and the pair already exists
1106  nothing is done here. */
1107 static void spice_append_pair (struct definition_t * def, const char * prop,
1108  const char * value, int replace) {
1109  struct pair_t * p = spice_find_property (def, prop);
1110  if (p != NULL) {
1111  if (replace) {
1113  p->value = spice_create_value (value);
1114  return;
1115  }
1116  else return;
1117  }
1118  p = create_pair ();
1119  p->key = strdup (prop);
1120  p->value = spice_create_value (value);
1121  def->pairs = netlist_append_pairs (def->pairs, p);
1122 }
1123 
1124 /* The function appends the given node name to the list of nodes of
1125  the given definition. */
1126 static void spice_append_node (struct definition_t * def, char * node) {
1127  struct node_t * n = create_node ();
1128  n->node = strdup (node);
1129  def->nodes = netlist_append_nodes (def->nodes, n);
1130 }
1131 
1132 // Converts the given string into upper case.
1133 static char * spice_toupper (char * str) {
1134  for (unsigned int i = 0; i < strlen (str); i++) {
1135  if (str[i] >= 'a' && str[i] <= 'z') str[i] = toupper (str[i]);
1136  }
1137  return str;
1138 }
1139 
1140 /* The function adjusts the instance name of the given component
1141  definition. */
1142 static void spice_adjust_instance (struct definition_t * def) {
1143  spice_toupper (def->instance);
1144 }
1145 
1146 /* This function is used by the overall netlist translator in order to
1147  fixup the properties, nodes, instance name and property units of
1148  the given definition. */
1149 static void spice_fixup_definition (struct definition_t * def) {
1150  spice_adjust_instance (def);
1152  spice_translate_nodes (def, 0);
1153  spice_translate_units (def);
1155 }
1156 
1157 /* The function adds the given definition to the list of valid
1158  definitions. The definition is placed at the beginning of the
1159  list. */
1160 static struct definition_t *
1161 spice_add_definition (struct definition_t * root, struct definition_t * def) {
1162  spice_fixup_definition (def);
1163  def->next = root;
1164  return def;
1165 }
1166 
1167 /* Forward declaration for recursive calls. */
1168 static void netlist_destroy_intern (struct definition_t *);
1169 
1170 /* Deletes a definition and all its content. */
1171 static void
1173  netlist_free_nodes (def->nodes);
1174  netlist_free_pairs (def->pairs);
1175  netlist_free_values (def->values);
1176  if (def->subcircuit) free (def->subcircuit);
1177  if (def->text) free (def->text);
1178  if (def->sub) netlist_destroy_intern (def->sub);
1179  free (def->type);
1180  free (def->instance);
1181  free (def);
1182 }
1183 
1184 /* The function deletes the given definition list. */
1185 static void netlist_destroy_intern (struct definition_t * root) {
1186  struct definition_t * def, * next;
1187  for (def = root; def != NULL; def = next) {
1188  next = def->next;
1190  }
1191 }
1192 
1193 /* Deletes all available definition lists. */
1194 void spice_destroy (void) {
1195  netlist_destroy_intern (definition_root);
1196  netlist_destroy_intern (device_root);
1197  for (struct definition_t * def = subcircuit_root; def; def = def->next) {
1198  netlist_destroy_intern (def->sub);
1199  }
1200  netlist_destroy_intern (subcircuit_root);
1201  definition_root = subcircuit_root = device_root = NULL;
1203  spice_nodes = NULL;
1204  if (spice_title) free (spice_title);
1205  spice_title = NULL;
1206 }
1207 
1208 /* Unchains a definition and deletes it. */
1209 struct definition_t *
1210 spice_del_definition (struct definition_t * root, struct definition_t * def) {
1211  struct definition_t * prev;
1212  if (def == root) {
1213  root = def->next;
1215  }
1216  else {
1217  // find previous to the candidate to be deleted
1218  for (prev = root; prev != NULL && prev->next != def; prev = prev->next) ;
1219  if (prev != NULL) {
1220  prev->next = def->next;
1222  }
1223  }
1224  return root;
1225 }
1226 
1227 /* This function creates an internal node name used during the
1228  conversion process. The returned string is static and must be
1229  copied by the caller. Successive calls result in different node
1230  names. */
1231 static char * spice_create_intern_node (void) {
1232  static int intern = 0;
1233  static char txt[32];
1234  sprintf (txt, "_cnet%d", intern++);
1235  return txt;
1236 }
1237 
1238 /* This function places an internal node in between the given
1239  components. The first node of the 'dn' component becomes the first
1240  node of the 'up' component. */
1241 static void spice_adjust_vsource_nodes (struct definition_t * up,
1242  struct definition_t * dn) {
1243  struct node_t * node = spice_get_node (dn, 1);
1244  spice_append_node (up, node->node);
1245  char * inode = spice_create_intern_node ();
1246  spice_append_node (up, inode);
1247  free (node->node);
1248  node->node = strdup (inode);
1249 }
1250 
1251 /* The function copies both of the nodes from the 'right' component
1252  into the 'left' component. */
1253 static void spice_adjust_isource_nodes (struct definition_t * left,
1254  struct definition_t * right) {
1255  struct node_t * node;
1256  node = spice_get_node (right, 1);
1257  spice_append_node (left, node->node);
1258  node = spice_get_node (right, 2);
1259  spice_append_node (left, node->node);
1260 }
1261 
1262 /* The function creates a new definition based upon the given
1263  definition. The type of the new component must be given as
1264  well. */
1265 static struct definition_t *
1266 spice_create_definition (struct definition_t * base, const char * type) {
1267  struct definition_t * res = create_definition ();
1268  res->type = strdup (type);
1269  res->action = PROP_COMPONENT;
1270  res->instance = strdup (base->instance);
1271  res->define = base->define;
1272  return res;
1273 }
1274 
1275 /* The function returns the actual property value stored in the given
1276  definition of the given property. If there is no such property it
1277  returns 0. */
1278 static double
1279 spice_get_property_value (struct definition_t * def, const char * key) {
1280  struct pair_t * prop = spice_find_property (def, key);
1281  return prop ? spice_evaluate_value (prop->value) : 0;
1282 }
1283 
1284 /* This function replaces or appends the given key/value pair in the
1285  given definition. */
1286 static void
1287 spice_set_property_value (struct definition_t * def, const char * key,
1288  double val) {
1289  struct pair_t * prop = spice_find_property (def, key);
1290  if (prop != NULL) {
1291  // just replace the key/value pair
1292  if (prop->value->scale) {
1293  free (prop->value->scale);
1294  prop->value->scale = NULL;
1295  }
1296  if (prop->value->unit) {
1297  free (prop->value->unit);
1298  prop->value->unit = NULL;
1299  }
1300  prop->value->value = val;
1301  }
1302  else {
1303  // create key/value pair and append it
1304  prop = create_pair ();
1305  prop->key = strdup (key);
1306  prop->value = create_value ();
1307  prop->value->value = val;
1308  def->pairs = netlist_append_pairs (def->pairs, prop);
1309  }
1310 }
1311 
1312 // Helper structure for property extraction routine.
1314  const char * field[16];
1315 };
1316 
1317 /* The function extracts a list of properties from the given value
1318  list and assign the property names stored in the field extractor
1319  structure. The extracted properties are saved into the given
1320  definition. */
1321 static void spice_extract_properties (struct definition_t * def,
1322  struct value_t * values,
1323  struct property_field_t * field) {
1324  int i = 0;
1325  struct value_t * val;
1326  // go through each not yet processed value
1327  foreach_value (values, val) {
1328  if (field->field[i] == NULL) break; // stop at the end
1329  if (val->hint & HINT_NAME) {
1330  spice_set_property_string (def, field->field[i], val->ident);
1331  }
1332  else if (val->hint & (HINT_NODE | HINT_NUMBER)) {
1333  spice_append_pair (def, field->field[i], val->ident, 0);
1334  }
1335  else break;
1336  spice_value_done (val);
1337  if (val->hint & HINT_MSTOP) break; // stop here if necessary
1338  i++;
1339  }
1340 }
1341 
1342 /* This function tries to reproduce a Spice netlist line. It is used
1343  if no proper translation could be found for the line and is printed
1344  as commentary line then. */
1345 static char * spice_untranslated_text (struct definition_t * def) {
1346  struct value_t * val;
1347  char str[256];
1348  sprintf (str, "%s%s:%s ", def->action ? "." : "", def->type, def->instance);
1349  char * txt = (char *) malloc (strlen (str) + 1);
1350  strcpy (txt, str);
1351  for (val = def->values; val != NULL; val = val->next) {
1352  if (val->hint == HINT_NODE) {
1353  sprintf (str, "%s ", val->ident);
1354  }
1355  else if (val->hint & (HINT_NODE | HINT_NUMBER)) {
1356  sprintf (str, "%s%s ", val->ident, val->hint & HINT_MSTOP ? ")" : "");
1357  }
1358  else if (val->hint & HINT_PAIR) {
1359  sprintf (str, "%s%s=%s%s ", val->hint & HINT_MSTART ? "(" : "",
1360  val->ident, val->unit, val->hint & HINT_MSTOP ? ")" : "");
1361  }
1362  else if (val->hint & HINT_NAME) {
1363  sprintf (str, "%s%s%s%s",
1364  (val->hint & HINT_MSTART) ? " " : "",
1365  val->ident,
1366  ((val->hint & HINT_MSTART) && val->next &&
1367  (val->next->hint & HINT_MSTOP)) ||
1368  (val->hint & HINT_MSTOP) ? "" : " ",
1369  (val->hint & HINT_MSTART && val->next) ? "(" :
1370  (val->hint & HINT_MSTOP) ? ")" : " ");
1371  }
1372  txt = (char *) realloc (txt, strlen (txt) + strlen (str) + 1);
1373  strcat (txt, str);
1374  }
1375  return spice_toupper (txt);
1376 }
1377 
1378 #define VAL_IS_NUMBER(val) \
1379  ((val) != NULL && \
1380  (val)->hint & (HINT_NUMBER | HINT_NODE) && \
1381  !((val)->hint & HINT_DONE))
1382 
1383 #define VAL_IS_DONE(val) \
1384  ((val) == NULL || (val)->hint & HINT_DONE)
1385 
1386 /* The function counts values in a property list up to a stop
1387  value. */
1388 static int spice_count_real_values (struct value_t * values) {
1389  int ret = 0;
1390  struct value_t * val;
1391  // go through each not yet processed value
1392  foreach_value (values, val) {
1393  if (val->hint & (HINT_NODE | HINT_NUMBER))
1394  ret++;
1395  if (val->hint & HINT_MSTOP) break; // stop here if necessary
1396  }
1397  return ret;
1398 }
1399 
1400 /* This function is the independent source translator. If necessary
1401  new kinds of sources are created. This must be done since Qucs has
1402  separate sources for each type of excitation and Spice summarizes
1403  these voltage/current excitations in a single source. */
1404 static struct definition_t *
1406  struct definition_t * def, char type) {
1407  struct definition_t * ac = NULL, * dc = def, * pulse = NULL, * expo = NULL;
1408  struct value_t * prop;
1409  char * ui = (char *) ((type == 'U') ? "U" : "I");
1410 
1411  // adjust the DC part of the source
1412  if ((prop = spice_find_property (dc->values, "DC")) != NULL) {
1413  spice_value_done (prop);
1414  prop = prop->next;
1415  if (VAL_IS_NUMBER (prop)) {
1416  spice_append_pair (def, ui, prop->ident, 1);
1417  spice_value_done (prop);
1418  }
1419  }
1420  free (dc->type);
1421  dc->type = strdup (type == 'U' ? "Vdc" : "Idc");
1422 
1423  // adjust the sinusoidal part of the source
1424  if ((prop = spice_find_property (dc->values, "SIN")) != NULL) {
1425  ac = spice_create_definition (dc, type == 'U' ? "Vac" : "Iac");
1426  spice_value_done (prop);
1427  prop = prop->next;
1428  if (VAL_IS_NUMBER (prop)) {
1429  // adjust DC offset
1430  nr_double_t off;
1431  off = spice_get_property_value (dc, ui);
1432  spice_append_pair (dc, ui, prop->ident, 1);
1433  off += spice_get_property_value (dc, ui);
1434  spice_set_property_value (dc, ui, off);
1435  spice_value_done (prop);
1436  // extract frequency, phase and theta
1437  prop = prop->next;
1438  struct property_field_t field =
1439  { { ui, "f", "Phase", "Theta", NULL } };
1440  spice_extract_properties (ac, prop, &field);
1441  }
1442  double v, f;
1443  f = spice_get_property_value (ac, "f");
1444  v = spice_get_property_value (ac, "Phase") * f * -360.0;
1445  spice_set_property_value (ac, "Phase", v);
1446  v = spice_get_property_value (ac, "Theta") / f;
1447  spice_set_property_value (ac, "Theta", f > 0 ? v : 0);
1448  }
1449 
1450  // adjust the AC part of the source
1451  if ((prop = spice_find_property (dc->values, "AC")) != NULL) {
1452  char * Mag = NULL, * Phase = NULL;
1453  spice_value_done (prop);
1454  prop = prop->next;
1455  if (VAL_IS_NUMBER (prop)) {
1456  Mag = strdup (prop->ident);
1457  spice_value_done (prop);
1458  prop = prop->next;
1459  if (VAL_IS_NUMBER (prop)) {
1460  Phase = strdup (prop->ident);
1461  spice_value_done (prop);
1462  }
1463  }
1464  if (ac == NULL) {
1465  ac = spice_create_definition (dc, type == 'U' ? "Vac" : "Iac");
1466  }
1467  if (Mag) {
1468  spice_append_pair (ac, ui, Mag, 1);
1469  free (Mag);
1470  }
1471  else {
1472  spice_append_pair (ac, ui, "0", 0);
1473  }
1474  if (Phase) {
1475  spice_append_pair (ac, "Phase", Phase, 1);
1476  free (Phase);
1477  }
1478  }
1479 
1480  // adjust the pulse part of the source
1481  if ((prop = spice_find_property (dc->values, "PULSE")) != NULL) {
1482  pulse = spice_create_definition (dc, type == 'U' ? "Vpulse" : "Ipulse");
1483  spice_value_done (prop);
1484  prop = prop->next;
1485 
1486  // periodic
1487  if (spice_count_real_values (prop) > 6) {
1488  free (pulse->type);
1489  pulse->type = type == 'U' ? strdup ("Vrect") : strdup ("Irect");
1490  double add, off = 0;
1491  if (VAL_IS_NUMBER (prop)) {
1492  add = spice_get_property_value (dc, ui);
1493  spice_append_pair (dc, ui, prop->ident, 1);
1494  off = spice_get_property_value (dc, ui);
1495  add += off;
1496  spice_set_property_value (dc, ui, add);
1497  prop = prop->next;
1498  }
1499  if (VAL_IS_NUMBER (prop)) {
1500  struct property_field_t field =
1501  { { ui, "Td", "Tr", "Tf", "TH", "TL", NULL } };
1502  spice_extract_properties (pulse, prop, &field);
1503  }
1504  double v;
1505  v = spice_get_property_value (pulse, ui); // V2
1506  v -= off;
1507  spice_set_property_value (pulse, ui, v);
1508  v = spice_get_property_value (pulse, "TH"); // PW
1509  v += spice_get_property_value (pulse, "Tr");
1510  spice_set_property_value (pulse, "TH", v);
1511  v = spice_get_property_value (pulse, "TL"); // PER
1512  v -= spice_get_property_value (pulse, "TH");
1513  spice_set_property_value (pulse, "TL", v);
1514  }
1515  // single pulse
1516  else {
1517  if (VAL_IS_NUMBER (prop)) {
1518  spice_append_pair (pulse, type == 'U' ? "U1" : "I1", prop->ident, 0);
1519  spice_append_pair (dc, ui, "0", 0);
1520  spice_value_done (prop);
1521  prop = prop->next;
1522  struct property_field_t field =
1523  { { type == 'U' ? "U2" : "I2", "T1", "Tr", "Tf", "T2", NULL } };
1524  spice_extract_properties (pulse, prop, &field);
1525  }
1526  double v;
1527  v = spice_get_property_value (pulse, "T1");
1528  v += spice_get_property_value (pulse, "Tr");
1529  v += spice_get_property_value (pulse, "Tf");
1530  v += spice_get_property_value (pulse, "T2");
1531  spice_set_property_value (pulse, "T2", v);
1532  }
1533  }
1534 
1535  // adjust the exponential part of the source
1536  if ((prop = spice_find_property (dc->values, "EXP")) != NULL) {
1537  expo = spice_create_definition (dc, type == 'U' ? "Vexp" : "Iexp");
1538  spice_value_done (prop);
1539  prop = prop->next;
1540  // extract pulse values, rise and fall constants
1541  struct property_field_t field =
1542  { { type == 'U' ? "U1" : "I1", type == 'U' ? "U2" : "I2", "T1", "Tr",
1543  "T2", "Tf", NULL } };
1544  spice_extract_properties (expo, prop, &field);
1545  }
1546 
1547  // set DC value to zero if necessary
1548  if (spice_find_property (dc, ui) == NULL) {
1549  spice_append_pair (def, ui, "0", 1);
1550  }
1551 
1552  // finally add sources to list of definitions
1553  if (ac) {
1554  if (type == 'U')
1555  spice_adjust_vsource_nodes (ac, dc);
1556  else
1557  spice_adjust_isource_nodes (ac, dc);
1558  root = spice_add_definition (root, ac);
1559  }
1560  if (pulse) {
1561  if (type == 'U')
1562  spice_adjust_vsource_nodes (pulse, ac ? ac : dc);
1563  else
1564  spice_adjust_isource_nodes (pulse, ac ? ac : dc);
1565  root = spice_add_definition (root, pulse);
1566  }
1567  if (expo) {
1568  if (type == 'U')
1569  spice_adjust_vsource_nodes (expo, pulse ? pulse : ac ? ac : dc);
1570  else
1571  spice_adjust_isource_nodes (expo, pulse ? pulse : ac ? ac : dc);
1572  root = spice_add_definition (root, expo);
1573  }
1574  return root;
1575 }
1576 
1577 /* This little function returns a static string containing an instance
1578  name of a parameter sweep. Successive calls produces different
1579  names. */
1580 static char * spice_create_intern_para (void) {
1581  static int intern = 1;
1582  static char txt[32];
1583  sprintf (txt, "SW%d", intern++);
1584  return txt;
1585 }
1586 
1587 /* The function is used to translate the lin/log10/log8 sweeps into an
1588  appropriate sweep in Qucs. Depending on the given arguments it
1589  computes the number of points in a sweep and stores the new type of
1590  sweep in the given type variable. */
1591 static int spice_evaluate_points (char ** type, double start, double stop,
1592  double points) {
1593  int ret = 1;
1594  if (!strcasecmp (*type, "dec")) { // logarithmic
1595  ret = (int) ((log10 (stop) - log10 (start)) * points);
1596  free (*type);
1597  *type = strdup ("log");
1598  }
1599  else if (!strcasecmp (*type, "lin")) { // linear
1600  ret = (int) points;
1601  free (*type);
1602  *type = strdup ("lin");
1603  }
1604  else if (!strcasecmp (*type, "oct")) { // octaves
1605  ret = (int) (((log10 (stop) - log10 (start)) / log10 (8.0)) * points);
1606  free (*type);
1607  *type = strdup ("log");
1608  }
1609  return ret;
1610 }
1611 
1612 /* This function creates a new parameter sweep (for DC analysis) and
1613  adjust all properties except the 'Sim' property which must be
1614  assigned after calling this function. */
1615 static struct definition_t * spice_create_para (struct definition_t * base) {
1616  struct property_field_t props =
1617  { { "Param", "Start", "Stop", "Points", NULL } };
1618  struct definition_t * para = create_definition ();
1619 
1620  para->type = strdup ("SW");
1621  para->action = PROP_ACTION;
1622  para->instance = strdup (spice_create_intern_para ());
1623  para->define = base->define;
1624  spice_extract_properties (para, base->values, &props);
1625  spice_set_property_string (para, "Type", "lin");
1626  double v;
1627  v = spice_get_property_value (para, "Stop");
1628  v -= spice_get_property_value (para, "Start");
1629  v /= spice_get_property_value (para, "Points");
1630  v += 1;
1631  spice_set_property_value (para, "Points", v);
1632 
1633  return para;
1634 }
1635 
1636 /* This little helper returns the number of not yet processed values
1637  in th given value list. */
1638 static int spice_count_values (struct value_t * values) {
1639  int res = 0; struct value_t * val;
1640  foreach_value (values, val) res++;
1641  return res;
1642 }
1643 
1644 /* The function looks through the list of definitions if there is a
1645  component with the given type and instance names and returns it.
1646  Otherwise the function returns NULL. */
1647 static struct definition_t *
1648 spice_find_definition (struct definition_t * root, const char * type,
1649  char * inst) {
1650  for (struct definition_t * def = root; def != NULL; def = def->next) {
1651  if (!strcasecmp (def->type, type) && !strcasecmp (def->instance, inst))
1652  return def;
1653  }
1654  return NULL;
1655 }
1656 
1657 /* The function looks through the list of definitions if there is a
1658  component with the given type and returns it. Otherwise the
1659  function returns NULL. */
1660 static struct definition_t *
1661 spice_find_definition (struct definition_t * root, const char * type) {
1662  for (struct definition_t * def = root; def != NULL; def = def->next) {
1663  if (!strcasecmp (def->type, type))
1664  return def;
1665  }
1666  return NULL;
1667 }
1668 
1669 /* The function appends the given key/value pair to the properties of
1670  any definition of the given type. */
1671 static void spice_add_property (struct definition_t * root, const char * type,
1672  const char * key, char * value) {
1673  for (struct definition_t * def = root; def != NULL; def = def->next) {
1674  if (!strcmp (def->type, type))
1675  spice_append_pair (def, key, value, 0);
1676  }
1677 }
1678 
1679 /* The following little function removes the value list of the given
1680  definition entirely if all values are marked to be processed. */
1681 static void spice_free_values (struct definition_t * def) {
1682  if (spice_count_values (def->values) <= 0) {
1683  struct value_t * val, * next;
1684  for (val = def->values; val != NULL; val = next) {
1685  next = val->next;
1686  netlist_free_value (val);
1687  }
1688  def->values = NULL;
1689  }
1690 }
1691 
1692 /* Spice node lists. */
1693 struct node_t * spice_nodes = NULL;
1694 
1695 /* Collects the nodes specified in the PLOT and PRINT statement
1696  marking them as potential "external" nodes. */
1697 static void spice_collect_external_nodes (struct definition_t * def) {
1698  struct value_t * val;
1699  foreach_value (def->values, val) {
1700  if (val->hint & HINT_MSTART && val->next && val->ident[0] == 'V') {
1701  struct node_t * n = spice_translate_node (val->next->ident);
1702  if (!qucs_find_node (spice_nodes, n->node)) {
1703  n->next = spice_nodes;
1704  spice_nodes = n;
1705  }
1706  else netlist_free_nodes (n);
1707  }
1708  }
1709 }
1710 
1711 /* This function goes through the list of device descriptions and
1712  checks whether the given model is already in the list. Returns
1713  NULL if there is no such model. */
1714 static struct definition_t * spice_find_Model (char * instance) {
1715  struct definition_t * dev;
1716  for (dev = device_root; dev; dev = dev->next) {
1717  if (!strcmp (dev->instance, instance))
1718  return dev;
1719  }
1720  return NULL;
1721 }
1722 
1723 /* The function appends a new device model. It creates the actual
1724  model description and adjusts the nodes and optional/required
1725  properties. */
1726 static struct definition_t * spice_add_Model (struct definition_t * def) {
1727  struct definition_t * Model;
1728  if (strcasecmp (def->type, "MODEL"))
1729  return NULL;
1730  if (spice_find_Model (def->instance))
1731  return NULL;
1732  Model = create_definition ();
1733  Model->action = PROP_COMPONENT;
1734  Model->instance = strdup (def->instance);
1735  Model->define = def->define;
1736  spice_adjust_device (Model, def);
1737  if (spice_translate_type (Model)) {
1738  spice_fixup_definition (Model);
1740  Model->next = device_root;
1741  device_root = Model;
1742  }
1743  else {
1744  free (Model->instance);
1745  free (Model);
1746  Model = NULL;
1747  }
1748  return Model;
1749 }
1750 
1751 /* Finds a second coupled inductor definition using the same inductors
1752  as the original one if there is any. */
1753 static struct definition_t *
1754 spice_find_coupled (struct definition_t * root, struct definition_t * coupled,
1755  const char * type, char * inst) {
1756  for (struct definition_t * def = root; def != NULL; def = def->next) {
1757  if (def != coupled && !strcmp (def->type, type) && !def->action) {
1758  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1759  continue;
1760  char * linst1 = def->values->ident;
1761  char * linst2 = def->values->next->ident;
1762  if (!strcasecmp (linst1, inst) || !strcasecmp (linst2, inst))
1763  return def;
1764  }
1765  }
1766  return NULL;
1767 }
1768 
1769 /* Looks for a mutual inductor instance referencing the two given
1770  inductors and returns it. */
1771 static struct definition_t *
1772 spice_find_coupled (struct definition_t * root, const char * type,
1773  char * inst1, char * inst2) {
1774  for (struct definition_t * def = root; def != NULL; def = def->next) {
1775  if (!strcmp (def->type, type) && !def->action) {
1776  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1777  continue;
1778  char * linst1 = def->values->ident;
1779  char * linst2 = def->values->next->ident;
1780  if ((!strcasecmp (linst1, inst1) && !strcasecmp (linst2, inst2)) ||
1781  (!strcasecmp (linst1, inst2) && !strcasecmp (linst2, inst1)))
1782  return def;
1783  }
1784  }
1785  return NULL;
1786 }
1787 
1788 /* Looks for the inductor definition used in a coupled inductor.
1789  Emits an error message if there is no such inductor. */
1790 static struct definition_t *
1792  struct definition_t * def, const char * type,
1793  char * inst) {
1794  static struct definition_t * target;
1795  target = spice_find_definition (root, type, inst);
1796  if (target == NULL) {
1797  fprintf (stderr, "spice error, no such inductor `%s' found as "
1798  "referenced by %s `%s'\n", inst, def->type, def->instance);
1799  spice_errors++;
1800  }
1801  return target;
1802 }
1803 
1804 // Get the coefficient of coupling.
1805 static struct value_t *
1807  struct value_t * val = NULL;
1808  foreach_value (def->values, val) {
1809  if (val->hint & HINT_NUMBER) break;
1810  }
1811  return val;
1812 }
1813 
1814 // Generates a coupled inductor instance description.
1815 static char *
1817  struct definition_t * k3) {
1818  char * inst = (char *) malloc (strlen (k1->instance) +
1819  strlen (k2->instance) +
1820  strlen (k3->instance) + 1);
1821  strcpy (inst, k1->instance);
1822  strcat (inst, k2->instance);
1823  strcat (inst, k3->instance);
1824  return inst;
1825 }
1826 
1827 /* Post translation function for coupled inductors. */
1828 static struct definition_t *
1830  struct definition_t * def) {
1831  struct definition_t * target1, * target2, * target3;
1832  char * linst1 = def->values->ident; // get inductivity 1
1833  char * linst2 = def->values->next->ident; // get inductivity 2
1834  nr_double_t l1, l2, l3, k, t;
1835  char * n1, * n2, * n3, * n4;
1836  struct node_t * nn;
1837 
1838  // initialize local variables
1839  n1 = n2 = n3 = n4 = NULL;
1840  l1 = l2 = l3 = k = t = 0;
1841 
1842  // find and handle inductivity 1
1843  target1 = spice_find_coupled_inductor (root, def, "L", linst1);
1844 
1845  // find and handle inductivity 2
1846  target2 = spice_find_coupled_inductor (root, def, "L", linst2);
1847 
1848  // if both inductors found
1849  if (!target1 || !target2) return root;
1850 
1851  l1 = spice_get_property_value (target1, "L");
1852  l2 = spice_get_property_value (target2, "L");
1853 
1854  // check three inductors
1855  struct definition_t * k1 = def, * k2, * k3;
1856  char * k12, * k13, * k23;
1857  k2 = spice_find_coupled (root, k1, "Tr", linst1);
1858  k3 = spice_find_coupled (root, k1, "Tr", linst2);
1859 
1860  // handle three inductors
1861  if (k2 != NULL && k3 != NULL) {
1862  char * linst3, * linst4;
1863  if (!strcasecmp (k2->values->ident, linst1))
1864  linst3 = k2->values->next->ident;
1865  else
1866  linst3 = k2->values->ident;
1867  if (!strcasecmp (k3->values->ident, linst2))
1868  linst4 = k3->values->next->ident;
1869  else
1870  linst4 = k3->values->ident;
1871  spice_value_done (k1->values);
1872  spice_value_done (k1->values->next);
1873 
1874  if (strcasecmp (linst3, linst4)) {
1875  fprintf (stderr, "spice error, cannot translate coupled inductors "
1876  "`%s' and `%s'\n", linst3, linst4);
1877  spice_errors++;
1878  }
1879  else if (k2 != k3) {
1880  // find and handle inductivity 3
1881  target3 = spice_find_coupled_inductor (root, k2, "L", linst3);
1882  if (target3 != NULL) {
1883  // construct three mutual inductors
1884  struct value_t * val;
1885  char * inst = spice_coupled_instance (k1, k2, k3);
1886  free (k1->type); k1->type = strdup ("MUT2");
1887  free (k1->instance); k1->instance = inst;
1888  netlist_free_pairs (k1->pairs); k1->pairs = NULL;
1889  spice_value_done (k2->values);
1890  spice_value_done (k2->values->next);
1891  spice_value_done (k3->values);
1892  spice_value_done (k3->values->next);
1893  spice_append_node (k1, spice_get_node(target1, 1)->node);
1894  spice_append_node (k1, spice_get_node(target3, 1)->node);
1895  spice_append_node (k1, spice_get_node(target3, 2)->node);
1896  spice_append_node (k1, spice_get_node(target2, 2)->node);
1897  spice_append_node (k1, spice_get_node(target2, 1)->node);
1898  spice_append_node (k1, spice_get_node(target1, 2)->node);
1899  l3 = spice_get_property_value (target3, "L");
1900  spice_set_property_value (k1, "L1", l1);
1901  spice_set_property_value (k1, "L2", l2);
1902  spice_set_property_value (k1, "L3", l3);
1903  if ((val = spice_get_value_coupled (k1)) != NULL) {
1904  k12 = val->ident;
1905  spice_append_pair (k1, "k12", k12, 0);
1906  spice_value_done (val);
1907  }
1908  if ((val = spice_get_value_coupled (k2)) != NULL) {
1909  k13 = val->ident;
1910  spice_append_pair (k1, "k13", k13, 0);
1911  spice_value_done (val);
1912  }
1913  if ((val = spice_get_value_coupled (k3)) != NULL) {
1914  k23 = val->ident;
1915  spice_append_pair (k1, "k23", k23, 0);
1916  spice_value_done (val);
1917  }
1918  root = spice_del_definition (root, target1);
1919  root = spice_del_definition (root, target2);
1920  root = spice_del_definition (root, target3);
1921  root = spice_del_definition (root, k2);
1922  root = spice_del_definition (root, k3);
1923  return root;
1924  }
1925  }
1926  }
1927 
1928  spice_value_done (def->values);
1929  spice_value_done (def->values->next);
1930 
1931  // node replacer 1
1932  nn = spice_get_node (target1, 2);
1933  n4 = nn->node;
1934  nn->node = strdup (spice_create_intern_node ());
1935  n1 = strdup (nn->node);
1936 
1937  // node replacer 2
1938  nn = spice_get_node (target2, 2);
1939  n3 = nn->node;
1940  nn->node = strdup (spice_create_intern_node ());
1941  n2 = strdup (nn->node);
1942 
1943  // get the coefficient of coupling
1944  struct value_t * val;
1945  spice_append_pair (def, "T", "1", 1);
1946  if ((val = spice_get_value_coupled (def)) != NULL) {
1947  spice_append_pair (def, "T", val->ident, 1);
1948  spice_value_done (val);
1949  }
1950 
1951  // apply the turns ratio of the transformer and its nodes
1952  k = spice_get_property_value (def, "T");
1953  t = sqrt (l1 / l2);
1954  spice_set_property_value (def, "T", t);
1955  spice_append_node (def, n1);
1956  spice_append_node (def, n2);
1957  spice_append_node (def, n3);
1958  spice_append_node (def, n4);
1959  // adapt inductivities of original inductors
1960  spice_set_property_value (target1, "L", l1 - k * l1);
1961  spice_set_property_value (target2, "L", l2 - k * l1 / t / t);
1962  // insert the actual mutual inductance if necessary
1963  if (k > 0) {
1964  struct definition_t * Mind = spice_create_definition (def, "L");
1965  spice_append_node (Mind, n1);
1966  spice_append_node (Mind, n4);
1967  spice_set_property_value (Mind, "L", k * l1);
1968  root = spice_add_definition (root, Mind);
1969  }
1970  free (n1); free (n2); free (n3); free (n4);
1971  return root;
1972 }
1973 
1974 /* Finds an additional mutual inductor definition using the same
1975  inductors as the original one if there is any. */
1976 static struct definition_t *
1979  const char * type, char * inst) {
1980  for (struct definition_t * def = root; def != NULL; def = def->next) {
1981  if (!strcmp (def->type, type) && !def->action) {
1982  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1983  continue;
1984  if (!coupled->get (def->instance)) {
1985  char * linst1 = def->values->ident;
1986  char * linst2 = def->values->next->ident;
1987  if (!strcasecmp (linst1, inst) || !strcasecmp (linst2, inst))
1988  return def;
1989  }
1990  }
1991  }
1992  return NULL;
1993 }
1994 
1995 /* Looks recursively for mutual inductors. In the end the two hash
1996  maps contain all the inductors coupled by those mutual inductors in
1997  the other hash map. */
1998 static struct definition_t *
2002  const char * type, char * inst) {
2003  char * linst;
2004  struct definition_t * l, * k;
2005 
2006  // find mutual inductors referencing the given inductor instance
2007  while ((k = spice_find_coupled (root, K_hash, type, inst)) != NULL) {
2008  // already had this one?
2009  if (K_hash->get (k->instance))
2010  continue;
2011  K_hash->put (k->instance, k);
2012 
2013  // first referenced inductor
2014  linst = k->values->ident;
2015  if (!L_hash->get (linst)) {
2016  if ((l = spice_find_coupled_inductor (root, k, "L", linst)) != NULL) {
2017  L_hash->put (linst, l);
2018  // recurse
2019  root = spice_search_coupled (root, K_hash, L_hash, type, linst);
2020  }
2021  }
2022 
2023  // second referenced inductor
2024  linst = k->values->next->ident;
2025  if (!L_hash->get (linst)) {
2026  if ((l = spice_find_coupled_inductor (root, k, "L", linst)) != NULL) {
2027  L_hash->put (linst, l);
2028  // recurse
2029  root = spice_search_coupled (root, K_hash, L_hash, type, linst);
2030  }
2031  }
2032  }
2033  return root;
2034 }
2035 
2036 /* Post translation function for multiple coupled inductors. */
2037 static struct definition_t *
2039  struct definition_t * def) {
2040  char * linst1, * linst2;
2044  struct definition_t * l;
2045 
2046  // save first 2 referenced inductors and the mutual inductor
2047  linst1 = def->values->ident;
2048  if ((l = spice_find_coupled_inductor (root, def, "L", linst1)) != NULL)
2049  L_hash.put (linst1, l);
2050  linst2 = def->values->next->ident;
2051  if ((l = spice_find_coupled_inductor (root, def, "L", linst2)) != NULL)
2052  L_hash.put (linst2, l);
2053  K_hash.put (def->instance, def);
2054 
2055  // look for more mutual inductors involving the first 2 inductors
2056  root = spice_search_coupled (root, &K_hash, &L_hash, "Tr", linst1);
2057  root = spice_search_coupled (root, &K_hash, &L_hash, "Tr", linst2);
2058 
2059  // create coupling coefficient matrix
2060  int i, o, s = L_hash.count ();
2061  nr_double_t * kval = new nr_double_t[s * s];
2062  struct definition_t * k;
2063  struct value_t * val;
2065  // outer loop
2066  for (ito = qucs::hashiterator<struct definition_t> (L_hash), o = 0;
2067  *ito; ++ito, ++o) {
2068  // inner loop
2069  for (iti = qucs::hashiterator<struct definition_t> (L_hash), i = 0;
2070  *iti; ++iti, ++i) {
2071  if (i > o) {
2072  // cross-coupling coefficients
2073  nr_double_t kvalue = 0;
2074  k = spice_find_coupled (root, "Tr",
2075  iti.currentKey (), ito.currentKey ());
2076  if (k != NULL) {
2077  if ((val = spice_get_value_coupled (k)) != NULL) {
2078  kvalue = spice_evaluate_value (val);
2079  }
2080  }
2081  kval[s * o + i] = kvalue;
2082  kval[s * i + o] = kvalue;
2083  }
2084  else if (i == o) {
2085  // self-coupling coefficient
2086  kval[s * o + i] = 1;
2087  }
2088  }
2089  }
2090 
2091  spice_value_done (def->values);
2092  spice_value_done (def->values->next);
2093 
2094  // adjust MUTX instance
2095  free (def->type); def->type = strdup ("MUTX");
2096  netlist_free_pairs (def->pairs); def->pairs = NULL;
2097 
2098  // create L property vector
2099  struct pair_t * pair = create_pair ();
2100  pair->key = strdup ("L");
2101  def->pairs = netlist_append_pairs (def->pairs, pair);
2102  for (it = qucs::hashiterator<struct definition_t> (L_hash); *it; ++it) {
2103  spice_append_node (def, spice_get_node(it.currentVal (), 1)->node);
2104  spice_append_node (def, spice_get_node(it.currentVal (), 2)->node);
2105  val = create_value ();
2106  val->value = spice_get_property_value (it.currentVal (), "L");
2107  pair->value = netlist_append_values (pair->value, val);
2108  root = spice_del_definition (root, it.currentVal ());
2109  }
2110 
2111  // create k property vector
2112  pair = create_pair ();
2113  pair->key = strdup ("k");
2114  def->pairs = netlist_append_pairs (def->pairs, pair);
2115  for (i = 0; i < s * s; i++) {
2116  val = create_value ();
2117  val->value = kval[i];
2118  pair->value = netlist_append_values (pair->value, val);
2119  }
2120 
2121  // remove remaining coupled inductors from definition list
2122  for (it = qucs::hashiterator<struct definition_t> (K_hash); *it; ++it) {
2123  if (def != it.currentVal ()) {
2124  root = spice_del_definition (root, it.currentVal ());
2125  }
2126  }
2127 
2128  delete[] kval;
2129  return root;
2130 }
2131 
2132 /* Contructs an edd equation name. */
2133 static char *
2134 spice_create_eqnstr (struct definition_t * def, int p, char type) {
2135  char * n = (char *) malloc (strlen (def->instance) + 4 + 3);
2136  sprintf (n, "%s.%c%d", def->instance, type, p);
2137  return n;
2138 }
2139 
2140 /* The function adds edd equation properties to the given netlist
2141  definition and also adds the appropriate equation instances. */
2142 static struct definition_t *
2144  struct definition_t * def, int p,
2145  struct definition_t ** i, struct definition_t ** q) {
2146  struct definition_t * ieqn, * qeqn;
2147  char I_[4], Q_[4];
2148  char * ieq = spice_create_eqnstr (def, p, 'I');
2149  char * qeq = spice_create_eqnstr (def, p, 'Q');
2150  sprintf (I_, "I%d", p);
2151  sprintf (Q_, "Q%d", p);
2152  spice_set_property_string (def, Q_, qeq);
2153  spice_set_property_string (def, I_, ieq);
2154  ieqn = spice_create_definition (def, "Eqn");
2155  qeqn = spice_create_definition (def, "Eqn");
2156  spice_set_property_string (ieqn, "Export", "no");
2157  spice_set_property_string (qeqn, "Export", "no");
2158  spice_set_property_string (ieqn, ieq, "0");
2159  spice_set_property_string (qeqn, qeq, "0");
2160  root = spice_add_definition (root, qeqn);
2161  root = spice_add_definition (root, ieqn);
2162  sprintf (ieq, "Eqn%sI%d", def->instance, p);
2163  sprintf (qeq, "Eqn%sQ%d", def->instance, p);
2164  free (ieqn->instance);
2165  free (qeqn->instance);
2166  qeqn->instance = strdup (qeq);
2167  ieqn->instance = strdup (ieq);
2168  free (ieq);
2169  free (qeq);
2170  if (i) (*i) = ieqn;
2171  if (q) (*q) = qeqn;
2172  return root;
2173 }
2174 
2175 /* Since there no or little documentation about the polynom orders in
2176  the SPICE2G6 'POLY' statements the following piece of code is a
2177  straight re-implementation of the Fortran code in SPICE2G6. */
2178 static void spice2g6_nxtpwr (int * seq, int nd) {
2179  int i, k, ps;
2180 
2181  // special handling of one-dimensional polynoms
2182  if (nd == 1) {
2183  seq[0]++;
2184  return;
2185  }
2186 
2187  // two and more-dimensional polynoms
2188  k = nd;
2189  do {
2190  if (seq[k - 1] != 0) break;
2191  }
2192  while (--k != 0);
2193 
2194  if (k == 0) {
2195  seq[0]++;
2196  }
2197  else if (k != nd) {
2198  seq[k - 1]--;
2199  seq[k]++;
2200  }
2201  else {
2202  for (i = 0; i < k - 1; i++)
2203  if (seq[i] != 0) break;
2204  if (i == k - 1) {
2205  seq[0] = seq[nd - 1] + 1;
2206  seq[nd-1] = 0;
2207  return;
2208  }
2209  ps = 1;
2210  k = nd - 1;
2211  while (seq[k - 1] < 1) {
2212  ps += seq[k];
2213  seq[k] = 0;
2214  k--;
2215  }
2216  seq[k] += ps;
2217  seq[k - 1]--;
2218  }
2219 }
2220 
2221 /* The function takes the given spice value, converts it into an
2222  appropriate real value and save optional scale and unit and finally
2223  returns the actual value. */
2224 static double spice_get_value (struct value_t * val) {
2225  const char * str;
2226  char * end;
2227  double v;
2228  val->value = strtod (val->ident, &end);
2229  if (*end) {
2230  str = spice_evaluate_scale (end, &end, &v);
2231  val->value *= v;
2232  val->scale = str ? strdup (str) : NULL;
2233  if (*end) val->unit = strdup (end);
2234  }
2235  return val->value;
2236 }
2237 
2238 /* Creates a 'nd' dimensional polynomial expression extracted from the
2239  coefficient list of a value. */
2240 static char *
2241 spice_create_poly (struct value_t * prop, int nd, int integrate) {
2242  struct value_t * val;
2243 
2244  // contruct polynomial expression
2245  int * pn = (int *) calloc (nd, sizeof (int));
2246  static char expr[1024];
2247  char value[256];
2248  strcpy (expr, "");
2249 
2250  // go through spice values
2251  foreach_value (prop, val) {
2252  if (!VAL_IS_NUMBER (val)) break;
2253 
2254  double k = spice_get_value (val);
2255  spice_value_done (val);
2256 
2257  // construct single polynom
2258  if (k != 0.0) {
2259 
2260  // coefficient
2261  sprintf (value, "%+g", k);
2262  strcat (expr, value);
2263 
2264  // remaining polynom
2265  for (int i = 0; i < nd; i++) {
2266  int n = integrate ? i + 1 : i + 2;
2267  int e = integrate ? pn[i] + 2 : pn[i];
2268  switch (e) {
2269  case 0:
2270  strcpy (value, "");
2271  break;
2272  case 1:
2273  sprintf (value, "*V%d", n);
2274  break;
2275  case 2:
2276  sprintf (value, "*V%d*V%d", n, n);
2277  break;
2278  default:
2279  sprintf (value, "*V%d^%d", n, e);
2280  break;
2281  }
2282  strcat (expr, value);
2283 
2284  // coefficient correction
2285  if (integrate && e > 1) {
2286  sprintf (value, "/%d", e);
2287  strcat (expr, value);
2288  }
2289  }
2290  }
2291 
2292  // prepare next polynom
2293  spice2g6_nxtpwr (pn, nd);
2294  }
2295  free (pn);
2296  return expr;
2297 }
2298 
2299 /* Translates E and G poly sources. */
2300 static struct definition_t *
2301 spice_translate_poly (struct definition_t * root, struct definition_t * def) {
2302  struct value_t * prop;
2303  int nd, type = -1;
2304 
2305  // only handle appropriate sources
2306  if (strcasecmp (def->type, "E") && strcasecmp (def->type, "G") &&
2307  strcasecmp (def->type, "F") && strcasecmp (def->type, "H"))
2308  return root;
2309 
2310  // save source type information
2311  if (!strcasecmp (def->type, "E"))
2312  type = 0;
2313  else if (!strcasecmp (def->type, "G"))
2314  type = 1;
2315  else if (!strcasecmp (def->type, "H"))
2316  type = 2;
2317  else if (!strcasecmp (def->type, "F"))
2318  type = 3;
2319 
2320  if ((prop = spice_find_property (def->values, "POLY")) != NULL) {
2321  // retype poly source into EDD
2322  free (def->type);
2323  def->type = strdup ("EDD");
2324  spice_value_done (prop);
2325  // get number of polynomial terms
2326  prop = prop->next;
2327  nd = (int) spice_evaluate_value (prop);
2328  spice_value_done (prop);
2329 
2330  // contruct properties, equations and nodes of the EDD
2331  if (type <= 1) {
2332  // handle E and G voltage controlled sources
2333  prop = prop->next;
2334  for (int i = nd * 2 - 1; i >= 0; i--) {
2335  int p = (i + 1) / 2 + 1;
2336  struct node_t * node = spice_translate_node (prop->ident);
2337  def->nodes = netlist_append_nodes (def->nodes, node);
2338  if (i & 1) root = spice_add_edd_equation (root, def, p, NULL, NULL);
2339  spice_value_done (prop);
2340  prop = prop->next;
2341  }
2342  }
2343  else {
2344  // handle F and H current controlled sources
2345  prop = prop->next;
2346  for (int i = nd; i > 0; i--) {
2347  struct definition_t * vdc, * ibuf;
2348  char * vn, * np, * nn;
2349  int p = i + 1;
2350  // find referenced voltage source (where current flows through)
2351  vn = prop->ident;
2352  vdc = spice_find_definition (root, "Vdc", vn);
2353  if (vdc) {
2354  // create intermediate current controlled voltage source
2355  // passing voltage to an EDD branch
2356  ibuf = spice_create_definition (def, "CCVS");
2357  vn = (char *) malloc (strlen (ibuf->instance) + 3);
2358  sprintf (vn, "%sV%d", ibuf->instance, p);
2359  free (ibuf->instance);
2360  ibuf->instance = vn;
2361  struct node_t * node = spice_get_node (vdc, 1);
2362  np = strdup (spice_create_intern_node ());
2363  nn = strdup (spice_create_intern_node ());
2364  spice_append_node (ibuf, node->node);
2365  free (node->node);
2366  node->node = strdup (nn);
2367  spice_append_node (def, np);
2368  spice_append_node (def, (char *) "gnd");
2369  spice_append_node (ibuf, np);
2370  spice_append_node (ibuf, (char *) "gnd");
2371  spice_append_node (ibuf, nn);
2372  spice_set_property_string (ibuf, "G", "1");
2373  root = spice_add_definition (root, ibuf);
2374  free (nn);
2375  free (np);
2376  }
2377  else {
2378  fprintf (stderr, "spice error, no such voltage source `%s' found as "
2379  "referenced by the %s `%s' instance\n", def->type,
2380  def->instance, vn);
2381  spice_errors++;
2382  }
2383  root = spice_add_edd_equation (root, def, p, NULL, NULL);
2384  spice_value_done (prop);
2385  prop = prop->next;
2386  }
2387  }
2388 
2389  // add first (really evaluating) I and Q equations
2390  struct definition_t * ieqn, * qeqn;
2391  root = spice_add_edd_equation (root, def, 1, &ieqn, &qeqn);
2392 
2393  // contruct polynomial expression
2394  char * expr = spice_create_poly (prop, nd, 0);
2395 
2396  // replace first current branch to reflect polynom
2397  char * ieq = spice_create_eqnstr (def, 1, 'I');
2398  spice_set_property_string (ieqn, ieq, expr);
2399  free (ieq);
2400 
2401  // finally add buffering controlled source
2402  struct definition_t * obuf = NULL;
2403  struct node_t * pnode, * nnode;
2404  char * intp;
2405 
2406  if ((type & 1) == 0)
2407  obuf = spice_create_definition (def, "CCVS");
2408  else if ((type & 1) == 1)
2409  obuf = spice_create_definition (def, "CCCS");
2410 
2411  pnode = spice_get_node (def, 1);
2412  nnode = spice_get_node (def, 2);
2413  intp = strdup (spice_create_intern_node ());
2414 
2415  spice_append_node (obuf, intp);
2416  spice_append_node (obuf, nnode->node);
2417  spice_append_node (obuf, pnode->node);
2418  spice_append_node (obuf, (char *) "gnd");
2419 
2420  free (pnode->node);
2421  pnode->node = strdup (intp);
2422  free (nnode->node);
2423  nnode->node = strdup ("gnd");
2424  free (intp);
2425 
2426  spice_set_property_string (obuf, "G", "1");
2427  root = spice_add_definition (root, obuf);
2428  }
2429  return root;
2430 }
2431 
2432 /* Translates non-linear L and C poly definitions. */
2433 static struct definition_t *
2435  struct definition_t * def) {
2436  struct value_t * prop;
2437  int type = -1;
2438  double lc = 0.0;
2439 
2440  // save type information
2441  if (!strcasecmp (def->type, "C"))
2442  type = 0;
2443  else if (!strcasecmp (def->type, "L"))
2444  type = 1;
2445 
2446  if ((prop = spice_find_property (def->values, "POLY")) != NULL) {
2447  // retype poly LC into EDD
2448  free (def->type);
2449  def->type = strdup ("EDD");
2450  spice_value_done (prop);
2451 
2452  // get constant L or C value
2453  struct pair_t * p;
2454  if ((p = spice_find_property (def, "C")) != NULL) {
2455  lc = spice_get_property_value (def, "C");
2456  def->pairs = spice_del_property (def->pairs, p);
2457  }
2458  else if ((p = spice_find_property (def, "L")) != NULL) {
2459  lc = spice_get_property_value (def, "L");
2460  def->pairs = spice_del_property (def->pairs, p);
2461  }
2462 
2463  // add I and Q equations
2464  struct definition_t * ieqn, * qeqn;
2465  root = spice_add_edd_equation (root, def, 1, &ieqn, &qeqn);
2466 
2467  // contruct polynomial expression
2468  char * expr1 = strdup (spice_create_poly (prop, 1, 1));
2469  char * expr2 = expr1;
2470  if (lc != 0.0) {
2471  expr2 = (char *) malloc (strlen (expr1) + 256);
2472  sprintf (expr2, "%+g*V1%s", lc, expr1);
2473  free (expr1);
2474  }
2475 
2476  // replace first charge branch to reflect polynom
2477  char * qeq = spice_create_eqnstr (def, 1, 'Q');
2478  spice_set_property_string (qeqn, qeq, expr2);
2479  free (expr2);
2480  free (qeq);
2481 
2482  // finally add converting gyrator if necessary
2483  if (type == 1) {
2484  struct definition_t * gyra = NULL;
2485  struct node_t * pnode, * nnode;
2486  char * intp;
2487 
2488  gyra = spice_create_definition (def, "Gyrator");
2489 
2490  pnode = spice_get_node (def, 1);
2491  nnode = spice_get_node (def, 2);
2492  intp = strdup (spice_create_intern_node ());
2493 
2494  spice_append_node (gyra, intp);
2495  spice_append_node (gyra, nnode->node);
2496  spice_append_node (gyra, pnode->node);
2497  spice_append_node (gyra, (char *) "gnd");
2498 
2499  free (pnode->node);
2500  pnode->node = strdup (intp);
2501  free (nnode->node);
2502  nnode->node = strdup ("gnd");
2503  free (intp);
2504 
2505  spice_set_property_string (gyra, "R", "1");
2506  root = spice_add_definition (root, gyra);
2507  }
2508  }
2509  return root;
2510 }
2511 
2512 /* This function must be called after the actual Spice netlist
2513  translator in order to adjust some references or whatever in the
2514  resulting netlist. */
2515 static struct definition_t *
2517  for (struct definition_t * def = root; def != NULL; def = def->next) {
2518  // post-process parameter sweep
2519  if (def->action && !strcmp (def->type, "SW")) {
2520  // adjust the actual 'Param' name
2521  struct pair_t * prop = spice_find_property (def, "Param");
2522  char * val = spice_toupper (prop->value->ident);
2523  struct definition_t * target;
2524  // get the target voltage or current source and adjust the property
2525  target = spice_find_definition (root, "Vdc", val);
2526  if (target) {
2527  prop = spice_find_property (target, "U");
2528  prop->value->ident = strdup (val);
2529  }
2530  else {
2531  target = spice_find_definition (root, "Idc", val);
2532  if (target) {
2533  prop = spice_find_property (target, "I");
2534  prop->value->ident = strdup (val);
2535  }
2536  else {
2537  fprintf (stderr, "spice error, no such source `%s' found as "
2538  "referenced by the .DC analysis\n", val);
2539  spice_errors++;
2540  }
2541  }
2542  }
2543  // post-process current-controlled current/voltage source
2544  if (!def->action && (!strcmp (def->type, "CCCS") ||
2545  !strcmp (def->type, "CCVS"))) {
2546  struct definition_t * target;
2547  struct value_t * val = spice_find_device_instance (def);
2548  if (val) {
2549  char * key = val->ident;
2550  target = spice_find_definition (root, "Vdc", key);
2551  if (target) {
2552  // adjust the controlling nodes of the source
2553  spice_adjust_vsource_nodes (def, target);
2554  spice_translate_nodes (def, 1);
2555  }
2556  else {
2557  fprintf (stderr, "spice error, no such voltage source `%s' found "
2558  "as referenced by the %s `%s' instance\n", def->type,
2559  def->instance, key);
2560  spice_errors++;
2561  }
2562  }
2563  }
2564  // post-process F and H poly sources
2565  if (!def->action && (!strcmp (def->type, "F") ||
2566  !strcmp (def->type, "H"))) {
2567  root = spice_translate_poly (root, def);
2568  }
2569  // post-process switches
2570  if (!def->action && !strcmp (def->type, "Relais")) {
2571  struct pair_t * pon = spice_find_property_nocase (def, "VON");
2572  struct pair_t * pof = spice_find_property_nocase (def, "VOFF");
2573  if (pon != NULL && pof != NULL) {
2574  nr_double_t von = spice_evaluate_value (pon->value);
2575  nr_double_t vof = spice_evaluate_value (pof->value);
2576  def->pairs = spice_del_property (def->pairs, pon);
2577  def->pairs = spice_del_property (def->pairs, pof);
2578  nr_double_t vh = (von - vof) / 2;
2579  nr_double_t vt = (von + vof) / 2;
2580  spice_set_property_value (def, "Vt", vt);
2581  spice_set_property_value (def, "Vh", fabs (vh));
2582  }
2583  }
2584  // post-process pulse and rectangular sources
2585  if (!def->action && (!strcmp (def->type, "Vpulse") ||
2586  !strcmp (def->type, "Ipulse") ||
2587  !strcmp (def->type, "Vrect") ||
2588  !strcmp (def->type, "Irect"))) {
2589  struct definition_t * tran;
2590  struct pair_t * tr = spice_find_property (def, "Tr");
2591  struct pair_t * tf = spice_find_property (def, "Tf");
2592  if (tr == NULL || tf == NULL) {
2593  if ((tran = spice_find_definition (definition_root, "TR")) != NULL) {
2594  nr_double_t start = spice_get_property_value (tran, "Start");
2595  nr_double_t stop = spice_get_property_value (tran, "Stop");
2596  nr_double_t points = spice_get_property_value (tran, "Points");
2597  nr_double_t tstep = (stop - start) / (points - 1);
2598  nr_double_t add = 0;
2599  if (!tf) {
2600  spice_set_property_value (def, "Tf", tstep);
2601  add += tstep;
2602  }
2603  if (!tr) {
2604  spice_set_property_value (def, "Tr", tstep);
2605  add += tstep;
2606  }
2607  if (!strcmp (&def->type[1], "pulse")) {
2608  nr_double_t t2 = spice_get_property_value (def, "T2");
2609  spice_set_property_value (def, "T2", t2 + add);
2610  }
2611  }
2612  }
2613  }
2614  // post-process sinusoidal sources
2615  if (!def->action && (!strcmp (def->type, "Vac") ||
2616  !strcmp (def->type, "Iac"))) {
2617  struct definition_t * tran;
2618  struct pair_t * f = spice_find_property (def, "f");
2619  if (f == NULL) {
2620  if ((tran = spice_find_definition (definition_root, "TR")) != NULL) {
2621  nr_double_t stop = spice_get_property_value (tran, "Stop");
2622  spice_set_property_value (def, "f", 1 / stop);
2623  }
2624  }
2625  }
2626  // post-process resistors
2627  if (!def->action && !strcmp (def->type, "R")) {
2628  // drop the second "R" given in Model
2629  struct pair_t * r1 = spice_find_property_nocase (def, "R");
2630  struct pair_t * r2 = spice_find_property_nocase (r1->next, "R");
2631  if (r2 != NULL) {
2632  def->pairs = spice_del_property (def->pairs, r2);
2633  }
2634  // calculate R value
2635  struct pair_t * L = spice_find_property_nocase (def, "L");
2636  struct pair_t * W = spice_find_property_nocase (def, "W");
2637  struct pair_t * R = spice_find_property_nocase (def, "RSH");
2638  struct pair_t * D = spice_find_property_nocase (def, "DEFW");
2639  struct pair_t * N = spice_find_property_nocase (def, "NARROW");
2640  nr_double_t l = 0, w = 0, r = 0, d = 0, n = 0;
2641  if (L) {
2642  l = spice_evaluate_value (L->value);
2643  def->pairs = spice_del_property (def->pairs, L);
2644  }
2645  if (W) {
2646  w = spice_evaluate_value (W->value);
2647  def->pairs = spice_del_property (def->pairs, W);
2648  }
2649  if (R) {
2650  r = spice_evaluate_value (R->value);
2651  def->pairs = spice_del_property (def->pairs, R);
2652  }
2653  if (D) {
2654  d = spice_evaluate_value (D->value);
2655  def->pairs = spice_del_property (def->pairs, D);
2656  }
2657  if (N) {
2658  n = spice_evaluate_value (N->value);
2659  def->pairs = spice_del_property (def->pairs, N);
2660  }
2661  if (d == 0) d = 1e-6;
2662  if (w == 0) w = d;
2663  if (l != 0 && w != 0 && r != 0) {
2664  r = r * (l - n) / (w - n);
2665  spice_set_property_value (def, "R", r);
2666  }
2667  // handle Spice 2g6 syntax
2668  struct value_t * val;
2669  foreach_value (def->values, val) {
2670  if (!(val->hint & HINT_DONE) && (val->hint & HINT_NUMBER)) {
2671  spice_append_pair (def, "Tc2", val->ident, 0);
2672  spice_value_done (val);
2673  break;
2674  }
2675  }
2676  }
2677  // post-process capacitor
2678  if (!def->action && !strcmp (def->type, "C")) {
2679  // calculate C value
2680  struct pair_t * L = spice_find_property_nocase (def, "L");
2681  struct pair_t * W = spice_find_property_nocase (def, "W");
2682  struct pair_t * C = spice_find_property_nocase (def, "CJ");
2683  struct pair_t * S = spice_find_property_nocase (def, "CJSW");
2684  struct pair_t * D = spice_find_property_nocase (def, "DEFW");
2685  struct pair_t * N = spice_find_property_nocase (def, "NARROW");
2686  nr_double_t l = 0, w = 0, c = 0, d = 0, n = 0, s = 0;
2687  if (L) {
2688  l = spice_evaluate_value (L->value);
2689  def->pairs = spice_del_property (def->pairs, L);
2690  }
2691  if (W) {
2692  w = spice_evaluate_value (W->value);
2693  def->pairs = spice_del_property (def->pairs, W);
2694  }
2695  if (C) {
2696  c = spice_evaluate_value (C->value);
2697  def->pairs = spice_del_property (def->pairs, C);
2698  }
2699  if (S) {
2700  s = spice_evaluate_value (S->value);
2701  def->pairs = spice_del_property (def->pairs, S);
2702  }
2703  if (D) {
2704  d = spice_evaluate_value (D->value);
2705  def->pairs = spice_del_property (def->pairs, D);
2706  }
2707  if (N) {
2708  n = spice_evaluate_value (N->value);
2709  def->pairs = spice_del_property (def->pairs, N);
2710  }
2711  if (d == 0) d = 1e-6;
2712  if (w == 0) w = d;
2713  if (l != 0 && w != 0 && c != 0) {
2714  c = c * (l - n) * (w - n) + 2 * s * (l + w - 2 * n);
2715  spice_set_property_value (def, "C", c);
2716  }
2717  }
2718  // post-process lossless transmission line
2719  if (!def->action && !strcmp (def->type, "TLIN4P")) {
2720  struct pair_t * pt = spice_find_property (def, "TD");
2721  struct pair_t * pf = spice_find_property (def, "F");
2722  struct pair_t * pl = spice_find_property (def, "NL");
2723  nr_double_t len = 1e-3;
2724  if (pt != NULL) {
2725  // delay given
2726  len = spice_evaluate_value (pt->value) * C0;
2727  def->pairs = spice_del_property (def->pairs, pt);
2728  spice_set_property_value (def, "L", len);
2729  }
2730  else if (pf != NULL && pl != NULL) {
2731  // frequency and normalized length given
2732  nr_double_t f = spice_evaluate_value (pf->value);
2733  nr_double_t l = spice_evaluate_value (pl->value);
2734  def->pairs = spice_del_property (def->pairs, pf);
2735  def->pairs = spice_del_property (def->pairs, pl);
2736  len = C0 / f * l;
2737  spice_set_property_value (def, "L", len);
2738  }
2739  else if (pf != NULL) {
2740  // only frequency given, default normalized length
2741  nr_double_t f = spice_evaluate_value (pf->value);
2742  def->pairs = spice_del_property (def->pairs, pf);
2743  len = C0 / f * 0.25;
2744  spice_set_property_value (def, "L", len);
2745  }
2746  else {
2747  fprintf (stderr, "spice error, either TD or F required in "
2748  "lossless `%s' line \n", def->instance);
2749  spice_errors++;
2750  }
2751  }
2752  // post-process mutual inductors (transformer)
2753  if (!def->action && !strcmp (def->type, "Tr")) {
2754  if (1)
2755  root = spice_translate_coupled_x (root, def);
2756  else
2757  root = spice_translate_coupled (root, def);
2758  }
2759  // post-process general analysis options
2760  if (def->action && strstr (def->type, "OPT")) {
2761  struct value_t * val;
2762  if ((val = spice_find_property (def->values, "ABSTOL")) != NULL) {
2763  spice_add_property (root, "DC", "abstol", val->unit);
2764  spice_add_property (root, "TR", "abstol", val->unit);
2765  }
2766  if ((val = spice_find_property (def->values, "RELTOL")) != NULL) {
2767  spice_add_property (root, "DC", "reltol", val->unit);
2768  spice_add_property (root, "TR", "reltol", val->unit);
2769  }
2770  if ((val = spice_find_property (def->values, "VNTOL")) != NULL) {
2771  spice_add_property (root, "DC", "vntol", val->unit);
2772  spice_add_property (root, "TR", "vntol", val->unit);
2773  }
2774  if ((val = spice_find_property (def->values, "ITL1")) != NULL) {
2775  spice_add_property (root, "DC", "MaxIter", val->unit);
2776  }
2777  if ((val = spice_find_property (def->values, "ITL4")) != NULL) {
2778  spice_add_property (root, "TR", "MaxIter", val->unit);
2779  }
2780  }
2781  // post-process print and plot statements
2782  if ((def->action && !strcmp (def->type, "PRINT")) ||
2783  !strcmp (def->type, "PLOT")) {
2785  }
2786  // post-process untranslated netlist lines
2787  if (def->define == NULL) {
2788  def->text = spice_untranslated_text (def);
2789  }
2790  // remove values if possible
2791  spice_free_values (def);
2792  }
2793  return root;
2794 }
2795 
2796 /* The function translates special actions defined in the Spice
2797  netlist including the types of simulations. */
2798 static struct definition_t *
2800  struct definition_t * def) {
2801  // translate transient analysis
2802  if (!strcasecmp (def->type, "TRAN")) {
2803  free (def->type);
2804  def->type = strdup ("TR");
2805  struct value_t * val;
2806  int i = 0;
2807  foreach_value (def->values, val) {
2808  switch (i++) {
2809  case 0:
2810  spice_append_pair (def, "Points", val->ident, 0);
2811  break;
2812  case 1:
2813  spice_append_pair (def, "Stop", val->ident, 0);
2814  break;
2815  case 2:
2816  spice_append_pair (def, "Start", val->ident, 0);
2817  break;
2818  case 3:
2819  break;
2820  }
2821  spice_value_done (val);
2822  }
2823  double v;
2824  v = spice_get_property_value (def, "Stop");
2825  v -= spice_get_property_value (def, "Start");
2826  v /= spice_get_property_value (def, "Points");
2827  v += 1;
2828  spice_set_property_value (def, "Points", v);
2829  }
2830  // translate AC analysis
2831  else if (!strcasecmp (def->type, "AC")) {
2832  struct value_t * val;
2833  char * type = NULL;
2834  int i = 0;
2835  foreach_value (def->values, val) {
2836  switch (i++) {
2837  case 0:
2838  type = strdup (val->ident);
2839  break;
2840  case 1:
2841  spice_append_pair (def, "Points", val->ident, 0);
2842  break;
2843  case 2:
2844  spice_append_pair (def, "Start", val->ident, 0);
2845  break;
2846  case 3:
2847  spice_append_pair (def, "Stop", val->ident, 0);
2848  break;
2849  }
2850  spice_value_done (val);
2851  }
2852  double v;
2853  v = spice_evaluate_points (&type,
2854  spice_get_property_value (def, "Start"),
2855  spice_get_property_value (def, "Stop"),
2856  spice_get_property_value (def, "Points"));
2857  spice_set_property_value (def, "Points", v + 1);
2858  spice_set_property_string (def, "Type", type);
2859  free (type);
2860  }
2861  // translate DC analysis
2862  else if (!strcasecmp (def->type, "DC")) {
2863  struct definition_t * para1 = NULL, * para2 = NULL;
2864  if (spice_count_values (def->values) >= 4) {
2865  para1 = spice_create_para (def);
2866  spice_set_property_string (para1, "Sim",
2867  spice_toupper (def->instance));
2868  if (spice_count_values (def->values) >= 4) {
2869  para2 = spice_create_para (def);
2870  spice_set_property_string (para2, "Sim",
2871  spice_toupper (para1->instance));
2872  }
2873  }
2874  if (para1) root = spice_add_definition (root, para1);
2875  if (para2) root = spice_add_definition (root, para2);
2876  }
2877  // translate subcircuit definition
2878  else if (!strcasecmp (def->type, "SUBCKT")) {
2879  free (def->type);
2880  def->type = strdup ("Def");
2881  def->sub = spice_checker_intern (def->sub);
2882  }
2883  // translate operating point analysis
2884  else if (!strcasecmp (def->type, "OP")) {
2885  free (def->type);
2886  def->type = strdup ("DC");
2887  spice_set_property_string (def, "saveOPs", "yes");
2888  }
2889  return root;
2890 }
2891 
2892 /* The following function translates the given definition 'sub' into a
2893  valid Qucs subcircuit instance. */
2895  struct value_t * val;
2896  free (sub->type);
2897  sub->type = strdup ("Sub");
2898  foreach_value (sub->values, val) {
2899  if (val->hint & HINT_NAME) {
2900  spice_set_property_string (sub, "Type", val->ident);
2901  break;
2902  }
2903  }
2904 }
2905 
2906 /* The function returns a static string containing successive instance
2907  names for the nodeset functionality in Qucs. */
2908 static char * spice_create_intern_nodeset (void) {
2909  static int intern = 1;
2910  static char txt[32];
2911  sprintf (txt, "NS%d", intern++);
2912  return txt;
2913 }
2914 
2915 /* The following function translates the nodeset functionality defined
2916  by Spice into appropriate definitions for Qucs. */
2917 static struct definition_t *
2919  struct definition_t * def) {
2920  struct value_t * val;
2921  struct definition_t * node = def;
2922  free (def->type);
2923  def->type = strdup ("NodeSet");
2924  free (node->instance);
2925  node->instance = strdup (spice_create_intern_nodeset ());
2926  node->action = PROP_COMPONENT;
2927  foreach_value (def->values->next, val) {
2928  if (val->hint & HINT_NODE) {
2929  node->nodes = spice_translate_node (val->ident);
2930  }
2931  if (val->hint & HINT_NUMBER) {
2932  spice_append_pair (node, "U", val->ident, 1);
2933  }
2934  if (val->hint & HINT_NAME) {
2935  node = spice_create_definition (node, "NodeSet");
2936  root = spice_add_definition (root, node);
2937  free (node->instance);
2938  node->instance = strdup (spice_create_intern_nodeset ());
2939  }
2940  }
2941  return root;
2942 }
2943 
2944 /* This is the overall Spice netlist translator. It adjusts the list
2945  of definitions into usable structures. */
2946 static struct definition_t * spice_translator (struct definition_t * root) {
2947  for (struct definition_t * def = root; def != NULL; def = def->next) {
2948  if ((def->define = spice_find_definition (def->type)) != NULL) {
2949  strcpy (def->type, def->define->type);
2950  def->nodes = spice_get_nodes (def);
2951  def->pairs = spice_get_pairs (def);
2952  if (!def->action) { // handle normal components
2953  // devices
2954  if (!strcasecmp (def->type, "Q") || !strcasecmp (def->type, "M") ||
2955  !strcasecmp (def->type, "J") || !strcasecmp (def->type, "D") ||
2956  !strcasecmp (def->type, "S") || !strcasecmp (def->type, "R") ||
2957  !strcasecmp (def->type, "C")) {
2958  spice_translate_device (root, def);
2959  }
2960  // controlled sources
2961  if (!strcasecmp (def->type, "E") || !strcasecmp (def->type, "G")) {
2962  root = spice_translate_poly (root, def);
2963  }
2964  // controlled sources
2965  if (!strcasecmp (def->type, "C") || !strcasecmp (def->type, "L")) {
2966  root = spice_translate_poly_lc (root, def);
2967  }
2968  // voltage sources
2969  if (!strcasecmp (def->type, "V")) {
2970  root = spice_translate_source (root, def, 'U');
2971  }
2972  // current sources
2973  if (!strcasecmp (def->type, "I")) {
2974  root = spice_translate_source (root, def, 'I');
2975  }
2976  // subcircuits
2977  if (!strcasecmp (def->type, "X")) {
2979  }
2980  spice_translate_type (def);
2981  }
2982  else { // handle special actions (dot '.' commands)
2983  // nodeset functionality
2984  if (!strcasecmp (def->type, "NODESET") ||
2985  !strcasecmp (def->type, "IC")) {
2986  root = spice_translate_nodeset (root, def);
2987  }
2988  else {
2989  root = spice_translate_action (root, def);
2990  }
2991  }
2992  spice_fixup_definition (def);
2993  }
2994  else {
2995  // handle device description
2996  if (!strcasecmp (def->type, "MODEL")) {
2997  spice_add_Model (def);
2998  }
2999  }
3000  // remove values if possible
3001  spice_free_values (def);
3002  }
3003  return root;
3004 }
3005 
3006 /* TODO list for Spice Translator:
3007  - current sources
3008  - subcircuits
3009  - file includes
3010  - transmission lines
3011  - voltage dependent sources
3012  - current dependent sources
3013  - initial conditions
3014  - options (partly done)
3015  - mutual inductors (transformer)
3016  - mesfet if available in Qucs
3017  - other mosfet models if available in Qucs
3018  - three mutual inductors
3019  - current controlled switch (gyrator + voltage controlled switch)
3020  - single-frequency FM (using pm-modulator)
3021  - controlled E, G, F, and H poly sources
3022  - analog behavioural B, E, G, F, and H sources
3023  - piece-wise linear (PWL) voltage and current sources
3024  - temperature analysis (.TEMP)
3025  - temperature option (.OPTIONS TNOM=27)
3026  - non-linear L and C poly components
3027 */
3028 
3029 #if 0
3030 // My debugger...
3031 static void spice_lister (struct definition_t * root) {
3032  struct value_t * val;
3033  for (struct definition_t * def = root; def != NULL; def = def->next) {
3034  fprintf (stderr, "%s:%s", def->type, def->instance);
3035  for (val = def->values; val != NULL; val = val->next) {
3036  if (val->ident)
3037  fprintf (stderr, " %s[%d]", val->ident, val->hint);
3038  else
3039  fprintf (stderr, " %g[%d]", val->value, val->hint);
3040  }
3041  fprintf (stderr, "\n");
3042  }
3043 }
3044 #endif
3045 
3046 // Adjusts the hint value of the last entry in the value list.
3047 void spice_add_last_hint (struct value_t * val, int hint) {
3048  if (val == NULL) return;
3049  for (; val->next != NULL; val = val->next) ;
3050  val->hint |= hint;
3051 }
3052 
3053 // Adjusts the hint value of the last entry in the value list.
3054 void spice_set_last_hint (struct value_t * val, int hint) {
3055  if (val == NULL) return;
3056  for (; val->next != NULL; val = val->next) ;
3057  val->hint = hint;
3058 }
3059 
3060 /* This function is the overall spice checker and translator. */
3062 #if 0
3063  spice_lister (root);
3064 #endif
3065  root = spice_translator (root);
3066  root = spice_post_translator (root);
3067  return root;
3068 }
3069 
3070 /* This function is the overall spice checker and translator. */
3071 int spice_checker (void) {
3072  spice_errors = 0;
3073  definition_root = spice_checker_intern (definition_root);
3074  return spice_errors;
3075 }
#define HINT_DONE
Definition: parse_spice.y:35
start
Definition: parse_zvr.y:126
static char * spice_create_eqnstr(struct definition_t *def, int p, char type)
#define PROP_POS_RANGE
Definition: netdefs.h:129
static struct definition_t * spice_post_translator(struct definition_t *root)
static void spice_adjust_device(struct definition_t *def, struct definition_t *trandef)
l
Definition: parse_vcd.y:213
struct node_t * netlist_append_nodes(struct node_t *n1, struct node_t *n2)
struct node_translation_t node_translations[]
Definition: vdc.cpp:85
type_t * currentVal(void)
Definition: hash.cpp:398
static char * spice_create_poly(struct value_t *prop, int nd, int integrate)
#define N(n)
Definition: equation.cpp:58
static int spice_evaluate_points(char **type, double start, double stop, double points)
#define I_(r)
Definition: hbsolver.cpp:685
const char * trans_type
const char * type
Definition: netdefs.h:33
type_t * put(char *, type_t *)
Definition: hash.cpp:192
static struct pair_t * spice_generate_Model_pairs(struct value_t *values)
#define VAL_IS_DONE(val)
struct node_t * nodes
Definition: netdefs.h:64
struct node_t * next
Definition: netdefs.h:37
struct pair_t * netlist_append_pairs(struct pair_t *p1, struct pair_t *p2)
#define C(c)
Definition: eqndefined.cpp:73
struct pair_t * spice_del_property(struct pair_t *root, struct pair_t *pair)
char * scale
Definition: netdefs.h:44
static struct property_t req_spice_C[]
Definition: check_spice.cpp:65
void spice_destroy(void)
static struct definition_t * spice_search_coupled(struct definition_t *root, qucs::hash< struct definition_t > *K_hash, qucs::hash< struct definition_t > *L_hash, const char *type, char *inst)
static char * spice_toupper(char *str)
struct value_t * values
Definition: netdefs.h:80
#define PROP_REAL
Definition: netdefs.h:174
static struct definition_t * spice_find_coupled(struct definition_t *root, struct definition_t *coupled, const char *type, char *inst)
static char * spice_coupled_instance(struct definition_t *k1, struct definition_t *k2, struct definition_t *k3)
static const char * spice_evaluate_scale(char *value, char **endptr, double *factor)
struct value_t * next
Definition: netdefs.h:50
#define HINT_PAIR
Definition: parse_spice.y:34
t
Definition: parse_vcd.y:290
char * type
Definition: netdefs.h:62
char * spice_title
Definition: check_spice.cpp:51
static struct property_t req_spice_R[]
Definition: check_spice.cpp:56
#define PROP_NO_PROP
Definition: netdefs.h:122
Global physical constants header file.
#define K
Absolute 0 in centigrade.
Definition: constants.h:59
#define PROP_NO_RANGE
Definition: netdefs.h:126
static struct node_t * spice_get_node(struct definition_t *def, int pos)
static struct property_t req_spice_G[]
Definition: check_spice.cpp:74
static struct property_t req_spice_IC[]
Definition: check_spice.cpp:92
const char * key
Definition: netdefs.h:86
#define PROP_NO_STR
Definition: netdefs.h:125
static void spice_translate_units(struct definition_t *def)
const char * type
Definition: netdefs.h:103
#define create_definition()
Definition: netdefs.h:191
static void netlist_free_pairs(struct pair_t *pair)
struct property_translation_t property_translations[]
struct definition_t * device_root
Definition: check_spice.cpp:49
#define HINT_NODE
Definition: parse_spice.y:31
n
Definition: parse_citi.y:147
#define S(con)
Definition: property.cpp:158
int action
Definition: netdefs.h:71
static void spice_free_values(struct definition_t *def)
#define PROP_LINEAR
Definition: netdefs.h:120
struct definition_t * spice_checker_intern(struct definition_t *root)
struct node_t * spice_nodes
double value
Definition: netdefs.h:45
Definition: netdefs.h:54
r
Definition: parse_mdl.y:515
instance
static struct property_t req_spice_I[]
Definition: check_spice.cpp:71
const char * key
static void spice_append_node(struct definition_t *def, char *node)
static void spice_adjust_optional_properties(struct definition_t *def)
static struct define_t * spice_find_definition(const char *n)
static struct definition_t * spice_translate_source(struct definition_t *root, struct definition_t *def, char type)
char * ident
Definition: netdefs.h:42
char * instance
Definition: netdefs.h:63
static struct definition_t * spice_create_para(struct definition_t *base)
int nodes
Definition: netdefs.h:104
#define PROP_ACTION
Definition: netdefs.h:115
#define PROP_NODES
Definition: netdefs.h:121
char * node
Definition: netdefs.h:34
struct definition_t * sub
Definition: netdefs.h:67
#define R(con)
i
Definition: parse_mdl.y:516
n2
Definition: parse_zvr.y:187
static struct property_t req_spice_V[]
Definition: check_spice.cpp:68
int qucs_find_node(struct node_t *root, char *node)
struct value_t * value
Definition: netdefs.h:56
char * unit
Definition: netdefs.h:43
nr_complex_t sqrt(const nr_complex_t z)
Compute principal value of square root.
Definition: complex.cpp:271
static struct definition_t * spice_find_device(struct definition_t *root, char *type)
next
Definition: parse_spice.y:859
void netlist_free_pair(struct pair_t *pair)
static struct property_t req_spice_E[]
Definition: check_spice.cpp:77
static int spice_count_values(struct value_t *values)
static void spice_translate_device(struct definition_t *root, struct definition_t *def)
int spice_errors
Definition: check_spice.cpp:50
stop
Definition: parse_zvr.y:127
static char * spice_create_intern_node(void)
struct property_t * required
Definition: netdefs.h:108
struct definition_t * definition_root
Definition: check_spice.cpp:47
points
Definition: parse_zvr.y:129
struct property_t::@6 defaultval
#define HINT_MSTOP
Definition: parse_spice.y:37
#define PROP_COMPONENT
Definition: netdefs.h:116
static struct definition_t * spice_create_definition(struct definition_t *base, const char *type)
void spice_adjust_properties(struct definition_t *def)
free($1)
const char * s
Definition: netdefs.h:90
static struct pair_t * spice_find_property(struct definition_t *def, const char *prop)
add($1)
static struct node_t * spice_get_nodes(struct definition_t *def)
static struct definition_t * spice_translate_coupled_x(struct definition_t *root, struct definition_t *def)
int count(void)
Definition: hash.cpp:122
static void spice_translate_subcircuit(struct definition_t *sub)
#define foreach_value(values, val)
nr_complex_t log10(const nr_complex_t z)
Compute principal value of decimal logarithm of z.
Definition: complex.cpp:225
static struct value_t * spice_create_value(const char *ident)
struct spice_device_t spice_devices[]
void spice_add_last_hint(struct value_t *val, int hint)
char * subcircuit
Definition: netdefs.h:79
struct definition_t * spice_del_definition(struct definition_t *root, struct definition_t *def)
nr_complex_t integrate(vector v, const nr_complex_t)
Definition: vector.cpp:1207
static struct definition_t * spice_translate_action(struct definition_t *root, struct definition_t *def)
struct define_t spice_definition_available[]
Definition: check_spice.cpp:96
static struct definition_t * spice_translator(struct definition_t *root)
struct define_t * define
Definition: netdefs.h:81
value
Definition: parse_vcd.y:315
#define PROP_IS_PROP(prop)
Definition: netdefs.h:178
static struct define_t * spice_get_qucs_definition(struct definition_t *def)
static struct property_t req_spice_NODESET[]
Definition: check_spice.cpp:89
#define create_value()
Definition: netdefs.h:193
static struct value_t * spice_find_device_instance(struct definition_t *def)
static double spice_get_property_value(struct definition_t *def, const char *key)
static void spice_collect_external_nodes(struct definition_t *def)
static struct definition_t * spice_translate_nodeset(struct definition_t *root, struct definition_t *def)
nodes
type
Definition: parse_vcd.y:164
#define PROP_MIN_VAL(k)
Definition: netdefs.h:133
static void spice_append_pair(struct definition_t *def, const char *prop, const char *value, int replace)
#define PROP_IS_VAL(prop)
Definition: netdefs.h:179
static struct property_t req_spice_L[]
Definition: check_spice.cpp:62
static int spice_count_nodes(struct definition_t *def)
static struct definition_t * spice_translate_poly_lc(struct definition_t *root, struct definition_t *def)
static struct definition_t * spice_translate_coupled(struct definition_t *root, struct definition_t *def)
static struct node_t * spice_translate_node(char *node)
static struct definition_t * spice_find_coupled_inductor(struct definition_t *root, struct definition_t *def, const char *type, char *inst)
static void spice_adjust_default_properties(struct definition_t *def)
static char * spice_create_intern_nodeset(void)
static struct definition_t * spice_add_edd_equation(struct definition_t *root, struct definition_t *def, int p, struct definition_t **i, struct definition_t **q)
static struct definition_t * spice_add_definition(struct definition_t *root, struct definition_t *def)
static struct definition_t * spice_add_Model(struct definition_t *def)
v
Definition: parse_zvr.y:141
const char * trans_type_prop
static void spice_adjust_vsource_nodes(struct definition_t *up, struct definition_t *dn)
n1
Definition: parse_zvr.y:179
struct pair_t * pairs
Definition: netdefs.h:65
char * text
Definition: netdefs.h:78
void spice_set_last_hint(struct value_t *val, int hint)
const char * qucs_gnd
#define VAL_IS_NUMBER(val)
static void netlist_free_value(struct value_t *value)
static int spice_count_real_values(struct value_t *values)
static void spice_adjust_instance(struct definition_t *def)
const char * field[16]
List int
Definition: parse_citi.y:183
pairs
static struct property_t req_spice_T[]
Definition: check_spice.cpp:86
#define create_pair()
Definition: netdefs.h:197
char * currentKey(void)
Definition: hash.cpp:392
static struct pair_t * spice_get_pairs(struct definition_t *def)
unit
struct property_t * optional
Definition: netdefs.h:109
static struct value_t * spice_get_value_coupled(struct definition_t *def)
static void netlist_free_values(struct value_t *value)
static char * spice_untranslated_text(struct definition_t *def)
static struct property_t spice_noprops[]
Definition: check_spice.cpp:54
char * key
Definition: netdefs.h:55
static struct property_t req_spice_H[]
Definition: check_spice.cpp:83
struct unit_translation_t unit_translations[]
#define C0
speed of light in vacuum ( )
Definition: constants.h:47
static void netlist_free_nodes(struct node_t *node)
int spice_checker(void)
static void spice_set_property_value(struct definition_t *def, const char *key, double val)
static void spice_adjust_isource_nodes(struct definition_t *left, struct definition_t *right)
static void spice2g6_nxtpwr(int *seq, int nd)
struct pair_t * netlist_reverse_pairs(struct pair_t *pairs)
static void spice_value_done(struct value_t *val)
vcd scopes ident
Definition: parse_vcd.y:124
struct value_t * netlist_reverse_values(struct value_t *values)
#define D(con)
struct node_t * netlist_reverse_nodes(struct node_t *nodes)
static struct property_t req_spice_F[]
Definition: check_spice.cpp:80
#define HINT_NUMBER
Definition: parse_spice.y:32
static struct pair_t * spice_find_property_nocase(struct definition_t *def, const char *prop)
int hint
Definition: netdefs.h:48
node
type_t * get(char *)
Definition: hash.cpp:265
static char * spice_create_intern_para(void)
static void spice_extract_properties(struct definition_t *def, struct value_t *values, struct property_field_t *field)
struct value_t * netlist_append_values(struct value_t *v1, struct value_t *v2)
struct spice_device_table_t spice_device_table[]
values
Definition: parse_spice.y:223
static struct definition_t * spice_find_Model(char *instance)
static double spice_get_value(struct value_t *val)
#define HINT_NAME
Definition: parse_spice.y:33
key
vcd scale
Definition: parse_vcd.y:180
static void spice_translate_nodes(struct definition_t *def, int pass)
struct pair_t * next
Definition: netdefs.h:57
const char * type
struct definition_t * next
Definition: netdefs.h:66
static void netlist_free_definition(struct definition_t *def)
static struct property_t opt_spice_R[]
Definition: check_spice.cpp:58
static void netlist_destroy_intern(struct definition_t *)
static void spice_set_property_string(struct definition_t *def, const char *key, const char *val)
#define PROP_NONLINEAR
Definition: netdefs.h:119
nr_double_t d
Definition: netdefs.h:89
struct definition_t * subcircuit_root
Definition: check_spice.cpp:48
static struct definition_t * spice_translate_poly(struct definition_t *root, struct definition_t *def)
#define create_node()
Definition: netdefs.h:195
const char * trans
static int spice_translate_type(struct definition_t *def)
static void spice_fixup_definition(struct definition_t *def)
static double spice_evaluate_value(struct value_t *value)
#define PROP_NO_SUBSTRATE
Definition: netdefs.h:118
Expr HINT_NAME HINT_MSTART
Definition: parse_spice.y:893
static void spice_add_property(struct definition_t *root, const char *type, const char *key, char *value)
void spice_adjust_alias_properties(struct definition_t *def, struct pair_t *pair)