About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

sp_dplpexecutor.cpp

Go to the documentation of this file.
00001 /** @file sp_dplpexecutor.cpp Executor with IO device  */
00002 
00003 /* 
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008  Thomas Moor
00007 
00008 */
00009 
00010 
00011 // load configuration
00012 #include "corefaudes.h"
00013 
00014 
00015 #include "sp_dplpexecutor.h"
00016 #include <iostream>
00017 
00018 namespace faudes {
00019 
00020 // std faudes type
00021 FAUDES_TYPE_IMPLEMENTATION(DeviceExecutor,DeviceExecutor,LoggingExecutor)
00022 
00023 // constructor
00024 DeviceExecutor::DeviceExecutor(void) : ProposingExecutor() , pDevice(0) { 
00025   mMaxSyncGap=10*tpTime::Step;
00026   mSyncMode=0x0;
00027 }
00028 
00029 // constructor
00030 DeviceExecutor::DeviceExecutor(const DeviceExecutor& rOther) : ProposingExecutor() , pDevice(0) { 
00031   mMaxSyncGap=10*tpTime::Step;
00032   mSyncMode=0x0;
00033   DoAssign(rOther);
00034 }
00035 
00036 // destructor
00037 DeviceExecutor::~DeviceExecutor(void) { 
00038 }
00039 
00040 
00041 
00042 // DoAssign(other)
00043 void DeviceExecutor::DoAssign(const DeviceExecutor& rOther) {
00044   FD_DX("LoggingExecutor(" << this << ")::DoAssign(other)");
00045   // my members
00046   Devicep(NULL);
00047   // base
00048   ProposingExecutor::DoAssign(rOther);
00049 }
00050 
00051 // set io device
00052 void DeviceExecutor::Devicep(vDevice* dev) {
00053   pDevice=dev;
00054   mSyncError=false;
00055 #ifdef FAUDES_PLUGIN_IODEVICE
00056   if(!dev) return;
00057   pDevice->Reset();
00058 #endif
00059 }
00060 
00061 // reset the device
00062 void DeviceExecutor::DeviceReset(void) {
00063 #ifdef FAUDES_PLUGIN_IODEVICE
00064   if(!pDevice) return;
00065   pDevice->Reset();
00066 #endif
00067 }
00068 
00069 // start the device
00070 void DeviceExecutor::DeviceStart(void) {
00071 #ifdef FAUDES_PLUGIN_IODEVICE
00072   if(!pDevice) return;
00073   pDevice->Start();
00074 #endif
00075 }
00076 
00077 // stop the device
00078 void DeviceExecutor::DeviceStop(void) {
00079 #ifdef FAUDES_PLUGIN_IODEVICE
00080   if(!pDevice) return;
00081   pDevice->Stop();
00082 #endif
00083 }
00084 
00085 // clear static data
00086 void DeviceExecutor::Clear(void){
00087   Reset();
00088   ProposingExecutor::Clear();
00089 }
00090 
00091 // clear dynamic data
00092 void DeviceExecutor::Reset(long int seed){
00093   FD_DS("DeviceExecutor::Reset()");
00094 #ifdef FAUDES_PLUGIN_IODEVICE
00095   // reset the device
00096   if(pDevice) 
00097      pDevice->Reset();
00098   // overwrite input attributes 
00099   if(pDevice) {
00100     SimPriorityEventAttribute neverpa;
00101     neverpa.mPriority=-9999; // todo: have a never-priority                
00102     SimEventAttribute never;
00103     never.Priority(neverpa);
00104     EventSet::Iterator eit=pDevice->Inputs().Begin();
00105     for(;eit!=pDevice->Inputs().End(); eit++) {
00106       if(Alphabet().Exists(*eit)) EventAttribute(*eit,never);
00107     }
00108   }
00109 #endif
00110   // call base
00111   ProposingExecutor::Reset(seed);
00112   mSyncError=false;
00113   FD_DS("DeviceExecutor::Reset(): done");
00114 }
00115 
00116 // Convenience
00117 bool DeviceExecutor::DeviceResetRequest(void) {
00118 #ifdef FAUDES_PLUGIN_IODEVICE
00119   // bail out
00120   if(!pDevice) return false;
00121   // pass on to device
00122   return pDevice->ResetRequest();
00123 #else
00124   return false;
00125 #endif
00126 }
00127 
00128 //ExecuteEvent
00129 bool DeviceExecutor::ExecuteEvent(Idx event){
00130   FD_DS("DeviceExecutor::ExecuteEvent(): "<< EventName(event));
00131   /*
00132 #ifdef FAUDES_PLUGIN_IODEVICE
00133   // sync time
00134   if(pDevice) SyncStep(0);
00135 #endif
00136   */
00137   // execute event
00138   bool res=ProposingExecutor::ExecuteEvent(event);
00139   /*
00140 #ifdef FAUDES_PLUGIN_IODEVICE
00141   // pass on to callbacks
00142   if(res && pDevice) pDevice->WriteOutput(event);
00143 #endif
00144   */
00145   // report
00146   return res;
00147 }
00148 
00149 
00150 //SyncTime()
00151 bool DeviceExecutor::SyncTime(void){
00152 
00153   // no plugin, no run
00154 #ifndef FAUDES_PLUGIN_IODEVICE
00155   return false;
00156 #else
00157 
00158   // no device, no run
00159   if(!pDevice) return false;
00160 
00161   // figure situation
00162   tpTime::Type devNow=pDevice->CurrentTime();
00163   tpTime::Type genNow=CurrentTime();
00164   tpTime::Type syncTime=devNow-genNow;
00165   tpTime::Type propTime=ProposeNextTransition().Time;
00166 
00167   // report
00168   FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
00169 
00170   // time sync: no chance since generator is ahead
00171   if(mSyncMode & SyncStrictTime)
00172   if(syncTime < -mMaxSyncGap) {
00173     FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: gen time ahead");
00174     mSyncError=true;
00175     pDevice->Reset();
00176     return false;
00177   }
00178 
00179   // time sync: check whether proposal allows for sync
00180   if(mSyncMode & SyncStrictTime)
00181   if(syncTime - mMaxSyncGap > propTime || propTime==tpTime::UnDef) {
00182     FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: cannot sync enough time");
00183     mSyncError=true;
00184     pDevice->Reset();
00185     return false;
00186   }
00187 
00188   // fix undef time (aka deadlock)
00189   // note: this is pointless, since the executor will not recover
00190   if(propTime==tpTime::UnDef) propTime=tpTime::Max;
00191  
00192   // adjust by proposal
00193   if(syncTime > propTime) {
00194     FD_DS_SYNC("DeviceExecutor::SyncTime(): adjust by proposal");
00195     syncTime=propTime;
00196   }
00197 
00198   // time sync: pass generator time 
00199   FD_DS_SYNC("DeviceExecutor::SyncTime(): generator to pass " << syncTime);
00200   if(!ProposingExecutor::ExecuteTime(syncTime)) {
00201     tpTime::Type maxsync=EnabledTime().UB();
00202     if(maxsync >= syncTime-mMaxSyncGap) {
00203       syncTime=maxsync;
00204     }
00205     FD_DS_SYNC("DeviceExecutor::SyncTime(): retry: generator to pass " << syncTime);
00206     if(!ProposingExecutor::ExecuteTime(syncTime)) 
00207     if(mSyncMode & SyncStrictTime) {
00208       FD_DS_SYNC("DeviceExecutor::SyncTime(): exec error");
00209       mSyncError=true;
00210       pDevice->Reset();
00211       return false;
00212     }
00213   };
00214 
00215   // done
00216   FD_DS_SYNC("DeviceExecutor::SyncTime(): ok: device time " << 
00217     pDevice->CurrentTime() << " gen time " << CurrentTime());
00218   return true;
00219 
00220 #endif
00221 }
00222 
00223 
00224 //SyncEvents()
00225 Idx DeviceExecutor::SyncEvents(void){
00226 
00227   // no plugin, no run
00228 #ifndef FAUDES_PLUGIN_IODEVICE
00229   return 0;
00230 #else
00231 
00232   // no device, no run
00233   if(!pDevice) return 0;
00234 
00235   // ignore alien hardware event
00236   if(Idx sev=pDevice->PeekInput()) {
00237     if(!ParallelExecutor::Alphabet().Exists(sev)) {
00238       FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << "ignored");
00239       pDevice->ReadInput();
00240     }
00241   }
00242 
00243   // get and execute hardware events, if accepted
00244   if(Idx sev=pDevice->PeekInput()) {
00245     if(EnabledEvents().Exists(sev)) {
00246       pDevice->ReadInput();
00247       ProposingExecutor::ExecuteEvent(sev);
00248       FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " accepted");
00249       return sev;
00250     }
00251     FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " postponed");
00252   }
00253 
00254   // check and execute scheduled event
00255   const TimedEvent& proposedTrans=ProposeNextTransition();
00256   if(proposedTrans.Time==0 && proposedTrans.Event!=0) {
00257     FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: " << EventName(proposedTrans.Event));
00258     ProposingExecutor::ExecuteEvent(proposedTrans.Event);
00259     if(pDevice->Outputs().Exists(proposedTrans.Event))
00260       pDevice->WriteOutput(proposedTrans.Event);
00261     FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: execueted");
00262     return proposedTrans.Event; 
00263   }
00264 
00265   // get and execute hardware events
00266   if(Idx sev=pDevice->ReadInput()) {
00267     bool exec = ProposingExecutor::ExecuteEvent(sev);
00268     if(!exec && (mSyncMode & SyncStrictEvents)) {
00269       FD_DS_SYNC("DeviceExecutor::SyncEvents(): sync error: invalid input event");
00270       mSyncError=true;
00271       pDevice->Reset();
00272     }
00273     return (exec ? sev : 0);
00274   }
00275 
00276 
00277   FD_DS_SYNC("DeviceExecutor::SyncEvents(): no events ready");
00278   return 0;
00279 
00280 #endif
00281 }
00282 
00283 //SyncWait()
00284 bool DeviceExecutor::SyncWait(tpTime::Type duration){
00285 
00286   // no plugin, no run
00287 #ifndef FAUDES_PLUGIN_IODEVICE
00288   return false;
00289 #else
00290 
00291   // no device, no run
00292   if(!pDevice) return false;
00293 
00294   // report
00295   FD_DS_SYNC("DeviceExecutor::SyncWait(): sleep " << tpTime::Str(duration) );
00296 
00297   // adjust
00298   const TimedEvent& proposedTrans=ProposeNextTransition();
00299   if(proposedTrans.Time<duration) duration=proposedTrans.Time;
00300   if(duration <0) duration=0;
00301 
00302   // report
00303   FD_DS_SYNC("DeviceExecutor::SyncWait(): adjusted by proposal: " << tpTime::Str(duration) );
00304 
00305   // doit
00306   bool res=pDevice->WaitInputs(duration);
00307 
00308   // done
00309   return res;
00310 
00311 #endif // io plugin
00312 }
00313 
00314 
00315 //SyncWaitMs()
00316 bool DeviceExecutor::SyncWaitMs(int durationms) {
00317 
00318   // no plugin, no run
00319 #ifndef FAUDES_PLUGIN_IODEVICE
00320   return false;
00321 #else
00322 
00323   // no device, no run
00324   if(!pDevice) return false;
00325 
00326   // report
00327   FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): sleep " << durationms );
00328 
00329   // adjust
00330   const TimedEvent& proposedTrans=ProposeNextTransition();
00331   if(proposedTrans.Time*pDevice->TimeScale() <durationms) durationms=proposedTrans.Time *pDevice->TimeScale();
00332   if(durationms <0) durationms=0;
00333 
00334   // report
00335   FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): adjusted by proposal: " << durationms );
00336 
00337   // doit
00338   bool res=pDevice->WaitInputsMs(durationms);
00339 
00340   // done
00341   return res;
00342 
00343 #endif // io plugin
00344 }
00345 
00346 
00347 //SyncStep(duartion)
00348 Idx DeviceExecutor::SyncStep(tpTime::Type duration){
00349   FD_DS_SYNC("DeviceExecutor::SyncStep("<< tpTime::Str(duration) << ")");
00350 
00351   // no plugin, no run
00352 #ifndef FAUDES_PLUGIN_IODEVICE
00353   return 0;
00354 #else
00355 
00356   // no device, no run
00357   if(!pDevice) return 0;
00358 
00359   // result
00360   Idx res=0;
00361 
00362   // doit
00363   if(!SyncTime()) return res;
00364   if((res=SyncEvents())!=0) return res;
00365   if(!SyncWait(duration)) return res;
00366   if(!SyncTime()) return res;
00367   res=SyncEvents();
00368 
00369   // done  
00370   return res;
00371 
00372 #endif // io plugin
00373 }
00374 
00375 //SyncRun(duartion)
00376 bool DeviceExecutor::SyncRun(tpTime::Type duration){
00377   FD_DS_SYNC("DeviceExecutor::SyncRun("<< tpTime::Str(duration) << ")");
00378 
00379   // prepare
00380   tpTime::Type genNow=CurrentTime();
00381   tpTime::Type genStop=genNow+duration;
00382   tpTime::Type genLeft=genStop-genNow;
00383   if(duration==tpTime::Max) {
00384     genStop=tpTime::Max;
00385     genLeft=tpTime::Max;
00386   }
00387 
00388   // loop time
00389   while(genLeft>0) {
00390     // step
00391     if(SyncStep(genLeft)==0) return false;
00392     // update
00393     genNow=CurrentTime();
00394     genLeft=genStop-genNow;
00395     if(duration==tpTime::Max) genLeft=tpTime::Max;
00396   }
00397   // done
00398   return true;
00399 }
00400 
00401 } // namespace
00402 

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen