Qucs-core
0.0.19
|
00001 /* 00002 * input.cpp - input netlist class implementation 00003 * 00004 * Copyright (C) 2003-2008 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 <errno.h> 00033 #include <assert.h> 00034 00035 #include "logging.h" 00036 #include "component.h" 00037 #include "components.h" 00038 #include "net.h" 00039 #include "variable.h" 00040 #include "property.h" 00041 #include "environment.h" 00042 #include "nodeset.h" 00043 #include "input.h" 00044 #include "check_netlist.h" 00045 #include "equation.h" 00046 #include "module.h" 00047 00048 namespace qucs { 00049 00050 // Global variables. 00051 int netlist_check = 0; 00052 00053 // Constructor creates an unnamed instance of the input class. 00054 input::input () : object () { 00055 fd = stdin; 00056 subnet = NULL; 00057 env = NULL; 00058 } 00059 00060 // Constructor creates an named instance of the input class. 00061 input::input (char * file) : object (file) { 00062 if ((fd = fopen (file, "r")) == NULL) { 00063 logprint (LOG_ERROR, "cannot open file `%s': %s, using stdin instead\n", 00064 file, strerror (errno)); 00065 fd = stdin; 00066 } 00067 subnet = NULL; 00068 env = NULL; 00069 } 00070 00071 // Destructor deletes an input object. 00072 input::~input () { 00073 if (fd != stdin) fclose (fd); 00074 } 00075 00076 /* This function scans, parses and checks a netlist from the input 00077 file (specified by the constructor call) or stdin if there is no 00078 such file. Afterwards the function builds the netlist 00079 representation and stores it into the given netlist object. The 00080 function returns zero on success and non-zero otherwise. */ 00081 int input::netlist (net * netlist) { 00082 00083 // tell the scanner to use the specified file 00084 netlist_in = getFile (); 00085 00086 // save the netlist object 00087 subnet = netlist; 00088 00089 logprint (LOG_STATUS, "parsing netlist...\n"); 00090 00091 if (netlist_parse () != 0) 00092 return -1; 00093 00094 logprint (LOG_STATUS, "checking netlist...\n"); 00095 if (netlist_checker (env) != 0) 00096 return -1; 00097 00098 if (netlist_checker_variables (env) != 0) 00099 return -1; 00100 00101 #if DEBUG 00102 netlist_list (); 00103 #endif /* DEBUG */ 00104 netlist_status (); 00105 00106 logprint (LOG_STATUS, "creating netlist...\n"); 00107 factory (); 00108 00109 netlist_destroy (); 00110 return 0; 00111 } 00112 00113 /* The little helper function creates a vector given by the list of 00114 values. */ 00115 qucs::vector * input::createVector (struct value_t * values) { 00116 qucs::vector * v = new qucs::vector (); 00117 for (; values != NULL; values = values->next) v->add (values->value); 00118 return v; 00119 } 00120 00121 /* This function builds up the netlist representation from the checked 00122 netlist input. It creates circuit components as necessary. */ 00123 void input::factory (void) { 00124 00125 struct definition_t * def, * next; 00126 struct node_t * nodes; 00127 struct pair_t * pairs; 00128 circuit * c; 00129 object * o; 00130 analysis * a; 00131 substrate * s; 00132 nodeset * n; 00133 int i; 00134 00135 // go through the list of input definitions 00136 for (def = definition_root; def != NULL; def = next) { 00137 next = def->next; 00138 // handle actions 00139 if (def->action) { 00140 if ((a = createAnalysis (def->type)) != NULL) { 00141 a->setName (def->instance); 00142 00143 // add the properties to analysis 00144 for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) 00145 if (pairs->value->ident) { 00146 if (pairs->value->var && strcmp (pairs->key, "Param")) { 00147 variable * v; 00148 if ((v = def->env->getVariable (pairs->value->ident)) != NULL) { 00149 // equation variable reference in analysis property 00150 a->addProperty (pairs->key, v); 00151 } 00152 else { 00153 // should not be reached! 00154 a->addProperty (pairs->key, pairs->value->ident); 00155 } 00156 } 00157 else { 00158 // ususal string property 00159 a->addProperty (pairs->key, pairs->value->ident); 00160 } 00161 } else { 00162 if (pairs->value->var) { 00163 // add list sweeps and constants to the properties 00164 variable * v = new variable (pairs->key); 00165 eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR); 00166 c->v = createVector (pairs->value); 00167 v->setConstant (c); 00168 a->addProperty (pairs->key, v); 00169 } 00170 else { 00171 a->addProperty (pairs->key, pairs->value->value); 00172 } 00173 } 00174 // additionally add missing optional properties 00175 assignDefaultProperties (a, def->define); 00176 a->setEnv (def->env); 00177 subnet->insertAnalysis (a); 00178 } 00179 // remove this definition from the list 00180 definition_root = netlist_unchain_definition (definition_root, def); 00181 } 00182 } 00183 00184 // go through the list of input definitions 00185 for (def = definition_root; def != NULL; def = next) { 00186 next = def->next; 00187 // handle substrate definitions 00188 if (!def->action && def->substrate) { 00189 if ((s = createSubstrate (def->type)) != NULL) { 00190 s->setName (def->instance); 00191 00192 // add the properties to substrate 00193 for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) 00194 if (pairs->value->ident) { 00195 // a variable 00196 if (pairs->value->var) { 00197 // at this stage it should be ensured that the variable is 00198 // already in the root environment 00199 variable * v = def->env->getVariable (pairs->value->ident); 00200 s->addProperty (pairs->key, v); 00201 } 00202 // a usual string property 00203 else { 00204 s->addProperty (pairs->key, pairs->value->ident); 00205 } 00206 } else { 00207 s->addProperty (pairs->key, pairs->value->value); 00208 } 00209 // additionally add missing optional properties 00210 assignDefaultProperties (s, def->define); 00211 00212 // put new substrate definition into environment 00213 char * n = strrchr (def->instance, '.'); 00214 variable * v = new variable (n ? n + 1 : def->instance); 00215 v->setSubstrate (s); 00216 def->env->addVariable (v); 00217 } 00218 // remove this definition from the list 00219 definition_root = netlist_unchain_definition (definition_root, def); 00220 } 00221 // handle nodeset definitions 00222 else if (!def->action && def->nodeset) { 00223 n = new nodeset (); 00224 n->setName (def->nodes->node); 00225 n->setValue (def->pairs->value->value); 00226 subnet->addNodeset (n); 00227 // remove this definition from the list 00228 definition_root = netlist_unchain_definition (definition_root, def); 00229 } 00230 } 00231 00232 // go through the list of input definitions 00233 for (def = definition_root; def != NULL; def = next) { 00234 next = def->next; 00235 // handle component definitions 00236 if (!def->action && !def->substrate && !def->nodeset) { 00237 c = createCircuit (def->type); 00238 assert (c != NULL); 00239 o = (object *) c; 00240 c->setName (def->instance); 00241 c->setNonLinear (def->nonlinear != 0); 00242 c->setSubcircuit (def->subcircuit == nullptr ? "" : def->subcircuit); 00243 00244 // change size (number of ports) of variable sized components 00245 if (c->isVariableSized ()) { 00246 c->setSize (def->ncount); 00247 } 00248 // add appropriate nodes to circuit 00249 for (i = 0, nodes = def->nodes; nodes; nodes = nodes->next, i++) 00250 if (i < c->getSize ()) 00251 c->setNode (i, nodes->node); 00252 00253 // add the properties to circuit 00254 for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) { 00255 if (pairs->value == NULL) { 00256 // zero-length value lists 00257 variable * v = new variable (pairs->key); 00258 eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR); 00259 c->v = new qucs::vector (); 00260 v->setConstant (c); 00261 o->addProperty (pairs->key, v); 00262 } 00263 else if (pairs->value->ident) { 00264 if (pairs->value->var) { 00265 // at this stage it should be ensured that the variable is 00266 // already in the root environment 00267 variable * v = def->env->getVariable (pairs->value->ident); 00268 o->addProperty (pairs->key, v); 00269 } else { 00270 if (pairs->value->subst) { 00271 variable * v = def->env->getVariable (pairs->value->ident); 00272 c->setSubstrate (v->getSubstrate ()); 00273 } 00274 o->addProperty (pairs->key, pairs->value->ident); 00275 } 00276 } else { 00277 if (pairs->value->var) { 00278 // add value lists to the properties 00279 variable * v = new variable (pairs->key); 00280 eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR); 00281 c->v = createVector (pairs->value); 00282 v->setConstant (c); 00283 o->addProperty (pairs->key, v); 00284 } else { 00285 o->addProperty (pairs->key, pairs->value->value); 00286 } 00287 } 00288 } 00289 // set local circuit environment 00290 c->setEnv (def->env); 00291 00292 // additionally add missing optional properties 00293 assignDefaultProperties (c, def->define); 00294 00295 // insert the circuit into the netlist object 00296 subnet->insertCircuit (c); 00297 00298 // remove this definition from the list 00299 definition_root = netlist_unchain_definition (definition_root, def); 00300 } 00301 } 00302 } 00303 00304 /* This static function applies the optional missing properties's 00305 default values to the given object. */ 00306 void input::assignDefaultProperties (object * obj, struct define_t * def) { 00307 // go through optional properties 00308 for (int i = 0; PROP_IS_PROP (def->optional[i]); i++) { 00309 // is the property already assigned ? 00310 if (!obj->hasProperty (def->optional[i].key)) { 00311 if (PROP_IS_VAL (def->optional[i])) { 00312 // add double property 00313 obj->addProperty (def->optional[i].key, 00314 def->optional[i].defaultval.d,true); 00315 } 00316 else { 00317 // add string property 00318 obj->addProperty (def->optional[i].key, 00319 def->optional[i].defaultval.s,true); 00320 } 00321 } 00322 } 00323 } 00324 00325 // The function creates components specified by the type of component. 00326 circuit * input::createCircuit (char * type) { 00327 module * m; 00328 if ((m = module::modules.get (type)) != NULL) 00329 return m->circreate (); 00330 00331 logprint (LOG_ERROR, "no such circuit type `%s'\n", type); 00332 return NULL; 00333 } 00334 00335 // The function creates an analysis specified by the type of analysis. 00336 analysis * input::createAnalysis (char * type) { 00337 module * m; 00338 if ((m = module::modules.get (type)) != NULL) 00339 return m->anacreate (); 00340 00341 logprint (LOG_ERROR, "no such analysis type `%s'\n", type); 00342 return NULL; 00343 } 00344 00345 // The function creates a substrate specified by the type of substrate. 00346 substrate * input::createSubstrate (char * type) { 00347 if (!strcmp (type, "SUBST")) 00348 return new substrate (); 00349 00350 logprint (LOG_ERROR, "no such substrate type `%s'\n", type); 00351 return NULL; 00352 } 00353 00354 } // namespace qucs