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