1 /*
2    Copyright (C) 1998,1999,2000 T. Scott Dattalo
3 
4 This file is part of the libgpsim library of gpsim
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10 
11 This library 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 GNU
14 Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20 
21 
22 #include "modules.h"
23 
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <string>
27 #include <list>
28 #include <iostream>
29 
30 #include "../config.h"
31 
32 #ifndef _WIN32
33 #include <dlfcn.h>
34 #if !defined(_MAX_PATH)
35 #define _MAX_PATH 1024
36 #endif
37 #include <unistd.h>  // for getcwd
38 
39 #else
40 #include <direct.h>
41 #include <windows.h>
42 /*
43  * interface is a Module class member variable in gpsim,
44  * in WIN32 Platform SDK it is a macro, defined in BaseTypes.h
45  * the WIN32 Platform SDK definition should be undefined
46  */
47 #undef interface
48 #endif
49 
50 //#include "error.h"
51 #include "gpsim_interface.h"
52 #include "stimuli.h"
53 #include "symbol.h"
54 #include "xref.h"
55 #include "packages.h"
56 #include "cmd_manager.h"
57 
58 
59 // When a new library is loaded, all of the module types
60 // it supports are placed into the ModuleTypes map. This
61 // object is private to this file.
62 
63 typedef std::map<std::string, Module_Types *> ModuleTypeInfo_t;
64 ModuleTypeInfo_t ModuleTypes;
65 
66 ModuleLibraries_t ModuleLibraries;
67 
68 
69 //------------------------------------------------------------------------
70 // Add a new type to the ModuleTypes map if the name for that type
71 // does not exist already.
72 
AddModuleType(const char * pName,Module_Types * pType)73 static void AddModuleType(const char *pName, Module_Types *pType)
74 {
75   std::string sName = pName;
76   ModuleTypeInfo_t::iterator mti = ModuleTypes.find(sName);
77 
78   if (mti == ModuleTypes.end()) {
79     ModuleTypes[sName] = pType;
80   }
81 }
82 
83 
DynamicModuleLibraryInfo(std::string & sCanonicalName,std::string & sUserSuppliedName,void * pHandle)84 DynamicModuleLibraryInfo::DynamicModuleLibraryInfo(std::string &sCanonicalName,
85     std::string &sUserSuppliedName,
86     void   *pHandle)
87   : m_sCanonicalName(sCanonicalName),
88     m_sUserSuppliedName(sUserSuppliedName),
89     m_pHandle(pHandle)
90 {
91   const char * error;
92 
93   if (m_pHandle) {
94     get_mod_list = (Module_Types_FPTR)get_library_export("get_mod_list", m_pHandle, &error);
95   }
96 
97   if (!get_mod_list) {
98     std::cout << "WARNING: non-conforming module library\n"
99          "  gpsim libraries should have the get_mod_list() function defined\n";
100     std::cerr << error << '\n';
101     free_error_message(error);
102 
103   } else {
104     // Get a pointer to the list of modules that this library file supports.
105     Module_Types *pLibModList = get_mod_list();
106 
107     // Loop through the list of modules supported by the library and an entry
108     // ModuleTypes map for each one.
109 
110     if (pLibModList)
111       for (Module_Types *pModTypes = pLibModList;  pModTypes->names[0]; pModTypes++) {
112         AddModuleType(pModTypes->names[0], pModTypes);
113         AddModuleType(pModTypes->names[1], pModTypes);
114       }
115 
116     // If the module has an "initialize" function, then call it now.
117     typedef  void * (*void_FPTR)(void);
118     void * (*initialize)(void) = (void_FPTR)get_library_export("initialize", m_pHandle, nullptr);
119 
120     if (initialize) {
121       initialize();
122     }
123 
124     /*
125     ICommandHandler * pCliHandler = ml->GetCli();
126     if (pCliHandler != NULL)
127       CCommandManager::GetManager().Register(pCliHandler);
128     */
129   }
130 }
131 
132 
133 //========================================================================
134 
MakeCanonicalName(std::string & sPath,std::string & sName)135 void MakeCanonicalName(std::string &sPath, std::string &sName)
136 {
137 #ifdef _WIN32
138   sName = sPath;
139 #else
140   GetFileName(sPath, sName);
141 #endif
142 }
143 
144 
LoadFile(std::string & fName)145 int ModuleLibrary::LoadFile(std::string &fName)
146 {
147   const char *pszError;
148   bool bReturn = false;
149   std::string sPath = fName;
150   FixupLibraryName(sPath);
151   std::string sName;
152   MakeCanonicalName(sPath, sName);
153   ModuleLibraries_t::iterator mli = ModuleLibraries.find(sName);
154 
155   if (mli == ModuleLibraries.end()) {
156     void *handle = ::load_library(sPath.c_str(), &pszError);
157     if (handle == nullptr) {
158 //#ifdef THROW
159       char cw[_MAX_PATH];
160       getcwd(cw, sizeof(cw));
161 
162       std::string error_string = "failed to open library module " + sPath;
163       error_string += cw;
164       error_string += '\n';
165 
166       free_error_message(pszError);
167       throw Error(error_string);
168 //#endif //THROW
169 
170     } else {
171       ModuleLibraries[sName] = new DynamicModuleLibraryInfo(fName, sName, handle);
172       bReturn = true;
173     }
174   }
175 
176   /*
177   if(verbose)
178     DisplayFileList();
179   */
180   return bReturn;
181 }
182 
183 
InstantiateObject(std::string & sObjectName,std::string & sInstantiatedName)184 int ModuleLibrary::InstantiateObject(std::string &sObjectName, std::string &sInstantiatedName)
185 {
186   ModuleTypeInfo_t::iterator mti = ModuleTypes.find(sObjectName);
187 
188   if (mti != ModuleTypes.end()) {
189     Module *pModule = mti->second->module_constructor(sInstantiatedName.c_str());
190     pModule->set_module_type(sObjectName);
191     globalSymbolTable().addModule(pModule);
192     // Tell the gui or any modules that are interfaced to gpsim
193     // that a new module has been added.
194     gi.new_module(pModule);
195     return pModule != 0;
196   }
197 
198   return 0;
199 }
200 
201 
ListLoadableModules()202 void ModuleLibrary::ListLoadableModules()
203 {
204   for (auto &mt : ModuleTypes) {
205     std::cout << ' ' << mt.first << '\n';
206   }
207 }
208 
209 
210 /*****************************************************************************
211  *
212  * Module.cc
213  *
214  * Here's where much of the infrastructure of gpsim is defined.
215  *
216  * A Module is define to be something that gpsim knows how to simulate.
217  * When gpsim was originally designed, a module was simple a pic processor.
218  * This concept was expanded to accomodate devices like LEDs, switches,
219  * LCDs and so on.
220  */
221 
Module(const char * _name,const char * desc)222 Module::Module(const char *_name, const char *desc)
223   : gpsimObject(_name, desc), simulation_mode(eSM_STOPPED)
224 {
225   xref = new XrefObject;
226 
227   if (_name) {
228     // If there is a module symbol already with this
229     // name, then print a warning before deleting.
230     gpsimObject *pOldModule = globalSymbolTable().find(name());
231 
232     if (pOldModule) {
233       std::cout << "Warning: There already is a symbol in the symbol table named " << _name << '\n';
234       return;
235     }
236   }
237 
238   globalSymbolTable().addModule(this);
239 
240   // Create position attribute place holders if we're not using the gui
241   if (!get_interface().bUsingGUI()) {
242     addSymbol(new Float("xpos", 80.0));
243     addSymbol(new Float("ypos", 80.0));
244   }
245 }
246 
247 
248 #if 0 // warning: 'void dumpOneSymbol(const SymbolEntry_t&)' defined but not used
249 static void dumpOneSymbol(const SymbolEntry_t &sym)
250 {
251   cout << "  " << sym.second
252        << " stored as " << sym.first
253        << endl;
254 }
255 #endif
256 
257 
~Module()258 Module::~Module()
259 {
260   for (auto &si : m_scripts) {
261     ModuleScript *pMS = si.second;
262     delete pMS;
263   }
264 
265   deleteSymbol("xpos");
266   deleteSymbol("ypos");
267   /*
268   cout << "Stuff still in the symbol table:\n";
269   mSymbolTable.ForEachSymbolTable(dumpOneSymbol);
270   */
271   delete package;
272   delete xref;
273 
274   globalSymbolTable().removeModule(this);
275 }
276 
277 
reset(RESET_TYPE)278 void Module::reset(RESET_TYPE )
279 {
280   std::cout << " resetting module " << name() << '\n';
281 }
282 
283 
284 //-------------------------------------------------------------------
285 //-------------------------------------------------------------------
addSymbol(gpsimObject * pSym,std::string * ps_AliasedName)286 int Module::addSymbol(gpsimObject *pSym, std::string *ps_AliasedName)
287 {
288   return mSymbolTable.addSymbol(pSym, ps_AliasedName);
289 }
290 
291 
292 //-------------------------------------------------------------------
293 //-------------------------------------------------------------------
removeSymbol(gpsimObject * pSym)294 int Module::removeSymbol(gpsimObject *pSym)
295 {
296   return mSymbolTable.removeSymbol(pSym);
297 }
298 
299 
300 //-------------------------------------------------------------------
301 //-------------------------------------------------------------------
removeSymbol(const std::string & s)302 int Module::removeSymbol(const std::string &s)
303 {
304   return mSymbolTable.removeSymbol(s);
305 }
306 
307 
308 //-------------------------------------------------------------------
309 //-------------------------------------------------------------------
deleteSymbol(const std::string & s)310 int Module::deleteSymbol(const std::string &s)
311 {
312   return mSymbolTable.deleteSymbol(s);
313 }
314 
315 
316 //-------------------------------------------------------------------
317 //-------------------------------------------------------------------
deleteSymbol(gpsimObject * pSym)318 int Module::deleteSymbol(gpsimObject *pSym)
319 {
320   if (!pSym) {
321     return 0;
322   }
323 
324   if (!removeSymbol(pSym)) {
325     return 0;
326   }
327 
328   delete pSym;
329   return 1;
330 }
331 
332 
333 //-------------------------------------------------------------------
334 //-------------------------------------------------------------------
findSymbol(const std::string & searchString)335 gpsimObject *Module::findSymbol(const std::string &searchString)
336 {
337   return mSymbolTable.findSymbol(searchString);
338 }
339 
340 
341 //-------------------------------------------------------------------
342 //-------------------------------------------------------------------
create_pkg(unsigned int number_of_pins)343 void Module::create_pkg(unsigned int number_of_pins)
344 {
345   delete package;
346 
347   package = new Package(number_of_pins);
348 }
349 
350 
351 //-------------------------------------------------------------------
352 //-------------------------------------------------------------------
assign_pin(unsigned int pin_number,IOPIN * pin)353 void Module::assign_pin(unsigned int pin_number, IOPIN *pin)
354 {
355   if (package) {
356     package->assign_pin(pin_number, pin);
357   }
358 }
359 
360 
361 //-------------------------------------------------------------------
362 //-------------------------------------------------------------------
get_pin_count()363 int Module::get_pin_count()
364 {
365   if (package) {
366     return package->get_pin_count();
367   }
368 
369   return 0;
370 }
371 
372 
373 //-------------------------------------------------------------------
374 //-------------------------------------------------------------------
get_pin_name(unsigned int pin_number)375 std::string &Module::get_pin_name(unsigned int pin_number)
376 {
377   static std::string invalid;
378 
379   if (package) {
380     return package->get_pin_name(pin_number);
381   }
382 
383   return invalid;  //FIXME
384 }
385 
386 
387 //-------------------------------------------------------------------
388 //-------------------------------------------------------------------
get_pin_state(unsigned int pin_number)389 int Module::get_pin_state(unsigned int pin_number)
390 {
391   if (package) {
392     return package->get_pin_state(pin_number);
393   }
394 
395   return 0;
396 }
397 
398 
399 //-------------------------------------------------------------------
400 //-------------------------------------------------------------------
get_pin(unsigned int pin_number)401 IOPIN *Module::get_pin(unsigned int pin_number)
402 {
403   if (package) {
404     return package->get_pin(pin_number);
405   }
406 
407   return nullptr;
408 }
409 
410 
411 //-------------------------------------------------------------------
412 // Module Scripts
413 //
414 // Module command line scripts are named scripts created by symbol
415 // files. For example, with PIC cod files, it's possible to
416 // create assertions and simulation commands using the '.assert'
417 // and '.sim' directives. These commands are ASCII strings that
418 // are collected together.
419 //
420 
421 //-------------------------------------------------------------------
422 // Module::add_command
423 //
424 // Add a command line command to a Module Script.
425 //-------------------------------------------------------------------
add_command(std::string & script_name,std::string & command)426 void Module::add_command(std::string &script_name, std::string &command)
427 {
428   ModuleScript *script = m_scripts[script_name];
429 
430   if (!script) {
431     script = new ModuleScript(script_name);
432     m_scripts[script_name] = script;
433   }
434 
435   script->add_command(command);
436 }
437 
438 
439 //-------------------------------------------------------------------
440 // Module::run_script - execute a gpsim command line script
441 //
442 //-------------------------------------------------------------------
run_script(std::string & script_name)443 void Module::run_script(std::string &script_name)
444 {
445   ModuleScript *script = m_scripts[script_name];
446 
447   if (script) {
448     ICommandHandler *pCli = CCommandManager::GetManager().find("gpsimCLI");
449 
450     if (pCli) {
451       script->run(pCli);
452     }
453   }
454 }
455 
456 
457 //-------------------------------------------------------------------
458 //-------------------------------------------------------------------
ModuleScript(const std::string & name_)459 Module::ModuleScript::ModuleScript(const std::string &name_)
460   : name(name_)
461 {
462 }
463 
464 
465 //-------------------------------------------------------------------
466 //-------------------------------------------------------------------
~ModuleScript()467 Module::ModuleScript::~ModuleScript()
468 {
469   for (auto & command : m_commands) {
470     delete command;
471   }
472 }
473 
474 
475 //-------------------------------------------------------------------
476 //-------------------------------------------------------------------
add_command(const std::string & command)477 void Module::ModuleScript::add_command(const std::string &command)
478 {
479   std::string *new_command = new std::string(command);
480   m_commands.push_back(new_command);
481 }
482 
483 
484 //-------------------------------------------------------------------
485 //-------------------------------------------------------------------
run(ICommandHandler * pCommandHandler)486 void Module::ModuleScript::run(ICommandHandler *pCommandHandler)
487 {
488   if (!pCommandHandler) {
489     return;
490   }
491 
492   pCommandHandler->ExecuteScript(m_commands, nullptr);
493 }
494 
495 
496 //-------------------------------------------------------------------
497 //-------------------------------------------------------------------
concatenate(ModuleScript * pOtherScript)498 void Module::ModuleScript::concatenate(ModuleScript *pOtherScript)
499 {
500   if (!pOtherScript) {
501     return;
502   }
503 
504   for (auto &command : pOtherScript->m_commands) {
505     m_commands.push_back(command);
506   }
507 }
508