Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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$
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.
55  fd = stdin;
56  subnet = NULL;
57  env = NULL;
58 }
59 
60 // Constructor creates an named instance of the input class.
61 input::input (char * file) : object (file) {
62  if ((fd = fopen (file, "r")) == NULL) {
63  logprint (LOG_ERROR, "cannot open file `%s': %s, using stdin instead\n",
64  file, strerror (errno));
65  fd = stdin;
66  }
67  subnet = NULL;
68  env = NULL;
69 }
70 
71 // Destructor deletes an input object.
73  if (fd != stdin) fclose (fd);
74 }
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 int input::netlist (net * netlist) {
82 
83  // tell the scanner to use the specified file
84  netlist_in = getFile ();
85 
86  // save the netlist object
87  subnet = netlist;
88 
89  logprint (LOG_STATUS, "parsing netlist...\n");
90 
91  if (netlist_parse () != 0)
92  return -1;
93 
94  logprint (LOG_STATUS, "checking netlist...\n");
95  if (netlist_checker (env) != 0)
96  return -1;
97 
98  if (netlist_checker_variables (env) != 0)
99  return -1;
100 
101 #if DEBUG
102  netlist_list ();
103 #endif /* DEBUG */
104  netlist_status ();
105 
106  logprint (LOG_STATUS, "creating netlist...\n");
107  factory ();
108 
109  netlist_destroy ();
110  return 0;
111 }
112 
113 /* The little helper function creates a vector given by the list of
114  values. */
116  qucs::vector * v = new qucs::vector ();
117  for (; values != NULL; values = values->next) v->add (values->value);
118  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 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  for (def = definition_root; def != NULL; def = next) {
137  next = def->next;
138  // handle actions
139  if (def->action) {
140  if ((a = createAnalysis (def->type)) != NULL) {
141  a->setName (def->instance);
142 
143  // add the properties to analysis
144  for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
145  if (pairs->value->ident) {
146  if (pairs->value->var && strcmp (pairs->key, "Param")) {
147  variable * v;
148  if ((v = def->env->getVariable (pairs->value->ident)) != NULL) {
149  // equation variable reference in analysis property
150  a->addProperty (pairs->key, v);
151  }
152  else {
153  // should not be reached!
154  a->addProperty (pairs->key, pairs->value->ident);
155  }
156  }
157  else {
158  // ususal string property
159  a->addProperty (pairs->key, pairs->value->ident);
160  }
161  } else {
162  if (pairs->value->var) {
163  // add list sweeps and constants to the properties
164  variable * v = new variable (pairs->key);
165  eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
166  c->v = createVector (pairs->value);
167  v->setConstant (c);
168  a->addProperty (pairs->key, v);
169  }
170  else {
171  a->addProperty (pairs->key, pairs->value->value);
172  }
173  }
174  // additionally add missing optional properties
176  a->setEnv (def->env);
177  subnet->insertAnalysis (a);
178  }
179  // remove this definition from the list
181  }
182  }
183 
184  // go through the list of input definitions
185  for (def = definition_root; def != NULL; def = next) {
186  next = def->next;
187  // handle substrate definitions
188  if (!def->action && def->substrate) {
189  if ((s = createSubstrate (def->type)) != NULL) {
190  s->setName (def->instance);
191 
192  // add the properties to substrate
193  for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
194  if (pairs->value->ident) {
195  // a variable
196  if (pairs->value->var) {
197  // at this stage it should be ensured that the variable is
198  // already in the root environment
199  variable * v = def->env->getVariable (pairs->value->ident);
200  s->addProperty (pairs->key, v);
201  }
202  // a usual string property
203  else {
204  s->addProperty (pairs->key, pairs->value->ident);
205  }
206  } else {
207  s->addProperty (pairs->key, pairs->value->value);
208  }
209  // additionally add missing optional properties
211 
212  // put new substrate definition into environment
213  char * n = strrchr (def->instance, '.');
214  variable * v = new variable (n ? n + 1 : def->instance);
215  v->setSubstrate (s);
216  def->env->addVariable (v);
217  }
218  // remove this definition from the list
220  }
221  // handle nodeset definitions
222  else if (!def->action && def->nodeset) {
223  n = new nodeset ();
224  n->setName (def->nodes->node);
225  n->setValue (def->pairs->value->value);
226  subnet->addNodeset (n);
227  // remove this definition from the list
229  }
230  }
231 
232  // go through the list of input definitions
233  for (def = definition_root; def != NULL; def = next) {
234  next = def->next;
235  // handle component definitions
236  if (!def->action && !def->substrate && !def->nodeset) {
237  c = createCircuit (def->type);
238  assert (c != NULL);
239  o = (object *) c;
240  c->setName (def->instance);
241  c->setNonLinear (def->nonlinear != 0);
242  c->setSubcircuit (def->subcircuit);
243 
244  // change size (number of ports) of variable sized components
245  if (c->isVariableSized ()) {
246  c->setSize (def->ncount);
247  }
248  // add appropriate nodes to circuit
249  for (i = 0, nodes = def->nodes; nodes; nodes = nodes->next, i++)
250  if (i < c->getSize ())
251  c->setNode (i, nodes->node);
252 
253  // add the properties to circuit
254  for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) {
255  if (pairs->value == NULL) {
256  // zero-length value lists
257  variable * v = new variable (pairs->key);
258  eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
259  c->v = new qucs::vector ();
260  v->setConstant (c);
261  o->addProperty (pairs->key, v);
262  }
263  else if (pairs->value->ident) {
264  if (pairs->value->var) {
265  // at this stage it should be ensured that the variable is
266  // already in the root environment
267  variable * v = def->env->getVariable (pairs->value->ident);
268  o->addProperty (pairs->key, v);
269  } else {
270  if (pairs->value->subst) {
271  variable * v = def->env->getVariable (pairs->value->ident);
272  c->setSubstrate (v->getSubstrate ());
273  }
274  o->addProperty (pairs->key, pairs->value->ident);
275  }
276  } else {
277  if (pairs->value->var) {
278  // add value lists to the properties
279  variable * v = new variable (pairs->key);
280  eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
281  c->v = createVector (pairs->value);
282  v->setConstant (c);
283  o->addProperty (pairs->key, v);
284  } else {
285  o->addProperty (pairs->key, pairs->value->value);
286  }
287  }
288  }
289  // set local circuit environment
290  c->setEnv (def->env);
291 
292  // additionally add missing optional properties
294 
295  // insert the circuit into the netlist object
296  subnet->insertCircuit (c);
297 
298  // remove this definition from the list
300  }
301  }
302 }
303 
304 /* This static function applies the optional missing properties's
305  default values to the given object. */
306 void input::assignDefaultProperties (object * obj, struct define_t * def) {
307  // go through optional properties
308  for (int i = 0; PROP_IS_PROP (def->optional[i]); i++) {
309  // is the property already assigned ?
310  if (!obj->hasProperty (def->optional[i].key)) {
311  property * p;
312  if (PROP_IS_VAL (def->optional[i])) {
313  // add double property
314  p = obj->addProperty (def->optional[i].key,
315  def->optional[i].defaultval.d);
316  p->setDefault (true);
317  }
318  else {
319  // add string property
320  p = obj->addProperty (def->optional[i].key,
321  def->optional[i].defaultval.s);
322  p->setDefault (true);
323  }
324  }
325  }
326 }
327 
328 // The function creates components specified by the type of component.
330  module * m;
331  if ((m = module::modules.get (type)) != NULL)
332  return m->circreate ();
333 
334  logprint (LOG_ERROR, "no such circuit type `%s'\n", type);
335  return NULL;
336 }
337 
338 // The function creates an analysis specified by the type of analysis.
340  module * m;
341  if ((m = module::modules.get (type)) != NULL)
342  return m->anacreate ();
343 
344  logprint (LOG_ERROR, "no such analysis type `%s'\n", type);
345  return NULL;
346 }
347 
348 // The function creates a substrate specified by the type of substrate.
350  if (!strcmp (type, "SUBST"))
351  return new substrate ();
352 
353  logprint (LOG_ERROR, "no such substrate type `%s'\n", type);
354  return NULL;
355 }
356 
357 } // namespace qucs
void netlist_list(void)
FILE * netlist_in
Definition: parse_netlist.y:37
void setSubcircuit(char *)
Definition: circuit.cpp:312
void setName(char *)
Definition: nodeset.cpp:76
Definition: netdefs.h:33
int substrate
Definition: netdefs.h:72
void insertAnalysis(analysis *)
Definition: net.cpp:183
int subst
Definition: netdefs.h:47
int netlist_checker_variables(environment *env)
struct node_t * nodes
Definition: netdefs.h:64
struct node_t * next
Definition: netdefs.h:37
void setEnv(environment *e)
Definition: analysis.h:185
struct value_t * next
Definition: netdefs.h:50
char * type
Definition: netdefs.h:62
bool hasProperty(const char *)
Definition: object.cpp:206
const char * key
Definition: netdefs.h:86
object * next
Definition: object.h:88
int var
Definition: netdefs.h:46
n
Definition: parse_citi.y:147
int action
Definition: netdefs.h:71
int netlist_parse(void)
double value
Definition: netdefs.h:45
Definition: netdefs.h:54
int netlist_checker(environment *env)
char * ident
Definition: netdefs.h:42
char * instance
Definition: netdefs.h:63
char * node
Definition: netdefs.h:34
i
Definition: parse_mdl.y:516
int netlist_check
Definition: input.cpp:51
struct value_t * value
Definition: netdefs.h:56
analysis * createAnalysis(char *)
Definition: input.cpp:339
circuit_creator_t circreate
Definition: module.h:70
void setName(const char *)
Definition: object.cpp:78
base class for qucs circuit elements.
Definition: circuit.h:92
int netlist(net *)
Definition: input.cpp:81
struct property_t::@6 defaultval
void netlist_destroy(void)
FILE * getFile(void)
Definition: input.h:42
void addProperty(property *)
Definition: object.cpp:89
void setSize(int)
Set the number of ports the circuit element has.
Definition: circuit.cpp:195
int nodeset
Definition: netdefs.h:74
void setSubstrate(substrate *s)
Definition: variable.h:72
void setValue(nr_double_t val)
Definition: nodeset.h:43
void add(nr_complex_t)
Definition: vector.cpp:151
const char * s
Definition: netdefs.h:90
environment * env
Definition: input.h:56
static qucs::hash< module > modules
Definition: module.h:66
substrate * getSubstrate(void)
Definition: variable.h:73
char * subcircuit
Definition: netdefs.h:79
void insertCircuit(circuit *)
Definition: net.cpp:111
int nonlinear
Definition: netdefs.h:73
struct define_t * define
Definition: netdefs.h:81
#define PROP_IS_PROP(prop)
Definition: netdefs.h:178
int ncount
Definition: netdefs.h:77
generic object class.
Definition: object.h:52
nodes
type
Definition: parse_vcd.y:164
#define PROP_IS_VAL(prop)
Definition: netdefs.h:179
void setEnv(environment *e)
Definition: circuit.h:181
v
Definition: parse_zvr.y:141
struct pair_t * pairs
Definition: netdefs.h:65
void netlist_status(void)
struct definition_t * definition_root
void setConstant(eqn::constant *c)
Definition: variable.h:68
Definition: net.h:39
bool isVariableSized(void)
Definition: circuit.h:168
class for performing circuit analyses.
Definition: analysis.h:82
FILE * fd
Definition: input.h:54
void setNonLinear(bool l)
Definition: circuit.h:298
pairs
void setNode(int, const char *, int intern=0)
Definition: circuit.cpp:299
struct property_t * optional
Definition: netdefs.h:109
char * key
Definition: netdefs.h:55
The environment class definition.
substrate * createSubstrate(char *)
Definition: input.cpp:349
static void assignDefaultProperties(object *, struct define_t *)
Definition: input.cpp:306
void addNodeset(nodeset *)
Definition: net.cpp:548
#define LOG_ERROR
Definition: logging.h:28
#define LOG_STATUS
Definition: logging.h:29
analysis_creator_t anacreate
Definition: module.h:71
values
Definition: parse_spice.y:223
variable * getVariable(char *)
struct definition_t * netlist_unchain_definition(struct definition_t *root, struct definition_t *cand)
static qucs::vector * createVector(struct value_t *)
Definition: input.cpp:115
void logprint(int level, const char *format,...)
Definition: logging.c:37
void factory(void)
Definition: input.cpp:123
struct pair_t * next
Definition: netdefs.h:57
struct definition_t * next
Definition: netdefs.h:66
#define strrchr
Definition: compat.h:34
circuit * createCircuit(char *)
Definition: input.cpp:329
net * subnet
Definition: input.h:55
qucs::environment * env
Definition: netdefs.h:68
void addVariable(variable *, bool pass=true)
void setSubstrate(substrate *)
Definition: circuit.cpp:337
nr_double_t d
Definition: netdefs.h:89