Branch data Line data Source code
1 : : /*
2 : : * input.cpp - input netlist class implementation
3 : : *
4 : : * Copyright (C) 2003-2008 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 <errno.h>
33 : : #include <assert.h>
34 : :
35 : : #include "logging.h"
36 : : #include "component.h"
37 : : #include "components.h"
38 : : #include "net.h"
39 : : #include "variable.h"
40 : : #include "property.h"
41 : : #include "environment.h"
42 : : #include "nodeset.h"
43 : : #include "input.h"
44 : : #include "check_netlist.h"
45 : : #include "equation.h"
46 : : #include "module.h"
47 : :
48 : : namespace qucs {
49 : :
50 : : // Global variables.
51 : : int netlist_check = 0;
52 : :
53 : : // Constructor creates an unnamed instance of the input class.
54 : 0 : input::input () : object () {
55 : 0 : fd = stdin;
56 : 0 : subnet = NULL;
57 : 0 : env = NULL;
58 : 0 : }
59 : :
60 : : // Constructor creates an named instance of the input class.
61 : 103 : input::input (char * file) : object (file) {
62 [ + - ]: 103 : if ((fd = fopen (file, "r")) == NULL) {
[ - + # # ]
[ # # ]
63 : : logprint (LOG_ERROR, "cannot open file `%s': %s, using stdin instead\n",
64 [ # # ][ # # ]: 0 : file, strerror (errno));
[ # # ][ # # ]
[ # # ][ # # ]
65 : 0 : fd = stdin;
66 : : }
67 : 103 : subnet = NULL;
68 : 103 : env = NULL;
69 : 103 : }
70 : :
71 : : // Destructor deletes an input object.
72 : 103 : input::~input () {
73 [ + - ][ + - ]: 103 : if (fd != stdin) fclose (fd);
[ # # ][ # # ]
74 [ - + ][ # # ]: 206 : }
75 : :
76 : : /* This function scans, parses and checks a netlist from the input
77 : : file (specified by the constructor call) or stdin if there is no
78 : : such file. Afterwards the function builds the netlist
79 : : representation and stores it into the given netlist object. The
80 : : function returns zero on success and non-zero otherwise. */
81 : 103 : int input::netlist (net * netlist) {
82 : :
83 : : // tell the scanner to use the specified file
84 : 103 : netlist_in = getFile ();
85 : :
86 : : // save the netlist object
87 : 103 : subnet = netlist;
88 : :
89 : 103 : logprint (LOG_STATUS, "parsing netlist...\n");
90 : :
91 [ - + ]: 103 : if (netlist_parse () != 0)
92 : 0 : return -1;
93 : :
94 : 103 : logprint (LOG_STATUS, "checking netlist...\n");
95 [ - + ]: 103 : if (netlist_checker (env) != 0)
96 : 0 : return -1;
97 : :
98 [ - + ]: 103 : if (netlist_checker_variables (env) != 0)
99 : 0 : return -1;
100 : :
101 : : #if DEBUG
102 : 103 : netlist_list ();
103 : : #endif /* DEBUG */
104 : 103 : netlist_status ();
105 : :
106 : 103 : logprint (LOG_STATUS, "creating netlist...\n");
107 : 103 : factory ();
108 : :
109 : 103 : netlist_destroy ();
110 : 103 : return 0;
111 : : }
112 : :
113 : : /* The little helper function creates a vector given by the list of
114 : : values. */
115 : 6 : qucs::vector * input::createVector (struct value_t * values) {
116 [ + - ]: 6 : qucs::vector * v = new qucs::vector ();
117 [ + - ][ + + ]: 24 : for (; values != NULL; values = values->next) v->add (values->value);
118 : 6 : return v;
119 : : }
120 : :
121 : : /* This function builds up the netlist representation from the checked
122 : : netlist input. It creates circuit components as necessary. */
123 : 103 : void input::factory (void) {
124 : :
125 : : struct definition_t * def, * next;
126 : : struct node_t * nodes;
127 : : struct pair_t * pairs;
128 : : circuit * c;
129 : : object * o;
130 : : analysis * a;
131 : : substrate * s;
132 : : nodeset * n;
133 : : int i;
134 : :
135 : : // go through the list of input definitions
136 [ + + ]: 1222 : for (def = definition_root; def != NULL; def = next) {
137 : 1119 : next = def->next;
138 : : // handle actions
139 [ + + ]: 1119 : if (def->action) {
140 [ + - ]: 181 : if ((a = createAnalysis (def->type)) != NULL) {
141 : 181 : a->setName (def->instance);
142 : :
143 : : // add the properties to analysis
144 [ + + ]: 1968 : for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
145 [ + + ]: 1787 : if (pairs->value->ident) {
146 [ + + ][ + + ]: 674 : if (pairs->value->var && strcmp (pairs->key, "Param")) {
147 : : variable * v;
148 [ + - ]: 11 : if ((v = def->env->getVariable (pairs->value->ident)) != NULL) {
149 : : // equation variable reference in analysis property
150 : 11 : a->addProperty (pairs->key, v);
151 : : }
152 : : else {
153 : : // should not be reached!
154 : 0 : a->addProperty (pairs->key, pairs->value->ident);
155 : 11 : }
156 : : }
157 : : else {
158 : : // ususal string property
159 : 674 : a->addProperty (pairs->key, pairs->value->ident);
160 : : }
161 : : } else {
162 [ + + ]: 1113 : if (pairs->value->var) {
163 : : // add list sweeps and constants to the properties
164 [ + - ]: 4 : variable * v = new variable (pairs->key);
165 [ + - ]: 4 : eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
166 : 4 : c->v = createVector (pairs->value);
167 : 4 : v->setConstant (c);
168 : 4 : a->addProperty (pairs->key, v);
169 : : }
170 : : else {
171 : 1109 : a->addProperty (pairs->key, pairs->value->value);
172 : : }
173 : : }
174 : : // additionally add missing optional properties
175 : 181 : assignDefaultProperties (a, def->define);
176 : 181 : a->setEnv (def->env);
177 : 181 : subnet->insertAnalysis (a);
178 : : }
179 : : // remove this definition from the list
180 : 181 : definition_root = netlist_unchain_definition (definition_root, def);
181 : : }
182 : : }
183 : :
184 : : // go through the list of input definitions
185 [ + + ]: 1041 : for (def = definition_root; def != NULL; def = next) {
186 : 938 : next = def->next;
187 : : // handle substrate definitions
188 [ + - ][ + + ]: 938 : if (!def->action && def->substrate) {
189 [ + - ]: 3 : if ((s = createSubstrate (def->type)) != NULL) {
190 : 3 : s->setName (def->instance);
191 : :
192 : : // add the properties to substrate
193 [ + + ]: 21 : for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
194 [ - + ]: 18 : if (pairs->value->ident) {
195 : : // a variable
196 [ # # ]: 0 : if (pairs->value->var) {
197 : : // at this stage it should be ensured that the variable is
198 : : // already in the root environment
199 : 0 : variable * v = def->env->getVariable (pairs->value->ident);
200 : 0 : s->addProperty (pairs->key, v);
201 : : }
202 : : // a usual string property
203 : : else {
204 : 0 : s->addProperty (pairs->key, pairs->value->ident);
205 : : }
206 : : } else {
207 : 18 : s->addProperty (pairs->key, pairs->value->value);
208 : : }
209 : : // additionally add missing optional properties
210 : 3 : assignDefaultProperties (s, def->define);
211 : :
212 : : // put new substrate definition into environment
213 : 3 : char * n = strrchr (def->instance, '.');
214 [ - + ][ + - ]: 3 : variable * v = new variable (n ? n + 1 : def->instance);
215 : 3 : v->setSubstrate (s);
216 : 3 : def->env->addVariable (v);
217 : : }
218 : : // remove this definition from the list
219 : 3 : definition_root = netlist_unchain_definition (definition_root, def);
220 : : }
221 : : // handle nodeset definitions
222 [ + - ][ + + ]: 935 : else if (!def->action && def->nodeset) {
223 [ + - ]: 2 : n = new nodeset ();
224 : 2 : n->setName (def->nodes->node);
225 : 2 : n->setValue (def->pairs->value->value);
226 : 2 : subnet->addNodeset (n);
227 : : // remove this definition from the list
228 : 2 : definition_root = netlist_unchain_definition (definition_root, def);
229 : : }
230 : : }
231 : :
232 : : // go through the list of input definitions
233 [ + + ]: 1036 : for (def = definition_root; def != NULL; def = next) {
234 : 933 : next = def->next;
235 : : // handle component definitions
236 [ + - ][ + - ]: 933 : if (!def->action && !def->substrate && !def->nodeset) {
[ + - ]
237 : 933 : c = createCircuit (def->type);
238 [ - + ]: 933 : assert (c != NULL);
239 : 933 : o = (object *) c;
240 : 933 : c->setName (def->instance);
241 : 933 : c->setNonLinear (def->nonlinear != 0);
242 : 933 : c->setSubcircuit (def->subcircuit);
243 : :
244 : : // change size (number of ports) of variable sized components
245 [ - + ]: 933 : if (c->isVariableSized ()) {
246 : 0 : c->setSize (def->ncount);
247 : : }
248 : : // add appropriate nodes to circuit
249 [ + + ]: 3056 : for (i = 0, nodes = def->nodes; nodes; nodes = nodes->next, i++)
250 [ + - ]: 2123 : if (i < c->getSize ())
251 : 2123 : c->setNode (i, nodes->node);
252 : :
253 : : // add the properties to circuit
254 [ + + ]: 9475 : for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) {
255 [ - + ]: 8542 : if (pairs->value == NULL) {
256 : : // zero-length value lists
257 [ # # ]: 0 : variable * v = new variable (pairs->key);
258 [ # # ]: 0 : eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
259 [ # # ]: 0 : c->v = new qucs::vector ();
260 : 0 : v->setConstant (c);
261 : 0 : o->addProperty (pairs->key, v);
262 : : }
263 [ + + ]: 8542 : else if (pairs->value->ident) {
264 [ + + ]: 251 : if (pairs->value->var) {
265 : : // at this stage it should be ensured that the variable is
266 : : // already in the root environment
267 : 96 : variable * v = def->env->getVariable (pairs->value->ident);
268 : 96 : o->addProperty (pairs->key, v);
269 : : } else {
270 [ + + ]: 155 : if (pairs->value->subst) {
271 : 24 : variable * v = def->env->getVariable (pairs->value->ident);
272 : 24 : c->setSubstrate (v->getSubstrate ());
273 : : }
274 : 155 : o->addProperty (pairs->key, pairs->value->ident);
275 : : }
276 : : } else {
277 [ + + ]: 8291 : if (pairs->value->var) {
278 : : // add value lists to the properties
279 [ + - ]: 2 : variable * v = new variable (pairs->key);
280 [ + - ]: 2 : eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
281 : 2 : c->v = createVector (pairs->value);
282 : 2 : v->setConstant (c);
283 : 2 : o->addProperty (pairs->key, v);
284 : : } else {
285 : 8289 : o->addProperty (pairs->key, pairs->value->value);
286 : : }
287 : : }
288 : : }
289 : : // set local circuit environment
290 : 933 : c->setEnv (def->env);
291 : :
292 : : // additionally add missing optional properties
293 : 933 : assignDefaultProperties (c, def->define);
294 : :
295 : : // insert the circuit into the netlist object
296 : 933 : subnet->insertCircuit (c);
297 : :
298 : : // remove this definition from the list
299 : 933 : definition_root = netlist_unchain_definition (definition_root, def);
300 : : }
301 : : }
302 : 103 : }
303 : :
304 : : /* This static function applies the optional missing properties's
305 : : default values to the given object. */
306 : 1117 : void input::assignDefaultProperties (object * obj, struct define_t * def) {
307 : : // go through optional properties
308 [ + + ]: 6471 : for (int i = 0; PROP_IS_PROP (def->optional[i]); i++) {
309 : : // is the property already assigned ?
310 [ + + ]: 5354 : if (!obj->hasProperty (def->optional[i].key)) {
311 : : property * p;
312 [ + - ]: 545 : if (PROP_IS_VAL (def->optional[i])) {
313 : : // add double property
314 : 545 : p = obj->addProperty (def->optional[i].key,
315 : 545 : def->optional[i].defaultval.d);
316 : 545 : p->setDefault (true);
317 : : }
318 : : else {
319 : : // add string property
320 : 0 : p = obj->addProperty (def->optional[i].key,
321 : 0 : def->optional[i].defaultval.s);
322 : 0 : p->setDefault (true);
323 : : }
324 : : }
325 : : }
326 : 1117 : }
327 : :
328 : : // The function creates components specified by the type of component.
329 : 933 : circuit * input::createCircuit (char * type) {
330 : : module * m;
331 [ + - ]: 933 : if ((m = module::modules.get (type)) != NULL)
332 : 933 : return m->circreate ();
333 : :
334 : 0 : logprint (LOG_ERROR, "no such circuit type `%s'\n", type);
335 : 933 : return NULL;
336 : : }
337 : :
338 : : // The function creates an analysis specified by the type of analysis.
339 : 181 : analysis * input::createAnalysis (char * type) {
340 : : module * m;
341 [ + - ]: 181 : if ((m = module::modules.get (type)) != NULL)
342 : 181 : return m->anacreate ();
343 : :
344 : 0 : logprint (LOG_ERROR, "no such analysis type `%s'\n", type);
345 : 181 : return NULL;
346 : : }
347 : :
348 : : // The function creates a substrate specified by the type of substrate.
349 : 3 : substrate * input::createSubstrate (char * type) {
350 [ + - ]: 3 : if (!strcmp (type, "SUBST"))
351 [ + - ]: 3 : return new substrate ();
352 : :
353 : 0 : logprint (LOG_ERROR, "no such substrate type `%s'\n", type);
354 : 3 : return NULL;
355 : : }
356 : :
357 : : } // namespace qucs
|