Qucs-core
0.0.19
|
00001 /* 00002 * check_netlist.cpp - checker for the Qucs netlist 00003 * 00004 * Copyright (C) 2003-2009 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <cmath> 00033 #include <assert.h> 00034 #include <float.h> 00035 00036 #include "logging.h" 00037 #include "strlist.h" 00038 #include "netdefs.h" 00039 #include "equation.h" 00040 #include "check_netlist.h" 00041 #include "constants.h" 00042 #include "environment.h" 00043 #include "variable.h" 00044 #include "module.h" 00045 00046 using namespace qucs; 00047 using namespace qucs::eqn; 00048 00049 /* Global definitions for parser and checker. */ 00050 struct definition_t * definition_root = NULL; 00051 struct definition_t * subcircuit_root = NULL; 00052 environment * env_root = NULL; 00053 00054 /* The function counts the nodes in a definition line. */ 00055 static int checker_count_nodes (struct definition_t * def) 00056 { 00057 int count = 0; 00058 for (struct node_t * node = def->nodes; node != NULL; node = node->next) 00059 count++; 00060 return count; 00061 } 00062 00063 /* The function returns an available definition line for the given 00064 type. If there is no such definition type the function returns 00065 NULL. */ 00066 static struct define_t * checker_find_definition (char * type, int action) 00067 { 00068 struct define_t * def = module::getModule (type); 00069 if (def != NULL && action == def->action) return def; 00070 return NULL; 00071 } 00072 00073 /* The function returns the number of properties in a definition line 00074 specified by the given key. */ 00075 static int checker_find_property (const char * key, struct pair_t * pp) 00076 { 00077 int count = 0; 00078 while (pp != NULL) 00079 { 00080 if (!strcmp (pp->key, key)) 00081 count++; 00082 pp = pp->next; 00083 } 00084 return count; 00085 } 00086 00087 /* Checks if the given property key is either optional or required for 00088 the given definition type and returns the type of the property. */ 00089 static int checker_is_property (struct define_t * available, 00090 const char * key) 00091 { 00092 int i; 00093 for (i = 0; PROP_IS_PROP (available->required[i]); i++) 00094 { 00095 if (!strcmp (available->required[i].key, key)) 00096 return available->required[i].type; 00097 } 00098 for (i = 0; PROP_IS_PROP (available->optional[i]); i++) 00099 { 00100 if (!strcmp (available->optional[i].key, key)) 00101 return available->optional[i].type; 00102 } 00103 return PROP_NONE; 00104 } 00105 00106 /* Counts the number of definitions given by the specified type and 00107 instance name in the definition list. */ 00108 static int checker_count_definition (struct definition_t * root, 00109 const char * type, char * instance) 00110 { 00111 int count = 0; 00112 for (struct definition_t * def = root; def != NULL; def = def->next) 00113 { 00114 if (!strcmp (def->type, type) && !strcmp (def->instance, instance)) 00115 { 00116 if (++count > 1) 00117 def->duplicate = 1; 00118 } 00119 } 00120 return count; 00121 } 00122 00123 /* Returns the value for a given definition type, key and variable 00124 identifier if it is in the list of definitions. Otherwise the 00125 function returns NULL. */ 00126 static struct value_t * checker_find_variable (struct definition_t * root, 00127 const char * type, 00128 const char * key, 00129 char * ident) 00130 { 00131 struct pair_t * pair; 00132 for (struct definition_t * def = root; def != NULL; def = def->next) 00133 { 00134 if (!strcmp (def->type, type)) 00135 { 00136 for (pair = def->pairs; pair != NULL; pair = pair->next) 00137 { 00138 if (!strcmp (pair->key, key)) 00139 if (pair->value->ident != NULL && ident != NULL && 00140 strcmp (pair->value->ident, ident) == 0) 00141 return pair->value; 00142 } 00143 } 00144 } 00145 return NULL; 00146 } 00147 00148 /* The function returns the appropriate value for a given key within 00149 the given netlist definition if the value is a reference (a 00150 string). If there is no such key value pair the function returns 00151 NULL. */ 00152 static struct value_t * checker_find_reference (struct definition_t * def, 00153 const char * key) 00154 { 00155 struct pair_t * pair; 00156 for (pair = def->pairs; pair != NULL; pair = pair->next) 00157 { 00158 if (!strcmp (pair->key, key)) 00159 if (pair->value->ident != NULL) 00160 return pair->value; 00161 } 00162 return NULL; 00163 } 00164 00165 /* The function looks for the given property key within the properties 00166 of the given definition line and returns its value if the property 00167 is not an identifier. Otherwise the function returns NULL. */ 00168 static struct value_t * checker_find_prop_value (struct definition_t * def, 00169 const char * key) 00170 { 00171 struct pair_t * pair; 00172 for (pair = def->pairs; pair != NULL; pair = pair->next) 00173 { 00174 if (!strcmp (pair->key, key)) 00175 if (pair->value->ident == NULL) 00176 return pair->value; 00177 } 00178 return NULL; 00179 } 00180 00181 /* The function returns the number of properties in a definition line 00182 specified by the given key. */ 00183 static int checker_find_property (struct definition_t * def, 00184 const char * key) 00185 { 00186 return checker_find_property (key, def->pairs); 00187 } 00188 00189 /* This function looks for the specified property 'key' in the given 00190 definition and return its value (a string reference) if it is a 00191 reference. Otherwise the function returns NULL and emits an 00192 appropriate error message. */ 00193 static struct value_t * checker_validate_reference (struct definition_t * def, 00194 const char * key) 00195 { 00196 struct value_t * val; 00197 if ((val = checker_find_reference (def, key)) == NULL) 00198 { 00199 logprint (LOG_ERROR, "line %d: checker error, not a valid `%s' property " 00200 "found in `%s:%s'\n", def->line, key, def->type, def->instance); 00201 } 00202 return val; 00203 } 00204 00205 /* This function checks whether the given definition is a known 00206 microstrip component with a substrate definition. If the given 00207 identifier equals this substrate definition then the function 00208 returns the appropriate value. Otherwise it returns NULL. */ 00209 static struct value_t * checker_find_substrate (struct definition_t * def, 00210 char * ident) 00211 { 00212 struct value_t * val; 00213 if (checker_is_property (def->define, "Subst") == PROP_STR) 00214 { 00215 if ((val = checker_find_reference (def, "Subst")) != NULL) 00216 { 00217 if (ident != NULL && !strcmp (val->ident, ident)) 00218 return val; 00219 } 00220 } 00221 return NULL; 00222 } 00223 00224 /* Puts the given double value variable into an environment. */ 00225 static variable * checker_add_variable (environment * env, 00226 char * var, int type, bool pass) 00227 { 00228 variable * v = new variable (var); 00229 eqn::constant * c = new eqn::constant (type); 00230 switch (type) 00231 { 00232 case TAG_DOUBLE: 00233 c->d = 0.0; // initialize the variable 00234 break; 00235 case TAG_VECTOR: 00236 c->v = new qucs::vector (); 00237 break; 00238 } 00239 v->setConstant (c); 00240 env->addVariable (v, pass); 00241 return v; 00242 } 00243 00244 /* Resolves the variable of a property value. Returns non-zero on 00245 success, otherwise zero. */ 00246 static int checker_resolve_variable (struct definition_t * root, 00247 struct definition_t * def, 00248 struct pair_t * pair, int type) 00249 { 00250 struct value_t * val; 00251 struct value_t * value = pair->value; 00252 if (value->ident != NULL) 00253 { 00254 int found = 0; 00255 /* 1. find variable in parameter sweeps */ 00256 if ((val = checker_find_variable (root, "SW", "Param", value->ident))) 00257 { 00258 /* add parameter sweep variable to environment */ 00259 if (!strcmp (def->type, "SW") && !strcmp (pair->key, "Param")) 00260 { 00261 checker_add_variable (root->env, value->ident, TAG_DOUBLE, true); 00262 } 00263 /* mark both the variable identifier and the parameter sweep 00264 variable to be actually variables */ 00265 val->var = TAG_DOUBLE; 00266 value->var = TAG_DOUBLE; 00267 found++; 00268 } 00269 /* 2. find analysis in parameter sweeps */ 00270 if ((val = checker_find_variable (root, "SW", "Sim", value->ident))) 00271 { 00272 found++; 00273 } 00274 /* 3. find substrate in microstrip components */ 00275 if ((val = checker_find_substrate (def, value->ident))) 00276 { 00277 value->subst = 1; 00278 found++; 00279 } 00280 /* 4. find subcircuit definition in subcircuit components */ 00281 if ((val = checker_find_variable (root, "Sub", "Type", value->ident))) 00282 { 00283 found++; 00284 } 00285 /* 5. find special identifiers in certain properties */ 00286 if (value->range) 00287 { 00288 found++; 00289 } 00290 /* 6. find file reference in S-parameter file components */ 00291 if ((val = checker_find_variable (root, "SPfile", "File", value->ident))) 00292 { 00293 found++; 00294 } 00295 /* 7. find variable in equation */ 00296 if (root->env) 00297 { 00298 if (root->env->getChecker()->containsVariable (value->ident)) 00299 { 00300 variable * v; 00301 value->var = (type == PROP_LIST) ? TAG_VECTOR : TAG_DOUBLE; 00302 if ((v = root->env->getVariable (value->ident)) == NULL) 00303 { 00304 // put variable into the environment 00305 checker_add_variable (root->env, value->ident, value->var, false); 00306 } 00307 found++; 00308 } 00309 } 00310 /* 8. find file reference in file based sources */ 00311 if ((val = checker_find_variable (root, "Vfile", "File", value->ident))) 00312 { 00313 found++; 00314 } 00315 if ((val = checker_find_variable (root, "Ifile", "File", value->ident))) 00316 { 00317 found++; 00318 } 00319 /* 9. find property reference in the instance */ 00320 if (!found && 00321 checker_is_property (def->define, value->ident) != PROP_NONE) 00322 { 00323 if (root->env) 00324 { 00325 00326 // create reference variable names 00327 char * txt = (char *) 00328 malloc (strlen (def->instance) + 1 + strlen (value->ident) + 1); 00329 sprintf (txt, "%s.%s", def->instance, value->ident); 00330 char * ref = (char *) 00331 malloc (strlen (def->instance) + 5 + strlen (value->ident) + 1); 00332 sprintf (ref, "%s.%s.ref", def->instance, value->ident); 00333 00334 // replace property string 00335 free (value->ident); 00336 value->ident = strdup (ref); 00337 value->var = TAG_DOUBLE; 00338 00339 // already done previously? 00340 variable * v; 00341 if ((v = root->env->getVariable (ref)) == NULL) 00342 { 00343 // put variable into the environment 00344 checker_add_variable (root->env, ref, TAG_DOUBLE, false); 00345 // also add reference equation into environment 00346 root->env->getChecker()->addReference ("#propref", ref, txt); 00347 } 00348 00349 // done 00350 free (txt); 00351 free (ref); 00352 found++; 00353 } 00354 } 00355 /* not found */ 00356 if (!found) 00357 { 00358 logprint (LOG_ERROR, "line %d: checker error, no such variable `%s' " 00359 "used in a `%s:%s' property\n", def->line, value->ident, 00360 def->type, def->instance); 00361 return 0; 00362 } 00363 } 00364 return 1; 00365 } 00366 00367 /* Evaluates the unit scale in a property value. It adjusts the 00368 actual value and omits the scale. The function returns non-zero 00369 on success and zero otherwise. */ 00370 static int checker_evaluate_scale (struct value_t * value) 00371 { 00372 double val = value->value, factor = 1.0; 00373 char * scale; 00374 if (value->scale != NULL) 00375 { 00376 scale = value->scale; 00377 switch (*scale) 00378 { 00379 case 'E': 00380 scale++; 00381 factor = 1e18; 00382 break; 00383 case 'P': 00384 scale++; 00385 factor = 1e15; 00386 break; 00387 case 'T': 00388 scale++; 00389 factor = 1e12; 00390 break; 00391 case 'G': 00392 scale++; 00393 factor = 1e9; 00394 break; 00395 case 'M': 00396 scale++; 00397 factor = 1e6; 00398 break; 00399 case 'k': 00400 scale++; 00401 factor = 1e3; 00402 break; 00403 case 'm': 00404 scale++; 00405 if (*scale == 'i') 00406 { 00407 scale++; 00408 if (*scale == 'l') 00409 { 00410 scale++; 00411 factor = 2.54e-5; 00412 } 00413 } 00414 else 00415 factor = 1e-3; 00416 break; 00417 case 'u': 00418 scale++; 00419 factor = 1e-6; 00420 break; 00421 case 'n': 00422 scale++; 00423 factor = 1e-9; 00424 break; 00425 case 'p': 00426 scale++; 00427 factor = 1e-12; 00428 break; 00429 case 'f': 00430 scale++; 00431 if (*scale == 't') 00432 { 00433 scale++; 00434 factor = 0.3048; 00435 } 00436 else 00437 factor = 1e-15; 00438 break; 00439 case 'a': 00440 scale++; 00441 factor = 1e-18; 00442 break; 00443 case 'd': 00444 scale++; 00445 if (*scale == 'B') 00446 { 00447 scale++; 00448 val = std::pow (10.0, val / 10.0); 00449 if (*scale == 'm') 00450 { 00451 scale++; 00452 factor = 1e-3; 00453 } 00454 else if (*scale == 'u') 00455 { 00456 scale++; 00457 factor = 1e-6; 00458 } 00459 } 00460 break; 00461 case 'i': 00462 scale++; 00463 if (*scale == 'n') 00464 { 00465 scale++; 00466 factor = 2.54e-2; 00467 } 00468 break; 00469 case 'y': 00470 scale++; 00471 if (*scale == 'd') 00472 { 00473 scale++; 00474 factor = 0.9144; 00475 } 00476 break; 00477 } 00478 if (*scale != '\0') 00479 { 00480 value->unit = strdup (scale); 00481 } 00482 free (value->scale); 00483 value->scale = NULL; 00484 } 00485 value->value = val * factor; 00486 return 1; 00487 } 00488 00489 /* The function returns the number of instances of the given type within 00490 the list of definitions. */ 00491 static int checker_count_definitions (struct definition_t * root, 00492 const char * type, int action) 00493 { 00494 int count = 0; 00495 for (struct definition_t * def = root; def != NULL; def = def->next) 00496 { 00497 if (def->action == action) 00498 { 00499 if (type == NULL) 00500 count++; 00501 else if (!strcmp (def->type, type)) 00502 count++; 00503 } 00504 } 00505 return count; 00506 } 00507 00508 /* This function looks for the specified subcircuit type in the list 00509 of available subcircuits and returns its definition. If there is 00510 no such subcircuit the function returns NULL: */ 00511 static struct definition_t * checker_find_subcircuit (char * n) 00512 { 00513 struct definition_t * def; 00514 for (def = subcircuit_root; def != NULL; def = def->next) 00515 if (n != NULL && !strcmp (def->instance, n)) return def; 00516 return NULL; 00517 } 00518 00519 /* The function returns the subcircuit definition for the given 00520 subcircuit instance. */ 00521 static struct definition_t * 00522 checker_get_subcircuit (struct definition_t * def) 00523 { 00524 struct value_t * val; 00525 struct definition_t * sub = NULL; 00526 if ((val = checker_find_reference (def, "Type")) != NULL) 00527 sub = checker_find_subcircuit (val->ident); 00528 return sub; 00529 } 00530 00531 // Global variable indicating cycles in subcircuit definitions. 00532 static int checker_sub_cycles = 0; 00533 00534 /* The following function returns the number of circuit instances 00535 requiring a DC analysis (being nonlinear) in the list of definitions. */ 00536 static int checker_count_nonlinearities (struct definition_t * root) 00537 { 00538 int count = 0; 00539 struct definition_t * sub; 00540 for (struct definition_t * def = root; def != NULL; def = def->next) 00541 { 00542 if (def->nonlinear != 0) count++; 00543 // also recurse into subcircuits if possible 00544 if (checker_sub_cycles <= 0) 00545 { 00546 if (!strcmp (def->type, "Sub")) 00547 { 00548 if ((sub = checker_get_subcircuit (def)) != NULL) 00549 { 00550 count += checker_count_nonlinearities (sub->sub); 00551 } 00552 } 00553 } 00554 } 00555 return count; 00556 } 00557 00558 /* This function returns the number of action definitions with the 00559 given instance name. */ 00560 static int checker_count_action (struct definition_t * root, char * instance) 00561 { 00562 int count = 0; 00563 for (struct definition_t * def = root; def != NULL; def = def->next) 00564 { 00565 if (def->action == 1 && !strcmp (def->instance, instance)) 00566 count++; 00567 } 00568 return count; 00569 } 00570 00571 /* This (recursive) function detects any kind of cyclic definitions of 00572 parameter sweeps for the given instance name. The string list 00573 argument is used to pass the dependencies. The function returns 00574 zero if the parameter sweep in non-cyclic. */ 00575 static int checker_validate_para_cycles (struct definition_t * root, 00576 char * instance, strlist * deps) 00577 { 00578 int errors = 0; 00579 struct value_t * val; 00580 for (struct definition_t * def = root; def != NULL; def = def->next) 00581 { 00582 /* find the appropriate definition for the given instance */ 00583 if (def->action == 1 && !strcmp (def->instance, instance)) 00584 { 00585 /* emit error message if the instance is already in the dependencies */ 00586 if (deps->contains (instance)) 00587 { 00588 logprint (LOG_ERROR, "checker error, cyclic definition of `%s' " 00589 "detected, involves: %s\n", instance, deps->toString ()); 00590 return ++errors; 00591 } 00592 deps->append (instance); 00593 /* recurse into parameter sweeps */ 00594 if (!strcmp (def->type, "SW")) 00595 { 00596 if ((val = checker_find_reference (def, "Sim")) != NULL) 00597 { 00598 return checker_validate_para_cycles (root, val->ident, deps); 00599 } 00600 } 00601 } 00602 } 00603 return errors; 00604 } 00605 00606 /* This function validates each parameter sweep within the list of 00607 definitions and return non-zero on errors. Emits appropriate error 00608 messages. */ 00609 static int checker_validate_para (struct definition_t * root) 00610 { 00611 int errors = 0; 00612 struct value_t * val; 00613 for (struct definition_t * def = root; def != NULL; def = def->next) 00614 { 00615 /* find parameter sweep */ 00616 if (def->action == 1 && !strcmp (def->type, "SW")) 00617 { 00618 /* the 'Sim' property must be an identifier */ 00619 if ((val = checker_validate_reference (def, "Sim")) == NULL) 00620 { 00621 errors++; 00622 } 00623 else 00624 { 00625 /* check for self-referring sweeps */ 00626 if (!strcmp (def->instance, val->ident)) 00627 { 00628 logprint (LOG_ERROR, "line %d: checker error, definition `%s:%s' " 00629 "refers to itself\n", def->line, def->type, def->instance); 00630 errors++; 00631 } 00632 /* look for the referred analysis action definition */ 00633 if (checker_count_action (root, val->ident) != 1) 00634 { 00635 logprint (LOG_ERROR, "line %d: checker error, no such action `%s' " 00636 "found as referred in `%s:%s'\n", def->line, val->ident, 00637 def->type, def->instance); 00638 errors++; 00639 } 00640 /* finally detect cyclic definitions */ 00641 strlist * deps = new strlist (); 00642 errors += checker_validate_para_cycles (root, val->ident, deps); 00643 delete deps; 00644 } 00645 } 00646 } 00647 return errors; 00648 } 00649 00650 /* This function returns the next port definition in the given list of 00651 definitions or NULL if there is no such definition. */ 00652 static struct definition_t * checker_find_port (struct definition_t * root) 00653 { 00654 for (struct definition_t * def = root; def != NULL; def = def->next) 00655 { 00656 if (def->action == PROP_COMPONENT && !strcmp (def->type, "Pac")) 00657 { 00658 return def; 00659 } 00660 } 00661 return NULL; 00662 } 00663 00664 /* This function checks whether the port numbers for the S-parameter 00665 analysis are unique or not. It returns zero on success and 00666 non-zero if it detected duplicate entries. */ 00667 static int checker_validate_ports (struct definition_t * root) 00668 { 00669 int p, errors = 0; 00670 struct value_t * val; 00671 struct definition_t * port, * def = root; 00672 const char * prop = "Num"; 00673 while ((def = checker_find_port (def)) != NULL) 00674 { 00675 if ((val = checker_find_prop_value (def, prop)) != NULL) 00676 { 00677 p = (int) val->value; 00678 port = root; 00679 while ((port = checker_find_port (port)) != NULL) 00680 { 00681 if (port != def) 00682 { 00683 if ((val = checker_find_prop_value (port, prop)) != NULL) 00684 { 00685 if (p == (int) val->value) 00686 { 00687 logprint (LOG_ERROR, "line %d: checker error, `%s' definitions " 00688 "with duplicate `%s=%d' property found: `%s:%s' and " 00689 "`%s:%s'\n", def->line, def->type, prop, p, def->type, 00690 def->instance, port->type, port->instance); 00691 errors++; 00692 } 00693 } 00694 } 00695 port = port->next; 00696 } 00697 } 00698 def = def->next; 00699 } 00700 return errors; 00701 } 00702 00703 /* The following function checks whether the parametric sweeps in the 00704 netlist are valid or not. It returns zero on success and non-zero 00705 otherwise. */ 00706 static int checker_validate_lists (struct definition_t * root) 00707 { 00708 int errors = 0; 00709 // go through each definition 00710 for (struct definition_t * def = root; def != NULL; def = def->next) 00711 { 00712 /* sweeps possible in parameter sweep, ac-analysis and 00713 s-parameter analysis */ 00714 if (def->action == 1 && (!strcmp (def->type, "SW") || 00715 !strcmp (def->type, "AC") || 00716 !strcmp (def->type, "SP"))) 00717 { 00718 struct value_t * val; 00719 if((val = checker_find_reference (def, "Type")) == NULL) { 00720 logprint (LOG_ERROR, "line %d: checker error, required property " 00721 "`%s' is invalid in `%s:%s'\n", def->line, "Type", 00722 def->type, def->instance); 00723 errors++; 00724 continue; 00725 } 00726 char * type = val->ident; 00727 // list of constant values and constant values 00728 if (type && (!strcmp (type, "const") || !strcmp (type, "list"))) 00729 { 00730 // property 'Values' is required 00731 if ((val = checker_find_prop_value (def, "Values")) == NULL) 00732 { 00733 if (!strcmp (type, "const")) 00734 { 00735 if ((val = checker_validate_reference (def, "Values")) == NULL) 00736 { 00737 errors++; 00738 } 00739 } 00740 else 00741 { 00742 logprint (LOG_ERROR, "line %d: checker error, required property " 00743 "`%s' not found in `%s:%s'\n", def->line, "Values", 00744 def->type, def->instance); 00745 errors++; 00746 } 00747 } 00748 else 00749 { 00750 if (!strcmp (type, "const")) 00751 { 00752 // in constant sweeps only one value allowed 00753 if (val->next != NULL) 00754 { 00755 logprint (LOG_ERROR, "line %d: checker error, value of `%s' " 00756 "needs to be a single constant value in `%s:%s', no " 00757 "lists possible\n", def->line, "Values", 00758 def->type, def->instance); 00759 errors++; 00760 } 00761 val->var = TAG_UNKNOWN; 00762 } 00763 if (!strcmp (type, "list")) 00764 { 00765 val->var = TAG_VECTOR; 00766 } 00767 // check and evaluate the unit scale in a value list 00768 for (; val != NULL; val = val->next) 00769 { 00770 if (!checker_evaluate_scale (val)) 00771 errors++; 00772 } 00773 } 00774 // property 'Start' is invalid 00775 if (checker_find_property (def, "Start") > 0) 00776 { 00777 logprint (LOG_ERROR, "line %d: checker error, extraneous property " 00778 "`%s' is invalid in `%s:%s'\n", def->line, "Start", 00779 def->type, def->instance); 00780 errors++; 00781 } 00782 // property 'Stop' is invalid 00783 if (checker_find_property (def, "Stop") > 0) 00784 { 00785 logprint (LOG_ERROR, "line %d: checker error, extraneous property " 00786 "`%s' is invalid in `%s:%s'\n", def->line, "Stop", 00787 def->type, def->instance); 00788 errors++; 00789 } 00790 // property 'Points' is also invalid 00791 if (checker_find_property (def, "Points") > 0) 00792 { 00793 logprint (LOG_ERROR, "line %d: checker error, extraneous property " 00794 "`%s' is invalid in `%s:%s'\n", def->line, "Points", 00795 def->type, def->instance); 00796 errors++; 00797 } 00798 } 00799 // linearly and logarithmically stepped sweeps 00800 else if (type && (!strcmp (type, "lin") || !strcmp (type, "log"))) 00801 { 00802 // property 'Start' required 00803 if (checker_find_property (def, "Start") <= 0) 00804 { 00805 logprint (LOG_ERROR, "line %d: checker error, required property " 00806 "`%s' not found in `%s:%s'\n", def->line, "Start", 00807 def->type, def->instance); 00808 errors++; 00809 } 00810 // property 'Stop' required 00811 if (checker_find_property (def, "Stop") <= 0) 00812 { 00813 logprint (LOG_ERROR, "line %d: checker error, required property " 00814 "`%s' not found in `%s:%s'\n", def->line, "Stop", 00815 def->type, def->instance); 00816 errors++; 00817 } 00818 // property 'Points' is also required 00819 if (checker_find_property (def, "Points") <= 0) 00820 { 00821 logprint (LOG_ERROR, "line %d: checker error, required property " 00822 "`%s' not found in `%s:%s'\n", def->line, "Points", 00823 def->type, def->instance); 00824 errors++; 00825 } 00826 // property 'Values' is invalid 00827 if (checker_find_property (def, "Values") > 0) 00828 { 00829 logprint (LOG_ERROR, "line %d: checker error, extraneous property " 00830 "`%s' is invalid in `%s:%s'\n", def->line, "Values", 00831 def->type, def->instance); 00832 errors++; 00833 } 00834 } 00835 } 00836 } 00837 return errors; 00838 } 00839 00840 /* This function checks the actions to be taken in the netlist. It 00841 returns zero on success, non-zero otherwise. */ 00842 static int checker_validate_actions (struct definition_t * root) 00843 { 00844 int a, c, n, errors = 0; 00845 if ((n = checker_count_definitions (root, NULL, 1)) < 1) 00846 { 00847 logprint (LOG_ERROR, "checker error, no actions defined: nothing to do\n"); 00848 errors++; 00849 } 00850 else 00851 { 00852 // check requirements for s-parameter analysis 00853 if ((a = checker_count_definitions (root, "SP", 1)) >= 1) 00854 { 00855 if ((n = checker_count_definitions (root, "Pac", 0)) < 1) 00856 { 00857 logprint (LOG_ERROR, "checker error, %d `Pac' definitions found, at " 00858 "least 1 required\n", n); 00859 errors++; 00860 } 00861 } 00862 // count analyses requiring a DC solution 00863 a += checker_count_definitions (root, "AC", 1); 00864 // check dc-analysis requirements 00865 c = checker_count_nonlinearities (root); 00866 n = checker_count_definitions (root, "DC", 1); 00867 if (n > 1) 00868 { 00869 logprint (LOG_ERROR, "checker error, the .DC action is defined %dx, " 00870 "single or none required\n", n); 00871 errors++; 00872 } 00873 if (a >= 1 && c >= 1 && n < 1) 00874 { 00875 logprint (LOG_ERROR, "checker error, a .DC action is required for this " 00876 "circuit definition (accounted %d non-linearities)\n", c); 00877 errors++; 00878 } 00879 } 00880 errors += checker_validate_para (root); 00881 errors += checker_validate_ports (root); 00882 errors += checker_validate_lists (root); 00883 return errors; 00884 } 00885 00886 /* This function checks the validity of each microstrip component and 00887 its substrate and model references. It returns zero on success, 00888 emit error messages if necessary and returns non-zero on errors. */ 00889 static int checker_validate_strips (struct definition_t * root) 00890 { 00891 int errors = 0; 00892 struct value_t * val; 00893 for (struct definition_t * def = root; def != NULL; def = def->next) 00894 { 00895 if (!def->action) 00896 { 00897 /* find components with substrate property */ 00898 if (def->define && (checker_is_property (def->define, "Subst") == PROP_STR)) 00899 { 00900 /* check validity of 'Subst' property */ 00901 if ((val = checker_validate_reference (def, "Subst")) == NULL) 00902 { 00903 errors++; 00904 } 00905 else 00906 { 00907 if (checker_count_definition (root, "SUBST", val->ident) != 1) 00908 { 00909 logprint (LOG_ERROR, "line %d: checker error, no such substrate " 00910 "`%s' found as specified in `%s:%s'\n", def->line, 00911 val->ident, def->type, def->instance); 00912 errors++; 00913 } 00914 } 00915 /* check validity of 'Model' property */ 00916 #if DISABLE_FOR_NOW /* ThinkME!!! */ 00917 if ((val = checker_validate_reference (def, "Model")) == NULL) 00918 { 00919 errors++; 00920 } 00921 #endif 00922 } 00923 } 00924 } 00925 return errors; 00926 } 00927 00928 /* This function counts the number of occurrences of the given node 00929 name in the given netlist definition root. */ 00930 static int checker_count_nodes (struct definition_t * root, char * n) 00931 { 00932 int count = 0; 00933 struct node_t * node; 00934 for (struct definition_t * def = root; def != NULL; def = def->next) 00935 { 00936 if (!def->action && !def->nodeset) 00937 { 00938 for (node = def->nodes; node != NULL; node = node->next) 00939 if (!strcmp (node->node, n)) count++; 00940 } 00941 } 00942 return count; 00943 } 00944 00945 /* The function identifies duplicate nodesets for the same node which 00946 is not allowed. It returns the number of duplications. */ 00947 static int checker_count_nodesets (struct definition_t * root, char * n) 00948 { 00949 int count = 0; 00950 for (struct definition_t * def = root; def != NULL; def = def->next) 00951 { 00952 if (def->nodeset && !def->duplicate && def->nodes) 00953 { 00954 char * node = def->nodes->node; 00955 if (!strcmp (node, n)) 00956 { 00957 if (++count > 1) def->duplicate = 1; 00958 } 00959 } 00960 } 00961 return count; 00962 } 00963 00964 /* The following function checks whether the nodes specified by the 00965 nodeset functionality is valid in its current scope. It does not 00966 check across subcircuit boundaries. */ 00967 static int checker_validate_nodesets (struct definition_t * root) 00968 { 00969 int errors = 0; 00970 for (struct definition_t * def = root; def != NULL; def = def->next) 00971 { 00972 if (def->nodeset && checker_count_nodes (def) == 1) 00973 { 00974 char * node = def->nodes->node; 00975 if (checker_count_nodes (root, node) <= 0) 00976 { 00977 logprint (LOG_ERROR, "line %d: checker error, no such node `%s' found " 00978 "as referenced by `%s:%s'\n", def->line, node, def->type, 00979 def->instance); 00980 errors++; 00981 } 00982 if (checker_count_nodesets (root, node) > 1) 00983 { 00984 logprint (LOG_ERROR, "line %d: checker error, the node `%s' is not " 00985 "uniquely defined by `%s:%s'\n", def->line, node, def->type, 00986 def->instance); 00987 errors++; 00988 } 00989 } 00990 } 00991 return errors; 00992 } 00993 00994 /* This function should be called after the netlist and the equation 00995 list have been checked. It verifies that parameter sweep 00996 definitions and equation variable identifiers are unique. The 00997 function returns zero on success and non-zero otherwise. */ 00998 static int netlist_checker_variables_intern (struct definition_t * root, 00999 environment * env) 01000 { 01001 int errors = 0, pos; 01002 struct value_t * para, * ref; 01003 strlist * eqnvars = env->getChecker()->variables (); 01004 strlist * instances = new strlist (); 01005 strlist * vars = new strlist (); 01006 strlist * refs = new strlist (); 01007 // go through list of netlist definitions 01008 for (struct definition_t * def = root; def != NULL; def = def->next) 01009 { 01010 // find parameters sweeps 01011 if (def->action == 1 && !strcmp (def->type, "SW")) 01012 { 01013 para = checker_find_reference (def, "Param"); 01014 ref = checker_find_reference (def, "Sim"); 01015 if (para != NULL && ref != NULL) 01016 { 01017 // check whether sweep variable collides with equations 01018 if (eqnvars && eqnvars->contains (para->ident)) 01019 { 01020 logprint (LOG_ERROR, "checker error, equation variable `%s' " 01021 "already defined by `%s:%s'\n", para->ident, 01022 def->type, def->instance); 01023 errors++; 01024 } 01025 // check for duplicate parameter names in parameter sweeps, but 01026 // allow them in same order sweeps 01027 if ((pos = vars->index (para->ident)) != -1) 01028 { 01029 if (strcmp (ref->ident, refs->get (pos))) 01030 { 01031 logprint (LOG_ERROR, "checker error, variable `%s' in `%s:%s' " 01032 "already defined by `%s:%s'\n", para->ident, def->type, 01033 def->instance, def->type, instances->get (pos)); 01034 errors++; 01035 } 01036 } 01037 // check for duplicate simulations in parameter sweeps (same order 01038 // sweep) and allow same parameter name only 01039 if ((pos = refs->index (ref->ident)) != -1) 01040 { 01041 if (strcmp (para->ident, vars->get (pos))) 01042 { 01043 logprint (LOG_ERROR, "checker error, conflicting variables `%s' " 01044 "in `%s:%s' and `%s' in `%s:%s' for `%s'\n", 01045 para->ident, def->type, def->instance, 01046 vars->get (pos), def->type, instances->get (pos), 01047 ref->ident); 01048 errors++; 01049 } 01050 } 01051 // collect parameter sweep variables for the above two checks 01052 instances->add (def->instance); 01053 vars->add (para->ident); 01054 refs->add (ref->ident); 01055 } 01056 } 01057 } 01058 delete eqnvars; 01059 delete refs; 01060 delete vars; 01061 delete instances; 01062 return errors; 01063 } 01064 01065 /* This is the overall variable checker for the parsed netlist. See 01066 the above function for details. */ 01067 int netlist_checker_variables (environment * env) 01068 { 01069 return netlist_checker_variables_intern (definition_root, env); 01070 } 01071 01072 /* The function checks whether the given key-value combination is 01073 inside the allowed range defined by the given property definition 01074 and returns the number of error or zero otherwise. */ 01075 static int checker_value_in_prop_range (char * instance, struct define_t * def, 01076 struct pair_t * pp, 01077 struct property_t * prop) 01078 { 01079 int errors = 0; 01080 // check values 01081 if (PROP_IS_VAL (*prop)) 01082 { 01083 if (!PROP_IS_LST (*prop)) 01084 { 01085 // lists of values possible? 01086 if (pp->value->next != NULL) 01087 { 01088 logprint (LOG_ERROR, 01089 "checker error, value of `%s' needs to be " 01090 "a single value in `%s:%s', no lists possible\n", 01091 pp->key, def->type, instance); 01092 errors++; 01093 } 01094 } 01095 else 01096 { 01097 // a value list 01098 struct value_t * val = pp->value; 01099 val->var = TAG_VECTOR; 01100 // check and evaluate the unit scale in a value list 01101 for (; val != NULL; val = val->next) 01102 { 01103 if (!checker_evaluate_scale (val)) 01104 errors++; 01105 } 01106 } 01107 // check range of all values 01108 if (PROP_HAS_RANGE (*prop)) 01109 { 01110 struct value_t * val = pp->value; 01111 if (val->ident) 01112 { 01113 /* no range checking on variable identifier */ 01114 logprint (LOG_STATUS, 01115 "checker notice, value of `%s' (variable `%s') could be " 01116 "out of range `%c%g,%g%c' in `%s:%s'\n", 01117 pp->key, val->ident, prop->range.il, prop->range.l, 01118 prop->range.h, prop->range.ih, def->type, instance); 01119 val = NULL; 01120 } 01121 for (; val != NULL; val = val->next) 01122 { 01123 int rerror = 0; 01124 if (prop->range.il == '[' && (val->value < prop->range.l)) 01125 rerror++; 01126 if (prop->range.il == ']' && !(val->value > prop->range.l)) 01127 rerror++; 01128 if (prop->range.ih == '[' && !(val->value < prop->range.h)) 01129 rerror++; 01130 if (prop->range.ih == ']' && (val->value > prop->range.h)) 01131 rerror++; 01132 if (rerror) 01133 { 01134 logprint (LOG_ERROR, 01135 "checker error, value of `%s' (%g) is out of " 01136 "range `%c%g,%g%c' in `%s:%s'\n", 01137 pp->key, val->value, prop->range.il, prop->range.l, 01138 prop->range.h, prop->range.ih, def->type, instance); 01139 errors++; 01140 } 01141 } 01142 } 01143 // check fraction of integers 01144 if (PROP_IS_INT (*prop)) 01145 { 01146 double integral; 01147 if (modf (pp->value->value, &integral) != 0) 01148 { 01149 logprint (LOG_ERROR, 01150 "checker error, value of `%s' (%g) needs to be " 01151 "an integer in `%s:%s'\n", 01152 pp->key, pp->value->value, def->type, instance); 01153 errors++; 01154 } 01155 } 01156 } 01157 // check identifiers 01158 else 01159 { 01160 // no identifier given 01161 if (pp->value->ident == NULL) 01162 { 01163 logprint (LOG_ERROR, 01164 "checker error, value of `%s' (%g) needs to be " 01165 "an identifier in `%s:%s'\n", 01166 pp->key, pp->value->value, def->type, instance); 01167 errors++; 01168 } 01169 // check identifier range 01170 else 01171 { 01172 if (PROP_HAS_STR (*prop)) 01173 { 01174 int i, found = 0; 01175 char range[256]; 01176 sprintf (range, "["); 01177 for (i = 0; prop->range.str[i]; i++) 01178 { 01179 strcat (range, prop->range.str[i]); 01180 strcat (range, ","); 01181 if (!strcmp (prop->range.str[i], pp->value->ident)) found++; 01182 } 01183 if (!found) 01184 { 01185 range[strlen (range) - 1] = ']'; 01186 logprint (LOG_ERROR, 01187 "checker error, value of `%s' (%s) needs to be " 01188 "in %s in `%s:%s'\n", 01189 pp->key, pp->value->ident, range, def->type, instance); 01190 errors++; 01191 } 01192 else pp->value->range = 1; 01193 } 01194 } 01195 } 01196 return errors; 01197 } 01198 01199 /* The function checks whether the given key-value combination being 01200 part of the available definition is inside the allowed range and 01201 returns zero if not. Otherwise the function returns non-zero. */ 01202 static int checker_value_in_range (char * instance, struct define_t * def, 01203 struct pair_t * pp) 01204 { 01205 int i, errors = 0; 01206 // go through required properties 01207 for (i = 0; PROP_IS_PROP (def->required[i]); i++) 01208 { 01209 if (!strcmp (def->required[i].key, pp->key)) 01210 { 01211 errors += checker_value_in_prop_range (instance, def, pp, 01212 &def->required[i]); 01213 } 01214 } 01215 // go through optional properties 01216 for (i = 0; PROP_IS_PROP (def->optional[i]); i++) 01217 { 01218 if (!strcmp (def->optional[i].key, pp->key)) 01219 { 01220 errors += checker_value_in_prop_range (instance, def, pp, 01221 &def->optional[i]); 01222 } 01223 } 01224 return errors ? 0 : 1; 01225 } 01226 01227 /* The function determines the subcircuit definitions defined in the 01228 original netlist and builds an appropriate subcircuit definition 01229 list. It returns the given definition list with the subcircuits 01230 removed. */ 01231 static struct definition_t * 01232 checker_build_subcircuits (struct definition_t * root) 01233 { 01234 struct definition_t * def, * next, * prev; 01235 for (prev = NULL, def = root; def != NULL; def = next) 01236 { 01237 next = def->next; 01238 if (!strcmp (def->type, "Def")) 01239 { 01240 if (prev) 01241 { 01242 prev->next = next; 01243 } 01244 else 01245 { 01246 root = next; 01247 } 01248 def->sub = checker_build_subcircuits (def->sub); 01249 def->next = subcircuit_root; 01250 subcircuit_root = def; 01251 } 01252 else prev = def; 01253 } 01254 return root; 01255 } 01256 01257 /* The function produces a copy of the given circuit definition and 01258 marks it as a copy. The node definition are not included within 01259 the copy. */ 01260 static struct definition_t * 01261 checker_copy_subcircuit (struct definition_t * sub) 01262 { 01263 struct definition_t * copy; 01264 copy = (struct definition_t *) calloc (sizeof (struct definition_t), 1); 01265 copy->action = sub->action; 01266 copy->nonlinear = sub->nonlinear; 01267 copy->substrate = sub->substrate; 01268 copy->nodeset = sub->nodeset; 01269 copy->define = sub->define; 01270 copy->pairs = sub->pairs; 01271 copy->ncount = sub->ncount; 01272 copy->type = strdup (sub->type); 01273 copy->copy = 1; 01274 return copy; 01275 } 01276 01277 /* This function translates the node definitions of the given 01278 subcircuit element 'sub'. The translation is based upon the node 01279 definitions of the subcircuit 'type' and the instance 'inst' of 01280 such a subcircuit. The translated nodes are saved in an extra 01281 'xlate' field of each node of the subcircuit element 'sub'. */ 01282 static void checker_xlat_subcircuit_nodes (struct definition_t * type, 01283 struct definition_t * inst, 01284 struct definition_t * sub) 01285 { 01286 struct node_t * n, * ninst, * ntype; 01287 int i; 01288 // go through nodes of the subcircuit 'type' and 'inst' 01289 for (i = 1, ntype = type->nodes, ninst = inst->nodes; ntype != NULL; 01290 ntype = ntype->next, ninst = ninst->next, i++) 01291 { 01292 for (n = sub->nodes; n != NULL; n = n->next) 01293 { 01294 /* check whether a node in the subcircuit element 'sub' corresponds 01295 with the 'type', then assign the 'inst's node name */ 01296 if (!strcmp (n->node, ntype->node)) 01297 { 01298 n->xlate = strdup (ninst->node); 01299 n->xlatenr = i; 01300 } 01301 } 01302 } 01303 } 01304 01305 /* The function creates a subcircuit node name consisting of the given 01306 arguments. If the given 'instances' is NULL it is left out. The 01307 caller is responsible to free() the returned string. */ 01308 static char * checker_subcircuit_node (char * type, char * instances, 01309 char * instance, char * node) 01310 { 01311 char * txt = (char *) 01312 calloc (1, strlen (type) + strlen (instance) + strlen (node) + 01313 (instances ? strlen (instances) : 0) + 4); 01314 if (instances) 01315 sprintf (txt, "%s.%s.%s.%s", type, instances, instance, node); 01316 else 01317 sprintf (txt, "%s.%s.%s", type, instance, node); 01318 return txt; 01319 } 01320 01321 /* The function reverses the order of the given node list and returns 01322 the reversed list. */ 01323 struct node_t * netlist_reverse_nodes (struct node_t * nodes) 01324 { 01325 struct node_t * root, * next; 01326 for (root = NULL; nodes != NULL; nodes = next) 01327 { 01328 next = nodes->next; 01329 nodes->next = root; 01330 root = nodes; 01331 } 01332 return root; 01333 } 01334 01335 /* This function assigns new node names to the subcircuit element 01336 'copy' based upon the previous node translation between the 01337 subcircuit 'type' and the instance 'inst' of this type. The global 01338 'gnd' node is not touched. */ 01339 static void 01340 checker_copy_subcircuit_nodes (struct definition_t * type, 01341 struct definition_t * inst, 01342 struct definition_t * sub, 01343 struct definition_t * copy, 01344 char * instances) 01345 { 01346 struct node_t * n, * ncopy, * root = NULL; 01347 01348 // go through the list of the subcircuit element's 'sub' nodes 01349 for (n = sub->nodes; n != NULL; n = n->next) 01350 { 01351 01352 // create new node based upon the node translation 01353 ncopy = (struct node_t *) calloc (sizeof (struct node_t), 1); 01354 ncopy->xlatenr = n->xlatenr; 01355 if (n->xlate) // translated node 01356 { 01357 if (instances == NULL) 01358 ncopy->node = strdup (n->xlate); 01359 else 01360 ncopy->node = NULL; // leave it blank yet, indicates translation 01361 } 01362 else if (!strcmp (n->node, "gnd")) // ground node 01363 { 01364 ncopy->node = strdup (n->node); 01365 } 01366 else if (n->node[strlen (n->node) - 1] == '!') // global node 01367 { 01368 ncopy->node = strdup (n->node); 01369 } 01370 else // internal subcircuit element node 01371 { 01372 ncopy->node = checker_subcircuit_node (type->instance, instances, 01373 inst->instance, n->node); 01374 } 01375 // chain the new node list 01376 ncopy->next = root; 01377 root = ncopy; 01378 } 01379 01380 /* and finally reverse the created node list and assign it to the 01381 subcircuit element's 'copy' */ 01382 copy->nodes = netlist_reverse_nodes (root); 01383 } 01384 01385 // Returns the node at the given position. 01386 static struct node_t * checker_get_circuit_node (struct node_t * root, int n) 01387 { 01388 for (int i = 1; i < n; i++) 01389 { 01390 root = root->next; 01391 assert (root != NULL); 01392 } 01393 return root; 01394 } 01395 01396 // The function cleans the translated nodes of a subcircuit template. 01397 static void checker_cleanup_xlat_nodes (struct definition_t * sub) 01398 { 01399 for (struct node_t * n = sub->nodes; n != NULL; n = n->next) 01400 { 01401 free (n->xlate); 01402 n->xlate = NULL; 01403 n->xlatenr = 0; 01404 } 01405 } 01406 01407 /* The function is used to assign the nodes of the 'copy' subcircuit 01408 element which were left blank intentionally by the element copy in 01409 order to indicate that it is an external node. Again, if the 01410 current node translation indicates an external node it is blanked 01411 again, otherwise the node gets a unique internal name. If the 01412 'instances' list is NULL, then this indicates the root circuit list 01413 and node translations are done though they are 'external'. */ 01414 static void 01415 checker_copy_circuit_nodes (struct definition_t * type, 01416 struct definition_t * inst, 01417 struct definition_t * sub, 01418 struct definition_t * copy, 01419 char * instances) 01420 { 01421 struct node_t * n, * ncopy; 01422 01423 // go through the list of the subcircuit element's 'copy' nodes 01424 for (ncopy = copy->nodes; ncopy != NULL; ncopy = ncopy->next) 01425 { 01426 // these NULL nodes have intentionally been blanked 01427 if (ncopy->node == NULL) 01428 { 01429 assert (ncopy->xlatenr != 0); 01430 // get translated node 01431 n = checker_get_circuit_node (sub->nodes, ncopy->xlatenr); 01432 ncopy->xlatenr = n->xlatenr; 01433 if (n->xlate) // translated node 01434 { 01435 if (instances == NULL) 01436 // external node indicated by no instances given 01437 ncopy->node = strdup (n->xlate); 01438 else 01439 ncopy->node = NULL; // keep blank 01440 } 01441 else if (!strcmp (n->node, "gnd")) // global ground node 01442 { 01443 ncopy->node = strdup (n->node); 01444 } 01445 else if (n->node[strlen (n->node) - 1] == '!') // other global node 01446 { 01447 ncopy->node = strdup (n->node); 01448 } 01449 else // internal subcircuit element node 01450 { 01451 ncopy->node = checker_subcircuit_node (type->instance, instances, 01452 inst->instance, n->node); 01453 } 01454 } 01455 } 01456 } 01457 01458 /* This function returns the last entry of the given list of 01459 definitions or NULL if there is no such element. */ 01460 static struct definition_t * 01461 checker_find_last_definition (struct definition_t * root) 01462 { 01463 for (struct definition_t * def = root; def != NULL; def = def->next) 01464 if (def->next == NULL) return def; 01465 return NULL; 01466 } 01467 01468 /* Based upon the the given subcircuit instance identifier list the 01469 function returns a "." - concatenated string or NULL. */ 01470 static char * checker_subcircuit_instance_list (strlist * instances) 01471 { 01472 if (instances && instances->length () > 0) 01473 return instances->toString ("."); 01474 return NULL; 01475 } 01476 01477 /* The function creates a subcircuit instance name consisting of the 01478 given arguments. If the given 'instances' is NULL it is left out. 01479 The caller is responsible to free() the returned string. */ 01480 static char * checker_subcircuit_instance (char * type, char * instances, 01481 char * instance, char * base) 01482 { 01483 char * txt = (char *) 01484 calloc (1, strlen (type) + strlen (instance) + strlen (base) + 01485 (instances ? strlen (instances) : 0) + 4); 01486 if (instances) 01487 sprintf (txt, "%s.%s.%s.%s", type, instances, instance, base); 01488 else 01489 sprintf (txt, "%s.%s.%s", type, instance, base); 01490 return txt; 01491 } 01492 01493 /* This function produces a copy of the given subcircuit 'type' 01494 containing the subcircuit elements. Based upon the instance 'inst' 01495 definitions (node names and instance name) it assign new element 01496 instances and node names. The function returns a NULL terminated 01497 circuit element list in reverse order. */ 01498 static struct definition_t * 01499 checker_copy_subcircuits (struct definition_t * type, 01500 struct definition_t * inst, strlist * * instances, 01501 environment * parent) 01502 { 01503 struct definition_t * def, * copy; 01504 struct definition_t * root = NULL; 01505 strlist * instcopy; 01506 char * list; 01507 01508 // create environment for subcircuit instance 01509 environment * child = new environment (*(type->env)); 01510 parent->push_front_Child (child); 01511 01512 // put instance properties into subcircuit environment 01513 for (struct pair_t * pair = inst->pairs; pair != NULL; pair = pair->next) 01514 { 01515 // anything else than the 'Type' 01516 if (strcmp (pair->key, "Type")) 01517 { 01518 if (pair->value->ident == NULL) 01519 { 01520 // simple value 01521 child->setDoubleConstant (pair->key, pair->value->value); 01522 child->setDouble (pair->key, pair->value->value); 01523 } 01524 else 01525 { 01526 // reference to variable in upper environment 01527 child->setDoubleReference (pair->key, pair->value->ident); 01528 } 01529 } 01530 } 01531 01532 // go through element list of subcircuit 01533 for (def = type->sub; def != NULL; def = def->next) 01534 { 01535 01536 // translate the node list 01537 checker_xlat_subcircuit_nodes (type, inst, def); 01538 01539 // allow recursive subcircuits 01540 if (!strcmp (def->type, "Sub")) 01541 { 01542 // get subcircuit template definition 01543 struct definition_t * sub = checker_get_subcircuit (def); 01544 // create a copy of the current subcircuit instance list 01545 if ((*instances) == NULL) (*instances) = new strlist (); 01546 instcopy = new strlist (*(*instances)); 01547 // append instance name to recursive instance list 01548 (*instances)->append (inst->instance); 01549 copy = checker_copy_subcircuits (sub, def, instances, child); 01550 // put the expanded definitions into the sublist 01551 if (copy) 01552 { 01553 list = checker_subcircuit_instance_list (instcopy); 01554 // assign blanked node names to each subcircuit 01555 for (struct definition_t * c = copy; c != NULL; c = c->next) 01556 { 01557 checker_copy_circuit_nodes (type, inst, def, c, list); 01558 } 01559 // append the copies to the subcircuit list 01560 struct definition_t * last = checker_find_last_definition (copy); 01561 last->next = root; 01562 root = copy; 01563 } 01564 // restore original instance list 01565 delete *instances; 01566 *instances = instcopy; 01567 } 01568 else 01569 { 01570 // element copy 01571 copy = checker_copy_subcircuit (def); 01572 // assign new instance name to the element 01573 list = checker_subcircuit_instance_list (*instances); 01574 copy->instance = 01575 checker_subcircuit_instance (type->instance, list, 01576 inst->instance, def->instance); 01577 copy->subcircuit = strdup (type->instance); 01578 // assign node list 01579 checker_copy_subcircuit_nodes (type, inst, def, copy, list); 01580 // apply environment 01581 copy->env = child; 01582 // chain definition (circuit) list 01583 copy->next = root; 01584 root = copy; 01585 } 01586 01587 // cleanup translated nodes 01588 checker_cleanup_xlat_nodes (def); 01589 } 01590 01591 // try giving child environment a unique name 01592 strlist * icopy = new strlist (); 01593 icopy->append (type->instance); 01594 icopy->append (*(instances)); 01595 icopy->append (inst->instance); 01596 child->setName (std::string(icopy->toString ("."))); 01597 delete icopy; 01598 01599 return root; 01600 } 01601 01602 /* The function checks whether the subcircuit 'instance' with the 01603 subcircuit 'type' is defined in cycles. It recursively goes 01604 through the definitions and emits an appropriate error message if 01605 necessary. The function returns zero if there are no cycles 01606 detected and non-zero with cycles found. */ 01607 static int checker_validate_sub_cycles (struct definition_t * root, 01608 char * type, char * instance, 01609 strlist * * deps) 01610 { 01611 int errors = 0, error; 01612 struct value_t * val; 01613 01614 /* emit an appropriate error message if the subcircuit type is already 01615 in the dependencies */ 01616 if ((*deps)->contains (type)) 01617 { 01618 logprint (LOG_ERROR, "checker error, cyclic definition of `%s:%s' " 01619 "detected, involves: %s\n", 01620 type, instance, (*deps)->toString ()); 01621 return ++errors; 01622 } 01623 (*deps)->append (type); 01624 01625 // create temporary list of subcircuit types already tested 01626 strlist * checked = new strlist (); 01627 // go through the list of circuit elements of the subcircuit 01628 for (struct definition_t * def = root->sub; def != NULL; def = def->next) 01629 { 01630 // find the appropriate definitions 01631 if (!strcmp (def->type, "Sub")) 01632 { 01633 // recurse into subcircuit instances 01634 if ((val = checker_find_reference (def, "Type")) != NULL) 01635 { 01636 if (!checked->contains (val->ident)) // only if not already checked 01637 { 01638 struct definition_t * sub; 01639 checked->append (val->ident); 01640 // copy current dependencies 01641 strlist * copy = new strlist (*(*deps)); 01642 // validate subcircuit 01643 sub = checker_find_subcircuit (val->ident); 01644 if (sub != NULL) // if possible 01645 error = checker_validate_sub_cycles (sub, sub->instance, 01646 instance, deps); 01647 else 01648 error = 1; 01649 // on errors: go on 01650 if (error) 01651 { 01652 errors += error; 01653 delete copy; 01654 } 01655 // no errors: restore original dependencies 01656 else 01657 { 01658 delete *deps; 01659 *deps = copy; 01660 } 01661 } 01662 } 01663 } 01664 } 01665 delete checked; 01666 return errors; 01667 } 01668 01669 /* This function dynamically creates a circuit definition based on a 01670 given subcircuit definition including type, number of nodes and the 01671 properties. */ 01672 static struct define_t * netlist_create_define (struct definition_t * def) 01673 { 01674 int o, r; 01675 struct pair_t * p; 01676 struct define_t * d = 01677 (struct define_t *) calloc (sizeof (struct define_t), 1); 01678 d->type = strdup (def->instance); 01679 d->nodes = checker_count_nodes (def); 01680 d->action = PROP_COMPONENT; 01681 01682 // determine number of required and optional parameters 01683 for (o = r = 0, p = def->pairs; p != NULL; p = p->next) 01684 { 01685 if (p->value == NULL) 01686 r++; 01687 else 01688 o++; 01689 } 01690 d->required = 01691 (struct property_t *) calloc (sizeof (struct property_t), r + 2); 01692 d->optional = 01693 (struct property_t *) calloc (sizeof (struct property_t), o + 1); 01694 01695 // fill in parameters 01696 for (o = r = 0, p = def->pairs; p != NULL; p = p->next) 01697 { 01698 if (p->value == NULL) 01699 { 01700 // required 01701 d->required[r].key = strdup (p->key); 01702 d->required[r].type = PROP_REAL; 01703 d->required[r].defaultval.d = PROP_NO_VAL; 01704 d->required[r].defaultval.s = PROP_NO_STR; 01705 d->required[r].range.il = '.'; 01706 d->required[r].range.l = 0; 01707 d->required[r].range.h = 0; 01708 d->required[r].range.ih = '.'; 01709 r++; 01710 } 01711 else 01712 { 01713 // optional 01714 d->optional[o].key = strdup (p->key); 01715 d->optional[o].type = PROP_REAL; 01716 d->optional[o].defaultval.d = p->value->value; 01717 d->optional[o].defaultval.s = PROP_NO_STR; 01718 d->optional[o].range.il = '.'; 01719 d->optional[o].range.l = 0; 01720 d->optional[o].range.h = 0; 01721 d->optional[o].range.ih = '.'; 01722 o++; 01723 } 01724 } 01725 01726 // extra required 01727 d->required[r].key = strdup ("Type"); 01728 d->required[r].type = PROP_STR; 01729 d->required[r].defaultval.d = PROP_NO_VAL; 01730 d->required[r].defaultval.s = PROP_NO_STR; 01731 d->required[r].range.il = '.'; 01732 d->required[r].range.l = 0; 01733 d->required[r].range.h = 0; 01734 d->required[r].range.ih = '.'; 01735 return d; 01736 } 01737 01738 /* The function destroys the given circuit definition which must have 01739 been dynamically created before. */ 01740 static void netlist_free_define (struct define_t * d) 01741 { 01742 int i; 01743 struct property_t * p; 01744 free ((char *) d->type); 01745 // free required properties 01746 for (i = 0, p = d->required; p[i].key != NULL; i++) 01747 { 01748 free ((char *) p[i].key); 01749 } 01750 free (d->required); 01751 // free optional properties 01752 for (i = 0, p = d->optional; p[i].key != NULL; i++) 01753 { 01754 free ((char *) p[i].key); 01755 } 01756 free (d->optional); 01757 free (d); 01758 } 01759 01760 /* The function checks the presence of required and optional 01761 properties as well as their content in the given definition. It 01762 returns zero on success and non-zero otherwise. */ 01763 static int checker_validate_properties (struct definition_t * root, 01764 struct definition_t * def, 01765 struct define_t * available) 01766 { 01767 struct pair_t * pair; 01768 int i, n, errors = 0; 01769 01770 /* check whether the required properties are given */ 01771 for (i = 0; PROP_IS_PROP (available->required[i]); i++) 01772 { 01773 n = checker_find_property (available->required[i].key, def->pairs); 01774 if (n != 1) 01775 { 01776 logprint (LOG_ERROR, "line %d: checker error, required property " 01777 "`%s' occurred %dx in `%s:%s'\n", def->line, 01778 available->required[i].key, n, def->type, def->instance); 01779 errors++; 01780 } 01781 } 01782 /* check whether the optional properties are given zero/once */ 01783 for (i = 0; PROP_IS_PROP (available->optional[i]); i++) 01784 { 01785 n = checker_find_property (available->optional[i].key, def->pairs); 01786 if (n >= 2) 01787 { 01788 logprint (LOG_ERROR, "line %d: checker error, optional property " 01789 "`%s' occurred %dx in `%s:%s'\n", def->line, 01790 available->optional[i].key, n, def->type, def->instance); 01791 errors++; 01792 } 01793 } 01794 01795 /* check the property content */ 01796 for (pair = def->pairs; pair != NULL; pair = pair->next) 01797 { 01798 /* check whether properties are either required or optional */ 01799 int type = checker_is_property (available, pair->key); 01800 if (type == PROP_NONE) 01801 { 01802 if (strcmp (def->type, "Def")) 01803 { 01804 logprint (LOG_ERROR, 01805 "line %d: checker error, extraneous property `%s' is " 01806 "invalid in `%s:%s'\n", def->line, 01807 pair->key, def->type, def->instance); 01808 errors++; 01809 } 01810 } 01811 // do not check zero-length lists 01812 if (pair->value != NULL) 01813 { 01814 /* check and evaluate the unit scale in a property */ 01815 if (!checker_evaluate_scale (pair->value)) 01816 errors++; 01817 /* check whether properties are in range */ 01818 if (!checker_value_in_range (def->instance, available, pair)) 01819 { 01820 errors++; 01821 } 01822 /* check variables in properties */ 01823 if (!checker_resolve_variable (root, def, pair, type)) 01824 errors++; 01825 } 01826 } 01827 return errors; 01828 } 01829 01830 /* This function is used by the netlist checker to validate the 01831 subcircuits. It returns zero with no errors and non-zero on 01832 errors. */ 01833 static int checker_validate_subcircuits (struct definition_t * root) 01834 { 01835 int errors = 0; 01836 // go through list of definitions 01837 for (struct definition_t * def = root; def != NULL; def = def->next) 01838 { 01839 // check subcircuit instances 01840 if (!strcmp (def->type, "Sub")) 01841 { 01842 struct value_t * val; 01843 // validate the 'Type' reference 01844 if ((val = checker_validate_reference (def, "Type")) == NULL) 01845 { 01846 errors++; 01847 } 01848 else 01849 { 01850 // find an appropriate subcircuit type 01851 struct definition_t * sub = checker_find_subcircuit (val->ident); 01852 if (sub == NULL) 01853 { 01854 logprint (LOG_ERROR, "line %d: checker error, no such subcircuit " 01855 "`%s' found as referred in `%s:%s'\n", def->line, 01856 val->ident, def->type, def->instance); 01857 errors++; 01858 } 01859 else 01860 { 01861 // check the number of nodes of the instance and the type 01862 int n1 = checker_count_nodes (def); 01863 int n2 = checker_count_nodes (sub); 01864 if (n1 != n2) 01865 { 01866 logprint (LOG_ERROR, "line %d: checker error, subcircuit type " 01867 "`%s' requires %d nodes in `%s:%s', found %d\n", 01868 def->line, sub->instance, n2, 01869 def->type, def->instance, n1); 01870 errors++; 01871 } 01872 // check the subcircuit instance properties 01873 struct define_t * available = netlist_create_define (sub); 01874 errors += checker_validate_properties (root, def, available); 01875 netlist_free_define (available); 01876 // and finally check for cyclic definitions 01877 strlist * deps = new strlist (); 01878 int err = checker_validate_sub_cycles (sub, sub->instance, 01879 def->instance, &deps); 01880 errors += err; 01881 checker_sub_cycles = err; 01882 delete deps; 01883 } 01884 } 01885 } 01886 } 01887 return errors; 01888 } 01889 01890 /* Deletes node list of a definition. */ 01891 static void netlist_free_nodes (struct node_t * node) 01892 { 01893 struct node_t * n; 01894 for (; node != NULL; node = n) 01895 { 01896 n = node->next; 01897 free (node->node); 01898 free (node); 01899 } 01900 } 01901 01902 /* The following function free()'s the given value. */ 01903 static void netlist_free_value (struct value_t * value) 01904 { 01905 free (value->ident); 01906 if (value->unit) free (value->unit); 01907 free (value->scale); 01908 free (value); 01909 } 01910 01911 /* Deletes pair list of a definition. */ 01912 static void netlist_free_pairs (struct pair_t * pp) 01913 { 01914 struct pair_t * np; 01915 for (; pp != NULL; pp = np) 01916 { 01917 np = pp->next; 01918 struct value_t * nv, * value; 01919 for (value = pp->value; value != NULL; value = nv) 01920 { 01921 nv = value->next; 01922 netlist_free_value (value); 01923 } 01924 free (pp->key); 01925 free (pp); 01926 } 01927 } 01928 01929 /* Deletes the given definition. */ 01930 static void netlist_free_definition (struct definition_t * def) 01931 { 01932 netlist_free_nodes (def->nodes); 01933 if (!def->copy) netlist_free_pairs (def->pairs); 01934 free (def->subcircuit); 01935 free (def->type); 01936 free (def->instance); 01937 free (def); 01938 } 01939 01940 /* The function removes the given definition 'cand' from the 01941 definition root. It returns the new definition root. */ 01942 struct definition_t * 01943 netlist_unchain_definition (struct definition_t * root, 01944 struct definition_t * cand) 01945 { 01946 struct definition_t * prev; 01947 if (cand == root) 01948 { 01949 root = cand->next; 01950 netlist_free_definition (cand); 01951 } 01952 else 01953 { 01954 // find previous to the candidate to be deleted 01955 for (prev = root; prev != NULL && prev->next != cand; prev = prev->next) ; 01956 if (prev != NULL) 01957 { 01958 prev->next = cand->next; 01959 netlist_free_definition (cand); 01960 } 01961 } 01962 return root; 01963 } 01964 01965 /* The function expands the subcircuits within the given definition 01966 list and returns the expanded list with the subcircuit definitions 01967 removed. */ 01968 static struct definition_t * 01969 checker_expand_subcircuits (struct definition_t * root, environment * parent) 01970 { 01971 struct definition_t * def, * sub, * copy, * next, * prev; 01972 strlist * instances = NULL; 01973 01974 // go through the list of definitions 01975 for (prev = NULL, def = root; def != NULL; def = next) 01976 { 01977 next = def->next; 01978 // is this a subcircuit instance definition ? 01979 if (!strcmp (def->type, "Sub")) 01980 { 01981 // get the subcircuit type definition 01982 sub = checker_get_subcircuit (def); 01983 // and make a copy of it 01984 copy = checker_copy_subcircuits (sub, def, &instances, parent); 01985 if (instances) 01986 { 01987 delete instances; 01988 instances = NULL; 01989 } 01990 // remove the subcircuit instance from the original list 01991 if (prev) 01992 { 01993 prev->next = next; 01994 } 01995 else 01996 { 01997 root = next; 01998 } 01999 netlist_free_definition (def); 02000 // put the expanded definitions into the netlist 02001 if (copy) 02002 { 02003 struct definition_t * last = checker_find_last_definition (copy); 02004 last->next = root; 02005 if (!prev) prev = last; 02006 root = copy; 02007 } 02008 } 02009 // component in the root environment 02010 else 02011 { 02012 prev = def; 02013 def->env = parent; 02014 } 02015 } 02016 return root; 02017 } 02018 02019 /* This function is the checker routine for a parsed netlist. It 02020 returns zero on success or non-zero if the parsed netlist contained 02021 errors. */ 02022 static int netlist_checker_intern (struct definition_t * root) 02023 { 02024 struct definition_t * def; 02025 struct define_t * available; 02026 int n, errors = 0; 02027 02028 /* go through all definitions */ 02029 for (def = root; def != NULL; def = def->next) 02030 { 02031 02032 /* check whether the definition type is known */ 02033 available = checker_find_definition (def->type, def->action); 02034 if (available == NULL) 02035 { 02036 logprint (LOG_ERROR, "line %d: checker error, invalid definition type " 02037 "`%s'\n", def->line, def->type); 02038 errors++; 02039 } 02040 else 02041 { 02042 /* mark nodeset definitions */ 02043 def->nodeset = !strcmp (def->type, "NodeSet") ? 1 : 0; 02044 /* mark nonlinear circuit definitions */ 02045 def->nonlinear = available->nonlinear; 02046 /* mark substrate definitions */ 02047 def->substrate = available->substrate; 02048 /* save available definition */ 02049 def->define = available; 02050 /* check whether the number of nodes is correct and save the 02051 number of given nodes */ 02052 n = def->ncount = checker_count_nodes (def); 02053 if (available->nodes == PROP_NODES) 02054 { 02055 if (n < 1) 02056 { 02057 logprint (LOG_ERROR, 02058 "line %d: checker error, at least 1 node required in " 02059 "`%s:%s', found %d\n", def->line, def->type, 02060 def->instance, n); 02061 errors++; 02062 } 02063 } 02064 else if (available->nodes != n) 02065 { 02066 logprint (LOG_ERROR, 02067 "line %d: checker error, %d node(s) required in `%s:%s', " 02068 "found %d\n", def->line, 02069 available->nodes, def->type, def->instance, n); 02070 errors++; 02071 } 02072 /* check the properties except for subcircuits */ 02073 if (strcmp (def->type, "Sub")) 02074 { 02075 errors += checker_validate_properties (root, def, available); 02076 } 02077 } 02078 /* check the number of definitions */ 02079 n = checker_count_definition (root, def->type, def->instance); 02080 if (n != 1 && def->duplicate == 0) 02081 { 02082 logprint (LOG_ERROR, "checker error, found %d definitions of `%s:%s'\n", 02083 n, def->type, def->instance); 02084 errors++; 02085 } 02086 } 02087 /* check microstrip definitions */ 02088 errors += checker_validate_strips (root); 02089 /* check subcircuit definitions */ 02090 errors += checker_validate_subcircuits (root); 02091 /* check nodeset definitions */ 02092 errors += checker_validate_nodesets (root); 02093 return errors; 02094 } 02095 02096 #if DEBUG 02097 /* Debug function: Prints value representation. */ 02098 static void netlist_list_value (struct value_t * value) 02099 { 02100 if (value == NULL) 02101 logprint (LOG_STATUS, "[]"); 02102 else if (value->ident) 02103 logprint (LOG_STATUS, "%s", value->ident); 02104 else if (value->next) 02105 { 02106 logprint (LOG_STATUS, "["); 02107 for (; value != NULL; value = value->next) 02108 logprint (LOG_STATUS, "%g%s", value->value, value->next ? ";" : ""); 02109 logprint (LOG_STATUS, "]"); 02110 } 02111 else 02112 { 02113 logprint (LOG_STATUS, "%g", value->value); 02114 if (value->scale) 02115 logprint (LOG_STATUS, "%s", value->scale); 02116 if (value->unit) 02117 logprint (LOG_STATUS, "%s", value->unit); 02118 } 02119 } 02120 02121 /* Debug function: Prints definition list representation. */ 02122 static void netlist_lister (struct definition_t * root, const char * prefix) 02123 { 02124 struct definition_t * def; 02125 struct node_t * node; 02126 struct pair_t * pair; 02127 for (def = root; def != NULL; def = def->next) 02128 { 02129 logprint (LOG_STATUS, "%s%s:%s", prefix, def->type, def->instance); 02130 for (node = def->nodes; node != NULL; node = node->next) 02131 { 02132 logprint (LOG_STATUS, " %s", node->node); 02133 } 02134 for (pair = def->pairs; pair != NULL; pair = pair->next) 02135 { 02136 logprint (LOG_STATUS, " %s=\"", pair->key); 02137 netlist_list_value (pair->value); 02138 logprint (LOG_STATUS, "\""); 02139 } 02140 logprint (LOG_STATUS, "\n"); 02141 } 02142 } 02143 02144 /* Debug function: Prints the overall netlist representation. */ 02145 void netlist_list (void) 02146 { 02147 struct definition_t * def; 02148 logprint (LOG_STATUS, "subcircuit %s\n", "root"); 02149 netlist_lister (definition_root, " "); 02150 for (def = subcircuit_root; def != NULL; def = def->next) 02151 { 02152 logprint (LOG_STATUS, "subcircuit %s\n", def->instance); 02153 netlist_lister (def->sub, " "); 02154 } 02155 } 02156 #endif /* DEBUG */ 02157 02158 /* The function logs the content of the current netlist by telling how 02159 many instances of which kind of components are used in the netlist. */ 02160 void netlist_status (void) 02161 { 02162 struct define_t * def; 02163 struct definition_t * cir; 02164 int count; 02165 logprint (LOG_STATUS, "netlist content\n"); 02166 hashiterator<module> it; 02167 for (it = hashiterator<module> (module::modules); *it; ++it) 02168 { 02169 def = it.currentVal()->definition; 02170 for (count = 0, cir = definition_root; cir != NULL; cir = cir->next) 02171 { 02172 if (!strcmp (def->type, cir->type)) count++; 02173 } 02174 if (count > 0) 02175 { 02176 logprint (LOG_STATUS, " %5d %s instances\n", count, def->type); 02177 } 02178 } 02179 } 02180 02181 /* The function builds the equation list for a given list of 02182 definition and removes the definition containing the equations from 02183 the list. */ 02184 static struct definition_t * 02185 checker_build_equations (struct definition_t * root, eqn::node ** eroot) 02186 { 02187 struct definition_t * def, * next, * prev; 02188 eqn::node * eqns, * last; 02189 *eroot = NULL; 02190 // go through list of definitions 02191 for (prev = NULL, def = root; def != NULL; def = next) 02192 { 02193 next = def->next; 02194 if (!strcmp (def->type, "Eqn")) 02195 { 02196 // rechain definition list 02197 if (prev) 02198 { 02199 prev->next = next; 02200 } 02201 else 02202 { 02203 root = next; 02204 } 02205 // append equations 02206 eqns = (eqn::node *) def->eqns; 02207 last = eqn::checker::lastEquation (eqns); 02208 last->setNext (*eroot); 02209 *eroot = eqns; 02210 // free this definition 02211 netlist_free_definition (def); 02212 } 02213 else prev = def; 02214 } 02215 return root; 02216 } 02217 02218 /* The function creates an environment for the given definition root 02219 including equation checker and solver. */ 02220 static void checker_setup_env (struct definition_t * root, 02221 environment * env, eqn::node * eqns) 02222 { 02223 // create equation checker 02224 eqn::checker * checkee = new eqn::checker (); 02225 // pass equations to the checker 02226 checkee->setEquations (eqns); 02227 // add constants to the list of equations 02228 checkee->constants (); 02229 // pass checker 02230 env->setChecker (checkee); 02231 // create equation solver 02232 eqn::solver * solvee = new eqn::solver (checkee); 02233 // pass solver 02234 env->setSolver (solvee); 02235 // apply environment to the netlist root 02236 if (root) root->env = env; 02237 } 02238 02239 /* Adds the arguments of a subcircuit into the equation checker of the 02240 given environment. */ 02241 static void checker_subcircuit_args (struct definition_t * def, 02242 environment * env) 02243 { 02244 for (struct pair_t * pair = def->pairs; pair != NULL; pair = pair->next) 02245 { 02246 // anything else than the 'Type' 02247 if (strcmp (pair->key, "Type")) 02248 { 02249 // put it into the equation checker 02250 env->getChecker()->addDouble ("#subcircuit", 02251 pair->key, pair->value->value); 02252 // also put it into the environment 02253 variable * v = checker_add_variable (env, pair->key, TAG_DOUBLE, true); 02254 v->getConstant()->d = pair->value->value; 02255 } 02256 } 02257 } 02258 02259 /* This is the global netlist checker. It returns zero on success and 02260 non-zero on errors. */ 02261 int netlist_checker (environment * env) 02262 { 02263 int errors = 0; 02264 eqn::node * eqns; 02265 struct definition_t * def; 02266 02267 // create top-level environment 02268 env_root = new environment (env->getName ()); 02269 // create the subcircuit list 02270 definition_root = checker_build_subcircuits (definition_root); 02271 // get equation list 02272 definition_root = checker_build_equations (definition_root, &eqns); 02273 // setup the root environment 02274 checker_setup_env (definition_root, env_root, eqns); 02275 // check list of subcircuits 02276 errors += netlist_checker_intern (subcircuit_root); 02277 // check global netlist 02278 errors += netlist_checker_intern (definition_root); 02279 // check equations in root 02280 env_root->setDefinitions (definition_root); 02281 errors += env_root->equationChecker (0); 02282 env_root->setDefinitions (NULL); 02283 02284 // then check each subcircuit list 02285 for (def = subcircuit_root; def != NULL; def = def->next) 02286 { 02287 // get equation list 02288 def->sub = checker_build_equations (def->sub, &eqns); 02289 // setup the subcircuit environment 02290 environment * subenv = new environment (def->instance); 02291 env_root->push_front_Child (subenv); 02292 checker_setup_env (def, subenv, eqns); 02293 if (def->sub) def->sub->env = subenv; 02294 // add subcircuit parameters to equations 02295 checker_subcircuit_args (def, subenv); 02296 // check subcircuit netlist 02297 errors += netlist_checker_intern (def->sub); 02298 // check equations in subcircuit 02299 subenv->setDefinitions (def->sub); 02300 errors += subenv->equationChecker (0); 02301 subenv->setDefinitions (NULL); 02302 } 02303 02304 // check actions 02305 errors += checker_validate_actions (definition_root); 02306 02307 if (!errors) 02308 { 02309 // create actual root environment 02310 env->copy (*env_root); 02311 // and finally expand the subcircuits into the global netlist 02312 definition_root = checker_expand_subcircuits (definition_root, env); 02313 } 02314 02315 return errors ? -1 : 0; 02316 } 02317 02318 /* The function deletes the given definition list. */ 02319 static void netlist_destroy_intern (struct definition_t * root) 02320 { 02321 struct definition_t * def, * next; 02322 for (def = root; def != NULL; def = next) 02323 { 02324 next = def->next; 02325 netlist_free_definition (def); 02326 } 02327 } 02328 02329 /* Deletes all available definition lists. */ 02330 void netlist_destroy (void) 02331 { 02332 netlist_destroy_intern (definition_root); 02333 for (struct definition_t * def = subcircuit_root; def; def = def->next) 02334 { 02335 netlist_destroy_intern (def->sub); 02336 } 02337 netlist_destroy_intern (subcircuit_root); 02338 definition_root = subcircuit_root = NULL; 02339 netlist_lex_destroy (); 02340 } 02341 02342 /* Delete root environment(s) if necessary. */ 02343 void netlist_destroy_env (void) 02344 { 02345 if (env_root != NULL) 02346 { 02347 delete env_root; 02348 env_root = NULL; 02349 } 02350 } 02351