My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
check_netlist.cpp
Go to the documentation of this file.
1 /*
2  * check_netlist.cpp - checker for the Qucs netlist
3  *
4  * Copyright (C) 2003-2009 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_netlist.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 
36 #include "logging.h"
37 #include "strlist.h"
38 #include "netdefs.h"
39 #include "equation.h"
40 #include "check_netlist.h"
41 #include "constants.h"
42 #include "environment.h"
43 #include "variable.h"
44 #include "module.h"
45 
46 /* Global definitions for parser and checker. */
47 struct definition_t * definition_root = NULL;
48 struct definition_t * subcircuit_root = NULL;
50 
51 /* The function counts the nodes in a definition line. */
52 static int checker_count_nodes (struct definition_t * def) {
53  int count = 0;
54  for (struct node_t * node = def->nodes; node != NULL; node = node->next)
55  count++;
56  return count;
57 }
58 
59 /* The function returns an available definition line for the given
60  type. If there is no such definition type the function returns
61  NULL. */
62 static struct define_t * checker_find_definition (char * type, int action) {
63  struct define_t * def = module::getModule (type);
64  if (def != NULL && action == def->action) return def;
65  return NULL;
66 }
67 
68 /* The function returns the number of properties in a definition line
69  specified by the given key. */
70 static int checker_find_property (const char * key, struct pair_t * pp) {
71  int count = 0;
72  while (pp != NULL) {
73  if (!strcmp (pp->key, key))
74  count++;
75  pp = pp->next;
76  }
77  return count;
78 }
79 
80 /* Checks if the given property key is either optional or required for
81  the given definition type and returns the type of the property. */
82 static int checker_is_property (struct define_t * available,
83  const char * key) {
84  int i;
85  for (i = 0; PROP_IS_PROP (available->required[i]); i++) {
86  if (!strcmp (available->required[i].key, key))
87  return available->required[i].type;
88  }
89  for (i = 0; PROP_IS_PROP (available->optional[i]); i++) {
90  if (!strcmp (available->optional[i].key, key))
91  return available->optional[i].type;
92  }
93  return PROP_NONE;
94 }
95 
96 /* Counts the number of definitions given by the specified type and
97  instance name in the definition list. */
98 static int checker_count_definition (struct definition_t * root,
99  const char * type, char * instance) {
100  int count = 0;
101  for (struct definition_t * def = root; def != NULL; def = def->next) {
102  if (!strcmp (def->type, type) && !strcmp (def->instance, instance)) {
103  if (++count > 1)
104  def->duplicate = 1;
105  }
106  }
107  return count;
108 }
109 
110 /* Returns the value for a given definition type, key and variable
111  identifier if it is in the list of definitions. Otherwise the
112  function returns NULL. */
113 static struct value_t * checker_find_variable (struct definition_t * root,
114  const char * type,
115  const char * key,
116  char * ident) {
117  struct pair_t * pair;
118  for (struct definition_t * def = root; def != NULL; def = def->next) {
119  if (!strcmp (def->type, type)) {
120  for (pair = def->pairs; pair != NULL; pair = pair->next) {
121  if (!strcmp (pair->key, key))
122  if (pair->value->ident != NULL && ident != NULL &&
123  strcmp (pair->value->ident, ident) == 0)
124  return pair->value;
125  }
126  }
127  }
128  return NULL;
129 }
130 
131 /* The function returns the appropriate value for a given key within
132  the given netlist definition if the value is a reference (a
133  string). If there is no such key value pair the function returns
134  NULL. */
135 static struct value_t * checker_find_reference (struct definition_t * def,
136  const char * key) {
137  struct pair_t * pair;
138  for (pair = def->pairs; pair != NULL; pair = pair->next) {
139  if (!strcmp (pair->key, key))
140  if (pair->value->ident != NULL)
141  return pair->value;
142  }
143  return NULL;
144 }
145 
146 /* The function looks for the given property key within the properties
147  of the given definition line and returns its value if the property
148  is not an identifier. Otherwise the function returns NULL. */
149 static struct value_t * checker_find_prop_value (struct definition_t * def,
150  const char * key) {
151  struct pair_t * pair;
152  for (pair = def->pairs; pair != NULL; pair = pair->next) {
153  if (!strcmp (pair->key, key))
154  if (pair->value->ident == NULL)
155  return pair->value;
156  }
157  return NULL;
158 }
159 
160 /* The function returns the number of properties in a definition line
161  specified by the given key. */
162 static int checker_find_property (struct definition_t * def,
163  const char * key) {
164  return checker_find_property (key, def->pairs);
165 }
166 
167 /* This function looks for the specified property 'key' in the given
168  definition and return its value (a string reference) if it is a
169  reference. Otherwise the function returns NULL and emits an
170  appropriate error message. */
171 static struct value_t * checker_validate_reference (struct definition_t * def,
172  const char * key) {
173  struct value_t * val;
174  if ((val = checker_find_reference (def, key)) == NULL) {
175  logprint (LOG_ERROR, "line %d: checker error, not a valid `%s' property "
176  "found in `%s:%s'\n", def->line, key, def->type, def->instance);
177  }
178  return val;
179 }
180 
181 /* This function checks whether the given definition is a known
182  microstrip component with a substrate definition. If the given
183  identifier equals this substrate definition then the function
184  returns the appropriate value. Otherwise it returns NULL. */
185 static struct value_t * checker_find_substrate (struct definition_t * def,
186  char * ident) {
187  struct value_t * val;
188  if (checker_is_property (def->define, "Subst") == PROP_STR) {
189  if ((val = checker_find_reference (def, "Subst")) != NULL) {
190  if (ident != NULL && !strcmp (val->ident, ident))
191  return val;
192  }
193  }
194  return NULL;
195 }
196 
197 /* Puts the given double value variable into an environment. */
198 static variable * checker_add_variable (environment * env,
199  char * var, int type, bool pass) {
200  variable * v = new variable (var);
201  eqn::constant * c = new eqn::constant (type);
202  switch (type) {
203  case TAG_DOUBLE:
204  c->d = 0.0; // initialize the variable
205  break;
206  case TAG_VECTOR:
207  c->v = new vector ();
208  break;
209  }
210  v->setConstant (c);
211  env->addVariable (v, pass);
212  return v;
213 }
214 
215 /* Resolves the variable of a property value. Returns non-zero on
216  success, otherwise zero. */
217 static int checker_resolve_variable (struct definition_t * root,
218  struct definition_t * def,
219  struct pair_t * pair, int type) {
220  struct value_t * val;
221  struct value_t * value = pair->value;
222  if (value->ident != NULL) {
223  int found = 0;
224  /* 1. find variable in parameter sweeps */
225  if ((val = checker_find_variable (root, "SW", "Param", value->ident))) {
226  /* add parameter sweep variable to environment */
227  if (!strcmp (def->type, "SW") && !strcmp (pair->key, "Param")) {
228  checker_add_variable (root->env, value->ident, TAG_DOUBLE, true);
229  }
230  /* mark both the variable identifier and the parameter sweep
231  variable to be actually variables */
232  val->var = TAG_DOUBLE;
233  value->var = TAG_DOUBLE;
234  found++;
235  }
236  /* 2. find analysis in parameter sweeps */
237  if ((val = checker_find_variable (root, "SW", "Sim", value->ident))) {
238  found++;
239  }
240  /* 3. find substrate in microstrip components */
241  if ((val = checker_find_substrate (def, value->ident))) {
242  value->subst = 1;
243  found++;
244  }
245  /* 4. find subcircuit definition in subcircuit components */
246  if ((val = checker_find_variable (root, "Sub", "Type", value->ident))) {
247  found++;
248  }
249  /* 5. find special identifiers in certain properties */
250  if (value->range) {
251  found++;
252  }
253  /* 6. find file reference in S-parameter file components */
254  if ((val = checker_find_variable (root, "SPfile", "File", value->ident))) {
255  found++;
256  }
257  /* 7. find variable in equation */
258  if (root->env) {
259  if (root->env->getChecker()->containsVariable (value->ident)) {
260  variable * v;
261  value->var = (type == PROP_LIST) ? TAG_VECTOR : TAG_DOUBLE;
262  if ((v = root->env->getVariable (value->ident)) == NULL) {
263  // put variable into the environment
264  checker_add_variable (root->env, value->ident, value->var, false);
265  }
266  found++;
267  }
268  }
269  /* 8. find file reference in file based sources */
270  if ((val = checker_find_variable (root, "Vfile", "File", value->ident))) {
271  found++;
272  }
273  if ((val = checker_find_variable (root, "Ifile", "File", value->ident))) {
274  found++;
275  }
276  /* 9. find property reference in the instance */
277  if (!found &&
278  checker_is_property (def->define, value->ident) != PROP_NONE) {
279  if (root->env) {
280 
281  // create reference variable names
282  char * txt = (char *)
283  malloc (strlen (def->instance) + 1 + strlen (value->ident) + 1);
284  sprintf (txt, "%s.%s", def->instance, value->ident);
285  char * ref = (char *)
286  malloc (strlen (def->instance) + 5 + strlen (value->ident) + 1);
287  sprintf (ref, "%s.%s.ref", def->instance, value->ident);
288 
289  // replace property string
290  free (value->ident);
291  value->ident = strdup (ref);
292  value->var = TAG_DOUBLE;
293 
294  // already done previously?
295  variable * v;
296  if ((v = root->env->getVariable (ref)) == NULL) {
297  // put variable into the environment
298  checker_add_variable (root->env, ref, TAG_DOUBLE, false);
299  // also add reference equation into environment
300  root->env->getChecker()->addReference ("#propref", ref, txt);
301  }
302 
303  // done
304  free (txt);
305  free (ref);
306  found++;
307  }
308  }
309  /* not found */
310  if (!found) {
311  logprint (LOG_ERROR, "line %d: checker error, no such variable `%s' "
312  "used in a `%s:%s' property\n", def->line, value->ident,
313  def->type, def->instance);
314  return 0;
315  }
316  }
317  return 1;
318 }
319 
320 /* Evaluates the unit scale in a property value. It adjusts the
321  actual value and omits the scale. The function returns non-zero
322  on success and zero otherwise. */
323 static int checker_evaluate_scale (struct value_t * value) {
324  double val = value->value, factor = 1.0;
325  char * scale;
326  if (value->scale != NULL) {
327  scale = value->scale;
328  switch (*scale) {
329  case 'E':
330  scale++; factor = 1e18; break;
331  case 'P':
332  scale++; factor = 1e15; break;
333  case 'T':
334  scale++; factor = 1e12; break;
335  case 'G':
336  scale++; factor = 1e9; break;
337  case 'M':
338  scale++; factor = 1e6; break;
339  case 'k':
340  scale++; factor = 1e3; break;
341  case 'm':
342  scale++;
343  if (*scale == 'i') {
344  scale++;
345  if (*scale == 'l') {
346  scale++; factor = 2.54e-5;
347  }
348  }
349  else
350  factor = 1e-3;
351  break;
352  case 'u':
353  scale++; factor = 1e-6; break;
354  case 'n':
355  scale++; factor = 1e-9; break;
356  case 'p':
357  scale++; factor = 1e-12; break;
358  case 'f':
359  scale++;
360  if (*scale == 't') {
361  scale++; factor = 0.3048;
362  }
363  else
364  factor = 1e-15;
365  break;
366  case 'a':
367  scale++; factor = 1e-18; break;
368  case 'd':
369  scale++;
370  if (*scale == 'B') {
371  scale++; val = pow (10.0, val / 10.0);
372  if (*scale == 'm') {
373  scale++; factor = 1e-3;
374  }
375  else if (*scale == 'u') {
376  scale++; factor = 1e-6;
377  }
378  }
379  break;
380  case 'i':
381  scale++;
382  if (*scale == 'n') {
383  scale++; factor = 2.54e-2;
384  }
385  break;
386  case 'y':
387  scale++;
388  if (*scale == 'd') {
389  scale++; factor = 0.9144;
390  }
391  break;
392  }
393  if (*scale != '\0') {
394  value->unit = strdup (scale);
395  }
396  free (value->scale);
397  value->scale = NULL;
398  }
399  value->value = val * factor;
400  return 1;
401 }
402 
403 /* The function returns the number of instances of the given type within
404  the list of definitions. */
405 static int checker_count_definitions (struct definition_t * root,
406  const char * type, int action) {
407  int count = 0;
408  for (struct definition_t * def = root; def != NULL; def = def->next) {
409  if (def->action == action) {
410  if (type == NULL)
411  count++;
412  else if (!strcmp (def->type, type))
413  count++;
414  }
415  }
416  return count;
417 }
418 
419 /* This function looks for the specified subcircuit type in the list
420  of available subcircuits and returns its definition. If there is
421  no such subcircuit the function returns NULL: */
422 static struct definition_t * checker_find_subcircuit (char * n) {
423  struct definition_t * def;
424  for (def = subcircuit_root; def != NULL; def = def->next)
425  if (n != NULL && !strcmp (def->instance, n)) return def;
426  return NULL;
427 }
428 
429 /* The function returns the subcircuit definition for the given
430  subcircuit instance. */
431 static struct definition_t *
432 checker_get_subcircuit (struct definition_t * def) {
433  struct value_t * val;
434  struct definition_t * sub = NULL;
435  if ((val = checker_find_reference (def, "Type")) != NULL)
436  sub = checker_find_subcircuit (val->ident);
437  return sub;
438 }
439 
440 // Global variable indicating cycles in subcircuit definitions.
441 static int checker_sub_cycles = 0;
442 
443 /* The following function returns the number of circuit instances
444  requiring a DC analysis (being nonlinear) in the list of definitions. */
445 static int checker_count_nonlinearities (struct definition_t * root) {
446  int count = 0;
447  struct definition_t * sub;
448  for (struct definition_t * def = root; def != NULL; def = def->next) {
449  if (def->nonlinear != 0) count++;
450  // also recurse into subcircuits if possible
451  if (checker_sub_cycles <= 0) {
452  if (!strcmp (def->type, "Sub")) {
453  if ((sub = checker_get_subcircuit (def)) != NULL) {
454  count += checker_count_nonlinearities (sub->sub);
455  }
456  }
457  }
458  }
459  return count;
460 }
461 
462 /* This function returns the number of action definitions with the
463  given instance name. */
464 static int checker_count_action (struct definition_t * root, char * instance) {
465  int count = 0;
466  for (struct definition_t * def = root; def != NULL; def = def->next) {
467  if (def->action == 1 && !strcmp (def->instance, instance))
468  count++;
469  }
470  return count;
471 }
472 
473 /* This (recursive) function detects any kind of cyclic definitions of
474  parameter sweeps for the given instance name. The string list
475  argument is used to pass the dependencies. The function returns
476  zero if the parameter sweep in non-cyclic. */
477 static int checker_validate_para_cycles (struct definition_t * root,
478  char * instance, strlist * deps) {
479  int errors = 0;
480  struct value_t * val;
481  for (struct definition_t * def = root; def != NULL; def = def->next) {
482  /* find the appropriate definition for the given instance */
483  if (def->action == 1 && !strcmp (def->instance, instance)) {
484  /* emit error message if the instance is already in the dependencies */
485  if (deps->contains (instance)) {
486  logprint (LOG_ERROR, "checker error, cyclic definition of `%s' "
487  "detected, involves: %s\n", instance, deps->toString ());
488  return ++errors;
489  }
490  deps->append (instance);
491  /* recurse into parameter sweeps */
492  if (!strcmp (def->type, "SW")) {
493  if ((val = checker_find_reference (def, "Sim")) != NULL) {
494  return checker_validate_para_cycles (root, val->ident, deps);
495  }
496  }
497  }
498  }
499  return errors;
500 }
501 
502 /* This function validates each parameter sweep within the list of
503  definitions and return non-zero on errors. Emits appropriate error
504  messages. */
505 static int checker_validate_para (struct definition_t * root) {
506  int errors = 0;
507  struct value_t * val;
508  for (struct definition_t * def = root; def != NULL; def = def->next) {
509  /* find parameter sweep */
510  if (def->action == 1 && !strcmp (def->type, "SW")) {
511  /* the 'Sim' property must be an identifier */
512  if ((val = checker_validate_reference (def, "Sim")) == NULL) {
513  errors++;
514  }
515  else {
516  /* check for self-referring sweeps */
517  if (!strcmp (def->instance, val->ident)) {
518  logprint (LOG_ERROR, "line %d: checker error, definition `%s:%s' "
519  "refers to itself\n", def->line, def->type, def->instance);
520  errors++;
521  }
522  /* look for the referred analysis action definition */
523  if (checker_count_action (root, val->ident) != 1) {
524  logprint (LOG_ERROR, "line %d: checker error, no such action `%s' "
525  "found as referred in `%s:%s'\n", def->line, val->ident,
526  def->type, def->instance);
527  errors++;
528  }
529  /* finally detect cyclic definitions */
530  strlist * deps = new strlist ();
531  errors += checker_validate_para_cycles (root, val->ident, deps);
532  delete deps;
533  }
534  }
535  }
536  return errors;
537 }
538 
539 /* This function returns the next port definition in the given list of
540  definitions or NULL if there is no such definition. */
541 static struct definition_t * checker_find_port (struct definition_t * root) {
542  for (struct definition_t * def = root; def != NULL; def = def->next) {
543  if (def->action == PROP_COMPONENT && !strcmp (def->type, "Pac")) {
544  return def;
545  }
546  }
547  return NULL;
548 }
549 
550 /* This function checks whether the port numbers for the S-parameter
551  analysis are unique or not. It returns zero on success and
552  non-zero if it detected duplicate entries. */
553 static int checker_validate_ports (struct definition_t * root) {
554  int p, errors = 0;
555  struct value_t * val;
556  struct definition_t * port, * def = root;
557  const char * prop = "Num";
558  while ((def = checker_find_port (def)) != NULL) {
559  if ((val = checker_find_prop_value (def, prop)) != NULL) {
560  p = (int) val->value;
561  port = root;
562  while ((port = checker_find_port (port)) != NULL) {
563  if (port != def) {
564  if ((val = checker_find_prop_value (port, prop)) != NULL) {
565  if (p == (int) val->value) {
566  logprint (LOG_ERROR, "line %d: checker error, `%s' definitions "
567  "with duplicate `%s=%d' property found: `%s:%s' and "
568  "`%s:%s'\n", def->line, def->type, prop, p, def->type,
569  def->instance, port->type, port->instance);
570  errors++;
571  }
572  }
573  }
574  port = port->next;
575  }
576  }
577  def = def->next;
578  }
579  return errors;
580 }
581 
582 /* The following function checks whether the parametric sweeps in the
583  netlist are valid or not. It returns zero on success and non-zero
584  otherwise. */
585 static int checker_validate_lists (struct definition_t * root) {
586  int errors = 0;
587  // go through each definition
588  for (struct definition_t * def = root; def != NULL; def = def->next) {
589  /* sweeps possible in parameter sweep, ac-analysis and
590  s-parameter analysis */
591  if (def->action == 1 && (!strcmp (def->type, "SW") ||
592  !strcmp (def->type, "AC") ||
593  !strcmp (def->type, "SP"))) {
594  struct value_t * val = checker_find_reference (def, "Type");
595  char * type = val->ident;
596  // list of constant values and constant values
597  if (type && (!strcmp (type, "const") || !strcmp (type, "list"))) {
598  // property 'Values' is required
599  if ((val = checker_find_prop_value (def, "Values")) == NULL) {
600  if (!strcmp (type, "const")) {
601  if ((val = checker_validate_reference (def, "Values")) == NULL) {
602  errors++;
603  }
604  }
605  else {
606  logprint (LOG_ERROR, "line %d: checker error, required property "
607  "`%s' not found in `%s:%s'\n", def->line, "Values",
608  def->type, def->instance);
609  errors++;
610  }
611  }
612  else {
613  if (!strcmp (type, "const")) {
614  // in constant sweeps only one value allowed
615  if (val->next != NULL) {
616  logprint (LOG_ERROR, "line %d: checker error, value of `%s' "
617  "needs to be a single constant value in `%s:%s', no "
618  "lists possible\n", def->line, "Values",
619  def->type, def->instance);
620  errors++;
621  }
622  val->var = TAG_UNKNOWN;
623  }
624  if (!strcmp (type, "list")) {
625  val->var = TAG_VECTOR;
626  }
627  // check and evaluate the unit scale in a value list
628  for (; val != NULL; val = val->next) {
629  if (!checker_evaluate_scale (val))
630  errors++;
631  }
632  }
633  // property 'Start' is invalid
634  if (checker_find_property (def, "Start") > 0) {
635  logprint (LOG_ERROR, "line %d: checker error, extraneous property "
636  "`%s' is invalid in `%s:%s'\n", def->line, "Start",
637  def->type, def->instance);
638  errors++;
639  }
640  // property 'Stop' is invalid
641  if (checker_find_property (def, "Stop") > 0) {
642  logprint (LOG_ERROR, "line %d: checker error, extraneous property "
643  "`%s' is invalid in `%s:%s'\n", def->line, "Stop",
644  def->type, def->instance);
645  errors++;
646  }
647  // property 'Points' is also invalid
648  if (checker_find_property (def, "Points") > 0) {
649  logprint (LOG_ERROR, "line %d: checker error, extraneous property "
650  "`%s' is invalid in `%s:%s'\n", def->line, "Points",
651  def->type, def->instance);
652  errors++;
653  }
654  }
655  // linearly and logarithmically stepped sweeps
656  else if (type && (!strcmp (type, "lin") || !strcmp (type, "log"))) {
657  // property 'Start' required
658  if (checker_find_property (def, "Start") <= 0) {
659  logprint (LOG_ERROR, "line %d: checker error, required property "
660  "`%s' not found in `%s:%s'\n", def->line, "Start",
661  def->type, def->instance);
662  errors++;
663  }
664  // property 'Stop' required
665  if (checker_find_property (def, "Stop") <= 0) {
666  logprint (LOG_ERROR, "line %d: checker error, required property "
667  "`%s' not found in `%s:%s'\n", def->line, "Stop",
668  def->type, def->instance);
669  errors++;
670  }
671  // property 'Points' is also required
672  if (checker_find_property (def, "Points") <= 0) {
673  logprint (LOG_ERROR, "line %d: checker error, required property "
674  "`%s' not found in `%s:%s'\n", def->line, "Points",
675  def->type, def->instance);
676  errors++;
677  }
678  // property 'Values' is invalid
679  if (checker_find_property (def, "Values") > 0) {
680  logprint (LOG_ERROR, "line %d: checker error, extraneous property "
681  "`%s' is invalid in `%s:%s'\n", def->line, "Values",
682  def->type, def->instance);
683  errors++;
684  }
685  }
686  }
687  }
688  return errors;
689 }
690 
691 /* This function checks the actions to be taken in the netlist. It
692  returns zero on success, non-zero otherwise. */
693 static int checker_validate_actions (struct definition_t * root) {
694  int a, c, n, errors = 0;
695  if ((n = checker_count_definitions (root, NULL, 1)) < 1) {
696  logprint (LOG_ERROR, "checker error, no actions defined: nothing to do\n");
697  errors++;
698  }
699  else {
700  // check requirements for s-parameter analysis
701  if ((a = checker_count_definitions (root, "SP", 1)) >= 1) {
702  if ((n = checker_count_definitions (root, "Pac", 0)) < 1) {
703  logprint (LOG_ERROR, "checker error, %d `Pac' definitions found, at "
704  "least 1 required\n", n);
705  errors++;
706  }
707  }
708  // count analyses requiring a DC solution
709  a += checker_count_definitions (root, "AC", 1);
710  // check dc-analysis requirements
711  c = checker_count_nonlinearities (root);
712  n = checker_count_definitions (root, "DC", 1);
713  if (n > 1) {
714  logprint (LOG_ERROR, "checker error, the .DC action is defined %dx, "
715  "single or none required\n", n);
716  errors++;
717  }
718  if (a >= 1 && c >= 1 && n < 1) {
719  logprint (LOG_ERROR, "checker error, a .DC action is required for this "
720  "circuit definition (accounted %d non-linearities)\n", c);
721  errors++;
722  }
723  }
724  errors += checker_validate_para (root);
725  errors += checker_validate_ports (root);
726  errors += checker_validate_lists (root);
727  return errors;
728 }
729 
730 /* This function checks the validity of each microstrip component and
731  its substrate and model references. It returns zero on success,
732  emit error messages if necessary and returns non-zero on errors. */
733 static int checker_validate_strips (struct definition_t * root) {
734  int errors = 0;
735  struct value_t * val;
736  for (struct definition_t * def = root; def != NULL; def = def->next) {
737  if (!def->action) {
738  /* find components with substrate property */
739  if (checker_is_property (def->define, "Subst") == PROP_STR) {
740  /* check validity of 'Subst' property */
741  if ((val = checker_validate_reference (def, "Subst")) == NULL) {
742  errors++;
743  }
744  else {
745  if (checker_count_definition (root, "SUBST", val->ident) != 1) {
746  logprint (LOG_ERROR, "line %d: checker error, no such substrate "
747  "`%s' found as specified in `%s:%s'\n", def->line,
748  val->ident, def->type, def->instance);
749  errors++;
750  }
751  }
752  /* check validity of 'Model' property */
753 #if DISABLE_FOR_NOW /* ThinkME!!! */
754  if ((val = checker_validate_reference (def, "Model")) == NULL) {
755  errors++;
756  }
757 #endif
758  }
759  }
760  }
761  return errors;
762 }
763 
764 /* This function counts the number of occurrences of the given node
765  name in the given netlist definition root. */
766 static int checker_count_nodes (struct definition_t * root, char * n) {
767  int count = 0;
768  struct node_t * node;
769  for (struct definition_t * def = root; def != NULL; def = def->next) {
770  if (!def->action && !def->nodeset) {
771  for (node = def->nodes; node != NULL; node = node->next)
772  if (!strcmp (node->node, n)) count++;
773  }
774  }
775  return count;
776 }
777 
778 /* The function identifies duplicate nodesets for the same node which
779  is not allowed. It returns the number of duplications. */
780 static int checker_count_nodesets (struct definition_t * root, char * n) {
781  int count = 0;
782  for (struct definition_t * def = root; def != NULL; def = def->next) {
783  if (def->nodeset && !def->duplicate) {
784  char * node = def->nodes->node;
785  if (!strcmp (node, n)) {
786  if (++count > 1) def->duplicate = 1;
787  }
788  }
789  }
790  return count;
791 }
792 
793 /* The following function checks whether the nodes specified by the
794  nodeset functionality is valid in its current scope. It does not
795  check across subcircuit boundaries. */
796 static int checker_validate_nodesets (struct definition_t * root) {
797  int errors = 0;
798  for (struct definition_t * def = root; def != NULL; def = def->next) {
799  if (def->nodeset && checker_count_nodes (def) == 1) {
800  char * node = def->nodes->node;
801  if (checker_count_nodes (root, node) <= 0) {
802  logprint (LOG_ERROR, "line %d: checker error, no such node `%s' found "
803  "as referenced by `%s:%s'\n", def->line, node, def->type,
804  def->instance);
805  errors++;
806  }
807  if (checker_count_nodesets (root, node) > 1) {
808  logprint (LOG_ERROR, "line %d: checker error, the node `%s' is not "
809  "uniquely defined by `%s:%s'\n", def->line, node, def->type,
810  def->instance);
811  errors++;
812  }
813  }
814  }
815  return errors;
816 }
817 
818 /* This function should be called after the netlist and the equation
819  list have been checked. It verifies that parameter sweep
820  definitions and equation variable identifiers are unique. The
821  function returns zero on success and non-zero otherwise. */
822 static int netlist_checker_variables_intern (struct definition_t * root,
823  environment * env) {
824  int errors = 0, pos;
825  struct value_t * para, * ref;
826  strlist * eqnvars = env->getChecker()->variables ();
827  strlist * instances = new strlist ();
828  strlist * vars = new strlist ();
829  strlist * refs = new strlist ();
830  // go through list of netlist definitions
831  for (struct definition_t * def = root; def != NULL; def = def->next) {
832  // find parameters sweeps
833  if (def->action == 1 && !strcmp (def->type, "SW")) {
834  para = checker_find_reference (def, "Param");
835  ref = checker_find_reference (def, "Sim");
836  if (para != NULL && ref != NULL) {
837  // check whether sweep variable collides with equations
838  if (eqnvars && eqnvars->contains (para->ident)) {
839  logprint (LOG_ERROR, "checker error, equation variable `%s' "
840  "already defined by `%s:%s'\n", para->ident,
841  def->type, def->instance);
842  errors++;
843  }
844  // check for duplicate parameter names in parameter sweeps, but
845  // allow them in same order sweeps
846  if ((pos = vars->index (para->ident)) != -1) {
847  if (strcmp (ref->ident, refs->get (pos))) {
848  logprint (LOG_ERROR, "checker error, variable `%s' in `%s:%s' "
849  "already defined by `%s:%s'\n", para->ident, def->type,
850  def->instance, def->type, instances->get (pos));
851  errors++;
852  }
853  }
854  // check for duplicate simulations in parameter sweeps (same order
855  // sweep) and allow same parameter name only
856  if ((pos = refs->index (ref->ident)) != -1) {
857  if (strcmp (para->ident, vars->get (pos))) {
858  logprint (LOG_ERROR, "checker error, conflicting variables `%s' "
859  "in `%s:%s' and `%s' in `%s:%s' for `%s'\n",
860  para->ident, def->type, def->instance,
861  vars->get (pos), def->type, instances->get (pos),
862  ref->ident);
863  errors++;
864  }
865  }
866  // collect parameter sweep variables for the above two checks
867  instances->add (def->instance);
868  vars->add (para->ident);
869  refs->add (ref->ident);
870  }
871  }
872  }
873  delete eqnvars;
874  delete refs;
875  delete vars;
876  delete instances;
877  return errors;
878 }
879 
880 /* This is the overall variable checker for the parsed netlist. See
881  the above function for details. */
883  return netlist_checker_variables_intern (definition_root, env);
884 }
885 
886 /* The function checks whether the given key-value combination is
887  inside the allowed range defined by the given property definition
888  and returns the number of error or zero otherwise. */
889 static int checker_value_in_prop_range (char * instance, struct define_t * def,
890  struct pair_t * pp,
891  struct property_t * prop) {
892  int errors = 0;
893  // check values
894  if (PROP_IS_VAL (*prop)) {
895  if (!PROP_IS_LST (*prop)) {
896  // lists of values possible?
897  if (pp->value->next != NULL) {
899  "checker error, value of `%s' needs to be "
900  "a single value in `%s:%s', no lists possible\n",
901  pp->key, def->type, instance);
902  errors++;
903  }
904  }
905  else {
906  // a value list
907  struct value_t * val = pp->value;
908  val->var = TAG_VECTOR;
909  // check and evaluate the unit scale in a value list
910  for (; val != NULL; val = val->next) {
911  if (!checker_evaluate_scale (val))
912  errors++;
913  }
914  }
915  // check range of all values
916  if (PROP_HAS_RANGE (*prop)) {
917  struct value_t * val = pp->value;
918  if (val->ident) {
919  /* no range checking on variable identifier */
921  "checker notice, value of `%s' (variable `%s') could be "
922  "out of range `%c%g,%g%c' in `%s:%s'\n",
923  pp->key, val->ident, prop->range.il, prop->range.l,
924  prop->range.h, prop->range.ih, def->type, instance);
925  val = NULL;
926  }
927  for (; val != NULL; val = val->next) {
928  int rerror = 0;
929  if (prop->range.il == '[' && (val->value < prop->range.l))
930  rerror++;
931  if (prop->range.il == ']' && !(val->value > prop->range.l))
932  rerror++;
933  if (prop->range.ih == '[' && !(val->value < prop->range.h))
934  rerror++;
935  if (prop->range.ih == ']' && (val->value > prop->range.h))
936  rerror++;
937  if (rerror) {
939  "checker error, value of `%s' (%g) is out of "
940  "range `%c%g,%g%c' in `%s:%s'\n",
941  pp->key, val->value, prop->range.il, prop->range.l,
942  prop->range.h, prop->range.ih, def->type, instance);
943  errors++;
944  }
945  }
946  }
947  // check fraction of integers
948  if (PROP_IS_INT (*prop)) {
949  double integral;
950  if (modf (pp->value->value, &integral) != 0) {
952  "checker error, value of `%s' (%g) needs to be "
953  "an integer in `%s:%s'\n",
954  pp->key, pp->value->value, def->type, instance);
955  errors++;
956  }
957  }
958  }
959  // check identifiers
960  else {
961  // no identifier given
962  if (pp->value->ident == NULL) {
964  "checker error, value of `%s' (%g) needs to be "
965  "an identifier in `%s:%s'\n",
966  pp->key, pp->value->value, def->type, instance);
967  errors++;
968  }
969  // check identifier range
970  else {
971  if (PROP_HAS_STR (*prop)) {
972  int i, found = 0;
973  char range[256]; sprintf (range, "[");
974  for (i = 0; prop->range.str[i]; i++) {
975  strcat (range, prop->range.str[i]);
976  strcat (range, ",");
977  if (!strcmp (prop->range.str[i], pp->value->ident)) found++;
978  }
979  if (!found) {
980  range[strlen (range) - 1] = ']';
982  "checker error, value of `%s' (%s) needs to be "
983  "in %s in `%s:%s'\n",
984  pp->key, pp->value->ident, range, def->type, instance);
985  errors++;
986  }
987  else pp->value->range = 1;
988  }
989  }
990  }
991  return errors;
992 }
993 
994 /* The function checks whether the given key-value combination being
995  part of the available definition is inside the allowed range and
996  returns zero if not. Otherwise the function returns non-zero. */
997 static int checker_value_in_range (char * instance, struct define_t * def,
998  struct pair_t * pp) {
999  int i, errors = 0;
1000  // go through required properties
1001  for (i = 0; PROP_IS_PROP (def->required[i]); i++) {
1002  if (!strcmp (def->required[i].key, pp->key)) {
1003  errors += checker_value_in_prop_range (instance, def, pp,
1004  &def->required[i]);
1005  }
1006  }
1007  // go through optional properties
1008  for (i = 0; PROP_IS_PROP (def->optional[i]); i++) {
1009  if (!strcmp (def->optional[i].key, pp->key)) {
1010  errors += checker_value_in_prop_range (instance, def, pp,
1011  &def->optional[i]);
1012  }
1013  }
1014  return errors ? 0 : 1;
1015 }
1016 
1017 /* The function determines the subcircuit definitions defined in the
1018  original netlist and builds an appropriate subcircuit definition
1019  list. It returns the given definition list with the subcircuits
1020  removed. */
1021 static struct definition_t *
1022 checker_build_subcircuits (struct definition_t * root) {
1023  struct definition_t * def, * next, * prev;
1024  for (prev = NULL, def = root; def != NULL; def = next) {
1025  next = def->next;
1026  if (!strcmp (def->type, "Def")) {
1027  if (prev) {
1028  prev->next = next;
1029  } else {
1030  root = next;
1031  }
1032  def->sub = checker_build_subcircuits (def->sub);
1033  def->next = subcircuit_root;
1034  subcircuit_root = def;
1035  }
1036  else prev = def;
1037  }
1038  return root;
1039 }
1040 
1041 /* The function produces a copy of the given circuit definition and
1042  marks it as a copy. The node definition are not included within
1043  the copy. */
1044 static struct definition_t *
1045 checker_copy_subcircuit (struct definition_t * sub) {
1046  struct definition_t * copy;
1047  copy = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
1048  copy->action = sub->action;
1049  copy->nonlinear = sub->nonlinear;
1050  copy->substrate = sub->substrate;
1051  copy->nodeset = sub->nodeset;
1052  copy->define = sub->define;
1053  copy->pairs = sub->pairs;
1054  copy->ncount = sub->ncount;
1055  copy->type = strdup (sub->type);
1056  copy->copy = 1;
1057  return copy;
1058 }
1059 
1060 /* This function translates the node definitions of the given
1061  subcircuit element 'sub'. The translation is based upon the node
1062  definitions of the subcircuit 'type' and the instance 'inst' of
1063  such a subcircuit. The translated nodes are saved in an extra
1064  'xlate' field of each node of the subcircuit element 'sub'. */
1065 static void checker_xlat_subcircuit_nodes (struct definition_t * type,
1066  struct definition_t * inst,
1067  struct definition_t * sub) {
1068  struct node_t * n, * ninst, * ntype;
1069  int i;
1070  // go through nodes of the subcircuit 'type' and 'inst'
1071  for (i = 1, ntype = type->nodes, ninst = inst->nodes; ntype != NULL;
1072  ntype = ntype->next, ninst = ninst->next, i++) {
1073  for (n = sub->nodes; n != NULL; n = n->next) {
1074  /* check whether a node in the subcircuit element 'sub' corresponds
1075  with the 'type', then assign the 'inst's node name */
1076  if (!strcmp (n->node, ntype->node)) {
1077  n->xlate = strdup (ninst->node);
1078  n->xlatenr = i;
1079  }
1080  }
1081  }
1082 }
1083 
1084 /* The function creates a subcircuit node name consisting of the given
1085  arguments. If the given 'instances' is NULL it is left out. The
1086  caller is responsible to free() the returned string. */
1087 static char * checker_subcircuit_node (char * type, char * instances,
1088  char * instance, char * node) {
1089  char * txt = (char *)
1090  calloc (1, strlen (type) + strlen (instance) + strlen (node) +
1091  (instances ? strlen (instances) : 0) + 4);
1092  if (instances)
1093  sprintf (txt, "%s.%s.%s.%s", type, instances, instance, node);
1094  else
1095  sprintf (txt, "%s.%s.%s", type, instance, node);
1096  return txt;
1097 }
1098 
1099 /* The function reverses the order of the given node list and returns
1100  the reversed list. */
1101 struct node_t * netlist_reverse_nodes (struct node_t * nodes) {
1102  struct node_t * root, * next;
1103  for (root = NULL; nodes != NULL; nodes = next) {
1104  next = nodes->next;
1105  nodes->next = root;
1106  root = nodes;
1107  }
1108  return root;
1109 }
1110 
1111 /* This function assigns new node names to the subcircuit element
1112  'copy' based upon the previous node translation between the
1113  subcircuit 'type' and the instance 'inst' of this type. The global
1114  'gnd' node is not touched. */
1115 static void
1116 checker_copy_subcircuit_nodes (struct definition_t * type,
1117  struct definition_t * inst,
1118  struct definition_t * sub,
1119  struct definition_t * copy,
1120  char * instances) {
1121  struct node_t * n, * ncopy, * root = NULL;
1122 
1123  // go through the list of the subcircuit element's 'sub' nodes
1124  for (n = sub->nodes; n != NULL; n = n->next) {
1125 
1126  // create new node based upon the node translation
1127  ncopy = (struct node_t *) calloc (sizeof (struct node_t), 1);
1128  ncopy->xlatenr = n->xlatenr;
1129  if (n->xlate) { // translated node
1130  if (instances == NULL)
1131  ncopy->node = strdup (n->xlate);
1132  else
1133  ncopy->node = NULL; // leave it blank yet, indicates translation
1134  }
1135  else if (!strcmp (n->node, "gnd")) { // ground node
1136  ncopy->node = strdup (n->node);
1137  }
1138  else if (n->node[strlen (n->node) - 1] == '!') { // global node
1139  ncopy->node = strdup (n->node);
1140  }
1141  else { // internal subcircuit element node
1142  ncopy->node = checker_subcircuit_node (type->instance, instances,
1143  inst->instance, n->node);
1144  }
1145  // chain the new node list
1146  ncopy->next = root;
1147  root = ncopy;
1148  }
1149 
1150  /* and finally reverse the created node list and assign it to the
1151  subcircuit element's 'copy' */
1152  copy->nodes = netlist_reverse_nodes (root);
1153 }
1154 
1155 // Returns the node at the given position.
1156 static struct node_t * checker_get_circuit_node (struct node_t * root, int n) {
1157  for (int i = 1; i < n; i++) {
1158  root = root->next;
1159  assert (root != NULL);
1160  }
1161  return root;
1162 }
1163 
1164 // The function cleans the translated nodes of a subcircuit template.
1165 static void checker_cleanup_xlat_nodes (struct definition_t * sub) {
1166  for (struct node_t * n = sub->nodes; n != NULL; n = n->next) {
1167  if (n->xlate) free (n->xlate);
1168  n->xlate = NULL;
1169  n->xlatenr = 0;
1170  }
1171 }
1172 
1173 /* The function is used to assign the nodes of the 'copy' subcircuit
1174  element which were left blank intentionally by the element copy in
1175  order to indicate that it is an external node. Again, if the
1176  current node translation indicates an external node it is blanked
1177  again, otherwise the node gets a unique internal name. If the
1178  'instances' list is NULL, then this indicates the root circuit list
1179  and node translations are done though they are 'external'. */
1180 static void
1181 checker_copy_circuit_nodes (struct definition_t * type,
1182  struct definition_t * inst,
1183  struct definition_t * sub,
1184  struct definition_t * copy,
1185  char * instances) {
1186  struct node_t * n, * ncopy;
1187 
1188  // go through the list of the subcircuit element's 'copy' nodes
1189  for (ncopy = copy->nodes; ncopy != NULL; ncopy = ncopy->next) {
1190  // these NULL nodes have intentionally been blanked
1191  if (ncopy->node == NULL) {
1192  assert (ncopy->xlatenr != 0);
1193  // get translated node
1194  n = checker_get_circuit_node (sub->nodes, ncopy->xlatenr);
1195  ncopy->xlatenr = n->xlatenr;
1196  if (n->xlate) { // translated node
1197  if (instances == NULL)
1198  // external node indicated by no instances given
1199  ncopy->node = strdup (n->xlate);
1200  else
1201  ncopy->node = NULL; // keep blank
1202  }
1203  else if (!strcmp (n->node, "gnd")) { // global ground node
1204  ncopy->node = strdup (n->node);
1205  }
1206  else if (n->node[strlen (n->node) - 1] == '!') { // other global node
1207  ncopy->node = strdup (n->node);
1208  }
1209  else { // internal subcircuit element node
1210  ncopy->node = checker_subcircuit_node (type->instance, instances,
1211  inst->instance, n->node);
1212  }
1213  }
1214  }
1215 }
1216 
1217 /* This function returns the last entry of the given list of
1218  definitions or NULL if there is no such element. */
1219 static struct definition_t *
1220 checker_find_last_definition (struct definition_t * root) {
1221  for (struct definition_t * def = root; def != NULL; def = def->next)
1222  if (def->next == NULL) return def;
1223  return NULL;
1224 }
1225 
1226 /* Based upon the the given subcircuit instance identifier list the
1227  function returns a "." - concatenated string or NULL. */
1228 static char * checker_subcircuit_instance_list (strlist * instances) {
1229  if (instances && instances->length () > 0)
1230  return instances->toString (".");
1231  return NULL;
1232 }
1233 
1234 /* The function creates a subcircuit instance name consisting of the
1235  given arguments. If the given 'instances' is NULL it is left out.
1236  The caller is responsible to free() the returned string. */
1237 static char * checker_subcircuit_instance (char * type, char * instances,
1238  char * instance, char * base) {
1239  char * txt = (char *)
1240  calloc (1, strlen (type) + strlen (instance) + strlen (base) +
1241  (instances ? strlen (instances) : 0) + 4);
1242  if (instances)
1243  sprintf (txt, "%s.%s.%s.%s", type, instances, instance, base);
1244  else
1245  sprintf (txt, "%s.%s.%s", type, instance, base);
1246  return txt;
1247 }
1248 
1249 /* This function produces a copy of the given subcircuit 'type'
1250  containing the subcircuit elements. Based upon the instance 'inst'
1251  definitions (node names and instance name) it assign new element
1252  instances and node names. The function returns a NULL terminated
1253  circuit element list in reverse order. */
1254 static struct definition_t *
1255 checker_copy_subcircuits (struct definition_t * type,
1256  struct definition_t * inst, strlist * * instances,
1257  environment * parent) {
1258  struct definition_t * def, * copy;
1259  struct definition_t * root = NULL;
1260  strlist * instcopy;
1261  char * list;
1262 
1263  // create environment for subcircuit instance
1264  environment * child = new environment (*(type->env));
1265  parent->addChild (child);
1266 
1267  // put instance properties into subcircuit environment
1268  for (struct pair_t * pair = inst->pairs; pair != NULL; pair = pair->next) {
1269  // anything else than the 'Type'
1270  if (strcmp (pair->key, "Type")) {
1271  if (pair->value->ident == NULL) {
1272  // simple value
1273  child->setDoubleConstant (pair->key, pair->value->value);
1274  child->setDouble (pair->key, pair->value->value);
1275  }
1276  else {
1277  // reference to variable in upper environment
1278  child->setDoubleReference (pair->key, pair->value->ident);
1279  }
1280  }
1281  }
1282 
1283  // go through element list of subcircuit
1284  for (def = type->sub; def != NULL; def = def->next) {
1285 
1286  // translate the node list
1287  checker_xlat_subcircuit_nodes (type, inst, def);
1288 
1289  // allow recursive subcircuits
1290  if (!strcmp (def->type, "Sub")) {
1291  // get subcircuit template definition
1292  struct definition_t * sub = checker_get_subcircuit (def);
1293  // create a copy of the current subcircuit instance list
1294  if ((*instances) == NULL) (*instances) = new strlist ();
1295  instcopy = new strlist (*(*instances));
1296  // append instance name to recursive instance list
1297  (*instances)->append (inst->instance);
1298  copy = checker_copy_subcircuits (sub, def, instances, child);
1299  // put the expanded definitions into the sublist
1300  if (copy) {
1301  list = checker_subcircuit_instance_list (instcopy);
1302  // assign blanked node names to each subcircuit
1303  for (struct definition_t * c = copy; c != NULL; c = c->next) {
1304  checker_copy_circuit_nodes (type, inst, def, c, list);
1305  }
1306  // append the copies to the subcircuit list
1307  struct definition_t * last = checker_find_last_definition (copy);
1308  last->next = root;
1309  root = copy;
1310  }
1311  // restore original instance list
1312  delete *instances;
1313  *instances = instcopy;
1314  }
1315  else {
1316  // element copy
1317  copy = checker_copy_subcircuit (def);
1318  // assign new instance name to the element
1319  list = checker_subcircuit_instance_list (*instances);
1320  copy->instance =
1321  checker_subcircuit_instance (type->instance, list,
1322  inst->instance, def->instance);
1323  copy->subcircuit = strdup (type->instance);
1324  // assign node list
1325  checker_copy_subcircuit_nodes (type, inst, def, copy, list);
1326  // apply environment
1327  copy->env = child;
1328  // chain definition (circuit) list
1329  copy->next = root;
1330  root = copy;
1331  }
1332 
1333  // cleanup translated nodes
1334  checker_cleanup_xlat_nodes (def);
1335  }
1336 
1337  // try giving child environment a unique name
1338  strlist * icopy = new strlist ();
1339  icopy->append (type->instance);
1340  icopy->append (*(instances));
1341  icopy->append (inst->instance);
1342  child->setName (icopy->toString ("."));
1343  delete icopy;
1344 
1345  return root;
1346 }
1347 
1348 /* The function checks whether the subcircuit 'instance' with the
1349  subcircuit 'type' is defined in cycles. It recursively goes
1350  through the definitions and emits an appropriate error message if
1351  necessary. The function returns zero if there are no cycles
1352  detected and non-zero with cycles found. */
1353 static int checker_validate_sub_cycles (struct definition_t * root,
1354  char * type, char * instance,
1355  strlist * * deps) {
1356  int errors = 0, error;
1357  struct value_t * val;
1358 
1359  /* emit an appropriate error message if the subcircuit type is already
1360  in the dependencies */
1361  if ((*deps)->contains (type)) {
1362  logprint (LOG_ERROR, "checker error, cyclic definition of `%s:%s' "
1363  "detected, involves: %s\n",
1364  type, instance, (*deps)->toString ());
1365  return ++errors;
1366  }
1367  (*deps)->append (type);
1368 
1369  // create temporary list of subcircuit types already tested
1370  strlist * checked = new strlist ();
1371  // go through the list of circuit elements of the subcircuit
1372  for (struct definition_t * def = root->sub; def != NULL; def = def->next) {
1373  // find the appropriate definitions
1374  if (!strcmp (def->type, "Sub")) {
1375  // recurse into subcircuit instances
1376  if ((val = checker_find_reference (def, "Type")) != NULL) {
1377  if (!checked->contains (val->ident)) { // only if not already checked
1378  struct definition_t * sub;
1379  checked->append (val->ident);
1380  // copy current dependencies
1381  strlist * copy = new strlist (*(*deps));
1382  // validate subcircuit
1383  sub = checker_find_subcircuit (val->ident);
1384  if (sub != NULL) // if possible
1385  error = checker_validate_sub_cycles (sub, sub->instance,
1386  instance, deps);
1387  else
1388  error = 1;
1389  // on errors: go on
1390  if (error) {
1391  errors += error;
1392  delete copy;
1393  }
1394  // no errors: restore original dependencies
1395  else {
1396  delete *deps;
1397  *deps = copy;
1398  }
1399  }
1400  }
1401  }
1402  }
1403  delete checked;
1404  return errors;
1405 }
1406 
1407 /* This function dynamically creates a circuit definition based on a
1408  given subcircuit definition including type, number of nodes and the
1409  properties. */
1410 static struct define_t * netlist_create_define (struct definition_t * def) {
1411  int o, r;
1412  struct pair_t * p;
1413  struct define_t * d =
1414  (struct define_t *) calloc (sizeof (struct define_t), 1);
1415  d->type = strdup (def->instance);
1416  d->nodes = checker_count_nodes (def);
1417  d->action = PROP_COMPONENT;
1418 
1419  // determine number of required and optional parameters
1420  for (o = r = 0, p = def->pairs; p != NULL; p = p->next) {
1421  if (p->value == NULL)
1422  r++;
1423  else
1424  o++;
1425  }
1426  d->required =
1427  (struct property_t *) calloc (sizeof (struct property_t), r + 2);
1428  d->optional =
1429  (struct property_t *) calloc (sizeof (struct property_t), o + 1);
1430 
1431  // fill in parameters
1432  for (o = r = 0, p = def->pairs; p != NULL; p = p->next) {
1433  if (p->value == NULL) {
1434  // required
1435  d->required[r].key = strdup (p->key);
1436  d->required[r].type = PROP_REAL;
1437  d->required[r].defaultval.d = PROP_NO_VAL;
1438  d->required[r].defaultval.s = PROP_NO_STR;
1439  d->required[r].range.il = '.';
1440  d->required[r].range.l = 0;
1441  d->required[r].range.h = 0;
1442  d->required[r].range.ih = '.';
1443  r++;
1444  } else {
1445  // optional
1446  d->optional[o].key = strdup (p->key);
1447  d->optional[o].type = PROP_REAL;
1448  d->optional[o].defaultval.d = p->value->value;
1449  d->optional[o].defaultval.s = PROP_NO_STR;
1450  d->optional[o].range.il = '.';
1451  d->optional[o].range.l = 0;
1452  d->optional[o].range.h = 0;
1453  d->optional[o].range.ih = '.';
1454  o++;
1455  }
1456  }
1457 
1458  // extra required
1459  d->required[r].key = strdup ("Type");
1460  d->required[r].type = PROP_STR;
1461  d->required[r].defaultval.d = PROP_NO_VAL;
1462  d->required[r].defaultval.s = PROP_NO_STR;
1463  d->required[r].range.il = '.';
1464  d->required[r].range.l = 0;
1465  d->required[r].range.h = 0;
1466  d->required[r].range.ih = '.';
1467  return d;
1468 }
1469 
1470 /* The function destroys the given circuit definition which must have
1471  been dynamically created before. */
1472 static void netlist_free_define (struct define_t * d) {
1473  int i;
1474  struct property_t * p;
1475  free ((char *) d->type);
1476  // free required properties
1477  for (i = 0, p = d->required; p[i].key != NULL; i++) {
1478  free ((char *) p[i].key);
1479  }
1480  free (d->required);
1481  // free optional properties
1482  for (i = 0, p = d->optional; p[i].key != NULL; i++) {
1483  free ((char *) p[i].key);
1484  }
1485  free (d->optional);
1486  free (d);
1487 }
1488 
1489 /* The function checks the presence of required and optional
1490  properties as well as their content in the given definition. It
1491  returns zero on success and non-zero otherwise. */
1492 static int checker_validate_properties (struct definition_t * root,
1493  struct definition_t * def,
1494  struct define_t * available) {
1495  struct pair_t * pair;
1496  int i, n, errors = 0;
1497 
1498  /* check whether the required properties are given */
1499  for (i = 0; PROP_IS_PROP (available->required[i]); i++) {
1500  n = checker_find_property (available->required[i].key, def->pairs);
1501  if (n != 1) {
1502  logprint (LOG_ERROR, "line %d: checker error, required property "
1503  "`%s' occurred %dx in `%s:%s'\n", def->line,
1504  available->required[i].key, n, def->type, def->instance);
1505  errors++;
1506  }
1507  }
1508  /* check whether the optional properties are given zero/once */
1509  for (i = 0; PROP_IS_PROP (available->optional[i]); i++) {
1510  n = checker_find_property (available->optional[i].key, def->pairs);
1511  if (n >= 2) {
1512  logprint (LOG_ERROR, "line %d: checker error, optional property "
1513  "`%s' occurred %dx in `%s:%s'\n", def->line,
1514  available->optional[i].key, n, def->type, def->instance);
1515  errors++;
1516  }
1517  }
1518 
1519  /* check the property content */
1520  for (pair = def->pairs; pair != NULL; pair = pair->next) {
1521  /* check whether properties are either required or optional */
1522  int type = checker_is_property (available, pair->key);
1523  if (type == PROP_NONE) {
1524  if (strcmp (def->type, "Def")) {
1525  logprint (LOG_ERROR,
1526  "line %d: checker error, extraneous property `%s' is "
1527  "invalid in `%s:%s'\n", def->line,
1528  pair->key, def->type, def->instance);
1529  errors++;
1530  }
1531  }
1532  // do not check zero-length lists
1533  if (pair->value != NULL) {
1534  /* check and evaluate the unit scale in a property */
1535  if (!checker_evaluate_scale (pair->value))
1536  errors++;
1537  /* check whether properties are in range */
1538  if (!checker_value_in_range (def->instance, available, pair)) {
1539  errors++;
1540  }
1541  /* check variables in properties */
1542  if (!checker_resolve_variable (root, def, pair, type))
1543  errors++;
1544  }
1545  }
1546  return errors;
1547 }
1548 
1549 /* This function is used by the netlist checker to validate the
1550  subcircuits. It returns zero with no errors and non-zero on
1551  errors. */
1552 static int checker_validate_subcircuits (struct definition_t * root) {
1553  int errors = 0;
1554  // go through list of definitions
1555  for (struct definition_t * def = root; def != NULL; def = def->next) {
1556  // check subcircuit instances
1557  if (!strcmp (def->type, "Sub")) {
1558  struct value_t * val;
1559  // validate the 'Type' reference
1560  if ((val = checker_validate_reference (def, "Type")) == NULL) {
1561  errors++;
1562  }
1563  else {
1564  // find an appropriate subcircuit type
1565  struct definition_t * sub = checker_find_subcircuit (val->ident);
1566  if (sub == NULL) {
1567  logprint (LOG_ERROR, "line %d: checker error, no such subcircuit "
1568  "`%s' found as referred in `%s:%s'\n", def->line,
1569  val->ident, def->type, def->instance);
1570  errors++;
1571  }
1572  else {
1573  // check the number of nodes of the instance and the type
1574  int n1 = checker_count_nodes (def);
1575  int n2 = checker_count_nodes (sub);
1576  if (n1 != n2) {
1577  logprint (LOG_ERROR, "line %d: checker error, subcircuit type "
1578  "`%s' requires %d nodes in `%s:%s', found %d\n",
1579  def->line, sub->instance, n2,
1580  def->type, def->instance, n1);
1581  errors++;
1582  }
1583  // check the subcircuit instance properties
1584  struct define_t * available = netlist_create_define (sub);
1585  errors += checker_validate_properties (root, def, available);
1586  netlist_free_define (available);
1587  // and finally check for cyclic definitions
1588  strlist * deps = new strlist ();
1589  int err = checker_validate_sub_cycles (sub, sub->instance,
1590  def->instance, &deps);
1591  errors += err;
1592  checker_sub_cycles = err;
1593  delete deps;
1594  }
1595  }
1596  }
1597  }
1598  return errors;
1599 }
1600 
1601 /* Deletes node list of a definition. */
1602 static void netlist_free_nodes (struct node_t * node) {
1603  struct node_t * n;
1604  for (; node != NULL; node = n) {
1605  n = node->next;
1606  free (node->node);
1607  free (node);
1608  }
1609 }
1610 
1611 /* The following function free()'s the given value. */
1612 static void netlist_free_value (struct value_t * value) {
1613  if (value->ident) free (value->ident);
1614  if (value->unit) free (value->unit);
1615  if (value->scale) free (value->scale);
1616  free (value);
1617 }
1618 
1619 /* Deletes pair list of a definition. */
1620 static void netlist_free_pairs (struct pair_t * pp) {
1621  struct pair_t * np;
1622  for (; pp != NULL; pp = np) {
1623  np = pp->next;
1624  struct value_t * nv, * value;
1625  for (value = pp->value; value != NULL; value = nv) {
1626  nv = value->next;
1627  netlist_free_value (value);
1628  }
1629  free (pp->key);
1630  free (pp);
1631  }
1632 }
1633 
1634 /* Deletes the given definition. */
1635 static void netlist_free_definition (struct definition_t * def) {
1636  netlist_free_nodes (def->nodes);
1637  if (!def->copy) netlist_free_pairs (def->pairs);
1638  if (def->subcircuit) free (def->subcircuit);
1639  free (def->type);
1640  free (def->instance);
1641  free (def);
1642 }
1643 
1644 /* The function removes the given definition 'cand' from the
1645  definition root. It returns the new definition root. */
1646 struct definition_t *
1648  struct definition_t * cand) {
1649  struct definition_t * prev;
1650  if (cand == root) {
1651  root = cand->next;
1652  netlist_free_definition (cand);
1653  }
1654  else {
1655  // find previous to the candidate to be deleted
1656  for (prev = root; prev != NULL && prev->next != cand; prev = prev->next) ;
1657  if (prev != NULL) {
1658  prev->next = cand->next;
1659  netlist_free_definition (cand);
1660  }
1661  }
1662  return root;
1663 }
1664 
1665 /* The function expands the subcircuits within the given definition
1666  list and returns the expanded list with the subcircuit definitions
1667  removed. */
1668 static struct definition_t *
1669 checker_expand_subcircuits (struct definition_t * root, environment * parent) {
1670  struct definition_t * def, * sub, * copy, * next, * prev;
1671  strlist * instances = NULL;
1672 
1673  // go through the list of definitions
1674  for (prev = NULL, def = root; def != NULL; def = next) {
1675  next = def->next;
1676  // is this a subcircuit instance definition ?
1677  if (!strcmp (def->type, "Sub")) {
1678  // get the subcircuit type definition
1679  sub = checker_get_subcircuit (def);
1680  // and make a copy of it
1681  copy = checker_copy_subcircuits (sub, def, &instances, parent);
1682  if (instances) { delete instances; instances = NULL; }
1683  // remove the subcircuit instance from the original list
1684  if (prev) {
1685  prev->next = next;
1686  } else {
1687  root = next;
1688  }
1689  netlist_free_definition (def);
1690  // put the expanded definitions into the netlist
1691  if (copy) {
1692  struct definition_t * last = checker_find_last_definition (copy);
1693  last->next = root;
1694  if (!prev) prev = last;
1695  root = copy;
1696  }
1697  }
1698  // component in the root environment
1699  else {
1700  prev = def;
1701  def->env = parent;
1702  }
1703  }
1704  return root;
1705 }
1706 
1707 /* This function is the checker routine for a parsed netlist. It
1708  returns zero on success or non-zero if the parsed netlist contained
1709  errors. */
1710 static int netlist_checker_intern (struct definition_t * root) {
1711  struct definition_t * def;
1712  struct define_t * available;
1713  int n, errors = 0;
1714 
1715  /* go through all definitions */
1716  for (def = root; def != NULL; def = def->next) {
1717 
1718  /* check whether the definition type is known */
1719  available = checker_find_definition (def->type, def->action);
1720  if (available == NULL) {
1721  logprint (LOG_ERROR, "line %d: checker error, invalid definition type "
1722  "`%s'\n", def->line, def->type);
1723  errors++;
1724  }
1725  else {
1726  /* mark nodeset definitions */
1727  def->nodeset = !strcmp (def->type, "NodeSet") ? 1 : 0;
1728  /* mark nonlinear circuit definitions */
1729  def->nonlinear = available->nonlinear;
1730  /* mark substrate definitions */
1731  def->substrate = available->substrate;
1732  /* save available definition */
1733  def->define = available;
1734  /* check whether the number of nodes is correct and save the
1735  number of given nodes */
1736  n = def->ncount = checker_count_nodes (def);
1737  if (available->nodes == PROP_NODES) {
1738  if (n < 1) {
1739  logprint (LOG_ERROR,
1740  "line %d: checker error, at least 1 node required in "
1741  "`%s:%s', found %d\n", def->line, def->type,
1742  def->instance, n);
1743  errors++;
1744  }
1745  }
1746  else if (available->nodes != n) {
1747  logprint (LOG_ERROR,
1748  "line %d: checker error, %d node(s) required in `%s:%s', "
1749  "found %d\n", def->line,
1750  available->nodes, def->type, def->instance, n);
1751  errors++;
1752  }
1753  /* check the properties except for subcircuits */
1754  if (strcmp (def->type, "Sub")) {
1755  errors += checker_validate_properties (root, def, available);
1756  }
1757  }
1758  /* check the number of definitions */
1759  n = checker_count_definition (root, def->type, def->instance);
1760  if (n != 1 && def->duplicate == 0) {
1761  logprint (LOG_ERROR, "checker error, found %d definitions of `%s:%s'\n",
1762  n, def->type, def->instance);
1763  errors++;
1764  }
1765  }
1766  /* check microstrip definitions */
1767  errors += checker_validate_strips (root);
1768  /* check subcircuit definitions */
1769  errors += checker_validate_subcircuits (root);
1770  /* check nodeset definitions */
1771  errors += checker_validate_nodesets (root);
1772  return errors;
1773 }
1774 
1775 #if DEBUG
1776 /* Debug function: Prints value representation. */
1777 static void netlist_list_value (struct value_t * value) {
1778  if (value == NULL)
1779  logprint (LOG_STATUS, "[]");
1780  else if (value->ident)
1781  logprint (LOG_STATUS, "%s", value->ident);
1782  else if (value->next) {
1783  logprint (LOG_STATUS, "[");
1784  for (; value != NULL; value = value->next)
1785  logprint (LOG_STATUS, "%g%s", value->value, value->next ? ";" : "");
1786  logprint (LOG_STATUS, "]");
1787  } else {
1788  logprint (LOG_STATUS, "%g", value->value);
1789  if (value->scale)
1790  logprint (LOG_STATUS, "%s", value->scale);
1791  if (value->unit)
1792  logprint (LOG_STATUS, "%s", value->unit);
1793  }
1794 }
1795 
1796 /* Debug function: Prints definition list representation. */
1797 static void netlist_lister (struct definition_t * root, const char * prefix) {
1798  struct definition_t * def;
1799  struct node_t * node;
1800  struct pair_t * pair;
1801  for (def = root; def != NULL; def = def->next) {
1802  logprint (LOG_STATUS, "%s%s:%s", prefix, def->type, def->instance);
1803  for (node = def->nodes; node != NULL; node = node->next) {
1804  logprint (LOG_STATUS, " %s", node->node);
1805  }
1806  for (pair = def->pairs; pair != NULL; pair = pair->next) {
1807  logprint (LOG_STATUS, " %s=\"", pair->key);
1808  netlist_list_value (pair->value);
1809  logprint (LOG_STATUS, "\"");
1810  }
1811  logprint (LOG_STATUS, "\n");
1812  }
1813 }
1814 
1815 /* Debug function: Prints the overall netlist representation. */
1816 void netlist_list (void) {
1817  struct definition_t * def;
1818  logprint (LOG_STATUS, "subcircuit %s\n", "root");
1819  netlist_lister (definition_root, " ");
1820  for (def = subcircuit_root; def != NULL; def = def->next) {
1821  logprint (LOG_STATUS, "subcircuit %s\n", def->instance);
1822  netlist_lister (def->sub, " ");
1823  }
1824 }
1825 #endif /* DEBUG */
1826 
1827 /* The function logs the content of the current netlist by telling how
1828  many instances of which kind of components are used in the netlist. */
1829 void netlist_status (void) {
1830  struct define_t * def;
1831  struct definition_t * cir;
1832  int count;
1833  logprint (LOG_STATUS, "netlist content\n");
1835  for (it = qucs::hashiterator<module> (module::modules); *it; ++it) {
1836  def = it.currentVal()->definition;
1837  for (count = 0, cir = definition_root; cir != NULL; cir = cir->next) {
1838  if (!strcmp (def->type, cir->type)) count++;
1839  }
1840  if (count > 0) {
1841  logprint (LOG_STATUS, " %5d %s instances\n", count, def->type);
1842  }
1843  }
1844 }
1845 
1846 /* The function builds the equation list for a given list of
1847  definition and removes the definition containing the equations from
1848  the list. */
1849 static struct definition_t *
1850 checker_build_equations (struct definition_t * root, eqn::node ** eroot) {
1851  struct definition_t * def, * next, * prev;
1852  eqn::node * eqns, * last;
1853  *eroot = NULL;
1854  // go through list of definitions
1855  for (prev = NULL, def = root; def != NULL; def = next) {
1856  next = def->next;
1857  if (!strcmp (def->type, "Eqn")) {
1858  // rechain definition list
1859  if (prev) {
1860  prev->next = next;
1861  } else {
1862  root = next;
1863  }
1864  // append equations
1865  eqns = (eqn::node *) def->eqns;
1866  last = eqn::checker::lastEquation (eqns);
1867  last->setNext (*eroot);
1868  *eroot = eqns;
1869  // free this definition
1870  netlist_free_definition (def);
1871  }
1872  else prev = def;
1873  }
1874  return root;
1875 }
1876 
1877 /* The function creates an environment for the given definition root
1878  including equation checker and solver. */
1879 static void checker_setup_env (struct definition_t * root,
1880  environment * env, eqn::node * eqns) {
1881  // create equation checker
1882  eqn::checker * checkee = new eqn::checker ();
1883  // pass equations to the checker
1884  checkee->setEquations (eqns);
1885  // add constants to the list of equations
1886  checkee->constants ();
1887  // pass checker
1888  env->setChecker (checkee);
1889  // create equation solver
1890  eqn::solver * solvee = new eqn::solver (checkee);
1891  // pass solver
1892  env->setSolver (solvee);
1893  // apply environment to the netlist root
1894  if (root) root->env = env;
1895 }
1896 
1897 /* Adds the arguments of a subcircuit into the equation checker of the
1898  given environment. */
1899 static void checker_subcircuit_args (struct definition_t * def,
1900  environment * env) {
1901  for (struct pair_t * pair = def->pairs; pair != NULL; pair = pair->next) {
1902  // anything else than the 'Type'
1903  if (strcmp (pair->key, "Type")) {
1904  // put it into the equation checker
1905  env->getChecker()->addDouble ("#subcircuit",
1906  pair->key, pair->value->value);
1907  // also put it into the environment
1908  variable * v = checker_add_variable (env, pair->key, TAG_DOUBLE, true);
1909  v->getConstant()->d = pair->value->value;
1910  }
1911  }
1912 }
1913 
1914 /* This is the global netlist checker. It returns zero on success and
1915  non-zero on errors. */
1917  int errors = 0;
1918  eqn::node * eqns;
1919  struct definition_t * def;
1920 
1921  // create top-level environment
1922  env_root = new environment (env->getName ());
1923  // create the subcircuit list
1924  definition_root = checker_build_subcircuits (definition_root);
1925  // get equation list
1926  definition_root = checker_build_equations (definition_root, &eqns);
1927  // setup the root environment
1928  checker_setup_env (definition_root, env_root, eqns);
1929  // check list of subcircuits
1930  errors += netlist_checker_intern (subcircuit_root);
1931  // check global netlist
1932  errors += netlist_checker_intern (definition_root);
1933  // check equations in root
1934  env_root->setDefinitions (definition_root);
1935  errors += env_root->equationChecker (0);
1936  env_root->setDefinitions (NULL);
1937 
1938  // then check each subcircuit list
1939  for (def = subcircuit_root; def != NULL; def = def->next) {
1940  // get equation list
1941  def->sub = checker_build_equations (def->sub, &eqns);
1942  // setup the subcircuit environment
1943  environment * subenv = new environment (def->instance);
1944  env_root->addChild (subenv);
1945  checker_setup_env (def, subenv, eqns);
1946  if (def->sub) def->sub->env = subenv;
1947  // add subcircuit parameters to equations
1948  checker_subcircuit_args (def, subenv);
1949  // check subcircuit netlist
1950  errors += netlist_checker_intern (def->sub);
1951  // check equations in subcircuit
1952  subenv->setDefinitions (def->sub);
1953  errors += subenv->equationChecker (0);
1954  subenv->setDefinitions (NULL);
1955  }
1956 
1957  // check actions
1958  errors += checker_validate_actions (definition_root);
1959 
1960  if (!errors) {
1961  // create actual root environment
1962  env->copy (*env_root);
1963  // and finally expand the subcircuits into the global netlist
1964  definition_root = checker_expand_subcircuits (definition_root, env);
1965  }
1966 
1967  return errors ? -1 : 0;
1968 }
1969 
1970 /* The function deletes the given definition list. */
1971 static void netlist_destroy_intern (struct definition_t * root) {
1972  struct definition_t * def, * next;
1973  for (def = root; def != NULL; def = next) {
1974  next = def->next;
1975  netlist_free_definition (def);
1976  }
1977 }
1978 
1979 /* Deletes all available definition lists. */
1980 void netlist_destroy (void) {
1981  netlist_destroy_intern (definition_root);
1982  for (struct definition_t * def = subcircuit_root; def; def = def->next) {
1983  netlist_destroy_intern (def->sub);
1984  }
1985  netlist_destroy_intern (subcircuit_root);
1986  definition_root = subcircuit_root = NULL;
1988 }
1989 
1990 /* Delete root environment(s) if necessary. */
1991 void netlist_destroy_env (void) {
1992  if (env_root != NULL) {
1993  delete env_root;
1994  env_root = NULL;
1995  }
1996 }