Qucs-core  0.0.19
module.cpp
Go to the documentation of this file.
00001 /*
00002  * module.cpp - module class implementation
00003  *
00004  * Copyright (C) 2008, 2009, 2010 Stefan Jahn <stefan@lkcc.org>
00005  * New models added Mike Brinson 2013 mbrin72043@yahoo.co.uk
00006  *
00007  * This is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011  *
00012  * This software is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this package; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  *
00022  * $Id: module.cpp 1872 2013-03-06 14:13:37Z fransschreuder $
00023  *
00024  */
00025 
00026 #if HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029 
00030 #include <iostream>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <map>
00034 #include <list>
00035 
00036 #include "netdefs.h"
00037 #include "components.h"
00038 #include "analyses.h"
00039 #include "netdefs.h"
00040 #include "module.h"
00041 
00042 #ifdef __MINGW32__
00043  #include <windows.h>
00044 #else
00045  #include <dlfcn.h>
00046 #endif
00047 
00048 #include <cstdlib> //for exit
00049 
00050 // Global module hash.
00051 qucs::hash<module> module::modules;
00052 
00053 // Our global factories for making loaded circuit objects
00054 // The factories are populated as dynamic modules are loaded
00055 // factorycreate hold the loaded modules constructor function
00056 std::map< std::string, creator_t *, std::less<std::string> > factorycreate;
00057 // factorydef hold the loaded modules definitions
00058 std::map< std::string, defs_t *, std::less<std::string> > factorydef;
00059 
00060 #if __MINGW32__
00061   std::list<HINSTANCE> dl_list; // list to hold handles for dynamic libs
00062   std::list<HINSTANCE>::iterator itr;
00063 #else
00064   std::list<void *> dl_list; // list to hold handles for dynamic libs
00065   std::list<void *>::iterator itr;
00066 #endif
00067 
00068 // Constructor creates an instance of the module class.
00069 module::module () {
00070   definition = NULL;
00071   circreate = NULL;
00072   anacreate = NULL;
00073 }
00074 
00075 // Destructor deletes an instance of the module class.
00076 module::~module () {
00077 }
00078 
00079 // Definitions which do not fit elsewhere.
00080 static struct property_t props1[] = {
00081   PROP_NO_PROP };
00082 static struct property_t props2[] = {
00083   { "Type", PROP_STR, { PROP_NO_VAL, "DEF1" }, PROP_NO_RANGE },
00084   PROP_NO_PROP };
00085 
00086 struct define_t miscdef1 =
00087   { "Def", PROP_NODES, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR,
00088     props1, props1 };
00089 
00090 struct define_t miscdef2 =
00091   { "Sub", PROP_NODES, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR,
00092     props1, props2 };
00093 
00094 // Registers an analysis object to the list of available modules.
00095 void module::registerModule (analysis_definer_t define,
00096                              analysis_creator_t create) {
00097   module * m = new module ();
00098   m->definition = define ();
00099   m->anacreate = create;
00100   modules.put ((char *) define()->type, m);
00101 }
00102 
00103 // Registers a circuit object to the list of available modules.
00104 void module::registerModule (circuit_definer_t define,
00105                              circuit_creator_t create) {
00106   module * m = new module ();
00107   m->definition = define ();
00108   m->circreate = create;
00109   registerModule (define()->type, m);
00110 }
00111 
00112 // Registers a miscellaneous object to the list of available modules.
00113 void module::registerModule (misc_definer_t define) {
00114   module * m = new module ();
00115   m->definition = define ();
00116   registerModule (define()->type, m);
00117 }
00118 
00119 /* Registers a miscellaneous structure just defined by a somple
00120    define_t structure to the list of available modules. */
00121 void module::registerModule (struct define_t * define) {
00122   module * m = new module ();
00123   m->definition = define;
00124   registerModule (define->type, m);
00125 }
00126 
00127 // Puts a module into the available module hash.
00128 void module::registerModule (const char * type, module * m) {
00129   if (modules.get ((char *) type) != NULL) {
00130     logprint (LOG_ERROR, "module already registered: %s\n", type);
00131   }
00132   else {
00133     modules.put ((char *) type, m);
00134   }
00135 }
00136 
00137 /* Returns the definition of a module specified by its type name if
00138    such is existing and otherwise NULL. */
00139 struct define_t * module::getModule (char * type) {
00140   module * m = modules.get (type);
00141   if (m != NULL) {
00142     return m->definition;
00143   }
00144   return NULL;
00145 }
00146 
00147 // Helper macros.
00148 #define REGISTER_CIRCUIT(val) \
00149   registerModule (&val::definition, &val::create)
00150 #define REGISTER_ANALYSIS(val) \
00151   registerModule (&val::definition, &val::create)
00152 #define REGISTER_MISC(val) \
00153   registerModule (&val::definition)
00154 
00155 // Global static module registration.
00156 void module::registerModules (void) {
00157 
00158   // miscellaneous
00159   registerModule (&miscdef1);
00160   registerModule (&miscdef2);
00161   REGISTER_MISC (nodeset);
00162   REGISTER_MISC (substrate);
00163 
00164   // circuit components
00165   REGISTER_CIRCUIT (resistor);
00166   REGISTER_CIRCUIT (capacitor);
00167   REGISTER_CIRCUIT (pac);
00168   REGISTER_CIRCUIT (inductor);
00169   REGISTER_CIRCUIT (vccs);
00170   REGISTER_CIRCUIT (cccs);
00171   REGISTER_CIRCUIT (vcvs);
00172   REGISTER_CIRCUIT (ccvs);
00173   REGISTER_CIRCUIT (biastee);
00174   REGISTER_CIRCUIT (dcfeed);
00175   REGISTER_CIRCUIT (dcblock);
00176   REGISTER_CIRCUIT (circulator);
00177   REGISTER_CIRCUIT (attenuator);
00178   REGISTER_CIRCUIT (isolator);
00179   REGISTER_CIRCUIT (trafo);
00180   REGISTER_CIRCUIT (strafo);
00181   REGISTER_CIRCUIT (vdc);
00182   REGISTER_CIRCUIT (idc);
00183   REGISTER_CIRCUIT (vac);
00184   REGISTER_CIRCUIT (iac);
00185   REGISTER_CIRCUIT (iexp);
00186   REGISTER_CIRCUIT (vexp);
00187   REGISTER_CIRCUIT (ifile);
00188   REGISTER_CIRCUIT (vfile);
00189   REGISTER_CIRCUIT (vam);
00190   REGISTER_CIRCUIT (vpm);
00191   REGISTER_CIRCUIT (vpulse);
00192   REGISTER_CIRCUIT (ipulse);
00193   REGISTER_CIRCUIT (vrect);
00194   REGISTER_CIRCUIT (irect);
00195   REGISTER_CIRCUIT (gyrator);
00196   REGISTER_CIRCUIT (phaseshifter);
00197   REGISTER_CIRCUIT (tswitch);
00198   REGISTER_CIRCUIT (relais);
00199   REGISTER_CIRCUIT (tline);
00200   REGISTER_CIRCUIT (tline4p);
00201   REGISTER_CIRCUIT (ctline);
00202   REGISTER_CIRCUIT (coaxline);
00203   REGISTER_CIRCUIT (rectline);
00204   REGISTER_CIRCUIT (twistedpair);
00205   REGISTER_CIRCUIT (rlcg);
00206   REGISTER_CIRCUIT (coupler);
00207   REGISTER_CIRCUIT (hybrid);
00208   REGISTER_CIRCUIT (diode);
00209   REGISTER_CIRCUIT (eqndefined);
00210   REGISTER_CIRCUIT (rfedd);
00211   REGISTER_CIRCUIT (diac);
00212   REGISTER_CIRCUIT (thyristor);
00213   REGISTER_CIRCUIT (triac);
00214   REGISTER_CIRCUIT (tunneldiode);
00215   REGISTER_CIRCUIT (msline);
00216   REGISTER_CIRCUIT (mscorner);
00217   REGISTER_CIRCUIT (msstep);
00218   REGISTER_CIRCUIT (msopen);
00219   REGISTER_CIRCUIT (msgap);
00220   REGISTER_CIRCUIT (msmbend);
00221   REGISTER_CIRCUIT (mscoupled);
00222   REGISTER_CIRCUIT (mslange);
00223   REGISTER_CIRCUIT (mstee);
00224   REGISTER_CIRCUIT (mscross);
00225   REGISTER_CIRCUIT (msvia);
00226   REGISTER_CIRCUIT (msrstub);
00227   REGISTER_CIRCUIT (bondwire);
00228   REGISTER_CIRCUIT (cpwline);
00229   REGISTER_CIRCUIT (cpwopen);
00230   REGISTER_CIRCUIT (cpwshort);
00231   REGISTER_CIRCUIT (cpwgap);
00232   REGISTER_CIRCUIT (cpwstep);
00233   REGISTER_CIRCUIT (iprobe);
00234   REGISTER_CIRCUIT (vprobe);
00235   REGISTER_CIRCUIT (jfet);
00236   REGISTER_CIRCUIT (bjt);
00237   REGISTER_CIRCUIT (spfile);
00238   REGISTER_CIRCUIT (vnoise);
00239   REGISTER_CIRCUIT (inoise);
00240   REGISTER_CIRCUIT (mosfet);
00241   REGISTER_CIRCUIT (amplifier);
00242   REGISTER_CIRCUIT (opamp);
00243   REGISTER_CIRCUIT (iinoise);
00244   REGISTER_CIRCUIT (mutual);
00245   REGISTER_CIRCUIT (mutual2);
00246   REGISTER_CIRCUIT (mutualx);
00247   REGISTER_CIRCUIT (ivnoise);
00248   REGISTER_CIRCUIT (vvnoise);
00249   REGISTER_CIRCUIT (inverter);
00250   REGISTER_CIRCUIT (logicnor);
00251   REGISTER_CIRCUIT (logicor);
00252   REGISTER_CIRCUIT (logicnand);
00253   REGISTER_CIRCUIT (logicand);
00254   REGISTER_CIRCUIT (logicxnor);
00255   REGISTER_CIRCUIT (logicxor);
00256   REGISTER_CIRCUIT (digisource);
00257   REGISTER_CIRCUIT (buffer);
00258   REGISTER_CIRCUIT (hicumL2V2p1);
00259   REGISTER_CIRCUIT (HBT_X);
00260   REGISTER_CIRCUIT (mod_amp);
00261   REGISTER_CIRCUIT (hic2_full);
00262   REGISTER_CIRCUIT (log_amp);
00263   REGISTER_CIRCUIT (hic0_full);
00264   REGISTER_CIRCUIT (potentiometer);
00265   REGISTER_CIRCUIT (MESFET);
00266   REGISTER_CIRCUIT (EKV26MOS);
00267   REGISTER_CIRCUIT (bsim3v34nMOS);
00268   REGISTER_CIRCUIT (bsim3v34pMOS);
00269   REGISTER_CIRCUIT (bsim4v30nMOS);
00270   REGISTER_CIRCUIT (bsim4v30pMOS);
00271   REGISTER_CIRCUIT (hicumL0V1p2);
00272   REGISTER_CIRCUIT (hicumL0V1p2g);
00273   REGISTER_CIRCUIT (hicumL0V1p3);
00274   REGISTER_CIRCUIT (hicumL2V2p23);
00275   REGISTER_CIRCUIT (hicumL2V2p24);
00276   REGISTER_CIRCUIT (hicumL2V2p31n);
00277   REGISTER_CIRCUIT (photodiode);
00278   REGISTER_CIRCUIT (phototransistor);
00279   REGISTER_CIRCUIT (nigbt);
00280   REGISTER_CIRCUIT (dff_SR);
00281   REGISTER_CIRCUIT (tff_SR);
00282   REGISTER_CIRCUIT (jkff_SR);
00283   REGISTER_CIRCUIT (gatedDlatch);
00284   REGISTER_CIRCUIT (logic_1);
00285   REGISTER_CIRCUIT (logic_0);
00286   REGISTER_CIRCUIT (mux2to1);
00287   REGISTER_CIRCUIT (mux4to1);
00288   REGISTER_CIRCUIT (mux8to1);
00289   REGISTER_CIRCUIT (DLS_nto1);
00290   REGISTER_CIRCUIT (DLS_1ton);
00291   REGISTER_CIRCUIT (andor4x2);
00292   REGISTER_CIRCUIT (andor4x3);
00293   REGISTER_CIRCUIT (andor4x4);
00294   REGISTER_CIRCUIT (dmux2to4);
00295   REGISTER_CIRCUIT (dmux3to8);
00296   REGISTER_CIRCUIT (dmux4to16);
00297   REGISTER_CIRCUIT (ha1b);
00298   REGISTER_CIRCUIT (fa1b);
00299   REGISTER_CIRCUIT (fa2b);
00300   REGISTER_CIRCUIT (pad2bit);
00301   REGISTER_CIRCUIT (pad3bit);
00302   REGISTER_CIRCUIT (pad4bit);
00303   REGISTER_CIRCUIT (binarytogrey4bit);
00304   REGISTER_CIRCUIT (greytobinary4bit);
00305   REGISTER_CIRCUIT (comp_1bit);
00306   REGISTER_CIRCUIT (comp_2bit);
00307   REGISTER_CIRCUIT (comp_4bit);
00308   REGISTER_CIRCUIT (hpribin4bit);
00309   REGISTER_CIRCUIT (vcresistor);
00310   REGISTER_CIRCUIT (ecvs);
00311 
00312   // analyses
00313   REGISTER_ANALYSIS (dcsolver);
00314   REGISTER_ANALYSIS (acsolver);
00315   REGISTER_ANALYSIS (spsolver);
00316   REGISTER_ANALYSIS (trsolver);
00317   REGISTER_ANALYSIS (hbsolver);
00318   REGISTER_ANALYSIS (parasweep);
00319   REGISTER_ANALYSIS (e_trsolver);
00320 }
00321 
00322 // Global module unregistration.
00323 void module::unregisterModules (void) {
00324   qucs::hashiterator<module> it;
00325   for (it = qucs::hashiterator<module> (modules); *it; ++it) {
00326     delete it.currentVal ();
00327   }
00328   modules.clear ();
00329 }
00330 
00331 #if DEBUG
00332 // header prefix
00333 static const char * def_prefix =
00334 "/*\n"
00335 " * qucsdefs.h - netlist definitions for the Qucs netlists\n"
00336 " *\n"
00337 " * This is free software; you can redistribute it and/or modify\n"
00338 " * it under the terms of the GNU General Public License as published by\n"
00339 " * the Free Software Foundation; either version 2, or (at your option)\n"
00340 " * any later version.\n"
00341 " * \n"
00342 " */\n"
00343 "\n"
00344 "#ifndef __QUCSDEFS_H__\n"
00345 "#define __QUCSDEFS_H__\n";
00346 
00347 // header suffix
00348 static const char * def_suffix =
00349 "\n"
00350 "#endif /* __QUCSDEFS_H__ */\n";
00351 
00352 // start of list of definitions
00353 static const char * def_start =
00354 "\n"
00355 "// List of available components.\n"
00356 "struct define_t qucs_definition_available[] =\n";
00357 
00358 // end of list entry
00359 static const char * def_stop =
00360 "\n"
00361 "static struct define_t def_End = {\n"
00362 "  ((char *) 0), -1, 1, 0, 0, req_Def, opt_Def };\n";
00363 
00364 // Returns a compilable C-code string made from the given string.
00365 static char * printstr (const char * str) {
00366   static char txt[256];
00367   int nostr = (str == PROP_NO_STR);
00368   sprintf (txt, "%s%s%s",
00369            (str && !nostr) ? "\"" : "",
00370            str ? nostr ? "((char *) -1)" : str : "((char *) 0)",
00371            (str && !nostr) ? "\"" : "");
00372   return txt;
00373 }
00374 
00375 // Prints a property list as compilable C-code.
00376 static void printprop (const char * type, const char * prefix,
00377                        struct property_t * prop) {
00378   const char * key;
00379   const char ** str;
00380   const char * txt;
00381   fprintf (stdout, "static struct property_t %s_%s[] = {\n", prefix, type);
00382   do {
00383     key = prop->key;
00384     fprintf (stdout, "  { %s, %d, ", printstr (key), prop->type);
00385     fprintf (stdout, "{ %g, %s }, ", prop->defaultval.d,
00386              printstr (prop->defaultval.s));
00387     fprintf (stdout, "{ '%c', %g, %g, '%c',\n",
00388              prop->range.il, prop->range.l, prop->range.h, prop->range.ih);
00389     fprintf (stdout, "    {");
00390     str = prop->range.str;
00391     do {
00392       txt = *str;
00393       fprintf (stdout, " %s", printstr (txt));
00394       if (txt) fprintf (stdout, ",");
00395       str++;
00396     }
00397     while (txt != NULL);
00398     fprintf (stdout, " } } }");
00399     if (key) fprintf (stdout, ",");
00400     fprintf (stdout, "\n");
00401     prop++;
00402   }
00403   while (key != NULL);
00404   fprintf (stdout, "};\n");
00405 }
00406 
00407 /* The function emits a complete list of the registered component
00408    definitions as compilable C-code. */
00409 void module::print (void) {
00410   fprintf (stdout, "%s", def_prefix);
00411   qucs::hashiterator<module> it;
00412   for (it = qucs::hashiterator<module> (modules); *it; ++it) {
00413     module * m = it.currentVal ();
00414     struct define_t * def = m->definition;
00415     fprintf (stdout, "\n");
00416     printprop (def->type, "req", def->required);
00417     fprintf (stdout, "\n");
00418     printprop (def->type, "opt", def->optional);
00419     fprintf (stdout, "\n");
00420     fprintf (stdout, "static struct define_t def_%s = {\n", def->type);
00421     fprintf (stdout, "  %s, %d, %d, %d, %d, req_%s, opt_%s };\n",
00422              printstr (def->type), def->nodes, def->action, def->substrate,
00423              def->nonlinear, def->type, def->type);
00424   }
00425   fprintf (stdout, "%s", def_stop);
00426   fprintf (stdout, "%s", def_start);
00427   fprintf (stdout, "{\n");
00428   for (it = qucs::hashiterator<module> (modules); *it; ++it) {
00429     module * m = it.currentVal ();
00430     struct define_t * def = m->definition;
00431     fprintf (stdout, "  def_%s,\n", def->type);
00432   }
00433   fprintf (stdout, "  def_End\n");
00434   fprintf (stdout, "};\n");
00435   fprintf (stdout, "%s", def_suffix);
00436 }
00437 #endif /* DEBUG */
00438 
00439 
00440 // look for dynamic libs, load and register them
00441 void module::registerDynamicModules (char *proj, std::list<std::string> modlist)
00442 {
00443 /* How it is (WAS) supposed to work:
00444  * 1) It will list the working directory contents looking for libraries
00445  * 2) It will try to open each library and put its handle into a list
00446  *   - Just by opening the lib it will already populate the factorycreate and factorydef
00447  * 3) The factory is iterated to create new modules and add them to the global hash
00448  *
00449  * TODO:
00450  *   - Add destructor for loaded objects
00451  *   - Add other methods to find the libraries
00452  *
00453  * Update
00454  *  * project path is passed as paramter
00455  *  * module names are passed as parameter
00456 */
00457 
00458   fprintf(stdout,"project location: %s\n", proj);
00459   fprintf(stdout,"modules to load: %lu\n", modlist.size());
00460 
00461   std::list<std::string>::iterator it;
00462   for (it=modlist.begin(); it!=modlist.end(); ++it) {
00463 
00464     std::string absPathLib = proj;
00465 
00466 #ifdef __APPLE__
00467     absPathLib = absPathLib + "/" + *it + ".dylib";
00468 #endif
00469 #ifdef __linux__
00470   absPathLib = absPathLib + "/" + *it + ".so";
00471 #endif
00472 #ifdef __MINGW32__
00473   absPathLib = absPathLib + "\\" + *it + ".dll";
00474 #endif
00475 
00476     // which lib is going to be loaded
00477     fprintf( stdout, "try loading %s\n", absPathLib.c_str() );
00478 
00479 #if __MINGW32__
00480     // Load the DLL
00481     HINSTANCE dlib = ::LoadLibrary(TEXT(absPathLib.c_str()));
00482     if (!dlib) {
00483         std::cerr << "Unable to load DLL!\n";
00484         exit(-1);
00485     }
00486 #else //Linux and OSX
00487     // for some reason the RTLD_NOW alones makes dlopen
00488     // stick with the name (content) of the first loaded library
00489     void* dlib = dlopen(absPathLib.c_str(), RTLD_NOW|RTLD_LOCAL);
00490     if(dlib == NULL){
00491       std::cerr << dlerror() << std::endl;
00492       exit(-1);
00493     }
00494 #endif
00495 
00496     // add the handle to our list
00497     dl_list.insert(dl_list.end(), dlib);
00498 
00499   }
00500 
00501   // report on factorycreate
00502   std::cout << "factorycreate.size() is " << factorycreate.size() << '\n';
00503   std::cout << "factorycreate has registered:";
00504 
00505   // print map key names/registered objects into factory
00506   std::map<std::string, creator_t *, std::less<std::string> >::iterator fitr;
00507   for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr)
00508     std::cout << ' ' << fitr->first;
00509   std::cout << '\n';
00510 
00511   // loop again over registered keys in factory and register into hash
00512   for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr) {
00513 
00514     // fetch creator and definition by key name from factories
00515     circuit_creator_t mycreate = factorycreate[fitr->first];
00516     define_t *mydefine = factorydef[fitr->first]();
00517 
00518     /*
00519     printf("\n  type: %s\n",mydefine->type );
00520     printf("  nodes: %i\n",mydefine->nodes );
00521     printf("  action: %i\n",mydefine->action );
00522     printf("  required->key: %s\n",mydefine->required->key);
00523     */
00524 
00525     // modified registerModule to register dynamic loaded modules
00526     module * m = new module ();
00527     m->circreate = mycreate;
00528     m->definition = mydefine;
00529 
00530     if (modules.get ((char *) mydefine->type) != NULL) {
00531       logprint (LOG_ERROR, "load module already registered: %s\n", mydefine->type);
00532     }
00533     else {
00534       modules.put ((char *) mydefine->type, m);
00535     }
00536   }
00537 
00538   // print registered components
00539   /*
00540   qucs::hashiterator<module> it;
00541   for (it = qucs::hashiterator<module> (module::modules); *it; ++it) {
00542     module * m = it.currentVal ();
00543     struct define_t * def = m->definition;
00544     printf("\n" );
00545     printf("type: %s\n",def->type );
00546     printf("\n" );
00547   }
00548   */
00549 
00550 }
00551 
00552 // Close all the dynamic libs if any opened
00553 void module::closeDynamicLibs()
00554 {
00555   for(itr=dl_list.begin(); itr!=dl_list.end(); itr++){
00556 #if __MINGW32__
00557     FreeLibrary(*itr);
00558 #else
00559     dlclose(*itr);
00560 #endif
00561   }
00562 }