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