* module.cpp - module class implementation
*
* Copyright (C) 2008, 2009, 2010 Stefan Jahn <stefan@lkcc.org>
* New models added Mike Brinson 2013 mbrin72043@yahoo.co.uk
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $Id: module.cpp 1872 2013-03-06 14:13:37Z fransschreuder $
*
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <list>
#include "netdefs.h"
#include "components.h"
#include "analyses.h"
#include "netdefs.h"
#include "module.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <cstdlib>
qucs::hash<module> module::modules;
std::map< std::string, creator_t *, std::less<std::string> > factorycreate;
std::map< std::string, defs_t *, std::less<std::string> > factorydef;
#if _WIN32
std::list<HINSTANCE> dl_list;
std::list<HINSTANCE>::iterator itr;
#else
std::list<void *> dl_list;
std::list<void *>::iterator itr;
#endif
module::module () {
definition = NULL;
circreate = NULL;
anacreate = NULL;
}
module::~module () {
}
static struct property_t props1[] = {
PROP_NO_PROP };
static struct property_t props2[] = {
{ "Type", PROP_STR, { PROP_NO_VAL, "DEF1" }, PROP_NO_RANGE },
PROP_NO_PROP };
struct define_t miscdef1 =
{ "Def", PROP_NODES, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR,
props1, props1 };
struct define_t miscdef2 =
{ "Sub", PROP_NODES, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR,
props1, props2 };
void module::registerModule (analysis_definer_t define,
analysis_creator_t create) {
module * m = new module ();
m->definition = define ();
m->anacreate = create;
modules.put ((char *) define()->type, m);
}
void module::registerModule (circuit_definer_t define,
circuit_creator_t create) {
module * m = new module ();
m->definition = define ();
m->circreate = create;
registerModule (define()->type, m);
}
void module::registerModule (misc_definer_t define) {
module * m = new module ();
m->definition = define ();
registerModule (define()->type, m);
}
define_t structure to the list of available modules. */
void module::registerModule (struct define_t * define) {
module * m = new module ();
m->definition = define;
registerModule (define->type, m);
}
void module::registerModule (const char * type, module * m) {
if (modules.get ((char *) type) != NULL) {
logprint (LOG_ERROR, "module already registered: %s\n", type);
}
else {
modules.put ((char *) type, m);
}
}
such is existing and otherwise NULL. */
struct define_t * module::getModule (char * type) {
module * m = modules.get (type);
if (m != NULL) {
return m->definition;
}
return NULL;
}
#define REGISTER_CIRCUIT(val) \
registerModule (&val::definition, &val::create)
#define REGISTER_ANALYSIS(val) \
registerModule (&val::definition, &val::create)
#define REGISTER_MISC(val) \
registerModule (&val::definition)
void module::registerModules (void) {
registerModule (&miscdef1);
registerModule (&miscdef2);
REGISTER_MISC (nodeset);
REGISTER_MISC (substrate);
REGISTER_CIRCUIT (resistor);
REGISTER_CIRCUIT (capacitor);
REGISTER_CIRCUIT (capq);
REGISTER_CIRCUIT (pac);
REGISTER_CIRCUIT (inductor);
REGISTER_CIRCUIT (indq);
REGISTER_CIRCUIT (vccs);
REGISTER_CIRCUIT (cccs);
REGISTER_CIRCUIT (vcvs);
REGISTER_CIRCUIT (ccvs);
REGISTER_CIRCUIT (biastee);
REGISTER_CIRCUIT (dcfeed);
REGISTER_CIRCUIT (dcblock);
REGISTER_CIRCUIT (circulator);
REGISTER_CIRCUIT (attenuator);
REGISTER_CIRCUIT (isolator);
REGISTER_CIRCUIT (trafo);
REGISTER_CIRCUIT (strafo);
REGISTER_CIRCUIT (vdc);
REGISTER_CIRCUIT (idc);
REGISTER_CIRCUIT (vac);
REGISTER_CIRCUIT (iac);
REGISTER_CIRCUIT (iexp);
REGISTER_CIRCUIT (vexp);
REGISTER_CIRCUIT (ifile);
REGISTER_CIRCUIT (vfile);
REGISTER_CIRCUIT (vam);
REGISTER_CIRCUIT (vpm);
REGISTER_CIRCUIT (vpulse);
REGISTER_CIRCUIT (ipulse);
REGISTER_CIRCUIT (vrect);
REGISTER_CIRCUIT (irect);
REGISTER_CIRCUIT (gyrator);
REGISTER_CIRCUIT (phaseshifter);
REGISTER_CIRCUIT (tswitch);
REGISTER_CIRCUIT (relais);
REGISTER_CIRCUIT (tline);
REGISTER_CIRCUIT (tline4p);
REGISTER_CIRCUIT (ctline);
REGISTER_CIRCUIT (coaxline);
REGISTER_CIRCUIT (circline);
REGISTER_CIRCUIT (taperedline);
REGISTER_CIRCUIT (rectline);
REGISTER_CIRCUIT (twistedpair);
REGISTER_CIRCUIT (rlcg);
REGISTER_CIRCUIT (coupler);
REGISTER_CIRCUIT (hybrid);
REGISTER_CIRCUIT (diode);
REGISTER_CIRCUIT (eqndefined);
REGISTER_CIRCUIT (rfedd);
REGISTER_CIRCUIT (diac);
REGISTER_CIRCUIT (thyristor);
REGISTER_CIRCUIT (triac);
REGISTER_CIRCUIT (tunneldiode);
REGISTER_CIRCUIT (msline);
REGISTER_CIRCUIT (mscorner);
REGISTER_CIRCUIT (msstep);
REGISTER_CIRCUIT (msopen);
REGISTER_CIRCUIT (msgap);
REGISTER_CIRCUIT (msmbend);
REGISTER_CIRCUIT (mscoupled);
REGISTER_CIRCUIT (mslange);
REGISTER_CIRCUIT (mstee);
REGISTER_CIRCUIT (mscross);
REGISTER_CIRCUIT (msvia);
REGISTER_CIRCUIT (msrstub);
REGISTER_CIRCUIT (bondwire);
REGISTER_CIRCUIT (spiralinductor);
REGISTER_CIRCUIT (circularloop);
REGISTER_CIRCUIT (cpwline);
REGISTER_CIRCUIT (cpwopen);
REGISTER_CIRCUIT (cpwshort);
REGISTER_CIRCUIT (cpwgap);
REGISTER_CIRCUIT (cpwstep);
REGISTER_CIRCUIT (iprobe);
REGISTER_CIRCUIT (wprobe);
REGISTER_CIRCUIT (vprobe);
REGISTER_CIRCUIT (jfet);
REGISTER_CIRCUIT (bjt);
REGISTER_CIRCUIT (spembed);
REGISTER_CIRCUIT (spdeembed);
REGISTER_CIRCUIT (vnoise);
REGISTER_CIRCUIT (inoise);
REGISTER_CIRCUIT (mosfet);
REGISTER_CIRCUIT (amplifier);
REGISTER_CIRCUIT (opamp);
REGISTER_CIRCUIT (iinoise);
REGISTER_CIRCUIT (mutual);
REGISTER_CIRCUIT (mutual2);
REGISTER_CIRCUIT (mutualx);
REGISTER_CIRCUIT (ivnoise);
REGISTER_CIRCUIT (vvnoise);
REGISTER_CIRCUIT (inverter);
REGISTER_CIRCUIT (logicnor);
REGISTER_CIRCUIT (logicor);
REGISTER_CIRCUIT (logicnand);
REGISTER_CIRCUIT (logicand);
REGISTER_CIRCUIT (logicxnor);
REGISTER_CIRCUIT (logicxor);
REGISTER_CIRCUIT (digisource);
REGISTER_CIRCUIT (buffer);
#ifdef WITH_ADMS
REGISTER_CIRCUIT (EKV26MOS);
REGISTER_CIRCUIT (log_amp);
REGISTER_CIRCUIT (mod_amp);
REGISTER_CIRCUIT (MESFET);
REGISTER_CIRCUIT (nigbt);
REGISTER_CIRCUIT (photodiode);
REGISTER_CIRCUIT (phototransistor);
REGISTER_CIRCUIT (potentiometer);
REGISTER_CIRCUIT (dff_SR);
REGISTER_CIRCUIT (tff_SR);
REGISTER_CIRCUIT (jkff_SR);
REGISTER_CIRCUIT (gatedDlatch);
REGISTER_CIRCUIT (logic_1);
REGISTER_CIRCUIT (logic_0);
REGISTER_CIRCUIT (mux2to1);
REGISTER_CIRCUIT (mux4to1);
REGISTER_CIRCUIT (mux8to1);
REGISTER_CIRCUIT (DLS_nto1);
REGISTER_CIRCUIT (DLS_1ton);
REGISTER_CIRCUIT (andor4x2);
REGISTER_CIRCUIT (andor4x3);
REGISTER_CIRCUIT (andor4x4);
REGISTER_CIRCUIT (dmux2to4);
REGISTER_CIRCUIT (dmux3to8);
REGISTER_CIRCUIT (dmux4to16);
REGISTER_CIRCUIT (ha1b);
REGISTER_CIRCUIT (fa1b);
REGISTER_CIRCUIT (fa2b);
REGISTER_CIRCUIT (pad2bit);
REGISTER_CIRCUIT (pad3bit);
REGISTER_CIRCUIT (pad4bit);
REGISTER_CIRCUIT (binarytogrey4bit);
REGISTER_CIRCUIT (greytobinary4bit);
REGISTER_CIRCUIT (comp_1bit);
REGISTER_CIRCUIT (comp_2bit);
REGISTER_CIRCUIT (comp_4bit);
REGISTER_CIRCUIT (hpribin4bit);
REGISTER_CIRCUIT (vcresistor);
#endif
REGISTER_CIRCUIT (ecvs);
REGISTER_ANALYSIS (dcsolver);
REGISTER_ANALYSIS (acsolver);
REGISTER_ANALYSIS (spsolver);
REGISTER_ANALYSIS (trsolver);
REGISTER_ANALYSIS (hbsolver);
REGISTER_ANALYSIS (parasweep);
REGISTER_ANALYSIS (e_trsolver);
}
void module::unregisterModules (void) {
qucs::hashiterator<module> it;
for (it = qucs::hashiterator<module> (modules); *it; ++it) {
delete it.currentVal ();
}
modules.clear ();
}
#ifndef NOMODULEPRINT
static const char * def_prefix =
"/*\n"
" * qucsdefs.h - netlist definitions for the Qucs netlists\n"
" *\n"
" * This is free software; you can redistribute it and/or modify\n"
" * it under the terms of the GNU General Public License as published by\n"
" * the Free Software Foundation; either version 2, or (at your option)\n"
" * any later version.\n"
" * \n"
" */\n"
"\n"
"#ifndef __QUCSDEFS_H__\n"
"#define __QUCSDEFS_H__\n";
static const char * def_suffix =
"\n"
"#endif /* __QUCSDEFS_H__ */\n";
static const char * def_start =
"\n"
"// List of available components.\n"
"struct define_t qucs_definition_available[] =\n";
static const char * def_stop =
"\n"
"static struct define_t def_End = {\n"
" ((char *) 0), -1, 1, 0, 0, req_Def, opt_Def };\n";
static char * printstr (const char * str) {
static char txt[256];
int nostr = (str == PROP_NO_STR);
sprintf (txt, "%s%s%s",
(str && !nostr) ? "\"" : "",
str ? nostr ? "((char *) -1)" : str : "((char *) 0)",
(str && !nostr) ? "\"" : "");
return txt;
}
static void printprop (const char * type, const char * prefix,
struct property_t * prop) {
const char * key;
const char ** str;
const char * txt;
fprintf (stdout, "static struct property_t %s_%s[] = {\n", prefix, type);
do {
key = prop->key;
fprintf (stdout, " { %s, %d, ", printstr (key), prop->type);
fprintf (stdout, "{ %g, %s }, ", prop->defaultval.d,
printstr (prop->defaultval.s));
fprintf (stdout, "{ '%c', %g, %g, '%c',\n",
prop->range.il, prop->range.l, prop->range.h, prop->range.ih);
fprintf (stdout, " {");
str = prop->range.str;
do {
txt = *str;
fprintf (stdout, " %s", printstr (txt));
if (txt) fprintf (stdout, ",");
str++;
}
while (txt != NULL);
fprintf (stdout, " } } }");
if (key) fprintf (stdout, ",");
fprintf (stdout, "\n");
prop++;
}
while (key != NULL);
fprintf (stdout, "};\n");
}
definitions as compilable C-code. */
void module::print (void) {
fprintf (stdout, "%s", def_prefix);
qucs::hashiterator<module> it;
for (it = qucs::hashiterator<module> (modules); *it; ++it) {
module * m = it.currentVal ();
struct define_t * def = m->definition;
fprintf (stdout, "\n");
printprop (def->type, "req", def->required);
fprintf (stdout, "\n");
printprop (def->type, "opt", def->optional);
fprintf (stdout, "\n");
fprintf (stdout, "static struct define_t def_%s = {\n", def->type);
fprintf (stdout, " %s, %d, %d, %d, %d, req_%s, opt_%s };\n",
printstr (def->type), def->nodes, def->action, def->substrate,
def->nonlinear, def->type, def->type);
}
fprintf (stdout, "%s", def_stop);
fprintf (stdout, "%s", def_start);
fprintf (stdout, "{\n");
for (it = qucs::hashiterator<module> (modules); *it; ++it) {
module * m = it.currentVal ();
struct define_t * def = m->definition;
fprintf (stdout, " def_%s,\n", def->type);
}
fprintf (stdout, " def_End\n");
fprintf (stdout, "};\n");
fprintf (stdout, "%s", def_suffix);
}
#endif
void module::registerDynamicModules (char *proj, std::list<std::string> modlist)
{
* 1) It will list the working directory contents looking for libraries
* 2) It will try to open each library and put its handle into a list
* - Just by opening the lib it will already populate the factorycreate and factorydef
* 3) The factory is iterated to create new modules and add them to the global hash
*
* TODO:
* - Add destructor for loaded objects
* - Add other methods to find the libraries
*
* Update
* * project path is passed as parameter
* * module names are passed as parameter
*/
fprintf(stdout,"project location: %s\n", proj);
fprintf(stdout,"modules to load: %lu\n", modlist.size());
std::list<std::string>::iterator it;
for (it=modlist.begin(); it!=modlist.end(); ++it) {
std::string absPathLib = proj;
#ifdef __APPLE__
absPathLib = absPathLib + "/" + *it + ".dylib";
#endif
#ifdef __linux__
absPathLib = absPathLib + "/" + *it + ".so";
#endif
#ifdef _WIN32
absPathLib = absPathLib + "\\" + *it + ".dll";
#endif
fprintf( stdout, "try loading %s\n", absPathLib.c_str() );
#if _WIN32
HINSTANCE dlib = ::LoadLibrary(TEXT(absPathLib.c_str()));
if (!dlib) {
std::cerr << "Unable to load DLL!\n";
exit(-1);
}
#else
void* dlib = dlopen(absPathLib.c_str(), RTLD_NOW|RTLD_LOCAL);
if(dlib == NULL){
std::cerr << dlerror() << std::endl;
exit(-1);
}
#endif
dl_list.insert(dl_list.end(), dlib);
}
std::cout << "factorycreate.size() is " << factorycreate.size() << '\n';
std::cout << "factorycreate has registered:";
std::map<std::string, creator_t *, std::less<std::string> >::iterator fitr;
for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr)
std::cout << ' ' << fitr->first;
std::cout << '\n';
for (fitr=factorycreate.begin(); fitr!=factorycreate.end(); ++fitr) {
circuit_creator_t mycreate = factorycreate[fitr->first];
define_t *mydefine = factorydef[fitr->first]();
printf("\n type: %s\n",mydefine->type );
printf(" nodes: %i\n",mydefine->nodes );
printf(" action: %i\n",mydefine->action );
printf(" required->key: %s\n",mydefine->required->key);
*/
module * m = new module ();
m->circreate = mycreate;
m->definition = mydefine;
if (modules.get ((char *) mydefine->type) != NULL) {
logprint (LOG_ERROR, "load module already registered: %s\n", mydefine->type);
}
else {
modules.put ((char *) mydefine->type, m);
}
}
qucs::hashiterator<module> it;
for (it = qucs::hashiterator<module> (module::modules); *it; ++it) {
module * m = it.currentVal ();
struct define_t * def = m->definition;
printf("\n" );
printf("type: %s\n",def->type );
printf("\n" );
}
*/
}
void module::closeDynamicLibs()
{
for(itr=dl_list.begin(); itr!=dl_list.end(); itr++){
#if _WIN32
FreeLibrary(*itr);
#else
dlclose(*itr);
#endif
}
}