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

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3