00001 /*! @file Simulations/SimEventOS.C Stab to run a simulation modules configures with an xml file */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: $ 00035 // $Id: $ 00036 // 00037 00038 #include "Component/JobServerConfigurator.H" 00039 #include "Component/ModelManager.H" 00040 #include "Image/Image.H" 00041 #include "Image/Pixels.H" 00042 #include "Image/Point2D.H" 00043 #include "Media/SimFrameSeries.H" 00044 #include "Neuro/NeuroOpts.H" 00045 #include "Raster/Raster.H" 00046 #include "Simulation/SimEventQueueConfigurator.H" 00047 #include "Simulation/SimEventQueue.H" 00048 #include "Util/AllocAux.H" 00049 #include "Util/Pause.H" 00050 #include "Util/Types.H" 00051 #include "Util/csignals.H" 00052 #include "Util/log.H" 00053 #include "Util/sformat.H" 00054 #include "Util/StringUtil.H" 00055 #include "Util/Timer.H" 00056 #include "rutz/trace.h" 00057 00058 #include <signal.h> 00059 #include <stdio.h> 00060 #include <sys/types.h> 00061 #include <dlfcn.h> 00062 00063 #ifdef HAVE_LIBXML 00064 #include <libxml/parser.h> 00065 #include <libxml/tree.h> 00066 #endif 00067 00068 typedef int mainLoopFunc(const int argc, const char** argv); 00069 00070 mainLoopFunc* loadObject(ModelManager& manager, 00071 const std::string& libFile, 00072 const std::string& name, 00073 const std::string& mainOverrideName = "") 00074 { 00075 void* libPtr = dlopen(libFile.c_str(), RTLD_NOW | RTLD_GLOBAL); 00076 if (!libPtr) 00077 LFATAL("Can not load library: %s (%s)", libFile.c_str(), dlerror()); 00078 00079 std::string modInstFuncName = "createModule" + name; 00080 dlerror(); //reset any errors 00081 createSimEventModule* createObj = (createSimEventModule*) dlsym(libPtr, modInstFuncName.c_str()); 00082 00083 if (!createObj) 00084 LFATAL("Can not find the %s symbol: %s. \nCheck the module Name", modInstFuncName.c_str(), dlerror()); 00085 00086 mainLoopFunc* mainLoop = NULL; 00087 if(mainOverrideName != "") 00088 { 00089 dlerror(); //reset any errors 00090 mainLoop = (mainLoopFunc*) dlsym(libPtr, mainOverrideName.c_str()); 00091 if(!mainLoop) 00092 LFATAL("Can not find mainLoop symbol (%s): %s. \nCheck the module Name", mainOverrideName.c_str(), dlerror()); 00093 00094 } 00095 00096 nub::ref<SimModule> obj = createObj(manager); 00097 manager.addSubComponent(obj); 00098 00099 //dlclose(libPtr); 00100 00101 return mainLoop; 00102 } 00103 00104 void getNodeMatchText(xmlDocPtr doc, xmlNodePtr nodePtr, 00105 const char* nodeName, std::string &result) 00106 { 00107 xmlChar *tmp = NULL; 00108 if (!xmlStrcmp(nodePtr->name, (const xmlChar *)nodeName)) 00109 tmp = xmlNodeListGetString(doc, nodePtr->xmlChildrenNode, 1); 00110 00111 if (tmp != NULL) { 00112 result = std::string((const char*)tmp); 00113 xmlFree(tmp); 00114 } 00115 } 00116 00117 mainLoopFunc* configModules(const char* xmlFile, ModelManager& manager, 00118 const int argc, const char **argv, bool skipFirstArgs) 00119 { 00120 std::vector<const char*> argvals; 00121 00122 int argcnt=0; 00123 00124 for(int i=0; i<argc; i++) 00125 { 00126 if (skipFirstArgs && (i==1) ) continue; 00127 argvals.push_back(argv[i]); 00128 argcnt++; 00129 } 00130 00131 00132 // check if the file exists: 00133 xmlDocPtr doc = xmlReadFile(xmlFile, NULL, 0); 00134 if (doc == NULL) { 00135 LFATAL("Failed to parse %s", xmlFile); 00136 } 00137 00138 /* Get the root element node */ 00139 xmlNode *root_element = xmlDocGetRootElement(doc); 00140 00141 // look for object annotations 00142 xmlNodePtr cur = root_element; //->xmlChildrenNode; //dont care about top level 00143 00144 //Skip the top level if scenes is in the name 00145 if ((!xmlStrcmp(cur->name, (const xmlChar *)"SimModules"))) 00146 cur = root_element->xmlChildrenNode; //dont care about top level 00147 00148 mainLoopFunc* mainLoop = NULL; 00149 00150 while (cur != NULL) { 00151 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Module"))) { 00152 // get the scene data: 00153 xmlNodePtr modulePtr = cur->xmlChildrenNode; 00154 00155 std::string name, location, mainLoopFuncName; 00156 00157 while(modulePtr != NULL) { // read the attributes and polygons 00158 getNodeMatchText(doc, modulePtr, "Name", name); 00159 getNodeMatchText(doc, modulePtr, "Location", location); 00160 getNodeMatchText(doc, modulePtr, "MainLoop", mainLoopFuncName); 00161 00162 //Process the args 00163 if ((!xmlStrcmp(modulePtr->name, (const xmlChar *)"Args"))) { 00164 xmlNodePtr argPtr = modulePtr->xmlChildrenNode; 00165 00166 while(argPtr != NULL) 00167 { 00168 00169 if ((!xmlStrcmp(argPtr->name, (const xmlChar *)"arg"))) { 00170 xmlChar* name = xmlGetProp(argPtr, (const xmlChar*)"name"); 00171 xmlChar* value = xmlGetProp(argPtr, (const xmlChar*)"value"); 00172 00173 std::string arg = "--" + std::string((const char*)name) + 00174 "=" + std::string((const char*)value); 00175 argvals.push_back(strdup(arg.c_str())); 00176 argcnt++; 00177 00178 xmlFree(name); 00179 xmlFree(value); 00180 } 00181 argPtr = argPtr->next; 00182 } 00183 00184 } 00185 00186 modulePtr = modulePtr->next; 00187 } 00188 00189 mainLoopFunc* tmpMainLoop = loadObject(manager, location, name, mainLoopFuncName); 00190 if(tmpMainLoop) 00191 { 00192 if(!mainLoop) 00193 mainLoop = tmpMainLoop; 00194 else 00195 LFATAL("ERROR! Two Main Loops Defined In XML!"); 00196 } 00197 00198 } 00199 cur = cur->next; 00200 } 00201 xmlFreeDoc(doc); 00202 xmlCleanupParser(); 00203 00204 if (manager.parseCommandLine( 00205 (const int)argcnt, &argvals[0], "", 0, 0) == false) 00206 LFATAL("Bad Arguments!"); 00207 00208 return mainLoop; 00209 } 00210 00211 volatile int signum = 0; 00212 00213 void* RunSimOS(void* seq_p) 00214 { 00215 nub::ref<SimEventQueue> seq = *((nub::ref<SimEventQueue>*)seq_p); 00216 00217 PauseWaiter p; 00218 SimStatus status = SIM_CONTINUE; 00219 00220 Timer timer; 00221 //main loop: 00222 while(status == SIM_CONTINUE) 00223 { 00224 // Are we in pause mode, if so, hold execution: 00225 if (p.checkPause()) continue; 00226 00227 if (signum != 0) { 00228 char msg[255]; 00229 snprintf(msg, 255, "quitting because %s was caught", signame(signum)); 00230 LINFO("%s", msg); 00231 seq->post(rutz::make_shared(new SimEventBreak(seq.get(), msg))); 00232 status = seq->evolve(); 00233 break; 00234 } 00235 // Evolve for one time step and switch to the next one: 00236 status = seq->evolve(); 00237 } 00238 pthread_exit(NULL); 00239 } 00240 00241 int main(const int argc, const char **argv) 00242 { 00243 // 'volatile' because we will modify this from signal handlers 00244 00245 // catch signals and redirect them for a clean exit (in particular, 00246 // this gives us a chance to do useful things like flush and close 00247 // output files that would otherwise be left in a bogus state, like 00248 // mpeg output files): 00249 catchsignals(&signum); 00250 00251 MYLOGVERB = LOG_INFO; 00252 ModelManager manager("SimEvent Kernel"); 00253 00254 nub::ref<SimEventQueueConfigurator> 00255 seqc(new SimEventQueueConfigurator(manager)); 00256 manager.addSubComponent(seqc); 00257 00258 // Request a bunch of option aliases (shortcuts to lists of options): 00259 REQUEST_OPTIONALIAS_NEURO(manager); 00260 00261 std::string xmlFile = std::string(getenv("HOME")) + "/.SimEventOS.xml"; 00262 00263 mainLoopFunc* mainLoop = NULL; 00264 if (argc > 1) 00265 { 00266 if (argv[1][0] != '-') //This is an xml file, use it 00267 mainLoop = configModules(argv[1], manager, argc, argv, true); 00268 else 00269 mainLoop = configModules(xmlFile.c_str(), manager, argc, argv, false); 00270 } else { 00271 mainLoop = configModules(xmlFile.c_str(), manager, argc, argv, false); 00272 } 00273 00274 nub::ref<SimEventQueue> seq = seqc->getQ(); 00275 00276 manager.start(); 00277 00278 // temporary, for debugging... 00279 seq->printCallbacks(); 00280 00281 00282 //Start up our SimEventOS runtime thread 00283 pthread_t SimOSThread; 00284 int rc = pthread_create(&SimOSThread, NULL, RunSimOS, (void*)(&seq)); 00285 00286 //Execute an overridden mainloop if it exists 00287 if(mainLoop) 00288 rc = mainLoop(argc, argv); 00289 00290 //Wait for the SimOSThread loop to finish 00291 void* status; 00292 rc = pthread_join(SimOSThread, &status); 00293 00294 // print final memory allocation stats 00295 LINFO("Simulation terminated."); 00296 00297 // stop all our ModelComponents 00298 manager.stop(); 00299 00300 return rc; 00301 }