/******************************************************************* * * DESCRIPTION: class MainSimulator * * AUTHOR: Amir Barylko & Jorge Beyoglonian * Version 2: Daniel Rodriguez. * * EMAIL: mailto://amir@dc.uba.ar * mailto://jbeyoglo@dc.uba.ar * mailto://drodrigu@dc.uba.ar * * DATE: 27/06/1998 * DATE: 12/06/1999 (v2) * *******************************************************************/ /** include files **/ #include #include #include #include #include "mainsimu.h" // base header #include "ini.h" // class Ini #include "modeladm.h" // class SingleModelAdm #include "strutil.h" // lowerCase, str2Int #include "coupled.h" // class Coupled #include "zone.h" // class zone #include "flatcoup.h" // class FlatCoupledCell #include "tdcell.h" // #include "idcell.h" // #include "cppwrapper.h" #include "msgadm.h" #include "modeladm.h" /** private data **/ MainSimulator *MainSimulator::instance( NULL ); /******************************************************************* * Function Name: run ********************************************************************/ MainSimulator &MainSimulator::run() { if( !loader() ) { MException e( "The MainSimulator loader not found!" ) ; e.addText( "The loader must be seted before running the simulation." ) ; MTHROW( e ) ; } // cout << "At the begining of MainSimulator::run() " << endl; gettimeofday( &initStartTime, (struct timezone*) 0 ); loader()->loadData(); SingleCPPWrapper::Instance().initializeMessageQueues(); SingleCPPWrapper::Instance().startMessageMonitor(); while( !SingleCPPWrapper::Instance().isMessageMonitorStarted() ) ; cout << "MachineId is " << SingleCPPWrapper::Instance().getMachineID() << endl; ModelAdmin::ModelDB::const_iterator model_cursor ; const ModelAdmin::ModelDB &models = SingleModelAdm::Instance().getModelDB(); for( model_cursor = models.begin(); model_cursor != models.end(); model_cursor++) { (model_cursor->second)->printModelPartition(); } ZonePartitions::const_iterator cursor; cursor = SingleCPPWrapper::Instance().getZonePartitions().begin(); for( ; cursor != SingleCPPWrapper::Instance().getZonePartitions().end() ; cursor++ ) { cout << "Zone: " << (cursor->first) << " :: " << cursor->second << endl; } loadModels( loader()->modelsStream(), loader()->printParserInfo() ); cout << "----------------------------------------------------------------------------" << endl; createProcessors(); int machineId = SingleCPPWrapper::Instance().getMachineID() ; if (machineId == 0) { cout << "getMachine ID was evaluated to 0 " << endl; cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl; loadExternalEvents( loader()->eventsStream() ); Root::Instance().stopTime( loader()->stopTime() ); gettimeofday(&simStartTime, (struct timezone*) 0 ); Root::Instance().simulate(); gettimeofday( &simEndTime, (struct timezone*) 0 ); } else if (machineId != -1) { cout << "getMachine ID was evaluated to " << machineId << endl; cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl; SingleMsgAdm::Instance().run(); } else if (machineId == -1) { cout << "got an invalid machineID (-1)" << endl; } if( machineId == 0 ) { loader()->writeResults(); cout << "*******************************************************************\n"; cout << "The initialization time is " << calTimeDiff( initStartTime, simStartTime) << " m seconds \n"; cout << "The simulation time is " << calTimeDiff( simStartTime, simEndTime) << " m seconds \n"; cout << "The total simulation time is " << calTimeDiff( initStartTime, simEndTime) << " m seconds\n"; cout << "*******************************************************************\n"; } const list &messageTransferDelays = SingleCPPWrapper::Instance().getMessageTransferDelays(); cout << "*******************************************************************\n"; cout << " The number of remote messages went through the kernel : " << messageTransferDelays.size() << endl; list::const_iterator lCursor = messageTransferDelays.begin(); double total_time = 0; for( ; lCursor != messageTransferDelays.end(); lCursor++) total_time = total_time + *lCursor; if( messageTransferDelays.size() != 0) cout << " The average message transfer delay within the kernel : " << ( (double) total_time/messageTransferDelays.size() ) << " m seconds " << endl; else cout << " No remote Messages went through the kernel in this session" << endl; cout << "*******************************************************************\n"; SingleCPPWrapper::Instance().calCPPMessageDelay(); // if( SingleCPPWrapper::Instance().getMachineID() == 0 && SingleModelAdm::Instance().totalMachineCount() > 1 ) // SingleCPPWrapper::Instance().calSOAPMessageDelay(); cout << "At the end of MainSimulator::run() " << endl; return *this; } /******************************************************************* * Function Name: loadModels ********************************************************************/ MainSimulator &MainSimulator::loadModels( istream &file, bool printParserInfo ) { iniFile().parse( file ); Coupled &top( SingleModelAdm::Instance().newCoupled( "top" ) ) ; // cout << "before loading top " << endl; loadModel( top, iniFile(), printParserInfo ); // cout << "after loading top " << endl; if (top.isLocalMaster()) top.parentId(SingleProcessorAdmin::Instance().rootId); else top.parentId( top.masterId() ) ; return *this; } /******************************************************************* * Function Name: getParameter ********************************************************************/ const string MainSimulator::getParameter( const string &modelName, const string ¶meterName ) const { const Ini::IdList &idList( iniFile().definition( modelName, parameterName ) ); MASSERTMSG( !idList.empty(), "Parameter " + parameterName + " without value" ); return idList.front(); } /******************************************************************* * Function Name: MainSimulator * Description: Constructor ********************************************************************/ MainSimulator::MainSimulator() : separator( '@' ) , componentLabel( "components" ) , inPortsLabel("in") , outPortsLabel("out") , linksLabel("link") , sloader( NULL ) { registerNewAtomics(); } /******************************************************************* * Function Name: loadModel ********************************************************************/ MainSimulator &MainSimulator::loadModel( Coupled &parent, Ini &ini, bool printParserInfo ) { loadPorts( parent, ini ); if( parent.type() == Coupled::cell ) loadCells( static_cast( parent ), ini, printParserInfo ) ; else loadComponents( parent, ini, printParserInfo ) ; loadLinks( parent, ini ) ; if ( (parent.type() == Coupled::cell) && (parent.className() == COUPLED_CELL_NAME) ) { loadPortInTransitions( static_cast(parent), ini, printParserInfo ) ; // cout << "before loading the machine for " << parent.description() << endl; loadMachines(static_cast( parent ) ); // cout << "after loading the machines for " << parent.description() << endl; } else { loadMachines(parent) ; } return *this; } /******************************************************************* * Function Name: loadPorts ********************************************************************/ MainSimulator &MainSimulator::loadPorts( Coupled &parent, Ini &ini ) { string modelName( lowerCase( parent.description() ) ) ; Ini::IdList::const_iterator cursor ; // ports in if ( ini.exists( modelName, MainSimulator::inPortsLabel ) ) { const Ini::IdList &ilist( ini.definition( modelName, MainSimulator::inPortsLabel ) ) ; for( cursor = ilist.begin() ; cursor != ilist.end() ; cursor ++ ) parent.addInputPort( *cursor ) ; } // ports out if( ini.exists( modelName, MainSimulator::outPortsLabel ) ) { const Ini::IdList &ilist( ini.definition( modelName, MainSimulator::outPortsLabel ) ) ; for( cursor = ilist.begin() ; cursor != ilist.end() ; cursor ++ ) parent.addOutputPort( *cursor ) ; } return *this ; } /******************************************************************* * Function Name: loadComponent ********************************************************************/ MainSimulator &MainSimulator::loadComponents( Coupled &parent, Ini &ini, bool printParserInfo ) { string modelName( lowerCase( parent.description() ) ) ; bool exist = ini.exists( modelName, MainSimulator::componentLabel ) ; if( !exist ) { MException e( string("Ini: Coupled Model without components!, Label: ") + modelName + " / " + MainSimulator::componentLabel ) ; MTHROW( e ) ; } else { const Ini::IdList &ilist( ini.definition( modelName, MainSimulator::componentLabel ) ) ; Ini::IdList::const_iterator cursor ; for( cursor = ilist.begin() ; cursor != ilist.end() ; cursor ++ ) { string mName, atomicType ; bool isAtomic = splitString( *cursor, mName, atomicType, MainSimulator::separator ) ; if( isAtomic ) { Atomic &model( SingleModelAdm::Instance().newAtomic( atomicType, mName ) ) ; parent.addModel( model ) ; // cout << "before load Machines" << endl; loadMachines(model); } else { // es un acoplado Coupled *coupled ; // Si es un acoplado puede ser un CoupledCell if( ini.exists( mName, "type" ) ) { string type( ini.definition( mName, "type" ).front() ) ; if( type == "cell" ) coupled = &( SingleModelAdm::Instance().newCoupledCell( mName ) ) ; else if( type == "flat" ) { // cout << "beofore creating the flat cell model " << endl; coupled = &( SingleModelAdm::Instance().newFlatCoupledCell( mName ) ) ; } else MASSERTMSG( false, "Invalid coupled type " + type + "!" ) ; } else coupled = &( SingleModelAdm::Instance().newCoupled( mName ) ) ; parent.addModel( *coupled ) ; loadModel( *coupled, ini, printParserInfo ) ; } } } return *this ; } MainSimulator &MainSimulator::loadMachines(Atomic & atomic) { MachineId mid = SingleCPPWrapper::Instance().machineForModel(atomic.description()); atomic.addMachine(mid); atomic.setMachineProcId(mid, ( static_cast (SingleProcessorAdmin::Instance()) ).newId() ); return *this; } MainSimulator &MainSimulator::loadMachines(Coupled & coupled) { Coupled::DModelList::const_iterator cursor; Model* model; if ( (coupled.type() == Coupled::cell) && (coupled.className() == FLAT_COUPLED_CELL_NAME) ) { MachineId mid = SingleCPPWrapper::Instance().machineForModel(coupled.description()); coupled.addMachine(mid); coupled.setMachineProcId(mid, ( static_cast (SingleProcessorAdmin::Instance()) ).newId() ); } else { // cout << "loading machines for " << coupled.description() << endl; // cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl; for (cursor = coupled.childModels().begin(); cursor != coupled.childModels().end() ; cursor++) { /* cerr << "loading machines for " << coupled.description() << endl; cerr << "in loadMachines(coupled): cursor != coupled.childModels.end() " << endl; cerr << "childModels().size = " << coupled.childModels().size() << endl; cerr << (*coupled.childModels().begin())->description() << endl; */ model = *cursor; MachineId mid = model->machineForProcId( model->masterId() ) ; coupled.addMachine(mid); if (coupled.procInMachine(mid) == Processor::InvalidId) coupled.setMachineProcId(mid, SingleProcessorAdmin::Instance().newId()); } for (cursor = coupled.childModels().begin(); cursor != coupled.childModels().end() ; cursor++) { model = *cursor; if(model->isLocalMaster()) model->parentId(coupled.localProc()); else model->parentId( coupled.procInMachine( model->machineForProcId(model->masterId()))); } } return *this; } MainSimulator &MainSimulator::loadMachines(CoupledCell & coupledCell) { set machineIds; typedef map< MachineId, CellPartition* , less > CellsMap; CellsMap cellsMap; const ZonePartitions &zonePartitions = SingleCPPWrapper::Instance().getZonePartitions(); ZonePartitions::const_iterator cursor; for( cursor = zonePartitions.begin(); cursor != zonePartitions.end() ; cursor++ ) if( machineIds.find( cursor->second ) == machineIds.end() ) machineIds.insert( cursor->second ); set::const_iterator mcursor; string modelName, zone; for( mcursor = machineIds.begin(); mcursor != machineIds.end() ; mcursor++) { CellPartition *partition = new CellPartition(coupledCell.dimension(), coupledCell.borderWrapped() ); for ( cursor = zonePartitions.begin(); cursor != zonePartitions.end(); cursor++) { if( (cursor->second) == *mcursor ) { int index = (cursor->first).find( "(" ); if( index >= 0 ) { modelName = (cursor->first).substr(0, index); zone = (cursor->first).substr( index ); if(modelName == coupledCell.description() ) partition->addLocalZone(zone); } } } if( partition->totalElements() > 0 ) { cellsMap[ *mcursor ] = partition; coupledCell.setMachineProcId( *mcursor , SingleProcessorAdmin::Instance().newId() ); } else delete partition; } CellPosition counter(coupledCell.dimension().dimension(), 0 ); bool overflow = false; while( !overflow ) { int machineCount = 0; ProcId pid = SingleProcessorAdmin::Instance().newId() ; for( CellsMap::const_iterator cursor = cellsMap.begin(); cursor != cellsMap.end(); cursor++) { if( (cursor->second)->localCellsInclude(counter) ) { machineCount++; // cout << "before the first assertion" << endl; MASSERTMSG( machineCount == 1, "You can't have more than one machine for the same cell" + counter.print() ); coupledCell.setCellMachine(counter, cursor->first, pid) ; } } // cout << "before the second assertion" << endl; // cout << "counter is " << counter.print() << endl; MASSERTMSG( machineCount == 1, "One machine should be set to run " + counter.print() ); overflow = counter.next( coupledCell.dimension() ); } for (CellsMap::const_iterator cursor=cellsMap.begin(); cursor != cellsMap.end(); cursor++) delete cursor->second; return *this; } /******************************************************************* * Function Name: loadCells ********************************************************************/ MainSimulator &MainSimulator::loadCells( CoupledCell &parent, Ini &ini, bool printParserInfo ) { string modelName( lowerCase( parent.description() ) ) ; // get the width and height if ( ini.exists( modelName, "dim" ) ) { MASSERTMSG( !ini.exists( modelName, "width" ) && !ini.exists( modelName, "height" ), "The DIM clause can't coexist with the WITDH or the HEIGHT clauses"); Ini::IdList dimension = ini.definition( modelName, "dim" ); CellPosition cp( ini.join(dimension) ); nTupla dims( cp ); MASSERTMSG( dims.dimension() >= 2, "The tuple defined with the DIM clause is invalid. It's must have 2 or more elements."); parent.dim( dims ); } else { MASSERTMSG( !ini.exists( modelName, "dim" ), "The DIM clause can't coexist with the WITDH or the HEIGHT clauses"); int width = str2Int( ini.definition( modelName, "width" ).front() ) ; int height = str2Int( ini.definition( modelName, "height" ).front() ) ; parent.dim( DIM_WIDTH, width ); parent.dim( DIM_HEIGHT, height ); } Real initialValue( str2Real( ini.definition( modelName, "initialvalue" ).front() ) ) ; parent.initialCellValue( initialValue ) ; bool inertial = ini.definition( modelName, "delay" ).front() == "inertial" ; parent.inertialDelay( inertial ) ; bool wrapped = ini.definition( modelName, "border" ).front() == "wrapped" ; parent.borderWrapped( wrapped ) ; int milSec( str2Int( ini.definition( modelName, "defaultDelayTime" ).front() ) ) ; parent.defaultDelay( Time( 0, 0, 0, milSec ) ) ; CellPositionList neighborsList ; const Ini::IdList &neighbors( ini.definition( modelName, "neighbors" ) ) ; for( Ini::IdList::const_iterator cursor = neighbors.begin() ; cursor != neighbors.end() ; cursor++ ) neighborsList.push_back( CellPosition( *cursor ) ) ; loadDefaultTransitions( parent, ini, printParserInfo ) ; CellPositionList selectList ; if( ini.exists( modelName, "select" ) ) { const Ini::IdList &select( ini.definition( modelName, "select" ) ) ; for( Ini::IdList::const_iterator cursor = select.begin() ; cursor != select.end() ; cursor++ ) selectList.push_back( CellPosition( *cursor ) ) ; } // Rami: load the initial cell values so that they will be available for the cell // when the neighborhood get created CellPartition *partition = new CellPartition( parent.dimension(), parent.borderWrapped() ); MachineId machineId = SingleCPPWrapper::Instance().getMachineID() ; const ZonePartitions &zonePartitions = SingleCPPWrapper::Instance().getZonePartitions(); ZonePartitions::const_iterator cursor ; cursor = zonePartitions.begin(); for( ; cursor != zonePartitions.end() ; cursor++) { string modelName, zone; if( cursor->second == machineId ) { int index = (cursor->first).find( "(" ); if( index >= 0 ) { modelName = (cursor->first).substr(0, index); zone = (cursor->first).substr(index); if( modelName == parent.description() ) partition->addLocalZone(zone) ; } } } parent.createCells( neighborsList, selectList , partition ) ; // cout << "created the cells successfully " << endl; loadInitialCellValues( parent, ini ) ; // cout << "loaded initial cell values " << endl; loadLocalZones( parent, ini, printParserInfo ) ; // cout << "loaded local zones " << endl; return *this ; } /******************************************************************* * Function Name: loadLinks ********************************************************************/ MainSimulator &MainSimulator::loadLinks( Coupled &parent, Ini &ini ) { string modelName( lowerCase( parent.description() ) ) ; Ini::IdList::const_iterator cursor ; // links ( port(@model)? ) if( ini.exists( modelName, MainSimulator::linksLabel ) ) { const Ini::IdList &ilist( ini.definition( modelName, MainSimulator::linksLabel ) ) ; for( cursor = ilist.begin() ; cursor != ilist.end() ; cursor ++ ) { string sourceName, sourcePort, destName, destPort; if( !splitString( *cursor, sourcePort, sourceName, MainSimulator::separator ) ) sourceName = modelName ; cursor++; // the cursor must be valid if( !splitString( *cursor, destPort, destName, MainSimulator::separator ) ) destName = modelName ; //////////////////////////////////////////////////////// // If the model is of type CoupledCell and the input // port don't exist, then I create it. if (parent.className() != FLAT_COUPLED_CELL_NAME) { //Rami // string modelName = SingleProcessorAdmin::Instance().processor( destName ).model().className(); string modelName = SingleModelAdm::Instance().model( destName ).className(); if ( modelName == TRANSPORT_DELAY_CELL_NAME || modelName == INERTIAL_DELAY_CELL_NAME ) { // the addInPort method adds a port if not exist //Rami // static_cast(&SingleProcessorAdmin::Instance().processor( destName).model())->addInPort( destPort ); static_cast(&SingleModelAdm::Instance().model(destName))->addInputPort( destPort ); } } // NOTE: If the parent is a FlatCoupledCell, then addInfluence will create the port /////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // If the model is of type CoupledCell and the output // port don't exist, then I create it. if (parent.className() != FLAT_COUPLED_CELL_NAME) { //Rami // string modelName = SingleProcessorAdmin::Instance().processor( sourceName ).model().className(); string modelName = SingleModelAdm::Instance().model( sourceName ).className() ; if ( modelName == TRANSPORT_DELAY_CELL_NAME || modelName == INERTIAL_DELAY_CELL_NAME ) { // the addOutPort method adds a port if not exist //Rami // static_cast(&SingleProcessorAdmin::Instance().processor(sourceName).model())->addOutPort( sourcePort ); static_cast(&SingleModelAdm::Instance().model(sourceName))->addOutPort( sourcePort ); } } // NOTE: If the parent is a FlatCoupledCell, then addInfluence will create the port /////////////////////////////////////////////////////// parent.addInfluence( sourceName, sourcePort, destName, destPort ) ; } } return *this ; } /******************************************************************* * Function Name: loadExternalEvents ********************************************************************/ MainSimulator &MainSimulator::loadExternalEvents( istream &fileIn ) { Root::Instance().initialize() ; istream_iterator cursor( fileIn ) ; try { while( cursor != istream_iterator() ) { Time time( *cursor ) ; cursor ++ ; //Rami // Port &port( Root::Instance().top().port( *cursor ) ) ; Coupled &top = static_cast(SingleModelAdm::Instance().model("top")); Port &port(top.port( *cursor ) ) ; cursor ++ ; Root::Instance().addExternalEvent( time, port, str2Real( *cursor ) ) ; cursor++ ; } } catch( InvalidPortRequest &e ) { e.addLocation( MEXCEPTION_LOCATION() ) ; throw e ; } this->showEvents( Root::Instance().events() ) ; return *this; } /******************************************************************* * Function Name: loadInitialCellValues ********************************************************************/ MainSimulator &MainSimulator::loadInitialCellValues( CoupledCell &parent, Ini &ini ) { if( ini.exists( parent.description(), "initialRow" ) ) { MASSERTMSG( parent.dimension().dimension() == 2, "The initialRow clause must only be used when the dimension is 2"); const Ini::IdList &rowsList( ini.definition( parent.description(), "initialRow" ) ) ; register unsigned row = 0; Ini::IdList::const_iterator cursor = rowsList.begin(); while ( cursor != rowsList.end() ) { // the first value is the row number row = str2Int( (*cursor) ) ; MASSERTMSG( row < parent.dim(DIM_HEIGHT), "The number of row for initialRow is out of range. It's " + int2Str(row) + " and must be in [ 0, " + int2Str( parent.dim(DIM_HEIGHT) - 1 ) + "]" ) ; cursor++ ; // Los siguientes elementos son la descripcion de la fila register unsigned col = 0; while ( col < parent.dim( DIM_WIDTH ) ) { MASSERTMSG( cursor != rowsList.end(), "Insuficient data for initialRow. Last row with " + int2Str(col) + " elements. Note: May be a middle row definition with less elements." ) ; string rowVal( (*cursor) ); nTupla t; t.add(row,col); parent.setCellValue( CellPosition(t), str2Real(rowVal) ); col++ ; cursor++; } } } if( ini.exists( parent.description(), "initialRowValue" ) ) { MASSERTMSG( parent.dimension().dimension() == 2, "The initialRowValue clause must only be used when the dimension is 2"); const Ini::IdList &rowsList( ini.definition( parent.description(), "initialRowValue" ) ) ; register unsigned row = 0; Real val; for ( Ini::IdList::const_iterator cursor = rowsList.begin(); cursor != rowsList.end(); cursor++ ) { // the first value is the row number row = str2Int( (*cursor) ) ; MASSERTMSG( row < parent.dim(DIM_HEIGHT), "The number of row for initialRowValue is out of range. It's " + int2Str(row) + " and must be in [ 0, " + int2Str( parent.dim(DIM_HEIGHT) - 1 ) + "]" ) ; cursor++ ; MASSERTMSG( cursor != rowsList.end(), "Invalid initial row value for initialRowValue (must be a pair rowNumber rowValues)!" ); // the second is the description of the row string rowVal( *cursor ) ; MASSERTMSG( rowVal.size() == parent.dim(DIM_WIDTH), "The size of the rows for the initial values of the CoupledCell must be equal to the width value !" ); register unsigned col = 0; for (string::iterator rowCurs = rowVal.begin(); rowCurs != rowVal.end(); rowCurs++ ) { if (*rowCurs >= '0' && *rowCurs <= '9') val.value( *rowCurs - '0'); else val = Real::tundef; nTupla t; t.add( row, col); parent.setCellValue( CellPosition(t), val ); col++; } } } if( ini.exists( parent.description(), "initialCellsValue" ) ) loadInitialCellValuesFromFile( parent, ini.definition(parent.description(), "initialCellsValue").front() ); if( ini.exists( parent.description(), "initialMapValue" ) ) loadInitialCellValuesFromMapFile( parent, ini.definition(parent.description(), "initialMapValue").front() ); return *this ; } int getLineOnFile(FILE *fileIn, char *linea) { #define FILE_BUFFER_SIZE 25000 static char buffer[FILE_BUFFER_SIZE]; static long leido = FILE_BUFFER_SIZE; static long porLeer = FILE_BUFFER_SIZE; register bool encontre = false; register long pos = 0; while (!encontre) { if (leido == FILE_BUFFER_SIZE || porLeer == 0) { if (feof(fileIn) || (porLeer = fread( buffer, 1, FILE_BUFFER_SIZE, fileIn )) == 0) return 0; leido = 0; } if (buffer[leido] != '\n') linea[pos++] = buffer[leido++]; else { encontre = true; leido++; } porLeer--; } linea[pos] = 0; return 1; } /******************************************************************* * Function Name: loadInitialCellValuesFromFile ********************************************************************/ MainSimulator &MainSimulator::loadInitialCellValuesFromFile( CoupledCell &parent, const string &fileName ) { FILE *fileIn; char line[250], *posi; fileIn = fopen( trimSpaces(fileName), "r" ); MASSERTMSG( fileIn != NULL, "Can't open the file '" + fileName + "' defined by the initialCellsValue clause"); while (getLineOnFile(fileIn, line)) if (line != NULL && (posi = strchr(line, '=')) != NULL) parent.setCellValue( CellPosition(line), str2Real(posi+1) ); fclose(fileIn); return *this; } /******************************************************************* * Function Name: loadInitialCellValuesFromMapFile ********************************************************************/ MainSimulator &MainSimulator::loadInitialCellValuesFromMapFile( CoupledCell &parent, const string &fileName ) { FILE *fileIn; char line[250]; fileIn = fopen( trimSpaces(fileName), "r" ); MASSERTMSG( fileIn != NULL, "Can't open the file '" + fileName + "' defined by the initialMapValue clause"); CellPosition counter( parent.dimension().dimension(), 0 ); register bool overflow = false; while (!overflow) { MASSERTMSG( getLineOnFile(fileIn, line), "Insuficient data in file specified with InitialMapValue"); parent.setCellValue( counter, str2Real(line) ); overflow = counter.next( parent.dimension() ); } fclose(fileIn); return *this; } /******************************************************************* * Function Name: loadDefaultTransitions ********************************************************************/ MainSimulator &MainSimulator::loadDefaultTransitions( CoupledCell &parent, Ini &ini, bool printParserInfo ) { if( ini.exists( parent.description(), "localTransition" ) ) { parent.localTransition( ini.definition( parent.description(), "localTransition" ).front() ) ; this->registerTransition( parent.localTransition(), ini, printParserInfo ); } return *this; } /******************************************************************* * Function Name: loadPortInTransitions ********************************************************************/ MainSimulator &MainSimulator::loadPortInTransitions( CoupledCell &parent, Ini &ini, bool printParserInfo ) { // Only for CoupledCell and FlatCoupledCell if( ini.exists( parent.description(), "portintransition" ) ) { const Ini::IdList &portInTranList( ini.definition( parent.description(), "portintransition" ) ) ; // define Cursor for( Ini::IdList::const_iterator cursor = portInTranList.begin() ; cursor != portInTranList.end() ; cursor++ ) { string modelAndPortName( *cursor ) ; cursor++; MASSERTMSG( cursor != portInTranList.end(), "Invalid portInTransition specification. Second parameter missing!" ) ; string actionName( *cursor ), sourcePort, sourceName; MASSERTMSG( splitString( modelAndPortName, sourcePort, sourceName, MainSimulator::separator ), "Invalid portName@cellModelName in portInTransition" ); //////////////////////////////////////////////////// // get the ELSE statement string elseFunction( "" ); if( ini.exists( actionName, "else" ) ){ elseFunction = ini.definition( actionName, "else" ).front() ; MASSERTMSG( elseFunction != actionName, "The Else Function '" + elseFunction + "' can't be the same as the portInFunction.\nProbably it will generate an infinite loop." ); string ef = elseFunction, elseEF; while (ef != "") { elseEF = ""; if( ef != "" && ini.exists( ef, "else" ) ) elseEF = ini.definition( ef, "else" ).front() ; MASSERTMSG( ef != elseEF, "The Else Function '" + ef + "' can't be the same as the portInFunction.\nProbably it will generate an infinite loop." ); registerTransitionPortIn( ef, ini, printParserInfo, elseEF ); ef = elseEF; } } ////////////////////////////////////////////////////// // parse the function definition registerTransitionPortIn( actionName, ini, printParserInfo, elseFunction ); // NOTE: If the port not exist, the setPortInFunction will produce an exception. // Now, make an association between the function and the input port if (parent.className() == COUPLED_CELL_NAME) { // static_cast(&SingleProcessorAdmin::Instance().processor(sourceName).model())->setPortInFunction( sourcePort, actionName ); static_cast(&SingleModelAdm::Instance().model(sourceName))->setPortInFunction( sourcePort, actionName ); } else if (parent.className() == FLAT_COUPLED_CELL_NAME) static_cast(&parent)->setPortInFunction( sourceName, sourcePort, actionName ); else MASSERTMSG( false, "Can't set the PortIn Function in a model of type " + parent.className() ); } } return *this ; } /******************************************************************* * Function Name: loadLocalZones ********************************************************************/ MainSimulator &MainSimulator::loadLocalZones( CoupledCell &parent, Ini &ini, bool printParserInfo ) { if( ini.exists( parent.description(), "zone" ) ) { const Ini::IdList &zoneList( ini.definition( parent.description(), "zone" ) ) ; // zone Cursor for( Ini::IdList::const_iterator zoneCurs = zoneList.begin() ; zoneCurs != zoneList.end() ; zoneCurs++ ) { string fname( *zoneCurs ) ; registerTransition( fname, ini, printParserInfo ); zoneCurs++ ; MASSERTMSG( zoneCurs != zoneList.end() && *zoneCurs == "{", "Invalid zone specification, '{' missing!" ) ; zoneCurs++ ; while( zoneCurs != zoneList.end() && *zoneCurs != "}" ) { Zone zone( *zoneCurs ); for( Zone::Iterator cursor = zone.begin(); cursor != zone.end(); cursor++ ) parent.setLocalTransition( *cursor, fname ); zoneCurs++; } MASSERTMSG( zoneCurs != zoneList.end() && *zoneCurs == "}", "Invalid zone specification, '}' missing!" ) ; } // zone Cursor } return *this ; } /******************************************************************* * Method: registerTransition ********************************************************************/ MainSimulator &MainSimulator::registerTransition(const LocalTransAdmin::Function &fName, Ini &ini, bool printParserInfo ) { if( !SingleLocalTransAdmin::Instance().isRegistered( fName ) ) { if( ini.exists( fName ) && ini.exists( fName, "rule" ) ) { const Ini::IdList &fnList( ini.definition( fName, "rule" ) ) ; strstream buffer ; for( Ini::IdList::const_iterator cursor = fnList.begin() ; cursor != fnList.end() ; cursor++ ) buffer << " " << *cursor ; if( printParserInfo == true ) { ParserDebug().Stream() << "********* BUFFER ********" << endl ; ParserDebug().Stream().write(buffer.str(), buffer.pcount() ); ParserDebug().Stream() << endl ; } SingleLocalTransAdmin::Instance().registerTransition( fName, buffer, printParserInfo, false) ; } else { MException e( string( "The local transition " ) + fName + " is missing in the ini file!" ) ; MTHROW( e ) ; } } return *this; } /******************************************************************* * Method: registerTransitionPortIn ********************************************************************/ MainSimulator &MainSimulator::registerTransitionPortIn(const LocalTransAdmin::Function &fName, Ini &ini, bool printParserInfo, const string &elseFunction ) { if( !SingleLocalTransAdmin::Instance().isRegistered( fName ) ) { if( ini.exists( fName ) && ini.exists( fName, "rule" ) ) { const Ini::IdList &fnList( ini.definition( fName, "rule" ) ) ; strstream buffer ; for( Ini::IdList::const_iterator cursor = fnList.begin() ; cursor != fnList.end() ; cursor++ ) buffer << " " << *cursor ; if( printParserInfo == true ) { ParserDebug().Stream() << "********* BUFFER (for PortIn Transition) ********" << endl ; ParserDebug().Stream().write( buffer.str(), buffer.pcount() ) ; ParserDebug().Stream() << endl ; } SingleLocalTransAdmin::Instance().registerTransition( fName, buffer, printParserInfo, true, elseFunction) ; } else { MException e( string( "The local transition " ) + fName + " is missing in the ini file!" ) ; MTHROW( e ) ; } } return *this; } /******************************************************************* * Function Name: showEvents ********************************************************************/ void MainSimulator::showEvents( const EventList &events, ostream &out ) { for (EventList::const_iterator cursor = events.begin() ; cursor != events.end() ; cursor++ ) out << cursor->asString() << endl; } /******************************************************************* * Method: splitString ********************************************************************/ bool MainSimulator::splitString( const string &full, string &first, string &second, char separator ) { first = second = ""; register int index = full.find( separator ); if( index >= 0 ) { first = full.substr( 0, index ); second = full.substr( index + 1 ); } else first = full; return index >= 0; } MainSimulator &MainSimulator::createProcessors() { const ModelAdmin::ModelDB& modelDB = SingleModelAdm::Instance().getModelDB(); ModelAdmin::ModelDB::const_iterator cursor ; cursor = modelDB.begin(); for ( ; cursor != modelDB.end() ; cursor++ ) { Model *model = cursor->second; // cout << "printing model partition for " << model->description() << endl; // model->printModelPartition(); if ( model->localProc() != Processor::InvalidId ) model->createProcessor(); } return *this; } double MainSimulator::calTimeDiff( struct timeval &start_time, struct timeval& end_time) { long long total_time = 0; if ( start_time.tv_sec == end_time.tv_sec ) total_time = end_time.tv_usec - start_time.tv_usec; else if ( end_time.tv_sec > start_time.tv_sec ) if ( end_time.tv_usec >= start_time.tv_usec ) total_time = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_usec - start_time.tv_usec); else total_time = (end_time.tv_sec - start_time.tv_sec) * 1000000 + 1000000 - start_time.tv_usec + end_time.tv_usec ; else if ( end_time.tv_sec < start_time.tv_sec ) cout << "Error : end_time.tv_sec < start_time.tv_sec )" << endl; return ( (double) total_time/1000) ; }