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