Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
module.cpp
Go to the documentation of this file.
1 /*
2  * module.cpp - module class implementation
3  *
4  * Copyright (C) 2008, 2009, 2010 Stefan Jahn <stefan@lkcc.org>
5  * New models added Mike Brinson 2013 mbrin72043@yahoo.co.uk
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this package; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * $Id: module.cpp 1872 2013-03-06 14:13:37Z fransschreuder $
23  *
24  */
25 
26 #if HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include <iostream>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <map>
34 #include <list>
35 
36 #include "netdefs.h"
37 #include "components.h"
38 #include "analyses.h"
39 #include "netdefs.h"
40 #include "module.h"
41 
42 #ifdef __MINGW32__
43  #include <windows.h>
44 #else
45  #include <dlfcn.h>
46 #endif
47 
48 #include <cstdlib> //for exit
49 
50 // Global module hash.
51 qucs::hash<module> module::modules;
52 
53 // Our global factories for making loaded circuit objects
54 // The factories are populated as dynamic modules are loaded
55 // factorycreate hold the loaded modules constructor function
56 std::map< std::string, creator_t *, std::less<std::string> > factorycreate;
57 // factorydef hold the loaded modules definitions
58 std::map< std::string, defs_t *, std::less<std::string> > factorydef;
59 
60 #if __MINGW32__
61  std::list<HINSTANCE> dl_list; // list to hold handles for dynamic libs
62  std::list<HINSTANCE>::iterator itr;
63 #else
64  std::list<void *> dl_list; // list to hold handles for dynamic libs
65  std::list<void *>::iterator itr;
66 #endif
67 
68 // Constructor creates an instance of the module class.
69 module::module () {
70  definition = NULL;
71  circreate = NULL;
72  anacreate = NULL;
73 }
74 
75 // Destructor deletes an instance of the module class.
76 module::~module () {
77 }
78 
79 // Definitions which do not fit elsewhere.
80 static struct property_t props1[] = {
81  PROP_NO_PROP };
82 static struct property_t props2[] = {
83  { "Type", PROP_STR, { PROP_NO_VAL, "DEF1" }, PROP_NO_RANGE },
84  PROP_NO_PROP };
85 
88  props1, props1 };
89 
92  props1, props2 };
93 
94 // Registers an analysis object to the list of available modules.
95 void module::registerModule (analysis_definer_t define,
96  analysis_creator_t create) {
97  module * m = new module ();
98  m->definition = define ();
99  m->anacreate = create;
100  modules.put ((char *) define()->type, m);
101 }
102 
103 // Registers a circuit object to the list of available modules.
104 void module::registerModule (circuit_definer_t define,
105  circuit_creator_t create) {
106  module * m = new module ();
107  m->definition = define ();
108  m->circreate = create;
109  registerModule (define()->type, m);
110 }
111 
112 // Registers a miscellaneous object to the list of available modules.
113 void module::registerModule (misc_definer_t define) {
114  module * m = new module ();
115  m->definition = define ();
116  registerModule (define()->type, m);
117 }
118 
119 /* Registers a miscellaneous structure just defined by a somple
120  define_t structure to the list of available modules. */
121 void module::registerModule (struct define_t * define) {
122  module * m = new module ();
123  m->definition = define;
124  registerModule (define->type, m);
125 }
126 
127 // Puts a module into the available module hash.
128 void module::registerModule (const char * type, module * m) {
129  if (modules.get ((char *) type) != NULL) {
130  logprint (LOG_ERROR, "module already registered: %s\n", type);
131  }
132  else {
133  modules.put ((char *) type, m);
134  }
135 }
136 
137 /* Returns the definition of a module specified by its type name if
138  such is existing and otherwise NULL. */
139 struct define_t * module::getModule (char * type) {
140  module * m = modules.get (type);
141  if (m != NULL) {
142  return m->definition;
143  }
144  return NULL;
145 }
146 
147 // Helper macros.
148 #define REGISTER_CIRCUIT(val) \
149  registerModule (&val::definition, &val::create)
150 #define REGISTER_ANALYSIS(val) \
151  registerModule (&val::definition, &val::create)
152 #define REGISTER_MISC(val) \
153  registerModule (&val::definition)
154 
155 // Global static module registration.
156 void module::registerModules (void) {
157 
158  // miscellaneous
159  registerModule (&miscdef1);
160  registerModule (&miscdef2);
163 
164  // circuit components
258  REGISTER_CIRCUIT (hicumL2V2p1);
259  REGISTER_CIRCUIT (HBT_X);
260  REGISTER_CIRCUIT (mod_amp);
261  REGISTER_CIRCUIT (hic2_full);
262  REGISTER_CIRCUIT (log_amp);
263  REGISTER_CIRCUIT (hic0_full);
264  REGISTER_CIRCUIT (potentiometer);
265  REGISTER_CIRCUIT (MESFET);
266  REGISTER_CIRCUIT (EKV26MOS);
267  REGISTER_CIRCUIT (bsim3v34nMOS);
268  REGISTER_CIRCUIT (bsim3v34pMOS);
269  REGISTER_CIRCUIT (bsim4v30nMOS);
270  REGISTER_CIRCUIT (bsim4v30pMOS);
271  REGISTER_CIRCUIT (hicumL0V1p2);
272  REGISTER_CIRCUIT (hicumL0V1p2g);
273  REGISTER_CIRCUIT (hicumL0V1p3);
274  REGISTER_CIRCUIT (hicumL2V2p23);
275  REGISTER_CIRCUIT (hicumL2V2p24);
276  REGISTER_CIRCUIT (hicumL2V2p31n);
277  REGISTER_CIRCUIT (photodiode);
278  REGISTER_CIRCUIT (phototransistor);
279  REGISTER_CIRCUIT (nigbt);
280  REGISTER_CIRCUIT (dff_SR);
281  REGISTER_CIRCUIT (tff_SR);
282  REGISTER_CIRCUIT (jkff_SR);
283  REGISTER_CIRCUIT (gatedDlatch);
284  REGISTER_CIRCUIT (logic_1);
285  REGISTER_CIRCUIT (logic_0);
286  REGISTER_CIRCUIT (mux2to1);
287  REGISTER_CIRCUIT (mux4to1);
288  REGISTER_CIRCUIT (mux8to1);
289  REGISTER_CIRCUIT (DLS_nto1);
290  REGISTER_CIRCUIT (DLS_1ton);
291  REGISTER_CIRCUIT (andor4x2);
292  REGISTER_CIRCUIT (andor4x3);
293  REGISTER_CIRCUIT (andor4x4);
294  REGISTER_CIRCUIT (dmux2to4);
295  REGISTER_CIRCUIT (dmux3to8);
296  REGISTER_CIRCUIT (dmux4to16);
297  REGISTER_CIRCUIT (ha1b);
298  REGISTER_CIRCUIT (fa1b);
299  REGISTER_CIRCUIT (fa2b);
300  REGISTER_CIRCUIT (pad2bit);
301  REGISTER_CIRCUIT (pad3bit);
302  REGISTER_CIRCUIT (pad4bit);
303  REGISTER_CIRCUIT (binarytogrey4bit);
304  REGISTER_CIRCUIT (greytobinary4bit);
305  REGISTER_CIRCUIT (comp_1bit);
306  REGISTER_CIRCUIT (comp_2bit);
307  REGISTER_CIRCUIT (comp_4bit);
308  REGISTER_CIRCUIT (hpribin4bit);
309  REGISTER_CIRCUIT (vcresistor);
311 
312  // analyses
320 }
321 
322 // Global module unregistration.
323 void module::unregisterModules (void) {
325  for (it = qucs::hashiterator<module> (modules); *it; ++it) {
326  delete it.currentVal ();
327  }
328  modules.clear ();
329 }
330 
331 #if DEBUG
332 // header prefix
333 static const char * def_prefix =
334 "/*\n"
335 " * qucsdefs.h - netlist definitions for the Qucs netlists\n"
336 " *\n"
337 " * This is free software; you can redistribute it and/or modify\n"
338 " * it under the terms of the GNU General Public License as published by\n"
339 " * the Free Software Foundation; either version 2, or (at your option)\n"
340 " * any later version.\n"
341 " * \n"
342 " */\n"
343 "\n"
344 "#ifndef __QUCSDEFS_H__\n"
345 "#define __QUCSDEFS_H__\n";
346 
347 // header suffix
348 static const char * def_suffix =
349 "\n"
350 "#endif /* __QUCSDEFS_H__ */\n";
351 
352 // start of list of definitions
353 static const char * def_start =
354 "\n"
355 "// List of available components.\n"
356 "struct define_t qucs_definition_available[] =\n";
357 
358 // end of list entry
359 static const char * def_stop =
360 "\n"
361 "static struct define_t def_End = {\n"
362 " ((char *) 0), -1, 1, 0, 0, req_Def, opt_Def };\n";
363 
364 // Returns a compilable C-code string made from the given string.
365 static char * printstr (const char * str) {
366  static char txt[256];
367  int nostr = (str == PROP_NO_STR);
368  sprintf (txt, "%s%s%s",
369  (str && !nostr) ? "\"" : "",
370  str ? nostr ? "((char *) -1)" : str : "((char *) 0)",
371  (str && !nostr) ? "\"" : "");
372  return txt;
373 }
374 
375 // Prints a property list as compilable C-code.
376 static void printprop (const char * type, const char * prefix,
377  struct property_t * prop) {
378  const char * key;
379  const char ** str;
380  const char * txt;
381  fprintf (stdout, "static struct property_t %s_%s[] = {\n", prefix, type);
382  do {
383  key = prop->key;
384  fprintf (stdout, " { %s, %d, ", printstr (key), prop->type);
385  fprintf (stdout, "{ %g, %s }, ", prop->defaultval.d,
386  printstr (prop->defaultval.s));
387  fprintf (stdout, "{ '%c', %g, %g, '%c',\n",
388  prop->range.il, prop->range.l, prop->range.h, prop->range.ih);
389  fprintf (stdout, " {");
390  str = prop->range.str;
391  do {
392  txt = *str;
393  fprintf (stdout, " %s", printstr (txt));
394  if (txt) fprintf (stdout, ",");
395  str++;
396  }
397  while (txt != NULL);
398  fprintf (stdout, " } } }");
399  if (key) fprintf (stdout, ",");
400  fprintf (stdout, "\n");
401  prop++;
402  }
403  while (key != NULL);
404  fprintf (stdout, "};\n");
405 }
406 
407 /* The function emits a complete list of the registered component
408  definitions as compilable C-code. */
409 void module::print (void) {
410  fprintf (stdout, "%s", def_prefix);
412  for (it = qucs::hashiterator<module> (modules); *it; ++it) {
413  module * m = it.currentVal ();
414  struct define_t * def = m->definition;
415  fprintf (stdout, "\n");
416  printprop (def->type, "req", def->required);
417  fprintf (stdout, "\n");
418  printprop (def->type, "opt", def->optional);
419  fprintf (stdout, "\n");
420  fprintf (stdout, "static struct define_t def_%s = {\n", def->type);
421  fprintf (stdout, " %s, %d, %d, %d, %d, req_%s, opt_%s };\n",
422  printstr (def->type), def->nodes, def->action, def->substrate,
423  def->nonlinear, def->type, def->type);
424  }
425  fprintf (stdout, "%s", def_stop);
426  fprintf (stdout, "%s", def_start);
427  fprintf (stdout, "{\n");
428  for (it = qucs::hashiterator<module> (modules); *it; ++it) {
429  module * m = it.currentVal ();
430  struct define_t * def = m->definition;
431  fprintf (stdout, " def_%s,\n", def->type);
432  }
433  fprintf (stdout, " def_End\n");
434  fprintf (stdout, "};\n");
435  fprintf (stdout, "%s", def_suffix);
436 }
437 #endif /* DEBUG */
438 
439 
440 // look for dynamic libs, load and register them
441 void module::registerDynamicModules (char *proj, std::list<std::string> modlist)
442 {
443 /* How it is (WAS) supposed to work:
444  * 1) It will list the working directory contents looking for libraries
445  * 2) It will try to open each library and put its handle into a list
446  * - Just by opening the lib it will already populate the factorycreate and factorydef
447  * 3) The factory is iterated to create new modules and add them to the global hash
448  *
449  * TODO:
450  * - Add destructor for loaded objects
451  * - Add other methods to find the libraries
452  *
453  * Update
454  * * project path is passed as paramter
455  * * module names are passed as parameter
456 */
457 
458  fprintf(stdout,"project location: %s\n", proj);
459  fprintf(stdout,"modules to load: %lu\n", modlist.size());
460 
461  std::list<std::string>::iterator it;
462  for (it=modlist.begin(); it!=modlist.end(); ++it) {
463 
464  std::string absPathLib = proj;
465 
466 #ifdef __APPLE__
467  absPathLib = absPathLib + "/" + *it + ".dylib";
468 #endif
469 #ifdef __linux__
470  absPathLib = absPathLib + "/" + *it + ".so";
471 #endif
472 #ifdef __MINGW32__
473  absPathLib = absPathLib + "\\" + *it + ".dll";
474 #endif
475 
476  // which lib is going to be loaded
477  fprintf( stdout, "try loading %s\n", absPathLib.c_str() );
478 
479 #if __MINGW32__
480  // Load the DLL
481  HINSTANCE dlib = ::LoadLibrary(TEXT(absPathLib.c_str()));
482  if (!dlib) {
483  std::cerr << "Unable to load DLL!\n";
484  exit(-1);
485  }
486 #else //Linux and OSX
487  // for some reason the RTLD_NOW alones makes dlopen
488  // stick with the name (content) of the first loaded library
489  void* dlib = dlopen(absPathLib.c_str(), RTLD_NOW|RTLD_LOCAL);
490  if(dlib == NULL){
491  std::cerr << dlerror() << std::endl;
492  exit(-1);
493  }
494 #endif
495 
496  // add the handle to our list
497  dl_list.insert(dl_list.end(), dlib);
498 
499  }
500 
501  // report on factorycreate
502  std::cout << "factorycreate.size() is " << factorycreate.size() << '\n';
503  std::cout << "factorycreate has registered:";
504 
505  // print map key names/registered objects into factory
506  std::map<std::string, creator_t *, std::less<std::string> >::iterator fitr;
507  for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr)
508  std::cout << ' ' << fitr->first;
509  std::cout << '\n';
510 
511  // loop again over registered keys in factory and register into hash
512  for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr) {
513 
514  // fetch creator and definition by key name from factories
515  circuit_creator_t mycreate = factorycreate[fitr->first];
516  define_t *mydefine = factorydef[fitr->first]();
517 
518  /*
519  printf("\n type: %s\n",mydefine->type );
520  printf(" nodes: %i\n",mydefine->nodes );
521  printf(" action: %i\n",mydefine->action );
522  printf(" required->key: %s\n",mydefine->required->key);
523  */
524 
525  // modified registerModule to register dynamic loaded modules
526  module * m = new module ();
527  m->circreate = mycreate;
528  m->definition = mydefine;
529 
530  if (modules.get ((char *) mydefine->type) != NULL) {
531  logprint (LOG_ERROR, "load module already registered: %s\n", mydefine->type);
532  }
533  else {
534  modules.put ((char *) mydefine->type, m);
535  }
536  }
537 
538  // print registered components
539  /*
540  qucs::hashiterator<module> it;
541  for (it = qucs::hashiterator<module> (module::modules); *it; ++it) {
542  module * m = it.currentVal ();
543  struct define_t * def = m->definition;
544  printf("\n" );
545  printf("type: %s\n",def->type );
546  printf("\n" );
547  }
548  */
549 
550 }
551 
552 // Close all the dynamic libs if any opened
553 void module::closeDynamicLibs()
554 {
555  for(itr=dl_list.begin(); itr!=dl_list.end(); itr++){
556 #if __MINGW32__
557  FreeLibrary(*itr);
558 #else
559  dlclose(*itr);
560 #endif
561  }
562 }
Definition: vpm.cpp:85
Definition: rlcg.cpp:141
Definition: irect.cpp:109
Definition: vdc.cpp:85
type_t * currentVal(void)
Definition: hash.cpp:398
Definition: idc.cpp:73
Definition: vac.cpp:102
nr_double_t l
Definition: netdefs.h:94
Definition: pac.cpp:119
Definition: or.cpp:69
Definition: iac.cpp:80
Definition: cccs.cpp:109
Definition: trafo.cpp:83
struct define_t miscdef2
Definition: module.cpp:90
Definition: vcvs.cpp:105
Definition: msvia.cpp:147
Definition: diac.cpp:208
std::map< std::string, defs_t *, std::less< std::string > > factorydef
Definition: module.cpp:58
Definition: vrect.cpp:110
#define PROP_NO_PROP
Definition: netdefs.h:122
#define PROP_NO_RANGE
Definition: netdefs.h:126
Definition: bjt.cpp:826
const char * key
Definition: netdefs.h:86
#define PROP_NO_STR
Definition: netdefs.h:125
const char * type
Definition: netdefs.h:103
#define REGISTER_MISC(val)
Definition: module.cpp:152
#define PROP_LINEAR
Definition: netdefs.h:120
static struct property_t props1[]
Definition: module.cpp:80
nr_double_t h
Definition: netdefs.h:95
#define REGISTER_CIRCUIT(val)
Definition: module.cpp:148
Definition: diode.cpp:488
Definition: rfedd.cpp:452
int nodes
Definition: netdefs.h:104
#define PROP_ACTION
Definition: netdefs.h:115
#define PROP_NODES
Definition: netdefs.h:121
int action
Definition: netdefs.h:105
char il
Definition: netdefs.h:93
char ih
Definition: netdefs.h:96
struct property_t * required
Definition: netdefs.h:108
#define REGISTER_ANALYSIS(val)
Definition: module.cpp:150
Definition: xor.cpp:68
Definition: opamp.cpp:100
struct property_t::@6 defaultval
const char * str[8]
Definition: netdefs.h:97
#define PROP_COMPONENT
Definition: netdefs.h:116
Definition: vam.cpp:82
const char * s
Definition: netdefs.h:90
Definition: nor.cpp:69
int nonlinear
Definition: netdefs.h:107
Definition: iexp.cpp:98
Definition: mstee.cpp:294
std::list< void * > dl_list
Definition: module.cpp:64
struct property_t::@7 range
Definition: ifile.cpp:138
std::list< void * >::iterator itr
Definition: module.cpp:65
Definition: vccs.cpp:103
type
Definition: parse_vcd.y:164
static struct property_t props2[]
Definition: module.cpp:82
name prefix
Definition: parse_spice.y:131
Definition: ccvs.cpp:115
int substrate
Definition: netdefs.h:106
global analysis header file
External interface class for transient simulation.
Definition: ecvs.cpp:123
Definition: vfile.cpp:143
Definition: and.cpp:69
#define PROP_STR
Definition: netdefs.h:175
struct property_t * optional
Definition: netdefs.h:109
struct define_t * definition
Definition: module.h:69
Definition: jfet.cpp:441
Definition: tline.cpp:172
int type
Definition: netdefs.h:87
#define LOG_ERROR
Definition: logging.h:28
#define PROP_NO_VAL
Definition: netdefs.h:124
struct define_t miscdef1
Definition: module.cpp:86
Definition: vexp.cpp:99
Definition: triac.cpp:234
key
Definition: msgap.cpp:130
void logprint(int level, const char *format,...)
Definition: logging.c:37
nr_double_t d
Definition: netdefs.h:89
#define PROP_NO_SUBSTRATE
Definition: netdefs.h:118
std::map< std::string, creator_t *, std::less< std::string > > factorycreate
Definition: module.cpp:56