sp_dplpexecutor.cpp
Go to the documentation of this file.
1 /** @file sp_dplpexecutor.cpp Executor with IO device */
2 
3 /*
4  FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2008 Thomas Moor
7 
8 */
9 
10 
11 // load configuration
12 #include "corefaudes.h"
13 
14 
15 #include "sp_dplpexecutor.h"
16 #include <iostream>
17 
18 namespace faudes {
19 
20 // std faudes type
21 FAUDES_TYPE_IMPLEMENTATION(DeviceExecutor,DeviceExecutor,LoggingExecutor)
22 
23 // constructor
25  mMaxSyncGap=10*Time::Step();
26  mSyncMode=0x0;
27 }
28 
29 // constructor
32  mSyncMode=0x0;
33  DoAssign(rOther);
34 }
35 
36 // destructor
38 }
39 
40 
41 
42 // DoAssign(other)
44  FD_DX("LoggingExecutor(" << this << ")::DoAssign(other)");
45  // my members
46  Devicep(NULL);
47  // base
49 }
50 
51 // set io device
53  pDevice=dev;
54  mSyncError=false;
55 #ifdef FAUDES_PLUGIN_IODEVICE
56  if(!dev) return;
57  pDevice->Reset();
58 #endif
59 }
60 
61 // reset the device
63 #ifdef FAUDES_PLUGIN_IODEVICE
64  if(!pDevice) return;
65  pDevice->Reset();
66 #endif
67 }
68 
69 // start the device
71 #ifdef FAUDES_PLUGIN_IODEVICE
72  if(!pDevice) return;
73  pDevice->Start();
74 #endif
75 }
76 
77 // stop the device
79 #ifdef FAUDES_PLUGIN_IODEVICE
80  if(!pDevice) return;
81  pDevice->Stop();
82 #endif
83 }
84 
85 // clear static data
87  Reset();
89 }
90 
91 // clear dynamic data
92 void DeviceExecutor::Reset(long int seed){
93  FD_DS("DeviceExecutor::Reset()");
94 #ifdef FAUDES_PLUGIN_IODEVICE
95  // reset the device
96  if(pDevice)
97  pDevice->Reset();
98  // overwrite input attributes
99  if(pDevice) {
101  neverpa.mPriority=-9999; // todo: have a never-priority
102  SimEventAttribute never;
103  never.Priority(neverpa);
104  EventSet::Iterator eit=pDevice->Inputs().Begin();
105  for(;eit!=pDevice->Inputs().End(); eit++) {
106  if(Alphabet().Exists(*eit)) EventAttribute(*eit,never);
107  }
108  }
109 #endif
110  // call base
112  mSyncError=false;
113  FD_DS("DeviceExecutor::Reset(): done");
114 }
115 
116 // Convenience
118 #ifdef FAUDES_PLUGIN_IODEVICE
119  // bail out
120  if(!pDevice) return false;
121  // pass on to device
122  return pDevice->ResetRequest();
123 #else
124  return false;
125 #endif
126 }
127 
128 //ExecuteEvent
130  FD_DS("DeviceExecutor::ExecuteEvent(): "<< EventName(event));
131  /*
132 #ifdef FAUDES_PLUGIN_IODEVICE
133  // sync time
134  if(pDevice) SyncStep(0);
135 #endif
136  */
137  // execute event
138  bool res=ProposingExecutor::ExecuteEvent(event);
139  /*
140 #ifdef FAUDES_PLUGIN_IODEVICE
141  // pass on to callbacks
142  if(res && pDevice) pDevice->WriteOutput(event);
143 #endif
144  */
145  // report
146  return res;
147 }
148 
149 
150 //SyncTime()
152 
153  // no plugin, no run
154 #ifndef FAUDES_PLUGIN_IODEVICE
155  return false;
156 #else
157 
158  // no device, no run
159  if(!pDevice) return false;
160 
161  // figure situation
162  Time::Type devNow=pDevice->CurrentTime();
163  Time::Type genNow=CurrentTime();
164  Time::Type syncTime=devNow-genNow;
166 
167 
168  // time sync: no chance since generator is ahead
170  if(syncTime < -mMaxSyncGap) {
171  FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
172  FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: gen time ahead");
173  mSyncError=true;
174  pDevice->Reset();
175  return false;
176  }
177 
178  // time sync: check whether proposal allows for sync
180  if(syncTime - mMaxSyncGap > propTime || propTime==Time::UnDef()) {
181  FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
182  FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: cannot sync enough time");
183  mSyncError=true;
184  pDevice->Reset();
185  return false;
186  }
187 
188  // fix undef time (aka deadlock)
189  // note: this is pointless, since the executor will not recover
190  if(propTime==Time::UnDef()) propTime=Time::Max();
191 
192  // adjust by proposal
193  if(syncTime > propTime) {
194  FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
195  FD_DS_SYNC("DeviceExecutor::SyncTime(): adjust by proposal");
196  syncTime=propTime;
197  }
198 
199  // time sync: pass generator time
200  if(syncTime>0) {
201  FD_DS_SYNC("DeviceExecutor::SyncTime(): generator to pass " << syncTime);
202  if(!ProposingExecutor::ExecuteTime(syncTime)) {
203  Time::Type maxsync=EnabledTime().UB();
204  if(maxsync >= syncTime-mMaxSyncGap) {
205  syncTime=maxsync;
206  }
207  FD_DS_SYNC("DeviceExecutor::SyncTime(): retry: generator to pass " << syncTime);
208  if(!ProposingExecutor::ExecuteTime(syncTime))
209  if(mSyncMode & SyncStrictTime) {
210  FD_DS_SYNC("DeviceExecutor::SyncTime(): exec error");
211  mSyncError=true;
212  pDevice->Reset();
213  return false;
214  }
215  };
216  }
217 
218  // done
219  /*
220  FD_DS_SYNC("DeviceExecutor::SyncTime(): ok: device time " <<
221  pDevice->CurrentTime() << " gen time " << CurrentTime());
222  */
223  return true;
224 
225 #endif
226 }
227 
228 
229 //SyncEvents()
231 
232  // no plugin, no run
233 #ifndef FAUDES_PLUGIN_IODEVICE
234  return 0;
235 #else
236 
237  // no device, no run
238  if(!pDevice) return 0;
239 
240  // ignore alien hardware event
241  if(Idx sev=pDevice->PeekInput()) {
242  if(!ParallelExecutor::Alphabet().Exists(sev)) {
243  FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " ignored");
244  pDevice->ReadInput();
245  }
246  }
247 
248  // get and execute hardware events, if accepted
249  if(Idx sev=pDevice->PeekInput()) {
250  if(EnabledEvents().Exists(sev)) {
251  pDevice->ReadInput();
253  FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " accepted");
254  return sev;
255  }
256  FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " postponed");
257  }
258 
259  // check and execute scheduled event
260  const TimedEvent& proposedTrans=ProposeNextTransition();
261  if(proposedTrans.mTime==0 && proposedTrans.mEvent!=0) {
262  FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: " << EventName(proposedTrans.mEvent));
264  if(pDevice->Outputs().Exists(proposedTrans.mEvent))
265  pDevice->WriteOutput(proposedTrans.mEvent);
266  FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: execueted");
267  return proposedTrans.mEvent;
268  }
269 
270  // get and execute hardware events
271  if(Idx sev=pDevice->ReadInput()) {
272  bool exec = ProposingExecutor::ExecuteEvent(sev);
273  if(!exec && (mSyncMode & SyncStrictEvents)) {
274  FD_DS_SYNC("DeviceExecutor::SyncEvents(): sync error: invalid input event");
275  mSyncError=true;
276  pDevice->Reset();
277  }
278  return (exec ? sev : 0);
279  }
280 
281 
282  /*
283  FD_DS_SYNC("DeviceExecutor::SyncEvents(): no events ready");
284  */
285  return 0;
286 
287 #endif
288 }
289 
290 //SyncWait()
292 
293  // no plugin, no run
294 #ifndef FAUDES_PLUGIN_IODEVICE
295  return false;
296 #else
297 
298  // no device, no run
299  if(!pDevice) return false;
300 
301  // report
302  FD_DS_SYNC("DeviceExecutor::SyncWait(): sleep " << Time::Str(duration) );
303 
304  // adjust
305  const TimedEvent& proposedTrans=ProposeNextTransition();
306  if(proposedTrans.mTime<duration) duration=proposedTrans.mTime;
307  if(duration <0) duration=0;
308 
309  // report
310  FD_DS_SYNC("DeviceExecutor::SyncWait(): adjusted by proposal: " << Time::Str(duration) );
311 
312  // doit
313  bool res=pDevice->WaitInputs(duration);
314 
315  // done
316  return res;
317 
318 #endif // io plugin
319 }
320 
321 
322 //SyncWaitMs()
323 bool DeviceExecutor::SyncWaitMs(int durationms) {
324 
325  // no plugin, no run
326 #ifndef FAUDES_PLUGIN_IODEVICE
327  return false;
328 #else
329 
330  // no device, no run
331  if(!pDevice) return false;
332 
333  // report
334  /*
335  FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): sleep " << durationms );
336  */
337 
338  // adjust
339  const TimedEvent& proposedTrans=ProposeNextTransition();
340  if(proposedTrans.mTime*pDevice->TimeScale() <durationms) durationms=proposedTrans.mTime *pDevice->TimeScale();
341  if(durationms <0) durationms=0;
342 
343  // report
344  /*
345  FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): adjusted by proposal: " << durationms );
346  */
347 
348  // doit
349  bool res=pDevice->WaitInputsMs(durationms);
350 
351  // done
352  return res;
353 
354 #endif // io plugin
355 }
356 
357 
358 //SyncStep(duartion)
360  FD_DS_SYNC("DeviceExecutor::SyncStep("<< Time::Str(duration) << ")");
361 
362  // no plugin, no run
363 #ifndef FAUDES_PLUGIN_IODEVICE
364  return 0;
365 #else
366 
367  // no device, no run
368  if(!pDevice) return 0;
369 
370  // result
371  Idx res=0;
372 
373  // doit
374  if(!SyncTime()) return res;
375  if((res=SyncEvents())!=0) return res;
376  if(!SyncWait(duration)) return res;
377  if(!SyncTime()) return res;
378  res=SyncEvents();
379 
380  // done
381  return res;
382 
383 #endif // io plugin
384 }
385 
386 //SyncRun(duartion)
388  FD_DS_SYNC("DeviceExecutor::SyncRun("<< Time::Str(duration) << ")");
389 
390  // prepare
391  Time::Type genNow=CurrentTime();
392  Time::Type genStop=genNow+duration;
393  Time::Type genLeft=genStop-genNow;
394  if(duration==Time::Max()) {
395  genStop=Time::Max();
396  genLeft=Time::Max();
397  }
398 
399  // loop time
400  while(genLeft>0) {
401  // step
402  if(SyncStep(genLeft)==0) return false;
403  // update
404  genNow=CurrentTime();
405  genLeft=genStop-genNow;
406  if(duration==Time::Max()) genLeft=Time::Max();
407  }
408  // done
409  return true;
410 }
411 
412 } // namespace
413 
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Definition: cfl_types.h:946
Executer with IO device to handle external/physical events.
bool ExecuteEvent(Idx event)
Execute event.
vDevice * pDevice
Device reference.
bool mSyncError
Sync error flag.
Time::Type mMaxSyncGap
Max gap between physical and generator clock time
bool SyncWaitMs(int durationms)
Wait for input events.
~DeviceExecutor()
Explicit destructor.
int mSyncMode
Mode flags for synchronisation.
DeviceExecutor()
Creates an emtpy DeviceExecutor.
bool SyncTime(void)
Execute generator clock time to sync with device time.
void DeviceReset(void)
Convenience: Reset the device.
void DeviceStop(void)
Convenience: Stop the device.
void DeviceStart(void)
Convenience: Start the device.
virtual void Clear(void)
Clear all data (generators, simulation attributes etc)
bool SyncRun(Time::Type duration=Time::Max())
Run execution with synchronous physical signals.
Idx SyncEvents()
Execute scheduled or input events now.
Idx SyncStep(Time::Type duration=Time::Max())
Execute one transition with synchronous physical signals.
void DoAssign(const DeviceExecutor &rSrc)
Assignment method.
virtual bool DeviceResetRequest(void)
Query the device whther it has received an external reset request.
vDevice * Devicep()
Get device.
bool SyncWait(Time::Type duration=Time::Max())
Wait for input events.
Time::Type CurrentTime(void) const
Get clock time.
bool Exists(const Idx &rIndex) const
Test existence of index.
const EventSet & EnabledEvents() const
Get events that are enabled at current (timed) state.
const TimeInterval & EnabledTime() const
Get maximal duration that can pass without executing an event.
std::string EStr(Idx event) const
Pretty printable string of event.
Iterator End(void) const
Definition: sp_pexecutor.h:182
const EventSet & Alphabet(void) const
Overall alphabet.
std::string EventName(Idx index) const
Event name lookup.
Definition: sp_pexecutor.h:210
Executer that proposes which transition to execute.
bool ExecuteEvent(Idx event)
Execute event.
virtual void Reset(void)
Reset the ProposingExecutor.
bool ExecuteTime(Time::Type duration)
Execute time duration.
const SimEventAttribute & EventAttribute(Idx index) const
Simulation event attribute lookup.
virtual void Clear(void)
Clear all data (generators, simulation attributes etc)
void DoAssign(const ProposingExecutor &rSrc)
Assignment method.
const TimedEvent & ProposeNextTransition()
Propose next transition.
const sEventSet & Alphabet(void) const
Access alphabet (incl simulation event attributes)
Attribute for an event in the context of simulation.
void Priority(const SimPriorityEventAttribute &rPriorityAttribute)
Set priority behaviour.
Defining data to prioritise events.
void UB(Time::Type time)
Set the upper bound to a given value.
static Type UnDef(void)
Undefined time value.
Int Type
Datatype for point on time axis.
static std::string Str(Type time)
convert to string
static Type Step(void)
Smallest representable time step.
static Type Max(void)
Maximum time, associated with infinitiy.
Global Tyoedefs.
Definition: sp_executor.h:53
Time::Type mTime
Definition: sp_executor.h:56
Virtual base class to define the interface for event io.
Definition: iop_vdevice.h:261
virtual Idx PeekInput(void)
Peek for sensed events.
virtual bool WaitInputsMs(long int duration)
Wait for input trigger.
virtual const EventSet & Inputs(void) const
Get inputs as plain set.
virtual void TimeScale(unsigned int scale)
Set timescale.
Definition: iop_vdevice.h:364
virtual bool ResetRequest(void)
A device may ask for a reset by returning true for ResetRequest().
virtual void Stop(void)
Deactivate the device.
virtual void Start(void)
Activate the device.
virtual void WriteOutput(Idx output)=0
Run output command.
virtual void Reset(void)
Reset device.
virtual Idx ReadInput(void)
Read sensed input events.
virtual bool WaitInputs(Time::Type duration)
Wait for input trigger.
virtual Time::Type CurrentTime(void)
Report physical time in ftu.
virtual const EventSet & Outputs(void) const
Get outputs as plain set.
Includes all libFAUDES headers, no plugins.
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
Executor with IO device
#define FD_DS(message)
Definition: sp_executor.h:34
#define FD_DX(message)
Definition: sp_executor.h:27
#define FD_DS_SYNC(message)
Definition: sp_executor.h:39

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen