00001
00199 #include "libfaudes.h"
00200
00201 using namespace faudes;
00202
00203
00204
00205 #ifdef FAUDES_WINEXTRA
00206 #define sleep(sec) Sleep((sec) * 1000)
00207 #define usleep(usec) Sleep((usec) / 1000)
00208 #endif
00209
00210
00211
00212 void usage_exit(const std::string& message="") {
00213 std::cout << "simfaudes: " << message << std::endl;
00214 std::cout << "" << std::endl;
00215 std::cout << "simfaudes: usage: " << std::endl;
00216 std::cout << " simfaudes [-q][-v][-i][-bc] [-bt <nnn>][-bs <nnn>] [-l <logfile>] [-ls] [-le] [-lt] <simfile> " << std::endl;
00217 std::cout << "where " << std::endl;
00218 std::cout << " <simfile>: simulation configuration file" << std::endl;
00219 std::cout << "" << std::endl;
00220 std::cout << " -q: less console output " << std::endl;
00221 std::cout << " -qq: absolutely no console output " << std::endl;
00222 std::cout << " -v: more console output" << std::endl;
00223 std::cout << " -vv: event more console output" << std::endl;
00224 std::cout << " -i: interactive mode " << std::endl;
00225 std::cout << "" << std::endl;
00226 std::cout << " -bc: break on condition" << std::endl;
00227 std::cout << " -bt <nnn>: break on time <nnn> " << std::endl;
00228 std::cout << " -bs <nnn>: break on step <nnn> " << std::endl;
00229 std::cout << "" << std::endl;
00230 std::cout << " -l <logfile>: log to <logfile> " << std::endl;
00231 std::cout << " -ls: log states" << std::endl;
00232 std::cout << " -le: log events" << std::endl;
00233 std::cout << " -lt: log time" << std::endl;
00234 std::cout << " -la: log all" << std::endl;
00235 std::cout << " -t <nnn>: fifo trace buffer length <nnn> " << std::endl;
00236 std::cout << "" << std::endl;
00237 std::cout << " -d <devfile>: use io device configured from file" << std::endl;
00238 std::cout << "" << std::endl;
00239 std::cout << "" << std::endl;
00240 exit(-1);
00241 }
00242
00243
00244 int main(int argc, char* argv[])
00245 {
00246
00247 std::string mMark ="% simfaudes: ========================================= ";
00248
00249
00250 int mConsoleOut=0;
00251 bool mInteractive=false;
00252 std::string mSimFile="";
00253 std::string mDevFile="";
00254 bool mBreakCondition=false;
00255 tpTime::Type mBreakTime=tpTime::Max;
00256 int mBreakStep=-1;
00257 std::string mLogFile="";
00258 int mLogMode=0;
00259 int mTraceLength=5;
00260
00261
00262 for(int i=1; i<argc; i++) {
00263 std::string option(argv[i]);
00264
00265 if((option=="-q") || (option=="--quiet")) {
00266 mConsoleOut=-1;
00267 continue;
00268 }
00269
00270 if((option=="-qq") || (option=="--quietquiet")) {
00271 mConsoleOut=-2;
00272 continue;
00273 }
00274
00275 if((option=="-v") || (option=="--verbose")) {
00276 mConsoleOut=1;
00277 continue;
00278 }
00279
00280 if((option=="-vv") || (option=="--verboseverbose")) {
00281 mConsoleOut=2;
00282 continue;
00283 }
00284
00285 if((option=="-i") || (option=="--interactive")) {
00286 mInteractive=true;
00287 continue;
00288 }
00289
00290 if((option=="-d") || (option=="--device")) {
00291 i++; if(i>=argc) usage_exit();
00292 mDevFile=argv[i];
00293 continue;
00294 }
00295
00296 if((option=="-bc") || (option=="--breakcondition")) {
00297 mBreakCondition=true;
00298 continue;
00299 }
00300
00301 if((option=="-bt") || (option=="--breaktime")) {
00302 i++; if(i>=argc) usage_exit();
00303 mBreakTime=(tpTime::Type) ToIdx(argv[i]);
00304 continue;
00305 }
00306
00307 if((option=="-bs") || (option=="--breakstep")) {
00308 i++; if(i>=argc) usage_exit();
00309 mBreakStep=(int) ToIdx(argv[i]);
00310 continue;
00311 }
00312
00313 if((option=="-l") || (option=="--logfile")) {
00314 i++; if(i>=argc) usage_exit();
00315 mLogFile=argv[i];
00316 continue;
00317 }
00318
00319 if((option=="-ls") || (option=="--logstates")) {
00320 mLogMode |= LoggingExecutor::States;
00321 continue;
00322 }
00323
00324 if((option=="-le") || (option=="--logevents")) {
00325 mLogMode |= LoggingExecutor::Events;
00326 continue;
00327 }
00328
00329 if((option=="-lt") || (option=="--logtime")) {
00330 mLogMode |= LoggingExecutor::Time;
00331 continue;
00332 }
00333
00334 if((option=="-la") || (option=="--logall")) {
00335 mLogMode |= 0xff;
00336 continue;
00337 }
00338
00339 if((option=="-t") || (option=="--trace")) {
00340 i++; if(i>=argc) usage_exit();
00341 mTraceLength=(int) ToIdx(argv[i]);
00342 continue;
00343 }
00344
00345 if((option=="-?") || (option=="--help")) {
00346 usage_exit();
00347 continue;
00348 }
00349
00350 if(option.c_str()[0]=='-') {
00351 usage_exit("unknown option "+ option);
00352 continue;
00353 }
00354
00355 if(mSimFile!="")
00356 usage_exit("more than one filname specified" );
00357 mSimFile=option;
00358 }
00359
00360
00361 if(mSimFile=="")
00362 usage_exit("you must specify a filename" );
00363
00364
00365 if(mDevFile!="" && mInteractive)
00366 usage_exit("you must not specify both interactive and synchrone mode");
00367
00368
00369 DeviceExecutor mExecutor;
00370
00371
00372 mExecutor.Read(mSimFile);
00373 mExecutor.Reset();
00374
00375
00376 if(mConsoleOut>=1) {
00377 std::cout << mMark << "dumping configuration" << std::endl;
00378
00379 for(Idx i=0; i< mExecutor.Size(); i++) {
00380 std::cout << mMark << "found generator #" << i+1 << std::endl;
00381 mExecutor.At(i).Generator().Write();
00382 }
00383
00384 for(EventSet::Iterator eit=mExecutor.Alphabet().Begin();
00385 eit!=mExecutor.Alphabet().End(); eit++) {
00386 std::cout << mMark << "found event attributes for \"" <<
00387 mExecutor.EventName(*eit) << "\"" << std::endl;
00388 std::cout << mExecutor.Alphabet().Attribute(*eit).ToString() << std::endl;
00389 }
00390
00391 for(ProposingExecutor::ConditionIterator cit=mExecutor.ConditionsBegin();
00392 cit!=mExecutor.ConditionsEnd(); cit++) {
00393 std::cout << mMark << "found simulation condition \"" <<
00394 mExecutor.Conditions().SymbolicName(*cit) << "\"" << std::endl;
00395 std::cout << mExecutor.Condition(*cit).ToString() << std::endl;
00396 }
00397 }
00398
00399
00400
00401 if(mLogFile!="") {
00402 mExecutor.LogOpen(mLogFile,mLogMode | LoggingExecutor::Statistics);
00403 }
00404 if(mLogFile=="" && mLogMode!=0) {
00405 TokenWriter* ptw= new TokenWriter(TokenWriter::Stdout);
00406 mExecutor.LogOpen(*ptw, mLogMode | LoggingExecutor::Statistics);
00407 }
00408
00409
00410 mExecutor.TraceClear(mTraceLength);
00411
00412
00413 if(mDevFile!="") {
00414 #ifdef FAUDES_PLUGIN_IODEVICE
00415
00416
00417 vDevice* dev=vDevice::FromFile(mDevFile);
00418
00419
00420 #ifdef FAUDES_IODEVICE_SIMPLENET
00421 #ifdef FAUDES_WINEXTRA
00422
00423 if(dynamic_cast<nDevice*>(dev)) {
00424 WSADATA wsaData;
00425 if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0) {
00426 usage_exit("cannot start winsock (network error)");
00427 }
00428 }
00429 #endif
00430 #endif
00431
00432
00433 std::cout << mMark << "Execute via IO device: \""<< dev->Name() << "\"" << std::endl;
00434
00435
00436 mExecutor.Devicep(dev);
00437 if(mBreakTime==tpTime::UnDef) mBreakTime=tpTime::Max;
00438 mExecutor.DeviceStart();
00439 dev->Reset();
00440 while(dev->Status()!=vDevice::Up) {
00441 std::cout << mMark << "Starting IO device \""<< dev->Name() << "\" Status: " << dev->StatusString() << std::endl;
00442 sleep(1);
00443 }
00444 dev->CurrentTime(0);
00445 std::cout << mMark << "IO device \""<< dev->Name() << "\" is Up" << std::endl;
00446 #else
00447
00448 usage_exit("cannot load device \""+mDevFile+"\": device plugin not present");
00449 #endif
00450 }
00451
00452
00453
00454 bool mRunning=true;
00455 bool mInterTemp=mInteractive;
00456 SimConditionSet mSatisfied;
00457 mSatisfied.Name("SatisfiedConditions");
00458 while(mRunning) {
00459
00460 if(mConsoleOut>=2) {
00461 std::cout << mMark << "current state:" << std::endl;
00462 std::cout << mExecutor.CurrentParallelTimedStateStr() << std::endl;
00463 }
00464
00465 if(mConsoleOut>=0 && mConsoleOut<2) {
00466 std::cout << mMark << "current state:" << std::endl;
00467 std::cout << mExecutor.CurrentParallelStateStr() << std::endl;
00468 }
00469
00470 if(mConsoleOut>=1) {
00471 std::cout << mMark << "current time:" << std::endl;
00472 std::cout << "<Time> " << mExecutor.CurrentTime() << " </Time>" << std::endl;
00473 std::cout << "<Step> " << mExecutor.CurrentStep() << " </Step>" << std::endl;
00474 }
00475
00476 if(mConsoleOut==0) {
00477 std::cout << mMark << "current time:" << std::endl;
00478 std::cout << "<Time> " << mExecutor.CurrentTime() << " </Time>" << std::endl;
00479 }
00480
00481 if(mConsoleOut>=0) {
00482 mSatisfied.Clear();
00483 for(ProposingExecutor::ConditionIterator cit=mExecutor.ConditionsBegin();
00484 cit!=mExecutor.ConditionsEnd(); cit++) {
00485 if(mExecutor.Condition(*cit).Satisfied()) mSatisfied.Insert(*cit);
00486 }
00487 if(mSatisfied.Size()>0) {
00488 std::cout << mMark << "found conditions satisfied:" << std::endl;
00489 std::cout << mSatisfied.ToString() << std::endl;
00490 }
00491 }
00492
00493 if(mConsoleOut>=2) {
00494 std::cout << mMark << "simulation event states:" << std::endl;
00495 std::cout << mExecutor.EventStatesToString() << std::endl;
00496 }
00497
00498 if(mConsoleOut>=1) {
00499 std::cout << mMark << "enabled events:" << std::endl;
00500 std::cout << mExecutor.EnabledEvents().ToString() << std::endl;
00501 std::cout << mMark << "enabled interval:" << std::endl;
00502 std::cout << mExecutor.EnabledInterval().Str() << std::endl;
00503 std::cout << mMark << "enabled time:" << std::endl;
00504 std::cout << mExecutor.EnabledTime().Str() << std::endl;
00505 }
00506
00507 if(mExecutor.CurrentTime() >= tpTime::Max) {
00508 if(mConsoleOut>=-1) std::cout << mMark << "time is up" << std::endl;
00509 mInterTemp=false;
00510 mRunning=false;
00511 break;
00512 }
00513
00514 if(mExecutor.BreakCondition() && (mBreakCondition || mInteractive)) {
00515 if(mConsoleOut>=-1) std::cout << mMark << "break condition triggered" << std::endl;
00516 mInterTemp=mInteractive;
00517 mRunning=mInteractive;
00518 }
00519
00520 if(mBreakTime!=tpTime::UnDef)
00521 if(mExecutor.CurrentTime() >= mBreakTime) {
00522 if(mConsoleOut>=-1) std::cout << mMark << "break time reached" << std::endl;
00523 mInterTemp=mInteractive;
00524 mRunning=mInteractive;
00525 }
00526
00527 if(mBreakStep>=0)
00528 if(mExecutor.CurrentStep() >= mBreakStep) {
00529 if(mConsoleOut>=-1) std::cout << mMark << "break step reached" << std::endl;
00530 mInterTemp=mInteractive;
00531 mRunning=mInteractive;
00532 }
00533
00534 if(!mExecutor.IsSynchronous()) {
00535 if(mConsoleOut>=-1) std::cout << mMark << "device out of sync" << std::endl;
00536 mInterTemp=false;
00537 mRunning=false;
00538 break;
00539 }
00540
00541 TimedEvent mPropTrans=mExecutor.ProposeNextTransition();
00542 if(mConsoleOut>=0) {
00543 std::cout << mMark << "proposed action:" << std::endl;
00544 if(mPropTrans.Time>0)
00545 std::cout << "<ProposedTime> " << mPropTrans.Time << " </ProposedTime>" << std::endl;
00546 if(mPropTrans.Event!=0)
00547 std::cout << "<ProposedEvent> " << mExecutor.EventName(mPropTrans.Event) << " </ProposedEvent>" << std::endl;
00548 if((mPropTrans.Time<=0) && (mPropTrans.Event==0) )
00549 std::cout << "+DeadLock+" << std::endl;
00550 }
00551
00552 Idx mEvent=0;
00553
00554 while(mInterTemp) {
00555 std::cout << mMark << "enter command:" << std::endl;
00556 std::string line;
00557 std::getline(std::cin,line);
00558
00559 std::string choice;
00560 std::string param;
00561 std::istringstream sline(line);
00562 sline >> choice;
00563 sline >> param;
00564
00565 int ichoice =-1;
00566 std::istringstream schoice(choice);
00567 schoice >> ichoice;
00568 if(!schoice) ichoice=-1;
00569 int iparam =-1;
00570 std::istringstream sparam(param);
00571 sparam >> iparam;
00572 if(!sparam) iparam=-1;
00573
00574 std::string nchoice;
00575 if(choice.length()>2)
00576 if(choice.at(0)=='"' && choice.at(choice.length()-1)== '"')
00577 nchoice=choice.substr(1,choice.length()-2);
00578
00579 bool err=false;
00580 if(choice=="x" || choice == "exit") {
00581 mRunning=false;
00582 } else
00583 if(choice=="p" || choice=="proposal" || choice=="") {
00584 mExecutor.ExecuteTime(mPropTrans.Time);
00585 if(mExecutor.ExecuteEvent(mPropTrans.Event))
00586 mEvent=mPropTrans.Event;
00587 } else
00588 if(choice=="r" || choice=="run") {
00589 mInterTemp=false;
00590 } else
00591 if(choice=="v" || choice=="revert") {
00592 int step = mExecutor.CurrentStep()-1;
00593 if(iparam!=-1) step=iparam;
00594 std::cout << mMark << "revert to step " << step << std::endl;
00595 mExecutor.RevertToStep(step);
00596 } else
00597 if(choice=="t" || choice=="trace") {
00598 std::cout << mMark << "system trace" << std::endl;
00599 mExecutor.TraceWrite();
00600 continue;
00601 } else
00602 if(mExecutor.Alphabet().Exists(nchoice)) {
00603 if(mExecutor.ExecuteEvent(mExecutor.EventIndex(nchoice)))
00604 mEvent=mExecutor.EventIndex(nchoice);
00605 } else
00606 if(ichoice>0) {
00607 mExecutor.ExecuteTime(ichoice);
00608 } else
00609 if(mExecutor.Alphabet().Exists(choice)) {
00610 if(mExecutor.ExecuteEvent(mExecutor.EventIndex(nchoice)))
00611 mEvent=mExecutor.EventIndex(nchoice);
00612 } else {
00613 std::cout << mMark << "simfaudes interactive mode" << std::endl;
00614 std::cout << "%" << std::endl;
00615 std::cout << "% execute time and/or transitions" << std::endl;
00616 std::cout << "% * <nn> to pass a specified duration <nn> (excl brackets)" << std::endl;
00617 std::cout << "% * \"event\" to execute an event (incl quotes)" << std::endl;
00618 std::cout << "% * [P] or [Ret] to execute the recent proPosal " << std::endl;
00619 std::cout << "%" << std::endl;
00620 std::cout << "% show trace and revert" << std::endl;
00621 std::cout << "% * [T] to show a Trace of recent events and states" << std::endl;
00622 std::cout << "% * [V] <nn> to reVert to step <nn> (obmit <nn> for one step backward) "<< std::endl;
00623 std::cout << "%" << std::endl;
00624 std::cout << "% other" << std::endl;
00625 std::cout << "% * [X] to eXit" << std::endl<< std::endl;
00626 err=true;
00627 }
00628 if(!err) break;
00629 }
00630
00631 if(!mInterTemp && mDevFile=="") {
00632 mExecutor.ExecuteTime(mPropTrans.Time);
00633 if(mExecutor.ExecuteEvent(mPropTrans.Event))
00634 mEvent=mPropTrans.Event;
00635 }
00636 #ifdef FAUDES_PLUGIN_IODEVICE
00637
00638 if(mDevFile!="") {
00639 mEvent=mExecutor.SyncStep();
00640 mExecutor.SyncTime();
00641 }
00642 #endif
00643
00644 if(mConsoleOut>=0 && mEvent!=0) {
00645 std::cout << mMark << "execute event:" << std::endl;
00646 std::cout << "<ExecutedEvent> " << mExecutor.EventName(mEvent) << " </ExecutedEvent>"
00647 << std::endl;
00648 }
00649
00650 }
00651
00652
00653
00654 if(mConsoleOut>=-1) {
00655 std::cout << std::endl;
00656 for(ProposingExecutor::ConditionIterator cit=mExecutor.ConditionsBegin();
00657 cit!=mExecutor.ConditionsEnd(); cit++) {
00658 if(!mExecutor.Condition(*cit).IsEnabled()) continue;
00659 std::cout << mMark << "statistics for simulation condition \"" <<
00660 mExecutor.Conditions().SymbolicName(*cit) << "\"" << std::endl;
00661 mExecutor.Condition(*cit).mSamplesPeriod.Compile();
00662 std::cout << mExecutor.Condition(*cit).mSamplesPeriod.Str();
00663 mExecutor.Condition(*cit).mSamplesDuration.Compile();
00664 std::cout << mExecutor.Condition(*cit).mSamplesDuration.Str() << std::endl;
00665 }
00666 }
00667
00668
00669 mExecutor.LogClose();
00670
00671
00672 mExecutor.Reset();
00673
00674
00675 mExecutor.DeviceStop();
00676
00677
00678 return 0;
00679 }