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