My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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: check_spice.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <assert.h>
34 #include <float.h>
35 #include <ctype.h>
36 
37 #ifdef __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. */
185 struct value_t * netlist_reverse_values (struct value_t * values) {
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. */
197 struct pair_t * netlist_reverse_pairs (struct pair_t * pairs) {
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. */
209 struct node_t * netlist_reverse_nodes (struct node_t * nodes) {
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 *
439 spice_find_device_instance (struct definition_t * def) {
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.3)
658  def->type = strdup ("hicumL0V1p3");
659  else if (version >= 1.2)
660  def->type = strdup ("hicumL0V1p2");
661  else
662  def->type = strdup ("hic0_full");
663  if (tran->trans_type_prop != NULL) {
664  spice_set_property_string (def, "Type",
665  tran->trans_type_prop);
666  }
667  hic = true;
668  }
669  }
670  else if (level == 2 && version == 2.1) {
671  def->type = strdup ("hicumL2V2p1");
672  hic = true;
673  }
674  else if (level == 2 && version >= 2.21 && version <= 2.22) {
675  def->type = strdup ("hic2_full");
676  hic = true;
677  }
678  else if (level == 2 && version == 2.23) {
679  def->type = strdup ("hicumL2V2p23");
680  hic = true;
681  }
682  else if (level == 2 && version >= 2.24) {
683  def->type = strdup ("hicumL2V2p24");
684  hic = true;
685  }
686  }
687  }
688  }
689  if (!hic) {
690  def->type = strdup (tran->trans_type);
691  // append "Type" property
692  if (tran->trans_type_prop != NULL) {
693  spice_set_property_string (def, "Type", tran->trans_type_prop);
694  }
695  }
696  break;
697  }
698  }
699 }
700 
701 /* The function translates .MODEL specifications in device (MOSFET,
702  BJT, etc.) instances. */
703 static void spice_translate_device (struct definition_t * root,
704  struct definition_t * def) {
705  struct value_t * inst = spice_find_device_instance (def);
706 
707  // return if no Model given
708  if (inst == NULL) return;
709 
710  /* first look for the Model in the local definition root, then in
711  the global definition root */
712  struct definition_t * tran;
713  if ((tran = spice_find_device (root, inst->ident)) == NULL)
714  tran = spice_find_device (definition_root, inst->ident);
715  // really translate the instance here
716  if (tran != NULL) {
717  spice_value_done (inst);
718  spice_adjust_device (def, tran);
719  }
720  else if (!strcasecmp (def->type, "C")) {
721  // can probably be skipped
722  }
723  else {
724  fprintf (stderr, "spice error, no such .MODEL `%s' found as specified in "
725  "device instance `%s'\n", inst->ident, def->instance);
726  spice_errors++;
727  }
728 }
729 
730 /* Goes through the list of available definition and returns the
731  appropriate component definition. */
732 static struct define_t *
733 spice_get_qucs_definition (struct definition_t * def) {
734  struct define_t * entry;
735  for (entry = qucs_definition_available; entry->type != NULL; entry++)
736  if (!strcmp (entry->type, def->type)) return entry;
737  return NULL;
738 }
739 
740 // Helper structure for direct type translations.
742  const char * type; // Spice type
743  const char * trans; // Qucs type
744 }
745 spice_device_table[] = {
746  { "Q", "BJT" },
747  { "J", "JFET", },
748  { "M", "MOSFET" },
749  { "D", "Diode" },
750  { "V", "Vdc" },
751  { "I", "Idc" },
752  { "G", "VCCS" },
753  { "E", "VCVS" },
754  { "F", "CCCS" },
755  { "H", "CCVS" },
756  { "K", "Tr" },
757  { "S", "Relais" },
758  { "T", "TLIN4P" },
759  { NULL, NULL }
760 };
761 
762 /* This little function translates the Spice type definitions into Qucs
763  types. */
764 static int spice_translate_type (struct definition_t * def) {
765  struct spice_device_table_t * tran;
766  int found = 0;
767  for (tran = spice_device_table; tran->type && def->type; tran++) {
768  found = 1;
769  if (!strcasecmp (tran->type, def->type)) {
770  if (!spice_find_property (def->values, "POLY")) {
771  free (def->type);
772  def->type = strdup (tran->trans);
773  found++;
774  break;
775  }
776  }
777  }
778  return found;
779 }
780 
781 // Helper structure for node translations.
783  const char * type; // the type of definition
784  int pass; // pass number when the translation should be performed
785  int Mapping[6]; // node ordering
786  int Default[6]; // default nodes
787 }
788 node_translations[] = {
789  { "BJT", 0,
790  { 2, 1, 3, 4, -1 },
791  { 1, 2, 3, 0, -1 }
792  },
793  { "MOSFET", 0,
794  { 2, 1, 3, 4, -1 },
795  { 1, 2, 3, 3, -1 }
796  },
797  { "JFET", 0,
798  { 2, 1, 3, -1 },
799  { 1, 2, 3, -1 }
800  },
801  { "Diode", 0,
802  { 2, 1, -1 },
803  { 1, 2, -1 }
804  },
805  { "Iac", 0,
806  { 2, 1, -1 },
807  { 1, 2, -1 }
808  },
809  { "Idc", 0,
810  { 2, 1, -1 },
811  { 1, 2, -1 }
812  },
813  { "VCCS", 0,
814  { 3, 1, 2, 4, -1 },
815  { 1, 2, 3, 4, -1 }
816  },
817  { "VCVS", 0,
818  { 3, 1, 2, 4, -1 },
819  { 1, 2, 3, 4, -1 }
820  },
821  { "CCCS", 1,
822  { 3, 1, 2, 4, -1 },
823  { 1, 2, 3, 4, -1 }
824  },
825  { "CCVS", 1,
826  { 3, 1, 2, 4, -1 },
827  { 1, 2, 3, 4, -1 }
828  },
829  { "Tr", 1,
830  { 3, 1, 2, 4, -1 },
831  { 1, 2, 3, 4, -1 }
832  },
833  { "NodeSet", 1,
834  { 1, -1 },
835  { 1, -1 }
836  },
837  { "Relais", 0,
838  { 3, 1, 2, 4, -1 },
839  { 1, 2, 3, 4, -1 }
840  },
841  { "TLIN4P", 0,
842  { 1, 3, 4, 2, -1 },
843  { 1, 2, 3, 4, -1 }
844  },
845  { NULL, 0, { -1 }, { -1 } }
846 };
847 
848 // Counts the number of nodes stored in the given definition.
849 static int spice_count_nodes (struct definition_t * def) {
850  int res = 0;
851  for (struct node_t * node = def->nodes; node != NULL; node = node->next)
852  res++;
853  return res;
854 }
855 
856 // Deletes node list of a definition.
857 static void netlist_free_nodes (struct node_t * node) {
858  struct node_t * n;
859  for (; node != NULL; node = n) {
860  n = node->next;
861  free (node->node);
862  free (node);
863  }
864 }
865 
866 /* Deletes pair list of a definition. */
867 static void netlist_free_pairs (struct pair_t * pair) {
868  struct pair_t * n;
869  for (; pair != NULL; pair = n) {
870  n = pair->next;
871  netlist_free_pair (pair);
872  }
873 }
874 
875 // The function returns the node specified at the given position.
876 static struct node_t * spice_get_node (struct definition_t * def, int pos) {
877  struct node_t * node;
878  int i;
879  for (i = 1, node = def->nodes; node != NULL; node = node->next, i++)
880  if (i == pos) return node;
881  return NULL;
882 }
883 
884 /* This function transforms the collected node information in the
885  Spice list into the appropriate Qucs definition. */
886 static void spice_translate_nodes (struct definition_t * def, int pass) {
887  struct node_translation_t * nodes;
888  struct node_t * node;
889  // find node translator
890  for (nodes = node_translations; nodes->type != NULL; nodes++)
891  if (!strcmp (nodes->type, def->type)) break;
892  if (nodes->type == NULL || pass != nodes->pass) return;
893 
894  struct define_t * entry = spice_get_qucs_definition (def);
895  // adjust the number of nodes and append default nodes
896  if (entry->nodes > spice_count_nodes (def)) {
897  for (int n = spice_count_nodes (def); n < entry->nodes; n++) {
898  node = create_node ();
899  if (nodes->Default[n] == 0) { // default is the ground node
900  node->node = strdup (qucs_gnd);
901  }
902  else { // default is some other node
903  struct node_t * t = spice_get_node (def, nodes->Default[n]);
904  if (t != NULL)
905  node->node = strdup (t->node);
906  else {
907  // no node given, occurs in device descriptions
908  char txt[16];
909  sprintf (txt, "%s%d", "_node", n);
910  node->node = strdup (txt);
911  }
912  }
913  def->nodes = netlist_append_nodes (def->nodes, node);
914  }
915  }
916  // remap the node definitions if necessary
917  struct node_t * root = NULL;
918  for (int n = entry->nodes - 1; n >= 0; n--) {
919  struct node_t * t = spice_get_node (def, nodes->Mapping[n]);
920  node = create_node ();
921  node->node = strdup (t->node);
922  node->next = root;
923  root = node;
924  }
925  netlist_free_nodes (def->nodes);
926  def->nodes = root;
927 }
928 
929 // Helper structure for unit translations.
931  const char * key;
932  const char * trans;
933 }
934 unit_translations[] = {
935  { "OHM", "Ohm" },
936  { "OHMS", "Ohm" },
937  { "MHO", "S" },
938  { "S", "s" },
939  { "H", "H" },
940  { "F", "F" },
941  { "HZ", "Hz" },
942  { "V", "V" },
943  { "VOLT", "V" },
944  { "A", "A" },
945  { "M", "m" },
946  { NULL, NULL }
947 };
948 
949 /* This function tries to figure out units given in the Spice list and
950  translates these patterns into valid Qucs units. */
951 static void spice_translate_units (struct definition_t * def) {
952  for (struct pair_t * pair = def->pairs; pair != NULL; pair = pair->next) {
953  struct value_t * value = pair->value;
954  if (value->unit) {
955  struct unit_translation_t * unit;
956  int found = 0;
957  for (unit = unit_translations; unit->key != NULL; unit++) {
958  if (!strcasecmp (unit->key, value->unit)) {
959  free (value->unit);
960  value->unit = strdup (unit->trans);
961  found++;
962  break;
963  }
964  }
965  if (!found) { // no such unit found
966  free (value->unit);
967  value->unit = NULL;
968  }
969  }
970  }
971 }
972 
973 /* This function appends all the required Qucs properties not given in
974  the Spice netlist. */
975 static void spice_adjust_default_properties (struct definition_t * def) {
976  struct define_t * entry = spice_get_qucs_definition (def);
977  if (entry == NULL) return;
978 
979  // handle required properties only
980  for (int i = 0; PROP_IS_PROP (entry->required[i]); i++) {
981  struct property_t * prop = &entry->required[i];
982  if (spice_find_property (def, prop->key) == NULL) {
983  struct pair_t * pair = create_pair ();
984  pair->key = strdup (prop->key);
985  pair->value = create_value ();
986  if (PROP_IS_VAL (*prop)) {
987  pair->value->value = prop->defaultval.d;
988  }
989  else {
990  pair->value->ident = strdup (prop->defaultval.s);
991  }
992  def->pairs = netlist_append_pairs (def->pairs, pair);
993  }
994  }
995 }
996 
997 /* This function appends the optional Qucs properties not given in the
998  Spice netlist. */
999 static void spice_adjust_optional_properties (struct definition_t * def) {
1000  struct define_t * entry = spice_get_qucs_definition (def);
1001  if (entry == NULL) return;
1002 
1003  // handle optional properties if requested
1004  for (int i = 0; PROP_IS_PROP (entry->optional[i]); i++) {
1005  struct property_t * prop = &entry->optional[i];
1006  if (spice_find_property (def, prop->key) == NULL) {
1007  struct pair_t * pair = create_pair ();
1008  pair->key = strdup (prop->key);
1009  pair->value = create_value ();
1010  if (PROP_IS_VAL (*prop)) {
1011  pair->value->value = prop->defaultval.d;
1012  }
1013  else {
1014  pair->value->ident = strdup (prop->defaultval.s);
1015  }
1016  def->pairs = netlist_append_pairs (def->pairs, pair);
1017  }
1018  }
1019 }
1020 
1021 // Helper structure for property translations and aliases in devices.
1023  const char * type;
1024  const char * key;
1025  const char * trans;
1026 }
1028  /* BJT device */
1029  { NULL, "CCS", "Cjs" },
1030  { NULL, "VA", "Vaf" },
1031  { NULL, "VB", "Var" },
1032  { NULL, "IK", "Ikf" },
1033  { NULL, "PE", "Vje" },
1034  { NULL, "ME", "Mje" },
1035  { NULL, "PC", "Vjc" },
1036  { NULL, "MC", "Mjc" },
1037  { NULL, "PS", "Vjs" },
1038  { NULL, "MS", "Mjs" },
1039  /* MOSFET device */
1040  { NULL, "VTO", "Vt0" },
1041  { NULL, "U0", "Uo" },
1042  /* DIODE device */
1043  { NULL, "CJO", "Cj0" },
1044  /* OTHER devices */
1045  { "C", "IC", "V" },
1046  { "L", "IC", "I" },
1047  { NULL, "Z0", "Z" },
1048  { "R", "TC", "Tc1" },
1049  /* END of list */
1050  { NULL, NULL, NULL }
1051 };
1052 
1053 /* The function translates property and aliases of devices in the list
1054  of key/value pairs of the given definition. */
1056  struct pair_t * pair) {
1058  for (; prop->key != NULL; prop++) {
1059  if (!prop->type || !strcmp (prop->type, def->type)) {
1060  if (!strcasecmp (prop->key, pair->key)) {
1061  free (pair->key);
1062  pair->key = strdup (prop->trans);
1063  }
1064  }
1065  }
1066 }
1067 
1068 /* The function goes through the pair (property) list of the given
1069  definition and adjusts the spelling of the property keys according
1070  to the Qucs definitions. */
1072  struct define_t * entry = spice_get_qucs_definition (def);
1073  if (entry) {
1074  struct pair_t * pair;
1075  for (pair = def->pairs; pair != NULL; pair = pair->next) {
1076  int i, found = 0;
1077  // handle required properties
1078  for (i = 0; PROP_IS_PROP (entry->required[i]); i++) {
1079  if (!strcasecmp (entry->required[i].key, pair->key)) {
1080  free (pair->key);
1081  pair->key = strdup (entry->required[i].key);
1082  found++;
1083  break;
1084  }
1085  }
1086  // handle optional properties
1087  for (i = 0; PROP_IS_PROP (entry->optional[i]); i++) {
1088  if (!strcasecmp (entry->optional[i].key, pair->key)) {
1089  free (pair->key);
1090  pair->key = strdup (entry->optional[i].key);
1091  found++;
1092  break;
1093  }
1094  }
1095  // some other direct translations
1096  if (!found) spice_adjust_alias_properties (def, pair);
1097  }
1098  }
1099 }
1100 
1101 /* This function appends the given key/value pair to the given
1102  definition. If the replace flag is non-zero the pair gets
1103  replaced. If the replace flag is zero and the pair already exists
1104  nothing is done here. */
1105 static void spice_append_pair (struct definition_t * def, const char * prop,
1106  const char * value, int replace) {
1107  struct pair_t * p = spice_find_property (def, prop);
1108  if (p != NULL) {
1109  if (replace) {
1110  netlist_free_value (p->value);
1111  p->value = spice_create_value (value);
1112  return;
1113  }
1114  else return;
1115  }
1116  p = create_pair ();
1117  p->key = strdup (prop);
1118  p->value = spice_create_value (value);
1119  def->pairs = netlist_append_pairs (def->pairs, p);
1120 }
1121 
1122 /* The function appends the given node name to the list of nodes of
1123  the given definition. */
1124 static void spice_append_node (struct definition_t * def, char * node) {
1125  struct node_t * n = create_node ();
1126  n->node = strdup (node);
1127  def->nodes = netlist_append_nodes (def->nodes, n);
1128 }
1129 
1130 // Converts the given string into upper case.
1131 static char * spice_toupper (char * str) {
1132  for (unsigned int i = 0; i < strlen (str); i++) {
1133  if (str[i] >= 'a' && str[i] <= 'z') str[i] = toupper (str[i]);
1134  }
1135  return str;
1136 }
1137 
1138 /* The function adjusts the instance name of the given component
1139  definition. */
1140 static void spice_adjust_instance (struct definition_t * def) {
1141  spice_toupper (def->instance);
1142 }
1143 
1144 /* This function is used by the overall netlist translator in order to
1145  fixup the properties, nodes, instance name and property units of
1146  the given definition. */
1147 static void spice_fixup_definition (struct definition_t * def) {
1148  spice_adjust_instance (def);
1150  spice_translate_nodes (def, 0);
1151  spice_translate_units (def);
1152  spice_adjust_default_properties (def);
1153 }
1154 
1155 /* The function adds the given definition to the list of valid
1156  definitions. The definition is placed at the beginning of the
1157  list. */
1158 static struct definition_t *
1159 spice_add_definition (struct definition_t * root, struct definition_t * def) {
1160  spice_fixup_definition (def);
1161  def->next = root;
1162  return def;
1163 }
1164 
1165 /* Forward declaration for recursive calls. */
1166 static void netlist_destroy_intern (struct definition_t *);
1167 
1168 /* Deletes a definition and all its content. */
1169 static void
1170 netlist_free_definition (struct definition_t * def) {
1171  netlist_free_nodes (def->nodes);
1172  netlist_free_pairs (def->pairs);
1173  netlist_free_values (def->values);
1174  if (def->subcircuit) free (def->subcircuit);
1175  if (def->text) free (def->text);
1176  if (def->sub) netlist_destroy_intern (def->sub);
1177  free (def->type);
1178  free (def->instance);
1179  free (def);
1180 }
1181 
1182 /* The function deletes the given definition list. */
1183 static void netlist_destroy_intern (struct definition_t * root) {
1184  struct definition_t * def, * next;
1185  for (def = root; def != NULL; def = next) {
1186  next = def->next;
1187  netlist_free_definition (def);
1188  }
1189 }
1190 
1191 /* Deletes all available definition lists. */
1192 void spice_destroy (void) {
1193  netlist_destroy_intern (definition_root);
1194  netlist_destroy_intern (device_root);
1195  for (struct definition_t * def = subcircuit_root; def; def = def->next) {
1196  netlist_destroy_intern (def->sub);
1197  }
1198  netlist_destroy_intern (subcircuit_root);
1199  definition_root = subcircuit_root = device_root = NULL;
1200  netlist_free_nodes (spice_nodes);
1201  spice_nodes = NULL;
1202  if (spice_title) free (spice_title);
1203  spice_title = NULL;
1204 }
1205 
1206 /* Unchains a definition and deletes it. */
1207 struct definition_t *
1208 spice_del_definition (struct definition_t * root, struct definition_t * def) {
1209  struct definition_t * prev;
1210  if (def == root) {
1211  root = def->next;
1212  netlist_free_definition (def);
1213  }
1214  else {
1215  // find previous to the candidate to be deleted
1216  for (prev = root; prev != NULL && prev->next != def; prev = prev->next) ;
1217  if (prev != NULL) {
1218  prev->next = def->next;
1219  netlist_free_definition (def);
1220  }
1221  }
1222  return root;
1223 }
1224 
1225 /* This function creates an internal node name used during the
1226  conversion process. The returned string is static and must be
1227  copied by the caller. Successive calls result in different node
1228  names. */
1229 static char * spice_create_intern_node (void) {
1230  static int intern = 0;
1231  static char txt[32];
1232  sprintf (txt, "_cnet%d", intern++);
1233  return txt;
1234 }
1235 
1236 /* This function places an internal node in between the given
1237  components. The first node of the 'dn' component becomes the first
1238  node of the 'up' component. */
1239 static void spice_adjust_vsource_nodes (struct definition_t * up,
1240  struct definition_t * dn) {
1241  struct node_t * node = spice_get_node (dn, 1);
1242  spice_append_node (up, node->node);
1243  char * inode = spice_create_intern_node ();
1244  spice_append_node (up, inode);
1245  free (node->node);
1246  node->node = strdup (inode);
1247 }
1248 
1249 /* The function copies both of the nodes from the 'right' component
1250  into the 'left' component. */
1251 static void spice_adjust_isource_nodes (struct definition_t * left,
1252  struct definition_t * right) {
1253  struct node_t * node;
1254  node = spice_get_node (right, 1);
1255  spice_append_node (left, node->node);
1256  node = spice_get_node (right, 2);
1257  spice_append_node (left, node->node);
1258 }
1259 
1260 /* The function creates a new definition based upon the given
1261  definition. The type of the new component must be given as
1262  well. */
1263 static struct definition_t *
1264 spice_create_definition (struct definition_t * base, const char * type) {
1265  struct definition_t * res = create_definition ();
1266  res->type = strdup (type);
1267  res->action = PROP_COMPONENT;
1268  res->instance = strdup (base->instance);
1269  res->define = base->define;
1270  return res;
1271 }
1272 
1273 /* The function returns the actual property value stored in the given
1274  definition of the given property. If there is no such property it
1275  returns 0. */
1276 static double
1277 spice_get_property_value (struct definition_t * def, const char * key) {
1278  struct pair_t * prop = spice_find_property (def, key);
1279  return prop ? spice_evaluate_value (prop->value) : 0;
1280 }
1281 
1282 /* This function replaces or appends the given key/value pair in the
1283  given definition. */
1284 static void
1285 spice_set_property_value (struct definition_t * def, const char * key,
1286  double val) {
1287  struct pair_t * prop = spice_find_property (def, key);
1288  if (prop != NULL) {
1289  // just replace the key/value pair
1290  if (prop->value->scale) {
1291  free (prop->value->scale);
1292  prop->value->scale = NULL;
1293  }
1294  if (prop->value->unit) {
1295  free (prop->value->unit);
1296  prop->value->unit = NULL;
1297  }
1298  prop->value->value = val;
1299  }
1300  else {
1301  // create key/value pair and append it
1302  prop = create_pair ();
1303  prop->key = strdup (key);
1304  prop->value = create_value ();
1305  prop->value->value = val;
1306  def->pairs = netlist_append_pairs (def->pairs, prop);
1307  }
1308 }
1309 
1310 // Helper structure for property extraction routine.
1312  const char * field[16];
1313 };
1314 
1315 /* The function extracts a list of properties from the given value
1316  list and assign the property names stored in the field extractor
1317  structure. The extracted properties are saved into the given
1318  definition. */
1319 static void spice_extract_properties (struct definition_t * def,
1320  struct value_t * values,
1321  struct property_field_t * field) {
1322  int i = 0;
1323  struct value_t * val;
1324  // go through each not yet processed value
1325  foreach_value (values, val) {
1326  if (field->field[i] == NULL) break; // stop at the end
1327  if (val->hint & HINT_NAME) {
1328  spice_set_property_string (def, field->field[i], val->ident);
1329  }
1330  else if (val->hint & (HINT_NODE | HINT_NUMBER)) {
1331  spice_append_pair (def, field->field[i], val->ident, 0);
1332  }
1333  else break;
1334  spice_value_done (val);
1335  if (val->hint & HINT_MSTOP) break; // stop here if necessary
1336  i++;
1337  }
1338 }
1339 
1340 /* This function tries to reproduce a Spice netlist line. It is used
1341  if no proper translation could be found for the line and is printed
1342  as commentary line then. */
1343 static char * spice_untranslated_text (struct definition_t * def) {
1344  struct value_t * val;
1345  char str[256];
1346  sprintf (str, "%s%s:%s ", def->action ? "." : "", def->type, def->instance);
1347  char * txt = (char *) malloc (strlen (str) + 1);
1348  strcpy (txt, str);
1349  for (val = def->values; val != NULL; val = val->next) {
1350  if (val->hint == HINT_NODE) {
1351  sprintf (str, "%s ", val->ident);
1352  }
1353  else if (val->hint & (HINT_NODE | HINT_NUMBER)) {
1354  sprintf (str, "%s%s ", val->ident, val->hint & HINT_MSTOP ? ")" : "");
1355  }
1356  else if (val->hint & HINT_PAIR) {
1357  sprintf (str, "%s%s=%s%s ", val->hint & HINT_MSTART ? "(" : "",
1358  val->ident, val->unit, val->hint & HINT_MSTOP ? ")" : "");
1359  }
1360  else if (val->hint & HINT_NAME) {
1361  sprintf (str, "%s%s%s%s",
1362  (val->hint & HINT_MSTART) ? " " : "",
1363  val->ident,
1364  ((val->hint & HINT_MSTART) && val->next &&
1365  (val->next->hint & HINT_MSTOP)) ||
1366  (val->hint & HINT_MSTOP) ? "" : " ",
1367  (val->hint & HINT_MSTART && val->next) ? "(" :
1368  (val->hint & HINT_MSTOP) ? ")" : " ");
1369  }
1370  txt = (char *) realloc (txt, strlen (txt) + strlen (str) + 1);
1371  strcat (txt, str);
1372  }
1373  return spice_toupper (txt);
1374 }
1375 
1376 #define VAL_IS_NUMBER(val) \
1377  ((val) != NULL && \
1378  (val)->hint & (HINT_NUMBER | HINT_NODE) && \
1379  !((val)->hint & HINT_DONE))
1380 
1381 #define VAL_IS_DONE(val) \
1382  ((val) == NULL || (val)->hint & HINT_DONE)
1383 
1384 /* The function counts values in a property list up to a stop
1385  value. */
1386 static int spice_count_real_values (struct value_t * values) {
1387  int ret = 0;
1388  struct value_t * val;
1389  // go through each not yet processed value
1390  foreach_value (values, val) {
1391  if (val->hint & (HINT_NODE | HINT_NUMBER))
1392  ret++;
1393  if (val->hint & HINT_MSTOP) break; // stop here if necessary
1394  }
1395  return ret;
1396 }
1397 
1398 /* This function is the independent source translator. If necessary
1399  new kinds of sources are created. This must be done since Qucs has
1400  separate sources for each type of excitation and Spice summarizes
1401  these voltage/current excitations in a single source. */
1402 static struct definition_t *
1403 spice_translate_source (struct definition_t * root,
1404  struct definition_t * def, char type) {
1405  struct definition_t * ac = NULL, * dc = def, * pulse = NULL, * expo = NULL;
1406  struct value_t * prop;
1407  char * ui = (char *) ((type == 'U') ? "U" : "I");
1408 
1409  // adjust the DC part of the source
1410  if ((prop = spice_find_property (dc->values, "DC")) != NULL) {
1411  spice_value_done (prop);
1412  prop = prop->next;
1413  if (VAL_IS_NUMBER (prop)) {
1414  spice_append_pair (def, ui, prop->ident, 1);
1415  spice_value_done (prop);
1416  }
1417  }
1418  free (dc->type);
1419  dc->type = strdup (type == 'U' ? "Vdc" : "Idc");
1420 
1421  // adjust the sinusoidal part of the source
1422  if ((prop = spice_find_property (dc->values, "SIN")) != NULL) {
1423  ac = spice_create_definition (dc, type == 'U' ? "Vac" : "Iac");
1424  spice_value_done (prop);
1425  prop = prop->next;
1426  if (VAL_IS_NUMBER (prop)) {
1427  // adjust DC offset
1428  nr_double_t off;
1429  off = spice_get_property_value (dc, ui);
1430  spice_append_pair (dc, ui, prop->ident, 1);
1431  off += spice_get_property_value (dc, ui);
1432  spice_set_property_value (dc, ui, off);
1433  spice_value_done (prop);
1434  // extract frequency, phase and theta
1435  prop = prop->next;
1436  struct property_field_t field =
1437  { { ui, "f", "Phase", "Theta", NULL } };
1438  spice_extract_properties (ac, prop, &field);
1439  }
1440  double v, f;
1441  f = spice_get_property_value (ac, "f");
1442  v = spice_get_property_value (ac, "Phase") * f * -360.0;
1443  spice_set_property_value (ac, "Phase", v);
1444  v = spice_get_property_value (ac, "Theta") / f;
1445  spice_set_property_value (ac, "Theta", f > 0 ? v : 0);
1446  }
1447 
1448  // adjust the AC part of the source
1449  if ((prop = spice_find_property (dc->values, "AC")) != NULL) {
1450  char * Mag = NULL, * Phase = NULL;
1451  spice_value_done (prop);
1452  prop = prop->next;
1453  if (VAL_IS_NUMBER (prop)) {
1454  Mag = strdup (prop->ident);
1455  spice_value_done (prop);
1456  prop = prop->next;
1457  if (VAL_IS_NUMBER (prop)) {
1458  Phase = strdup (prop->ident);
1459  spice_value_done (prop);
1460  }
1461  }
1462  if (ac == NULL) {
1463  ac = spice_create_definition (dc, type == 'U' ? "Vac" : "Iac");
1464  }
1465  if (Mag) {
1466  spice_append_pair (ac, ui, Mag, 1);
1467  free (Mag);
1468  }
1469  else {
1470  spice_append_pair (ac, ui, "0", 0);
1471  }
1472  if (Phase) {
1473  spice_append_pair (ac, "Phase", Phase, 1);
1474  free (Phase);
1475  }
1476  }
1477 
1478  // adjust the pulse part of the source
1479  if ((prop = spice_find_property (dc->values, "PULSE")) != NULL) {
1480  pulse = spice_create_definition (dc, type == 'U' ? "Vpulse" : "Ipulse");
1481  spice_value_done (prop);
1482  prop = prop->next;
1483 
1484  // periodic
1485  if (spice_count_real_values (prop) > 6) {
1486  free (pulse->type);
1487  pulse->type = type == 'U' ? strdup ("Vrect") : strdup ("Irect");
1488  double add, off = 0;
1489  if (VAL_IS_NUMBER (prop)) {
1490  add = spice_get_property_value (dc, ui);
1491  spice_append_pair (dc, ui, prop->ident, 1);
1492  off = spice_get_property_value (dc, ui);
1493  add += off;
1494  spice_set_property_value (dc, ui, add);
1495  prop = prop->next;
1496  }
1497  if (VAL_IS_NUMBER (prop)) {
1498  struct property_field_t field =
1499  { { ui, "Td", "Tr", "Tf", "TH", "TL", NULL } };
1500  spice_extract_properties (pulse, prop, &field);
1501  }
1502  double v;
1503  v = spice_get_property_value (pulse, ui); // V2
1504  v -= off;
1505  spice_set_property_value (pulse, ui, v);
1506  v = spice_get_property_value (pulse, "TH"); // PW
1507  v += spice_get_property_value (pulse, "Tr");
1508  spice_set_property_value (pulse, "TH", v);
1509  v = spice_get_property_value (pulse, "TL"); // PER
1510  v -= spice_get_property_value (pulse, "TH");
1511  spice_set_property_value (pulse, "TL", v);
1512  }
1513  // single pulse
1514  else {
1515  if (VAL_IS_NUMBER (prop)) {
1516  spice_append_pair (pulse, type == 'U' ? "U1" : "I1", prop->ident, 0);
1517  spice_append_pair (dc, ui, "0", 0);
1518  spice_value_done (prop);
1519  prop = prop->next;
1520  struct property_field_t field =
1521  { { type == 'U' ? "U2" : "I2", "T1", "Tr", "Tf", "T2", NULL } };
1522  spice_extract_properties (pulse, prop, &field);
1523  }
1524  double v;
1525  v = spice_get_property_value (pulse, "T1");
1526  v += spice_get_property_value (pulse, "Tr");
1527  v += spice_get_property_value (pulse, "Tf");
1528  v += spice_get_property_value (pulse, "T2");
1529  spice_set_property_value (pulse, "T2", v);
1530  }
1531  }
1532 
1533  // adjust the exponential part of the source
1534  if ((prop = spice_find_property (dc->values, "EXP")) != NULL) {
1535  expo = spice_create_definition (dc, type == 'U' ? "Vexp" : "Iexp");
1536  spice_value_done (prop);
1537  prop = prop->next;
1538  // extract pulse values, rise and fall constants
1539  struct property_field_t field =
1540  { { type == 'U' ? "U1" : "I1", type == 'U' ? "U2" : "I2", "T1", "Tr",
1541  "T2", "Tf", NULL } };
1542  spice_extract_properties (expo, prop, &field);
1543  }
1544 
1545  // set DC value to zero if necessary
1546  if (spice_find_property (dc, ui) == NULL) {
1547  spice_append_pair (def, ui, "0", 1);
1548  }
1549 
1550  // finally add sources to list of definitions
1551  if (ac) {
1552  if (type == 'U')
1553  spice_adjust_vsource_nodes (ac, dc);
1554  else
1555  spice_adjust_isource_nodes (ac, dc);
1556  root = spice_add_definition (root, ac);
1557  }
1558  if (pulse) {
1559  if (type == 'U')
1560  spice_adjust_vsource_nodes (pulse, ac ? ac : dc);
1561  else
1562  spice_adjust_isource_nodes (pulse, ac ? ac : dc);
1563  root = spice_add_definition (root, pulse);
1564  }
1565  if (expo) {
1566  if (type == 'U')
1567  spice_adjust_vsource_nodes (expo, pulse ? pulse : ac ? ac : dc);
1568  else
1569  spice_adjust_isource_nodes (expo, pulse ? pulse : ac ? ac : dc);
1570  root = spice_add_definition (root, expo);
1571  }
1572  return root;
1573 }
1574 
1575 /* This little function returns a static string containing an instance
1576  name of a parameter sweep. Successive calls produces different
1577  names. */
1578 static char * spice_create_intern_para (void) {
1579  static int intern = 1;
1580  static char txt[32];
1581  sprintf (txt, "SW%d", intern++);
1582  return txt;
1583 }
1584 
1585 /* The function is used to translate the lin/log10/log8 sweeps into an
1586  appropriate sweep in Qucs. Depending on the given arguments it
1587  computes the number of points in a sweep and stores the new type of
1588  sweep in the given type variable. */
1589 static int spice_evaluate_points (char ** type, double start, double stop,
1590  double points) {
1591  int ret = 1;
1592  if (!strcasecmp (*type, "dec")) { // logarithmic
1593  ret = (int) ((log10 (stop) - log10 (start)) * points);
1594  free (*type);
1595  *type = strdup ("log");
1596  }
1597  else if (!strcasecmp (*type, "lin")) { // linear
1598  ret = (int) points;
1599  free (*type);
1600  *type = strdup ("lin");
1601  }
1602  else if (!strcasecmp (*type, "oct")) { // octaves
1603  ret = (int) (((log10 (stop) - log10 (start)) / log10 (8.0)) * points);
1604  free (*type);
1605  *type = strdup ("log");
1606  }
1607  return ret;
1608 }
1609 
1610 /* This function creates a new parameter sweep (for DC analysis) and
1611  adjust all properties except the 'Sim' property which must be
1612  assigned after calling this function. */
1613 static struct definition_t * spice_create_para (struct definition_t * base) {
1614  struct property_field_t props =
1615  { { "Param", "Start", "Stop", "Points", NULL } };
1616  struct definition_t * para = create_definition ();
1617 
1618  para->type = strdup ("SW");
1619  para->action = PROP_ACTION;
1620  para->instance = strdup (spice_create_intern_para ());
1621  para->define = base->define;
1622  spice_extract_properties (para, base->values, &props);
1623  spice_set_property_string (para, "Type", "lin");
1624  double v;
1625  v = spice_get_property_value (para, "Stop");
1626  v -= spice_get_property_value (para, "Start");
1627  v /= spice_get_property_value (para, "Points");
1628  v += 1;
1629  spice_set_property_value (para, "Points", v);
1630 
1631  return para;
1632 }
1633 
1634 /* This little helper returns the number of not yet processed values
1635  in th given value list. */
1636 static int spice_count_values (struct value_t * values) {
1637  int res = 0; struct value_t * val;
1638  foreach_value (values, val) res++;
1639  return res;
1640 }
1641 
1642 /* The function looks through the list of definitions if there is a
1643  component with the given type and instance names and returns it.
1644  Otherwise the function returns NULL. */
1645 static struct definition_t *
1646 spice_find_definition (struct definition_t * root, const char * type,
1647  char * inst) {
1648  for (struct definition_t * def = root; def != NULL; def = def->next) {
1649  if (!strcasecmp (def->type, type) && !strcasecmp (def->instance, inst))
1650  return def;
1651  }
1652  return NULL;
1653 }
1654 
1655 /* The function looks through the list of definitions if there is a
1656  component with the given type and returns it. Otherwise the
1657  function returns NULL. */
1658 static struct definition_t *
1659 spice_find_definition (struct definition_t * root, const char * type) {
1660  for (struct definition_t * def = root; def != NULL; def = def->next) {
1661  if (!strcasecmp (def->type, type))
1662  return def;
1663  }
1664  return NULL;
1665 }
1666 
1667 /* The function appends the given key/value pair to the properties of
1668  any definition of the given type. */
1669 static void spice_add_property (struct definition_t * root, const char * type,
1670  const char * key, char * value) {
1671  for (struct definition_t * def = root; def != NULL; def = def->next) {
1672  if (!strcmp (def->type, type))
1673  spice_append_pair (def, key, value, 0);
1674  }
1675 }
1676 
1677 /* The following little function removes the value list of the given
1678  definition entirely if all values are marked to be processed. */
1679 static void spice_free_values (struct definition_t * def) {
1680  if (spice_count_values (def->values) <= 0) {
1681  struct value_t * val, * next;
1682  for (val = def->values; val != NULL; val = next) {
1683  next = val->next;
1684  netlist_free_value (val);
1685  }
1686  def->values = NULL;
1687  }
1688 }
1689 
1690 /* Spice node lists. */
1691 struct node_t * spice_nodes = NULL;
1692 
1693 /* Collects the nodes specified in the PLOT and PRINT statement
1694  marking them as potential "external" nodes. */
1695 static void spice_collect_external_nodes (struct definition_t * def) {
1696  struct value_t * val;
1697  foreach_value (def->values, val) {
1698  if (val->hint & HINT_MSTART && val->next && val->ident[0] == 'V') {
1699  struct node_t * n = spice_translate_node (val->next->ident);
1700  if (!qucs_find_node (spice_nodes, n->node)) {
1701  n->next = spice_nodes;
1702  spice_nodes = n;
1703  }
1704  else netlist_free_nodes (n);
1705  }
1706  }
1707 }
1708 
1709 /* This function goes through the list of device descriptions and
1710  checks whether the given model is already in the list. Returns
1711  NULL if there is no such model. */
1712 static struct definition_t * spice_find_Model (char * instance) {
1713  struct definition_t * dev;
1714  for (dev = device_root; dev; dev = dev->next) {
1715  if (!strcmp (dev->instance, instance))
1716  return dev;
1717  }
1718  return NULL;
1719 }
1720 
1721 /* The function appends a new device model. It creates the actual
1722  model description and adjusts the nodes and optional/required
1723  properties. */
1724 static struct definition_t * spice_add_Model (struct definition_t * def) {
1725  struct definition_t * Model;
1726  if (strcasecmp (def->type, "MODEL"))
1727  return NULL;
1728  if (spice_find_Model (def->instance))
1729  return NULL;
1730  Model = create_definition ();
1731  Model->action = PROP_COMPONENT;
1732  Model->instance = strdup (def->instance);
1733  Model->define = def->define;
1734  spice_adjust_device (Model, def);
1735  if (spice_translate_type (Model)) {
1736  spice_fixup_definition (Model);
1737  spice_adjust_optional_properties (Model);
1738  Model->next = device_root;
1739  device_root = Model;
1740  }
1741  else {
1742  free (Model->instance);
1743  free (Model);
1744  Model = NULL;
1745  }
1746  return Model;
1747 }
1748 
1749 /* Finds a second coupled inductor definition using the same inductors
1750  as the original one if there is any. */
1751 static struct definition_t *
1752 spice_find_coupled (struct definition_t * root, struct definition_t * coupled,
1753  const char * type, char * inst) {
1754  for (struct definition_t * def = root; def != NULL; def = def->next) {
1755  if (def != coupled && !strcmp (def->type, type) && !def->action) {
1756  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1757  continue;
1758  char * linst1 = def->values->ident;
1759  char * linst2 = def->values->next->ident;
1760  if (!strcasecmp (linst1, inst) || !strcasecmp (linst2, inst))
1761  return def;
1762  }
1763  }
1764  return NULL;
1765 }
1766 
1767 /* Looks for a mutual inductor instance referencing the two given
1768  inductors and returns it. */
1769 static struct definition_t *
1770 spice_find_coupled (struct definition_t * root, const char * type,
1771  char * inst1, char * inst2) {
1772  for (struct definition_t * def = root; def != NULL; def = def->next) {
1773  if (!strcmp (def->type, type) && !def->action) {
1774  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1775  continue;
1776  char * linst1 = def->values->ident;
1777  char * linst2 = def->values->next->ident;
1778  if ((!strcasecmp (linst1, inst1) && !strcasecmp (linst2, inst2)) ||
1779  (!strcasecmp (linst1, inst2) && !strcasecmp (linst2, inst1)))
1780  return def;
1781  }
1782  }
1783  return NULL;
1784 }
1785 
1786 /* Looks for the inductor definition used in a coupled inductor.
1787  Emits an error message if there is no such inductor. */
1788 static struct definition_t *
1789 spice_find_coupled_inductor (struct definition_t * root,
1790  struct definition_t * def, const char * type,
1791  char * inst) {
1792  static struct definition_t * target;
1793  target = spice_find_definition (root, type, inst);
1794  if (target == NULL) {
1795  fprintf (stderr, "spice error, no such inductor `%s' found as "
1796  "referenced by %s `%s'\n", inst, def->type, def->instance);
1797  spice_errors++;
1798  }
1799  return target;
1800 }
1801 
1802 // Get the coefficient of coupling.
1803 static struct value_t *
1804 spice_get_value_coupled (struct definition_t * def) {
1805  struct value_t * val = NULL;
1806  foreach_value (def->values, val) {
1807  if (val->hint & HINT_NUMBER) break;
1808  }
1809  return val;
1810 }
1811 
1812 // Generates a coupled inductor instance description.
1813 static char *
1814 spice_coupled_instance (struct definition_t * k1, struct definition_t * k2,
1815  struct definition_t * k3) {
1816  char * inst = (char *) malloc (strlen (k1->instance) +
1817  strlen (k2->instance) +
1818  strlen (k3->instance) + 1);
1819  strcpy (inst, k1->instance);
1820  strcat (inst, k2->instance);
1821  strcat (inst, k3->instance);
1822  return inst;
1823 }
1824 
1825 /* Post translation function for coupled inductors. */
1826 static struct definition_t *
1827 spice_translate_coupled (struct definition_t * root,
1828  struct definition_t * def) {
1829  struct definition_t * target1, * target2, * target3;
1830  char * linst1 = def->values->ident; // get inductivity 1
1831  char * linst2 = def->values->next->ident; // get inductivity 2
1832  nr_double_t l1, l2, l3, k, t;
1833  char * n1, * n2, * n3, * n4;
1834  struct node_t * nn;
1835 
1836  // initialize local variables
1837  n1 = n2 = n3 = n4 = NULL;
1838  l1 = l2 = l3 = k = t = 0;
1839 
1840  // find and handle inductivity 1
1841  target1 = spice_find_coupled_inductor (root, def, "L", linst1);
1842 
1843  // find and handle inductivity 2
1844  target2 = spice_find_coupled_inductor (root, def, "L", linst2);
1845 
1846  // if both inductors found
1847  if (!target1 || !target2) return root;
1848 
1849  l1 = spice_get_property_value (target1, "L");
1850  l2 = spice_get_property_value (target2, "L");
1851 
1852  // check three inductors
1853  struct definition_t * k1 = def, * k2, * k3;
1854  char * k12, * k13, * k23;
1855  k2 = spice_find_coupled (root, k1, "Tr", linst1);
1856  k3 = spice_find_coupled (root, k1, "Tr", linst2);
1857 
1858  // handle three inductors
1859  if (k2 != NULL && k3 != NULL) {
1860  char * linst3, * linst4;
1861  if (!strcasecmp (k2->values->ident, linst1))
1862  linst3 = k2->values->next->ident;
1863  else
1864  linst3 = k2->values->ident;
1865  if (!strcasecmp (k3->values->ident, linst2))
1866  linst4 = k3->values->next->ident;
1867  else
1868  linst4 = k3->values->ident;
1869  spice_value_done (k1->values);
1870  spice_value_done (k1->values->next);
1871 
1872  if (strcasecmp (linst3, linst4)) {
1873  fprintf (stderr, "spice error, cannot translate coupled inductors "
1874  "`%s' and `%s'\n", linst3, linst4);
1875  spice_errors++;
1876  }
1877  else if (k2 != k3) {
1878  // find and handle inductivity 3
1879  target3 = spice_find_coupled_inductor (root, k2, "L", linst3);
1880  if (target3 != NULL) {
1881  // construct three mutual inductors
1882  struct value_t * val;
1883  char * inst = spice_coupled_instance (k1, k2, k3);
1884  free (k1->type); k1->type = strdup ("MUT2");
1885  free (k1->instance); k1->instance = inst;
1886  netlist_free_pairs (k1->pairs); k1->pairs = NULL;
1887  spice_value_done (k2->values);
1888  spice_value_done (k2->values->next);
1889  spice_value_done (k3->values);
1890  spice_value_done (k3->values->next);
1891  spice_append_node (k1, spice_get_node(target1, 1)->node);
1892  spice_append_node (k1, spice_get_node(target3, 1)->node);
1893  spice_append_node (k1, spice_get_node(target3, 2)->node);
1894  spice_append_node (k1, spice_get_node(target2, 2)->node);
1895  spice_append_node (k1, spice_get_node(target2, 1)->node);
1896  spice_append_node (k1, spice_get_node(target1, 2)->node);
1897  l3 = spice_get_property_value (target3, "L");
1898  spice_set_property_value (k1, "L1", l1);
1899  spice_set_property_value (k1, "L2", l2);
1900  spice_set_property_value (k1, "L3", l3);
1901  if ((val = spice_get_value_coupled (k1)) != NULL) {
1902  k12 = val->ident;
1903  spice_append_pair (k1, "k12", k12, 0);
1904  spice_value_done (val);
1905  }
1906  if ((val = spice_get_value_coupled (k2)) != NULL) {
1907  k13 = val->ident;
1908  spice_append_pair (k1, "k13", k13, 0);
1909  spice_value_done (val);
1910  }
1911  if ((val = spice_get_value_coupled (k3)) != NULL) {
1912  k23 = val->ident;
1913  spice_append_pair (k1, "k23", k23, 0);
1914  spice_value_done (val);
1915  }
1916  root = spice_del_definition (root, target1);
1917  root = spice_del_definition (root, target2);
1918  root = spice_del_definition (root, target3);
1919  root = spice_del_definition (root, k2);
1920  root = spice_del_definition (root, k3);
1921  return root;
1922  }
1923  }
1924  }
1925 
1926  spice_value_done (def->values);
1927  spice_value_done (def->values->next);
1928 
1929  // node replacer 1
1930  nn = spice_get_node (target1, 2);
1931  n4 = nn->node;
1932  nn->node = strdup (spice_create_intern_node ());
1933  n1 = strdup (nn->node);
1934 
1935  // node replacer 2
1936  nn = spice_get_node (target2, 2);
1937  n3 = nn->node;
1938  nn->node = strdup (spice_create_intern_node ());
1939  n2 = strdup (nn->node);
1940 
1941  // get the coefficient of coupling
1942  struct value_t * val;
1943  spice_append_pair (def, "T", "1", 1);
1944  if ((val = spice_get_value_coupled (def)) != NULL) {
1945  spice_append_pair (def, "T", val->ident, 1);
1946  spice_value_done (val);
1947  }
1948 
1949  // apply the turns ratio of the transformer and its nodes
1950  k = spice_get_property_value (def, "T");
1951  t = sqrt (l1 / l2);
1952  spice_set_property_value (def, "T", t);
1953  spice_append_node (def, n1);
1954  spice_append_node (def, n2);
1955  spice_append_node (def, n3);
1956  spice_append_node (def, n4);
1957  // adapt inductivities of original inductors
1958  spice_set_property_value (target1, "L", l1 - k * l1);
1959  spice_set_property_value (target2, "L", l2 - k * l1 / t / t);
1960  // insert the actual mutual inductance if necessary
1961  if (k > 0) {
1962  struct definition_t * Mind = spice_create_definition (def, "L");
1963  spice_append_node (Mind, n1);
1964  spice_append_node (Mind, n4);
1965  spice_set_property_value (Mind, "L", k * l1);
1966  root = spice_add_definition (root, Mind);
1967  }
1968  free (n1); free (n2); free (n3); free (n4);
1969  return root;
1970 }
1971 
1972 /* Finds an additional mutual inductor definition using the same
1973  inductors as the original one if there is any. */
1974 static struct definition_t *
1975 spice_find_coupled (struct definition_t * root,
1977  const char * type, char * inst) {
1978  for (struct definition_t * def = root; def != NULL; def = def->next) {
1979  if (!strcmp (def->type, type) && !def->action) {
1980  if (VAL_IS_DONE (def->values) || VAL_IS_DONE (def->values->next))
1981  continue;
1982  if (!coupled->get (def->instance)) {
1983  char * linst1 = def->values->ident;
1984  char * linst2 = def->values->next->ident;
1985  if (!strcasecmp (linst1, inst) || !strcasecmp (linst2, inst))
1986  return def;
1987  }
1988  }
1989  }
1990  return NULL;
1991 }
1992 
1993 /* Looks recursively for mutual inductors. In the end the two hash
1994  maps contain all the inductors coupled by those mutual inductors in
1995  the other hash map. */
1996 static struct definition_t *
1997 spice_search_coupled (struct definition_t * root,
2000  const char * type, char * inst) {
2001  char * linst;
2002  struct definition_t * l, * k;
2003 
2004  // find mutual inductors referencing the given inductor instance
2005  while ((k = spice_find_coupled (root, K_hash, type, inst)) != NULL) {
2006  // already had this one?
2007  if (K_hash->get (k->instance))
2008  continue;
2009  K_hash->put (k->instance, k);
2010 
2011  // first referenced inductor
2012  linst = k->values->ident;
2013  if (!L_hash->get (linst)) {
2014  if ((l = spice_find_coupled_inductor (root, k, "L", linst)) != NULL) {
2015  L_hash->put (linst, l);
2016  // recurse
2017  root = spice_search_coupled (root, K_hash, L_hash, type, linst);
2018  }
2019  }
2020 
2021  // second referenced inductor
2022  linst = k->values->next->ident;
2023  if (!L_hash->get (linst)) {
2024  if ((l = spice_find_coupled_inductor (root, k, "L", linst)) != NULL) {
2025  L_hash->put (linst, l);
2026  // recurse
2027  root = spice_search_coupled (root, K_hash, L_hash, type, linst);
2028  }
2029  }
2030  }
2031  return root;
2032 }
2033 
2034 /* Post translation function for multiple coupled inductors. */
2035 static struct definition_t *
2036 spice_translate_coupled_x (struct definition_t * root,
2037  struct definition_t * def) {
2038  char * linst1, * linst2;
2042  struct definition_t * l;
2043 
2044  // save first 2 referenced inductors and the mutual inductor
2045  linst1 = def->values->ident;
2046  if ((l = spice_find_coupled_inductor (root, def, "L", linst1)) != NULL)
2047  L_hash.put (linst1, l);
2048  linst2 = def->values->next->ident;
2049  if ((l = spice_find_coupled_inductor (root, def, "L", linst2)) != NULL)
2050  L_hash.put (linst2, l);
2051  K_hash.put (def->instance, def);
2052 
2053  // look for more mutual inductors involving the first 2 inductors
2054  root = spice_search_coupled (root, &K_hash, &L_hash, "Tr", linst1);
2055  root = spice_search_coupled (root, &K_hash, &L_hash, "Tr", linst2);
2056 
2057  // create coupling coefficient matrix
2058  int i, o, s = L_hash.count ();
2059  nr_double_t * kval = new nr_double_t[s * s];
2060  struct definition_t * k;
2061  struct value_t * val;
2063  // outer loop
2064  for (ito = qucs::hashiterator<struct definition_t> (L_hash), o = 0;
2065  *ito; ++ito, ++o) {
2066  // inner loop
2067  for (iti = qucs::hashiterator<struct definition_t> (L_hash), i = 0;
2068  *iti; ++iti, ++i) {
2069  if (i > o) {
2070  // cross-coupling coefficients
2071  nr_double_t kvalue = 0;
2072  k = spice_find_coupled (root, "Tr",
2073  iti.currentKey (), ito.currentKey ());
2074  if (k != NULL) {
2075  if ((val = spice_get_value_coupled (k)) != NULL) {
2076  kvalue = spice_evaluate_value (val);
2077  }
2078  }
2079  kval[s * o + i] = kvalue;
2080  kval[s * i + o] = kvalue;
2081  }
2082  else if (i == o) {
2083  // self-coupling coefficient
2084  kval[s * o + i] = 1;
2085  }
2086  }
2087  }
2088 
2089  spice_value_done (def->values);
2090  spice_value_done (def->values->next);
2091 
2092  // adjust MUTX instance
2093  free (def->type); def->type = strdup ("MUTX");
2094  netlist_free_pairs (def->pairs); def->pairs = NULL;
2095 
2096  // create L property vector
2097  struct pair_t * pair = create_pair ();
2098  pair->key = strdup ("L");
2099  def->pairs = netlist_append_pairs (def->pairs, pair);
2100  for (it = qucs::hashiterator<struct definition_t> (L_hash); *it; ++it) {
2101  spice_append_node (def, spice_get_node(it.currentVal (), 1)->node);
2102  spice_append_node (def, spice_get_node(it.currentVal (), 2)->node);
2103  val = create_value ();
2104  val->value = spice_get_property_value (it.currentVal (), "L");
2105  pair->value = netlist_append_values (pair->value, val);
2106  root = spice_del_definition (root, it.currentVal ());
2107  }
2108 
2109  // create k property vector
2110  pair = create_pair ();
2111  pair->key = strdup ("k");
2112  def->pairs = netlist_append_pairs (def->pairs, pair);
2113  for (i = 0; i < s * s; i++) {
2114  val = create_value ();
2115  val->value = kval[i];
2116  pair->value = netlist_append_values (pair->value, val);
2117  }
2118 
2119  // remove remaining coupled inductors from definition list
2120  for (it = qucs::hashiterator<struct definition_t> (K_hash); *it; ++it) {
2121  if (def != it.currentVal ()) {
2122  root = spice_del_definition (root, it.currentVal ());
2123  }
2124  }
2125 
2126  delete[] kval;
2127  return root;
2128 }
2129 
2130 /* Contructs an edd equation name. */
2131 static char *
2132 spice_create_eqnstr (struct definition_t * def, int p, char type) {
2133  char * n = (char *) malloc (strlen (def->instance) + 4 + 3);
2134  sprintf (n, "%s.%c%d", def->instance, type, p);
2135  return n;
2136 }
2137 
2138 /* The function adds edd equation properties to the given netlist
2139  definition and also adds the appropriate equation instances. */
2140 static struct definition_t *
2141 spice_add_edd_equation (struct definition_t * root,
2142  struct definition_t * def, int p,
2143  struct definition_t ** i, struct definition_t ** q) {
2144  struct definition_t * ieqn, * qeqn;
2145  char I_[4], Q_[4];
2146  char * ieq = spice_create_eqnstr (def, p, 'I');
2147  char * qeq = spice_create_eqnstr (def, p, 'Q');
2148  sprintf (I_, "I%d", p);
2149  sprintf (Q_, "Q%d", p);
2150  spice_set_property_string (def, Q_, qeq);
2151  spice_set_property_string (def, I_, ieq);
2152  ieqn = spice_create_definition (def, "Eqn");
2153  qeqn = spice_create_definition (def, "Eqn");
2154  spice_set_property_string (ieqn, "Export", "no");
2155  spice_set_property_string (qeqn, "Export", "no");
2156  spice_set_property_string (ieqn, ieq, "0");
2157  spice_set_property_string (qeqn, qeq, "0");
2158  root = spice_add_definition (root, qeqn);
2159  root = spice_add_definition (root, ieqn);
2160  sprintf (ieq, "Eqn%sI%d", def->instance, p);
2161  sprintf (qeq, "Eqn%sQ%d", def->instance, p);
2162  free (ieqn->instance);
2163  free (qeqn->instance);
2164  qeqn->instance = strdup (qeq);
2165  ieqn->instance = strdup (ieq);
2166  free (ieq);
2167  free (qeq);
2168  if (i) (*i) = ieqn;
2169  if (q) (*q) = qeqn;
2170  return root;
2171 }
2172 
2173 /* Since there no or little documentation about the polynom orders in
2174  the SPICE2G6 'POLY' statements the following piece of code is a
2175  straight re-implementation of the Fortran code in SPICE2G6. */
2176 static void spice2g6_nxtpwr (int * seq, int nd) {
2177  int i, k, ps;
2178 
2179  // special handling of one-dimensional polynoms
2180  if (nd == 1) {
2181  seq[0]++;
2182  return;
2183  }
2184 
2185  // two and more-dimensional polynoms
2186  k = nd;
2187  do {
2188  if (seq[k - 1] != 0) break;
2189  }
2190  while (--k != 0);
2191 
2192  if (k == 0) {
2193  seq[0]++;
2194  }
2195  else if (k != nd) {
2196  seq[k - 1]--;
2197  seq[k]++;
2198  }
2199  else {
2200  for (i = 0; i < k - 1; i++)
2201  if (seq[i] != 0) break;
2202  if (i == k - 1) {
2203  seq[0] = seq[nd - 1] + 1;
2204  seq[nd-1] = 0;
2205  return;
2206  }
2207  ps = 1;
2208  k = nd - 1;
2209  while (seq[k - 1] < 1) {
2210  ps += seq[k];
2211  seq[k] = 0;
2212  k--;
2213  }
2214  seq[k] += ps;
2215  seq[k - 1]--;
2216  }
2217 }
2218 
2219 /* The function takes the given spice value, converts it into an
2220  appropriate real value and save optional scale and unit and finally
2221  returns the actual value. */
2222 static double spice_get_value (struct value_t * val) {
2223  const char * str;
2224  char * end;
2225  double v;
2226  val->value = strtod (val->ident, &end);
2227  if (*end) {
2228  str = spice_evaluate_scale (end, &end, &v);
2229  val->value *= v;
2230  val->scale = str ? strdup (str) : NULL;
2231  if (*end) val->unit = strdup (end);
2232  }
2233  return val->value;
2234 }
2235 
2236 /* Creates a 'nd' dimensional polynomial expression extracted from the
2237  coefficient list of a value. */
2238 static char *
2239 spice_create_poly (struct value_t * prop, int nd, int integrate) {
2240  struct value_t * val;
2241 
2242  // contruct polynomial expression
2243  int * pn = (int *) calloc (nd, sizeof (int));
2244  static char expr[1024];
2245  char value[256];
2246  strcpy (expr, "");
2247 
2248  // go through spice values
2249  foreach_value (prop, val) {
2250  if (!VAL_IS_NUMBER (val)) break;
2251 
2252  double k = spice_get_value (val);
2253  spice_value_done (val);
2254 
2255  // construct single polynom
2256  if (k != 0.0) {
2257 
2258  // coefficient
2259  sprintf (value, "%+g", k);
2260  strcat (expr, value);
2261 
2262  // remaining polynom
2263  for (int i = 0; i < nd; i++) {
2264  int n = integrate ? i + 1 : i + 2;
2265  int e = integrate ? pn[i] + 2 : pn[i];
2266  switch (e) {
2267  case 0:
2268  strcpy (value, "");
2269  break;
2270  case 1:
2271  sprintf (value, "*V%d", n);
2272  break;
2273  case 2:
2274  sprintf (value, "*V%d*V%d", n, n);
2275  break;
2276  default:
2277  sprintf (value, "*V%d^%d", n, e);
2278  break;
2279  }
2280  strcat (expr, value);
2281 
2282  // coefficient correction
2283  if (integrate && e > 1) {
2284  sprintf (value, "/%d", e);
2285  strcat (expr, value);
2286  }
2287  }
2288  }
2289 
2290  // prepare next polynom
2291  spice2g6_nxtpwr (pn, nd);
2292  }
2293  free (pn);
2294  return expr;
2295 }
2296 
2297 /* Translates E and G poly sources. */
2298 static struct definition_t *
2299 spice_translate_poly (struct definition_t * root, struct definition_t * def) {
2300  struct value_t * prop;
2301  int nd, type = -1;
2302 
2303  // only handle appropriate sources
2304  if (strcasecmp (def->type, "E") && strcasecmp (def->type, "G") &&
2305  strcasecmp (def->type, "F") && strcasecmp (def->type, "H"))
2306  return root;
2307 
2308  // save source type information
2309  if (!strcasecmp (def->type, "E"))
2310  type = 0;
2311  else if (!strcasecmp (def->type, "G"))
2312  type = 1;
2313  else if (!strcasecmp (def->type, "H"))
2314  type = 2;
2315  else if (!strcasecmp (def->type, "F"))
2316  type = 3;
2317 
2318  if ((prop = spice_find_property (def->values, "POLY")) != NULL) {
2319  // retype poly source into EDD
2320  free (def->type);
2321  def->type = strdup ("EDD");
2322  spice_value_done (prop);
2323  // get number of polynomial terms
2324  prop = prop->next;
2325  nd = (int) spice_evaluate_value (prop);
2326  spice_value_done (prop);
2327 
2328  // contruct properties, equations and nodes of the EDD
2329  if (type <= 1) {
2330  // handle E and G voltage controlled sources
2331  prop = prop->next;
2332  for (int i = nd * 2 - 1; i >= 0; i--) {
2333  int p = (i + 1) / 2 + 1;
2334  struct node_t * node = spice_translate_node (prop->ident);
2335  def->nodes = netlist_append_nodes (def->nodes, node);
2336  if (i & 1) root = spice_add_edd_equation (root, def, p, NULL, NULL);
2337  spice_value_done (prop);
2338  prop = prop->next;
2339  }
2340  }
2341  else {
2342  // handle F and H current controlled sources
2343  prop = prop->next;
2344  for (int i = nd; i > 0; i--) {
2345  struct definition_t * vdc, * ibuf;
2346  char * vn, * np, * nn;
2347  int p = i + 1;
2348  // find referenced voltage source (where current flows through)
2349  vn = prop->ident;
2350  vdc = spice_find_definition (root, "Vdc", vn);
2351  if (vdc) {
2352  // create intermediate current controlled voltage source
2353  // passing voltage to an EDD branch
2354  ibuf = spice_create_definition (def, "CCVS");
2355  vn = (char *) malloc (strlen (ibuf->instance) + 3);
2356  sprintf (vn, "%sV%d", ibuf->instance, p);
2357  free (ibuf->instance);
2358  ibuf->instance = vn;
2359  struct node_t * node = spice_get_node (vdc, 1);
2360  np = strdup (spice_create_intern_node ());
2361  nn = strdup (spice_create_intern_node ());
2362  spice_append_node (ibuf, node->node);
2363  free (node->node);
2364  node->node = strdup (nn);
2365  spice_append_node (def, np);
2366  spice_append_node (def, (char *) "gnd");
2367  spice_append_node (ibuf, np);
2368  spice_append_node (ibuf, (char *) "gnd");
2369  spice_append_node (ibuf, nn);
2370  spice_set_property_string (ibuf, "G", "1");
2371  root = spice_add_definition (root, ibuf);
2372  free (nn);
2373  free (np);
2374  }
2375  else {
2376  fprintf (stderr, "spice error, no such voltage source `%s' found as "
2377  "referenced by the %s `%s' instance\n", def->type,
2378  def->instance, vn);
2379  spice_errors++;
2380  }
2381  root = spice_add_edd_equation (root, def, p, NULL, NULL);
2382  spice_value_done (prop);
2383  prop = prop->next;
2384  }
2385  }
2386 
2387  // add first (really evaluating) I and Q equations
2388  struct definition_t * ieqn, * qeqn;
2389  root = spice_add_edd_equation (root, def, 1, &ieqn, &qeqn);
2390 
2391  // contruct polynomial expression
2392  char * expr = spice_create_poly (prop, nd, 0);
2393 
2394  // replace first current branch to reflect polynom
2395  char * ieq = spice_create_eqnstr (def, 1, 'I');
2396  spice_set_property_string (ieqn, ieq, expr);
2397  free (ieq);
2398 
2399  // finally add buffering controlled source
2400  struct definition_t * obuf = NULL;
2401  struct node_t * pnode, * nnode;
2402  char * intp;
2403 
2404  if ((type & 1) == 0)
2405  obuf = spice_create_definition (def, "CCVS");
2406  else if ((type & 1) == 1)
2407  obuf = spice_create_definition (def, "CCCS");
2408 
2409  pnode = spice_get_node (def, 1);
2410  nnode = spice_get_node (def, 2);
2411  intp = strdup (spice_create_intern_node ());
2412 
2413  spice_append_node (obuf, intp);
2414  spice_append_node (obuf, nnode->node);
2415  spice_append_node (obuf, pnode->node);
2416  spice_append_node (obuf, (char *) "gnd");
2417 
2418  free (pnode->node);
2419  pnode->node = strdup (intp);
2420  free (nnode->node);
2421  nnode->node = strdup ("gnd");
2422  free (intp);
2423 
2424  spice_set_property_string (obuf, "G", "1");
2425  root = spice_add_definition (root, obuf);
2426  }
2427  return root;
2428 }
2429 
2430 /* Translates non-linear L and C poly definitions. */
2431 static struct definition_t *
2432 spice_translate_poly_lc (struct definition_t * root,
2433  struct definition_t * def) {
2434  struct value_t * prop;
2435  int type = -1;
2436  double lc = 0.0;
2437 
2438  // save type information
2439  if (!strcasecmp (def->type, "C"))
2440  type = 0;
2441  else if (!strcasecmp (def->type, "L"))
2442  type = 1;
2443 
2444  if ((prop = spice_find_property (def->values, "POLY")) != NULL) {
2445  // retype poly LC into EDD
2446  free (def->type);
2447  def->type = strdup ("EDD");
2448  spice_value_done (prop);
2449 
2450  // get constant L or C value
2451  struct pair_t * p;
2452  if ((p = spice_find_property (def, "C")) != NULL) {
2453  lc = spice_get_property_value (def, "C");
2454  def->pairs = spice_del_property (def->pairs, p);
2455  }
2456  else if ((p = spice_find_property (def, "L")) != NULL) {
2457  lc = spice_get_property_value (def, "L");
2458  def->pairs = spice_del_property (def->pairs, p);
2459  }
2460 
2461  // add I and Q equations
2462  struct definition_t * ieqn, * qeqn;
2463  root = spice_add_edd_equation (root, def, 1, &ieqn, &qeqn);
2464 
2465  // contruct polynomial expression
2466  char * expr1 = strdup (spice_create_poly (prop, 1, 1));
2467  char * expr2 = expr1;
2468  if (lc != 0.0) {
2469  expr2 = (char *) malloc (strlen (expr1) + 256);
2470  sprintf (expr2, "%+g*V1%s", lc, expr1);
2471  free (expr1);
2472  }
2473 
2474  // replace first charge branch to reflect polynom
2475  char * qeq = spice_create_eqnstr (def, 1, 'Q');
2476  spice_set_property_string (qeqn, qeq, expr2);
2477  free (expr2);
2478  free (qeq);
2479 
2480  // finally add converting gyrator if necessary
2481  if (type == 1) {
2482  struct definition_t * gyra = NULL;
2483  struct node_t * pnode, * nnode;
2484  char * intp;
2485 
2486  gyra = spice_create_definition (def, "Gyrator");
2487 
2488  pnode = spice_get_node (def, 1);
2489  nnode = spice_get_node (def, 2);
2490  intp = strdup (spice_create_intern_node ());
2491 
2492  spice_append_node (gyra, intp);
2493  spice_append_node (gyra, nnode->node);
2494  spice_append_node (gyra, pnode->node);
2495  spice_append_node (gyra, (char *) "gnd");
2496 
2497  free (pnode->node);
2498  pnode->node = strdup (intp);
2499  free (nnode->node);
2500  nnode->node = strdup ("gnd");
2501  free (intp);
2502 
2503  spice_set_property_string (gyra, "R", "1");
2504  root = spice_add_definition (root, gyra);
2505  }
2506  }
2507  return root;
2508 }
2509 
2510 /* This function must be called after the actual Spice netlist
2511  translator in order to adjust some references or whatever in the
2512  resulting netlist. */
2513 static struct definition_t *
2514 spice_post_translator (struct definition_t * root) {
2515  for (struct definition_t * def = root; def != NULL; def = def->next) {
2516  // post-process parameter sweep
2517  if (def->action && !strcmp (def->type, "SW")) {
2518  // adjust the actual 'Param' name
2519  struct pair_t * prop = spice_find_property (def, "Param");
2520  char * val = spice_toupper (prop->value->ident);
2521  struct definition_t * target;
2522  // get the target voltage or current source and adjust the property
2523  target = spice_find_definition (root, "Vdc", val);
2524  if (target) {
2525  prop = spice_find_property (target, "U");
2526  prop->value->ident = strdup (val);
2527  }
2528  else {
2529  target = spice_find_definition (root, "Idc", val);
2530  if (target) {
2531  prop = spice_find_property (target, "I");
2532  prop->value->ident = strdup (val);
2533  }
2534  else {
2535  fprintf (stderr, "spice error, no such source `%s' found as "
2536  "referenced by the .DC analysis\n", val);
2537  spice_errors++;
2538  }
2539  }
2540  }
2541  // post-process current-controlled current/voltage source
2542  if (!def->action && (!strcmp (def->type, "CCCS") ||
2543  !strcmp (def->type, "CCVS"))) {
2544  struct definition_t * target;
2545  struct value_t * val = spice_find_device_instance (def);
2546  if (val) {
2547  char * key = val->ident;
2548  target = spice_find_definition (root, "Vdc", key);
2549  if (target) {
2550  // adjust the controlling nodes of the source
2551  spice_adjust_vsource_nodes (def, target);
2552  spice_translate_nodes (def, 1);
2553  }
2554  else {
2555  fprintf (stderr, "spice error, no such voltage source `%s' found "
2556  "as referenced by the %s `%s' instance\n", def->type,
2557  def->instance, key);
2558  spice_errors++;
2559  }
2560  }
2561  }
2562  // post-process F and H poly sources
2563  if (!def->action && (!strcmp (def->type, "F") ||
2564  !strcmp (def->type, "H"))) {
2565  root = spice_translate_poly (root, def);
2566  }
2567  // post-process switches
2568  if (!def->action && !strcmp (def->type, "Relais")) {
2569  struct pair_t * pon = spice_find_property_nocase (def, "VON");
2570  struct pair_t * pof = spice_find_property_nocase (def, "VOFF");
2571  if (pon != NULL && pof != NULL) {
2572  nr_double_t von = spice_evaluate_value (pon->value);
2573  nr_double_t vof = spice_evaluate_value (pof->value);
2574  def->pairs = spice_del_property (def->pairs, pon);
2575  def->pairs = spice_del_property (def->pairs, pof);
2576  nr_double_t vh = (von - vof) / 2;
2577  nr_double_t vt = (von + vof) / 2;
2578  spice_set_property_value (def, "Vt", vt);
2579  spice_set_property_value (def, "Vh", fabs (vh));
2580  }
2581  }
2582  // post-process pulse and rectangular sources
2583  if (!def->action && (!strcmp (def->type, "Vpulse") ||
2584  !strcmp (def->type, "Ipulse") ||
2585  !strcmp (def->type, "Vrect") ||
2586  !strcmp (def->type, "Irect"))) {
2587  struct definition_t * tran;
2588  struct pair_t * tr = spice_find_property (def, "Tr");
2589  struct pair_t * tf = spice_find_property (def, "Tf");
2590  if (tr == NULL || tf == NULL) {
2591  if ((tran = spice_find_definition (definition_root, "TR")) != NULL) {
2592  nr_double_t start = spice_get_property_value (tran, "Start");
2593  nr_double_t stop = spice_get_property_value (tran, "Stop");
2594  nr_double_t points = spice_get_property_value (tran, "Points");
2595  nr_double_t tstep = (stop - start) / (points - 1);
2596  nr_double_t add = 0;
2597  if (!tf) {
2598  spice_set_property_value (def, "Tf", tstep);
2599  add += tstep;
2600  }
2601  if (!tr) {
2602  spice_set_property_value (def, "Tr", tstep);
2603  add += tstep;
2604  }
2605  if (!strcmp (&def->type[1], "pulse")) {
2606  nr_double_t t2 = spice_get_property_value (def, "T2");
2607  spice_set_property_value (def, "T2", t2 + add);
2608  }
2609  }
2610  }
2611  }
2612  // post-process sinusoidal sources
2613  if (!def->action && (!strcmp (def->type, "Vac") ||
2614  !strcmp (def->type, "Iac"))) {
2615  struct definition_t * tran;
2616  struct pair_t * f = spice_find_property (def, "f");
2617  if (f == NULL) {
2618  if ((tran = spice_find_definition (definition_root, "TR")) != NULL) {
2619  nr_double_t stop = spice_get_property_value (tran, "Stop");
2620  spice_set_property_value (def, "f", 1 / stop);
2621  }
2622  }
2623  }
2624  // post-process resistors
2625  if (!def->action && !strcmp (def->type, "R")) {
2626  // drop the second "R" given in Model
2627  struct pair_t * r1 = spice_find_property_nocase (def, "R");
2628  struct pair_t * r2 = spice_find_property_nocase (r1->next, "R");
2629  if (r2 != NULL) {
2630  def->pairs = spice_del_property (def->pairs, r2);
2631  }
2632  // calculate R value
2633  struct pair_t * L = spice_find_property_nocase (def, "L");
2634  struct pair_t * W = spice_find_property_nocase (def, "W");
2635  struct pair_t * R = spice_find_property_nocase (def, "RSH");
2636  struct pair_t * D = spice_find_property_nocase (def, "DEFW");
2637  struct pair_t * N = spice_find_property_nocase (def, "NARROW");
2638  nr_double_t l = 0, w = 0, r = 0, d = 0, n = 0;
2639  if (L) {
2640  l = spice_evaluate_value (L->value);
2641  def->pairs = spice_del_property (def->pairs, L);
2642  }
2643  if (W) {
2644  w = spice_evaluate_value (W->value);
2645  def->pairs = spice_del_property (def->pairs, W);
2646  }
2647  if (R) {
2648  r = spice_evaluate_value (R->value);
2649  def->pairs = spice_del_property (def->pairs, R);
2650  }
2651  if (D) {
2652  d = spice_evaluate_value (D->value);
2653  def->pairs = spice_del_property (def->pairs, D);
2654  }
2655  if (N) {
2656  n = spice_evaluate_value (N->value);
2657  def->pairs = spice_del_property (def->pairs, N);
2658  }
2659  if (d == 0) d = 1e-6;
2660  if (w == 0) w = d;
2661  if (l != 0 && w != 0 && r != 0) {
2662  r = r * (l - n) / (w - n);
2663  spice_set_property_value (def, "R", r);
2664  }
2665  // handle Spice 2g6 syntax
2666  struct value_t * val;
2667  foreach_value (def->values, val) {
2668  if (!(val->hint & HINT_DONE) && (val->hint & HINT_NUMBER)) {
2669  spice_append_pair (def, "Tc2", val->ident, 0);
2670  spice_value_done (val);
2671  break;
2672  }
2673  }
2674  }
2675  // post-process capacitor
2676  if (!def->action && !strcmp (def->type, "C")) {
2677  // calculate C value
2678  struct pair_t * L = spice_find_property_nocase (def, "L");
2679  struct pair_t * W = spice_find_property_nocase (def, "W");
2680  struct pair_t * C = spice_find_property_nocase (def, "CJ");
2681  struct pair_t * S = spice_find_property_nocase (def, "CJSW");
2682  struct pair_t * D = spice_find_property_nocase (def, "DEFW");
2683  struct pair_t * N = spice_find_property_nocase (def, "NARROW");
2684  nr_double_t l = 0, w = 0, c = 0, d = 0, n = 0, s = 0;
2685  if (L) {
2686  l = spice_evaluate_value (L->value);
2687  def->pairs = spice_del_property (def->pairs, L);
2688  }
2689  if (W) {
2690  w = spice_evaluate_value (W->value);
2691  def->pairs = spice_del_property (def->pairs, W);
2692  }
2693  if (C) {
2694  c = spice_evaluate_value (C->value);
2695  def->pairs = spice_del_property (def->pairs, C);
2696  }
2697  if (S) {
2698  s = spice_evaluate_value (S->value);
2699  def->pairs = spice_del_property (def->pairs, S);
2700  }
2701  if (D) {
2702  d = spice_evaluate_value (D->value);
2703  def->pairs = spice_del_property (def->pairs, D);
2704  }
2705  if (N) {
2706  n = spice_evaluate_value (N->value);
2707  def->pairs = spice_del_property (def->pairs, N);
2708  }
2709  if (d == 0) d = 1e-6;
2710  if (w == 0) w = d;
2711  if (l != 0 && w != 0 && c != 0) {
2712  c = c * (l - n) * (w - n) + 2 * s * (l + w - 2 * n);
2713  spice_set_property_value (def, "C", c);
2714  }
2715  }
2716  // post-process lossless transmission line
2717  if (!def->action && !strcmp (def->type, "TLIN4P")) {
2718  struct pair_t * pt = spice_find_property (def, "TD");
2719  struct pair_t * pf = spice_find_property (def, "F");
2720  struct pair_t * pl = spice_find_property (def, "NL");
2721  nr_double_t len = 1e-3;
2722  if (pt != NULL) {
2723  // delay given
2724  len = spice_evaluate_value (pt->value) * C0;
2725  def->pairs = spice_del_property (def->pairs, pt);
2726  spice_set_property_value (def, "L", len);
2727  }
2728  else if (pf != NULL && pl != NULL) {
2729  // frequency and normalized length given
2730  nr_double_t f = spice_evaluate_value (pf->value);
2731  nr_double_t l = spice_evaluate_value (pl->value);
2732  def->pairs = spice_del_property (def->pairs, pf);
2733  def->pairs = spice_del_property (def->pairs, pl);
2734  len = C0 / f * l;
2735  spice_set_property_value (def, "L", len);
2736  }
2737  else if (pf != NULL) {
2738  // only frequency given, default normalized length
2739  nr_double_t f = spice_evaluate_value (pf->value);
2740  def->pairs = spice_del_property (def->pairs, pf);
2741  len = C0 / f * 0.25;
2742  spice_set_property_value (def, "L", len);
2743  }
2744  else {
2745  fprintf (stderr, "spice error, either TD or F required in "
2746  "lossless `%s' line \n", def->instance);
2747  spice_errors++;
2748  }
2749  }
2750  // post-process mutual inductors (transformer)
2751  if (!def->action && !strcmp (def->type, "Tr")) {
2752  if (1)
2753  root = spice_translate_coupled_x (root, def);
2754  else
2755  root = spice_translate_coupled (root, def);
2756  }
2757  // post-process general analysis options
2758  if (def->action && strstr (def->type, "OPT")) {
2759  struct value_t * val;
2760  if ((val = spice_find_property (def->values, "ABSTOL")) != NULL) {
2761  spice_add_property (root, "DC", "abstol", val->unit);
2762  spice_add_property (root, "TR", "abstol", val->unit);
2763  }
2764  if ((val = spice_find_property (def->values, "RELTOL")) != NULL) {
2765  spice_add_property (root, "DC", "reltol", val->unit);
2766  spice_add_property (root, "TR", "reltol", val->unit);
2767  }
2768  if ((val = spice_find_property (def->values, "VNTOL")) != NULL) {
2769  spice_add_property (root, "DC", "vntol", val->unit);
2770  spice_add_property (root, "TR", "vntol", val->unit);
2771  }
2772  if ((val = spice_find_property (def->values, "ITL1")) != NULL) {
2773  spice_add_property (root, "DC", "MaxIter", val->unit);
2774  }
2775  if ((val = spice_find_property (def->values, "ITL4")) != NULL) {
2776  spice_add_property (root, "TR", "MaxIter", val->unit);
2777  }
2778  }
2779  // post-process print and plot statements
2780  if ((def->action && !strcmp (def->type, "PRINT")) ||
2781  !strcmp (def->type, "PLOT")) {
2782  spice_collect_external_nodes (def);
2783  }
2784  // post-process untranslated netlist lines
2785  if (def->define == NULL) {
2786  def->text = spice_untranslated_text (def);
2787  }
2788  // remove values if possible
2789  spice_free_values (def);
2790  }
2791  return root;
2792 }
2793 
2794 /* The function translates special actions defined in the Spice
2795  netlist including the types of simulations. */
2796 static struct definition_t *
2797 spice_translate_action (struct definition_t * root,
2798  struct definition_t * def) {
2799  // translate transient analysis
2800  if (!strcasecmp (def->type, "TRAN")) {
2801  free (def->type);
2802  def->type = strdup ("TR");
2803  struct value_t * val;
2804  int i = 0;
2805  foreach_value (def->values, val) {
2806  switch (i++) {
2807  case 0:
2808  spice_append_pair (def, "Points", val->ident, 0);
2809  break;
2810  case 1:
2811  spice_append_pair (def, "Stop", val->ident, 0);
2812  break;
2813  case 2:
2814  spice_append_pair (def, "Start", val->ident, 0);
2815  break;
2816  case 3:
2817  break;
2818  }
2819  spice_value_done (val);
2820  }
2821  double v;
2822  v = spice_get_property_value (def, "Stop");
2823  v -= spice_get_property_value (def, "Start");
2824  v /= spice_get_property_value (def, "Points");
2825  v += 1;
2826  spice_set_property_value (def, "Points", v);
2827  }
2828  // translate AC analysis
2829  else if (!strcasecmp (def->type, "AC")) {
2830  struct value_t * val;
2831  char * type = NULL;
2832  int i = 0;
2833  foreach_value (def->values, val) {
2834  switch (i++) {
2835  case 0:
2836  type = strdup (val->ident);
2837  break;
2838  case 1:
2839  spice_append_pair (def, "Points", val->ident, 0);
2840  break;
2841  case 2:
2842  spice_append_pair (def, "Start", val->ident, 0);
2843  break;
2844  case 3:
2845  spice_append_pair (def, "Stop", val->ident, 0);
2846  break;
2847  }
2848  spice_value_done (val);
2849  }
2850  double v;
2851  v = spice_evaluate_points (&type,
2852  spice_get_property_value (def, "Start"),
2853  spice_get_property_value (def, "Stop"),
2854  spice_get_property_value (def, "Points"));
2855  spice_set_property_value (def, "Points", v + 1);
2856  spice_set_property_string (def, "Type", type);
2857  free (type);
2858  }
2859  // translate DC analysis
2860  else if (!strcasecmp (def->type, "DC")) {
2861  struct definition_t * para1 = NULL, * para2 = NULL;
2862  if (spice_count_values (def->values) >= 4) {
2863  para1 = spice_create_para (def);
2864  spice_set_property_string (para1, "Sim",
2865  spice_toupper (def->instance));
2866  if (spice_count_values (def->values) >= 4) {
2867  para2 = spice_create_para (def);
2868  spice_set_property_string (para2, "Sim",
2869  spice_toupper (para1->instance));
2870  }
2871  }
2872  if (para1) root = spice_add_definition (root, para1);
2873  if (para2) root = spice_add_definition (root, para2);
2874  }
2875  // translate subcircuit definition
2876  else if (!strcasecmp (def->type, "SUBCKT")) {
2877  free (def->type);
2878  def->type = strdup ("Def");
2879  def->sub = spice_checker_intern (def->sub);
2880  }
2881  // translate operating point analysis
2882  else if (!strcasecmp (def->type, "OP")) {
2883  free (def->type);
2884  def->type = strdup ("DC");
2885  spice_set_property_string (def, "saveOPs", "yes");
2886  }
2887  return root;
2888 }
2889 
2890 /* The following function translates the given definition 'sub' into a
2891  valid Qucs subcircuit instance. */
2892 static void spice_translate_subcircuit (struct definition_t * sub) {
2893  struct value_t * val;
2894  free (sub->type);
2895  sub->type = strdup ("Sub");
2896  foreach_value (sub->values, val) {
2897  if (val->hint & HINT_NAME) {
2898  spice_set_property_string (sub, "Type", val->ident);
2899  break;
2900  }
2901  }
2902 }
2903 
2904 /* The function returns a static string containing successive instance
2905  names for the nodeset functionality in Qucs. */
2906 static char * spice_create_intern_nodeset (void) {
2907  static int intern = 1;
2908  static char txt[32];
2909  sprintf (txt, "NS%d", intern++);
2910  return txt;
2911 }
2912 
2913 /* The following function translates the nodeset functionality defined
2914  by Spice into appropriate definitions for Qucs. */
2915 static struct definition_t *
2916 spice_translate_nodeset (struct definition_t * root,
2917  struct definition_t * def) {
2918  struct value_t * val;
2919  struct definition_t * node = def;
2920  free (def->type);
2921  def->type = strdup ("NodeSet");
2922  free (node->instance);
2923  node->instance = strdup (spice_create_intern_nodeset ());
2924  node->action = PROP_COMPONENT;
2925  foreach_value (def->values->next, val) {
2926  if (val->hint & HINT_NODE) {
2927  node->nodes = spice_translate_node (val->ident);
2928  }
2929  if (val->hint & HINT_NUMBER) {
2930  spice_append_pair (node, "U", val->ident, 1);
2931  }
2932  if (val->hint & HINT_NAME) {
2933  node = spice_create_definition (node, "NodeSet");
2934  root = spice_add_definition (root, node);
2935  free (node->instance);
2936  node->instance = strdup (spice_create_intern_nodeset ());
2937  }
2938  }
2939  return root;
2940 }
2941 
2942 /* This is the overall Spice netlist translator. It adjusts the list
2943  of definitions into usable structures. */
2944 static struct definition_t * spice_translator (struct definition_t * root) {
2945  for (struct definition_t * def = root; def != NULL; def = def->next) {
2946  if ((def->define = spice_find_definition (def->type)) != NULL) {
2947  strcpy (def->type, def->define->type);
2948  def->nodes = spice_get_nodes (def);
2949  def->pairs = spice_get_pairs (def);
2950  if (!def->action) { // handle normal components
2951  // devices
2952  if (!strcasecmp (def->type, "Q") || !strcasecmp (def->type, "M") ||
2953  !strcasecmp (def->type, "J") || !strcasecmp (def->type, "D") ||
2954  !strcasecmp (def->type, "S") || !strcasecmp (def->type, "R") ||
2955  !strcasecmp (def->type, "C")) {
2956  spice_translate_device (root, def);
2957  }
2958  // controlled sources
2959  if (!strcasecmp (def->type, "E") || !strcasecmp (def->type, "G")) {
2960  root = spice_translate_poly (root, def);
2961  }
2962  // controlled sources
2963  if (!strcasecmp (def->type, "C") || !strcasecmp (def->type, "L")) {
2964  root = spice_translate_poly_lc (root, def);
2965  }
2966  // voltage sources
2967  if (!strcasecmp (def->type, "V")) {
2968  root = spice_translate_source (root, def, 'U');
2969  }
2970  // current sources
2971  if (!strcasecmp (def->type, "I")) {
2972  root = spice_translate_source (root, def, 'I');
2973  }
2974  // subcircuits
2975  if (!strcasecmp (def->type, "X")) {
2976  spice_translate_subcircuit (def);
2977  }
2978  spice_translate_type (def);
2979  }
2980  else { // handle special actions (dot '.' commands)
2981  // nodeset functionality
2982  if (!strcasecmp (def->type, "NODESET") ||
2983  !strcasecmp (def->type, "IC")) {
2984  root = spice_translate_nodeset (root, def);
2985  }
2986  else {
2987  root = spice_translate_action (root, def);
2988  }
2989  }
2990  spice_fixup_definition (def);
2991  }
2992  else {
2993  // handle device description
2994  if (!strcasecmp (def->type, "MODEL")) {
2995  spice_add_Model (def);
2996  }
2997  }
2998  // remove values if possible
2999  spice_free_values (def);
3000  }
3001  return root;
3002 }
3003 
3004 /* TODO list for Spice Translator:
3005  - current sources
3006  - subcircuits
3007  - file includes
3008  - transmission lines
3009  - voltage dependent sources
3010  - current dependent sources
3011  - initial conditions
3012  - options (partly done)
3013  - mutual inductors (transformer)
3014  - mesfet if available in Qucs
3015  - other mosfet models if available in Qucs
3016  - three mutual inductors
3017  - current controlled switch (gyrator + voltage controlled switch)
3018  - single-frequency FM (using pm-modulator)
3019  - controlled E, G, F, and H poly sources
3020  - analog behavioural B, E, G, F, and H sources
3021  - piece-wise linear (PWL) voltage and current sources
3022  - temperature analysis (.TEMP)
3023  - temperature option (.OPTIONS TNOM=27)
3024  - non-linear L and C poly components
3025 */
3026 
3027 #if 0
3028 // My debugger...
3029 static void spice_lister (struct definition_t * root) {
3030  struct value_t * val;
3031  for (struct definition_t * def = root; def != NULL; def = def->next) {
3032  fprintf (stderr, "%s:%s", def->type, def->instance);
3033  for (val = def->values; val != NULL; val = val->next) {
3034  if (val->ident)
3035  fprintf (stderr, " %s[%d]", val->ident, val->hint);
3036  else
3037  fprintf (stderr, " %g[%d]", val->value, val->hint);
3038  }
3039  fprintf (stderr, "\n");
3040  }
3041 }
3042 #endif
3043 
3044 // Adjusts the hint value of the last entry in the value list.
3045 void spice_add_last_hint (struct value_t * val, int hint) {
3046  if (val == NULL) return;
3047  for (; val->next != NULL; val = val->next) ;
3048  val->hint |= hint;
3049 }
3050 
3051 // Adjusts the hint value of the last entry in the value list.
3052 void spice_set_last_hint (struct value_t * val, int hint) {
3053  if (val == NULL) return;
3054  for (; val->next != NULL; val = val->next) ;
3055  val->hint = hint;
3056 }
3057 
3058 /* This function is the overall spice checker and translator. */
3060 #if 0
3061  spice_lister (root);
3062 #endif
3063  root = spice_translator (root);
3064  root = spice_post_translator (root);
3065  return root;
3066 }
3067 
3068 /* This function is the overall spice checker and translator. */
3069 int spice_checker (void) {
3070  spice_errors = 0;
3071  definition_root = spice_checker_intern (definition_root);
3072  return spice_errors;
3073 }