00001
00031 #ifndef __adevs_simulator_h_
00032 #define __adevs_simulator_h_
00033 #include "adevs_abstract_simulator.h"
00034 #include "adevs_models.h"
00035 #include "adevs_event_listener.h"
00036 #include "adevs_sched.h"
00037 #include "adevs_bag.h"
00038 #include "adevs_set.h"
00039 #include "object_pool.h"
00040 #include "adevs_lp.h"
00041 #include <cassert>
00042 #include <cstdlib>
00043 #include <iostream>
00044 #include <vector>
00045
00046 namespace adevs
00047 {
00048
00055 template <class X, class T = double> class Simulator:
00056 public AbstractSimulator<X,T>,
00057 private Schedule<X,T>::ImminentVisitor
00058 {
00059 public:
00066 Simulator(Devs<X,T>* model):
00067 AbstractSimulator<X,T>(),
00068 Schedule<X,T>::ImminentVisitor(),
00069 lps(NULL)
00070 {
00071 schedule(model,adevs_zero<T>());
00072 }
00077 T nextEventTime()
00078 {
00079 return sched.minPriority();
00080 }
00082 void execNextEvent()
00083 {
00084 computeNextOutput();
00085 computeNextState(bogus_input,sched.minPriority());
00086 }
00088 void execUntil(T tend)
00089 {
00090 while (nextEventTime() <= tend
00091 && nextEventTime() < adevs_inf<T>()) {
00092 execNextEvent();
00093 }
00094 }
00100 void computeNextOutput();
00109 void computeNextState(Bag<Event<X,T> >& input, T t);
00115 ~Simulator();
00120 void addModel(Atomic<X,T>* model)
00121 {
00122 schedule(model,adevs_zero<T>());
00123 }
00128 Simulator(LogicalProcess<X,T>* lp);
00140 void beginLookahead();
00145 void endLookahead();
00152 void lookNextEvent();
00153 private:
00154 typedef enum { OUTPUT_OK, OUTPUT_NOT_OK, RESTORING_OUTPUT } OutputStatus;
00155
00156 struct lp_support
00157 {
00158
00159 LogicalProcess<X,T>* lp;
00160 bool look_ahead, stop_forced;
00161 OutputStatus out_flag;
00162 Bag<Atomic<X,T>*> to_restore;
00163 };
00164
00165 lp_support* lps;
00166
00167 Bag<Event<X,T> > bogus_input;
00168
00169 Schedule<X,T> sched;
00170
00171 Bag<Atomic<X,T>*> activated;
00172
00173 object_pool<Bag<X> > io_pool;
00174 object_pool<Bag<Event<X,T> > > recv_pool;
00175
00176 Bag<Devs<X,T>*> added;
00177 Bag<Devs<X,T>*> removed;
00178 Set<Devs<X,T>*> next;
00179 Set<Devs<X,T>*> prev;
00180
00181 struct bottom_to_top_depth_compare
00182 {
00183 bool operator()(const Network<X,T>* m1, const Network<X,T>* m2) const
00184 {
00185 unsigned long int d1 = 0, d2 = 0;
00186
00187 const Network<X,T>* m = m1->getParent();
00188 while (m != NULL)
00189 {
00190 d1++;
00191 m = m->getParent();
00192 }
00193
00194 m = m2->getParent();
00195 while (m != NULL)
00196 {
00197 d2++;
00198 m = m->getParent();
00199 }
00200
00201 if (d1 == d2) return m1 < m2;
00202
00203 return d1 > d2;
00204 }
00205 };
00206 struct top_to_bottom_depth_compare
00207 {
00208 bool operator()(const Devs<X,T>* m1, const Devs<X,T>* m2) const
00209 {
00210 unsigned long int d1 = 0, d2 = 0;
00211
00212 const Network<X,T>* m = m1->getParent();
00213 while (m != NULL)
00214 {
00215 d1++;
00216 m = m->getParent();
00217 }
00218
00219 m = m2->getParent();
00220 while (m != NULL)
00221 {
00222 d2++;
00223 m = m->getParent();
00224 }
00225
00226 if (d1 == d2) return m1 < m2;
00227
00228 return d1 < d2;
00229 }
00230 };
00231 std::set<Network<X,T>*,bottom_to_top_depth_compare> model_func_eval_set;
00232 std::set<Devs<X,T>*,top_to_bottom_depth_compare> sorted_removed;
00237 void schedule(Devs<X,T>* model, T t);
00239 void route(Network<X,T>* parent, Devs<X,T>* src, X& x);
00245 void inject_event(Atomic<X,T>* model, X& value);
00250 void unschedule_model(Devs<X,T>* model);
00256 void clean_up(Devs<X,T>* model);
00263 void exec_event(Atomic<X,T>* model, T t);
00267 void getAllChildren(Network<X,T>* model, Set<Devs<X,T>*>& s);
00273 bool manage_lookahead_data(Atomic<X,T>* model);
00277 void visit(Atomic<X,T>* model);
00278 };
00279
00280 template <class X, class T>
00281 void Simulator<X,T>::visit(Atomic<X,T>* model)
00282 {
00283 assert(model->y == NULL);
00284 model->y = io_pool.make_obj();
00285
00286 if (model->x == NULL)
00287 activated.insert(model);
00288
00289
00290 model->output_func(*(model->y));
00291
00292 for (typename Bag<X>::iterator y_iter = model->y->begin();
00293 y_iter != model->y->end(); y_iter++)
00294 {
00295 route(model->getParent(),model,*y_iter);
00296 }
00297 }
00298
00299 template <class X, class T>
00300 void Simulator<X,T>::computeNextOutput()
00301 {
00302
00303 if (activated.empty() == false) return;
00304
00305 sched.visitImminent(this);
00306 }
00307
00308 template <class X, class T>
00309 void Simulator<X,T>::computeNextState(Bag<Event<X,T> >& input, T t)
00310 {
00311
00312 if (t < sched.minPriority())
00313 {
00314 typename Bag<Atomic<X,T>*>::iterator iter;
00315 for (iter = activated.begin(); iter != activated.end(); iter++)
00316 {
00317 clean_up(*iter);
00318 }
00319 activated.clear();
00320 }
00321
00322 else if (t == sched.minPriority())
00323 {
00324 computeNextOutput();
00325 }
00326
00327 for (typename Bag<Event<X,T> >::iterator iter = input.begin();
00328 iter != input.end(); iter++)
00329 {
00330 Atomic<X,T>* amodel = (*iter).model->typeIsAtomic();
00331 if (amodel != NULL)
00332 {
00333 inject_event(amodel,(*iter).value);
00334 }
00335 else
00336 {
00337 route((*iter).model->typeIsNetwork(),(*iter).model,(*iter).value);
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346 for (typename Bag<Atomic<X,T>*>::iterator iter = activated.begin();
00347 iter != activated.end(); iter++)
00348 {
00349 exec_event(*iter,t);
00350 }
00357 if (model_func_eval_set.empty() == false)
00358 {
00359 while (!model_func_eval_set.empty())
00360 {
00361 Network<X,T>* network_model = *(model_func_eval_set.begin());
00362 model_func_eval_set.erase(model_func_eval_set.begin());
00363 getAllChildren(network_model,prev);
00364 if (network_model->model_transition() &&
00365 network_model->getParent() != NULL)
00366 {
00367 model_func_eval_set.insert(network_model->getParent());
00368 }
00369 getAllChildren(network_model,next);
00370 }
00371
00372 set_assign_diff(added,next,prev);
00373
00374 set_assign_diff(removed,prev,next);
00375
00376
00377 next.clear();
00378 prev.clear();
00385 for (typename Bag<Devs<X,T>*>::iterator iter = added.begin();
00386 iter != added.end(); iter++)
00387 {
00388 schedule(*iter,t);
00389 }
00390
00391 added.clear();
00392
00393 for (typename Bag<Devs<X,T>*>::iterator iter = removed.begin();
00394 iter != removed.end(); iter++)
00395 {
00396 clean_up(*iter);
00397 unschedule_model(*iter);
00398
00399 sorted_removed.insert(*iter);
00400 }
00401
00402 removed.clear();
00403
00404 while (!sorted_removed.empty())
00405 {
00406
00407 Devs<X,T>* model_to_remove = *(sorted_removed.begin());
00408
00409 sorted_removed.erase(sorted_removed.begin());
00414 if (model_to_remove->typeIsNetwork() != NULL)
00415 {
00416 getAllChildren(model_to_remove->typeIsNetwork(),prev);
00417 typename Set<Devs<X,T>*>::iterator iter = prev.begin();
00418 for (; iter != prev.end(); iter++)
00419 sorted_removed.erase(*iter);
00420 prev.clear();
00421 }
00422
00423 delete model_to_remove;
00424 }
00425
00426 assert(prev.empty());
00427 assert(sorted_removed.empty());
00428 }
00429
00430
00431 for (typename Bag<Atomic<X,T>*>::iterator iter = activated.begin();
00432 iter != activated.end(); iter++)
00433 {
00434 clean_up(*iter);
00435 schedule(*iter,t);
00436 }
00437
00438 activated.clear();
00439
00440 if (lps != NULL && lps->stop_forced)
00441 {
00442 lookahead_impossible_exception err;
00443 throw err;
00444 }
00445 }
00446
00447 template <class X, class T>
00448 void Simulator<X,T>::clean_up(Devs<X,T>* model)
00449 {
00450 Atomic<X,T>* amodel = model->typeIsAtomic();
00451 if (amodel != NULL)
00452 {
00453 if (amodel->x != NULL)
00454 {
00455 amodel->x->clear();
00456 io_pool.destroy_obj(amodel->x);
00457 amodel->x = NULL;
00458 }
00459 if (amodel->y != NULL)
00460 {
00461 amodel->gc_output(*(amodel->y));
00462 amodel->y->clear();
00463 io_pool.destroy_obj(amodel->y);
00464 amodel->y = NULL;
00465 }
00466 }
00467 else
00468 {
00469 Set<Devs<X,T>*> components;
00470 model->typeIsNetwork()->getComponents(components);
00471 for (typename Set<Devs<X,T>*>::iterator iter = components.begin();
00472 iter != components.end(); iter++)
00473 {
00474 clean_up(*iter);
00475 }
00476 }
00477 }
00478
00479 template <class X, class T>
00480 void Simulator<X,T>::unschedule_model(Devs<X,T>* model)
00481 {
00482 if (model->typeIsAtomic() != NULL)
00483 {
00484 sched.schedule(model->typeIsAtomic(),adevs_inf<T>());
00485 activated.erase(model->typeIsAtomic());
00486 }
00487 else
00488 {
00489 Set<Devs<X,T>*> components;
00490 model->typeIsNetwork()->getComponents(components);
00491 for (typename Set<Devs<X,T>*>::iterator iter = components.begin();
00492 iter != components.end(); iter++)
00493 {
00494 unschedule_model(*iter);
00495 }
00496 }
00497 }
00498
00499 template <class X, class T>
00500 void Simulator<X,T>::schedule(Devs<X,T>* model, T t)
00501 {
00502 Atomic<X,T>* a = model->typeIsAtomic();
00503 if (a != NULL)
00504 {
00505 a->tL = t;
00506 T dt = a->ta();
00507 if (dt < adevs_zero<T>())
00508 {
00509 exception err("Negative time advance",a);
00510 throw err;
00511 }
00512 if (dt == adevs_inf<T>())
00513 sched.schedule(a,adevs_inf<T>());
00514 else
00515 sched.schedule(a,t+dt);
00516 }
00517 else
00518 {
00519 Set<Devs<X,T>*> components;
00520 model->typeIsNetwork()->getComponents(components);
00521 typename Set<Devs<X,T>*>::iterator iter = components.begin();
00522 for (; iter != components.end(); iter++)
00523 {
00524 schedule(*iter,t);
00525 }
00526 }
00527 }
00528
00529 template <class X, class T>
00530 void Simulator<X,T>::inject_event(Atomic<X,T>* model, X& value)
00531 {
00532 if (model->x == NULL)
00533 {
00534 if (model->y == NULL)
00535 activated.insert(model);
00536 model->x = io_pool.make_obj();
00537 }
00538 model->x->insert(value);
00539 }
00540
00541 template <class X, class T>
00542 void Simulator<X,T>::route(Network<X,T>* parent, Devs<X,T>* src, X& x)
00543 {
00544
00545 if (parent != src && (lps == NULL || lps->out_flag != RESTORING_OUTPUT))
00546 this->notify_output_listeners(src,x,sched.minPriority());
00547
00548 if (parent == NULL) return;
00549
00550 Bag<Event<X,T> >* recvs = recv_pool.make_obj();
00551 parent->route(x,src,*recvs);
00552
00553 Atomic<X,T>* amodel = NULL;
00554 typename Bag<Event<X,T> >::iterator recv_iter = recvs->begin();
00555 for (; recv_iter != recvs->end(); recv_iter++)
00556 {
00557
00558 if (src == (*recv_iter).model)
00559 {
00560 exception err("Model tried to influence self",src);
00561 throw err;
00562 }
00567 amodel = (*recv_iter).model->typeIsAtomic();
00568 if (amodel != NULL)
00569 {
00570
00571 if (lps == NULL || amodel->getProc() == lps->lp->getID())
00572 inject_event(amodel,(*recv_iter).value);
00573
00574 else if (lps->out_flag != RESTORING_OUTPUT)
00575 lps->lp->notifyInput(amodel,(*recv_iter).value);
00576 }
00577
00578 else if ((*recv_iter).model == parent)
00579 {
00580 route(parent->getParent(),parent,(*recv_iter).value);
00581 }
00582
00583 else
00584 {
00585 route((*recv_iter).model->typeIsNetwork(),
00586 (*recv_iter).model,(*recv_iter).value);
00587 }
00588 }
00589 recvs->clear();
00590 recv_pool.destroy_obj(recvs);
00591 }
00592
00593 template <class X, class T>
00594 void Simulator<X,T>::exec_event(Atomic<X,T>* model, T t)
00595 {
00596 if (!manage_lookahead_data(model)) return;
00597
00598 if (model->x == NULL)
00599 model->delta_int();
00600
00601 else if (model->y != NULL)
00602 model->delta_conf(*(model->x));
00603
00604 else
00605 model->delta_ext(t-model->tL,*(model->x));
00606
00607 this->notify_state_listeners(model,t);
00608
00609 if (model->model_transition() && model->getParent() != NULL)
00610 {
00611 model_func_eval_set.insert(model->getParent());
00612 }
00613 }
00614
00615 template <class X, class T>
00616 void Simulator<X,T>::getAllChildren(Network<X,T>* model, Set<Devs<X,T>*>& s)
00617 {
00618 Set<Devs<X,T>*> tmp;
00619
00620 model->getComponents(tmp);
00621
00622 s.insert(tmp.begin(),tmp.end());
00623
00624 typename Set<Devs<X,T>*>::iterator iter;
00625 for (iter = tmp.begin(); iter != tmp.end(); iter++)
00626 {
00627 if ((*iter)->typeIsNetwork() != NULL)
00628 {
00629 getAllChildren((*iter)->typeIsNetwork(),s);
00630 }
00631 }
00632 }
00633
00634 template <class X, class T>
00635 Simulator<X,T>::~Simulator()
00636 {
00637
00638 typename Bag<Atomic<X,T>*>::iterator iter;
00639 for (iter = activated.begin(); iter != activated.end(); iter++)
00640 {
00641 clean_up(*iter);
00642 }
00643 }
00644
00645 template <class X, class T>
00646 Simulator<X,T>::Simulator(LogicalProcess<X,T>* lp):
00647 AbstractSimulator<X,T>()
00648 {
00649 lps = new lp_support;
00650 lps->lp = lp;
00651 lps->look_ahead = false;
00652 lps->stop_forced = false;
00653 lps->out_flag = OUTPUT_OK;
00654 }
00655
00656 template <class X, class T>
00657 void Simulator<X,T>::beginLookahead()
00658 {
00659 if (lps == NULL)
00660 {
00661 adevs::exception err("tried to lookahead without lp support");
00662 throw err;
00663 }
00664 lps->look_ahead = true;
00665 if (!activated.empty())
00666 lps->out_flag = OUTPUT_NOT_OK;
00667 }
00668
00669 template <class X, class T>
00670 void Simulator<X,T>::lookNextEvent()
00671 {
00672 execNextEvent();
00673 }
00674
00675 template <class X, class T>
00676 void Simulator<X,T>::endLookahead()
00677 {
00678 if (lps == NULL) return;
00679 typename Bag<Atomic<X,T>*>::iterator iter = lps->to_restore.begin();
00680 for (; iter != lps->to_restore.end(); iter++)
00681 {
00682 (*iter)->endLookahead();
00683 schedule(*iter,(*iter)->tL_cp);
00684 (*iter)->tL_cp = adevs_sentinel<T>();
00685 assert((*iter)->x == NULL);
00686 assert((*iter)->y == NULL);
00687 }
00688 lps->to_restore.clear();
00689 assert(activated.empty());
00690 if (lps->out_flag == OUTPUT_NOT_OK)
00691 {
00692 lps->out_flag = RESTORING_OUTPUT;
00693 computeNextOutput();
00694 lps->out_flag = OUTPUT_OK;
00695 }
00696 lps->look_ahead = false;
00697 lps->stop_forced = false;
00698 }
00699
00700 template <class X, class T>
00701 bool Simulator<X,T>::manage_lookahead_data(Atomic<X,T>* model)
00702 {
00703 if (lps == NULL) return true;
00704 if (lps->look_ahead && model->tL_cp < adevs_zero<T>())
00705 {
00706 lps->to_restore.insert(model);
00707 model->tL_cp = model->tL;
00708 try
00709 {
00710 model->beginLookahead();
00711 }
00712 catch(method_not_supported_exception err)
00713 {
00714 lps->stop_forced = true;
00715 }
00716 }
00717 return !(lps->stop_forced);
00718 }
00719
00720 }
00721
00722 #endif