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 Simulator:
00045 public AbstractSimulator<X>
00046 {
00047 public:
00054 Simulator(Devs<X>* model):
00055 AbstractSimulator<X>(),lp(NULL)
00056 {
00057 schedule(model,0.0);
00058 }
00063 double nextEventTime()
00064 {
00065 return sched.minPriority();
00066 }
00068 void execNextEvent()
00069 {
00070 computeNextOutput();
00071 computeNextState(bogus_input,sched.minPriority());
00072 }
00074 void execUntil(double tend)
00075 {
00076 while (nextEventTime() <= tend && nextEventTime() < DBL_MAX)
00077 execNextEvent();
00078 }
00084 void computeNextOutput();
00093 void computeNextState(Bag<Event<X> >& input, double t);
00099 ~Simulator();
00104 void addModel(Atomic<X>* model)
00105 {
00106 schedule(model,0.0);
00107 }
00112 Simulator(LogicalProcess<X>* lp):
00113 AbstractSimulator<X>(),lp(lp)
00114 {
00115 }
00116 private:
00117
00118 LogicalProcess<X>* lp;
00119
00120 Bag<Event<X> > bogus_input;
00121
00122 Schedule<X> sched;
00123
00124 Bag<Atomic<X>*> imm;
00125
00126 Bag<Atomic<X>*> activated;
00127
00128 object_pool<Bag<X> > io_pool;
00129 object_pool<Bag<Event<X> > > recv_pool;
00130
00131 Bag<Devs<X>*> added;
00132 Bag<Devs<X>*> removed;
00133 Set<Devs<X>*> next;
00134 Set<Devs<X>*> prev;
00135
00136 struct bottom_to_top_depth_compare
00137 {
00138 bool operator()(const Network<X>* m1, const Network<X>* m2) const
00139 {
00140 unsigned long int d1 = 0, d2 = 0;
00141
00142 const Network<X>* m = m1->getParent();
00143 while (m != NULL)
00144 {
00145 d1++;
00146 m = m->getParent();
00147 }
00148
00149 m = m2->getParent();
00150 while (m != NULL)
00151 {
00152 d2++;
00153 m = m->getParent();
00154 }
00155
00156 if (d1 == d2) return m1 < m2;
00157
00158 return d1 > d2;
00159 }
00160 };
00161 struct top_to_bottom_depth_compare
00162 {
00163 bool operator()(const Devs<X>* m1, const Devs<X>* m2) const
00164 {
00165 unsigned long int d1 = 0, d2 = 0;
00166
00167 const Network<X>* m = m1->getParent();
00168 while (m != NULL)
00169 {
00170 d1++;
00171 m = m->getParent();
00172 }
00173
00174 m = m2->getParent();
00175 while (m != NULL)
00176 {
00177 d2++;
00178 m = m->getParent();
00179 }
00180
00181 if (d1 == d2) return m1 < m2;
00182
00183 return d1 < d2;
00184 }
00185 };
00186 std::set<Network<X>*,bottom_to_top_depth_compare> model_func_eval_set;
00187 std::set<Devs<X>*,top_to_bottom_depth_compare> sorted_removed;
00192 void schedule(Devs<X>* model, double t);
00194 void route(Network<X>* parent, Devs<X>* src, X& x);
00199 void inject_event(Atomic<X>* model, X& value);
00204 void unschedule_model(Devs<X>* model);
00210 void clean_up(Devs<X>* model);
00216 void exec_event(Atomic<X>* model, bool internal, double t);
00220 void getAllChildren(Network<X>* model, Set<Devs<X>*>& s);
00221 };
00222
00223 template <class X>
00224 void Simulator<X>::computeNextOutput()
00225 {
00226
00227 if (imm.empty() == false) return;
00228
00229 sched.getImminent(imm);
00230
00231
00232 for (typename Bag<Atomic<X>*>::iterator imm_iter = imm.begin();
00233 imm_iter != imm.end(); imm_iter++)
00234 {
00235 Atomic<X>* model = *imm_iter;
00236
00237 if (model->y == NULL)
00238 {
00239 model->y = io_pool.make_obj();
00240 model->output_func(*(model->y));
00241
00242 for (typename Bag<X>::iterator y_iter = model->y->begin();
00243 y_iter != model->y->end(); y_iter++)
00244 {
00245 route(model->getParent(),model,*y_iter);
00246 }
00247 }
00248 }
00249 }
00250
00251 template <class X>
00252 void Simulator<X>::computeNextState(Bag<Event<X> >& input, double t)
00253 {
00254
00255 if (t < sched.minPriority())
00256 {
00257 typename Bag<Atomic<X>*>::iterator iter;
00258 for (iter = activated.begin(); iter != activated.end(); iter++)
00259 {
00260 clean_up(*iter);
00261 }
00262 activated.clear();
00263 for (iter = imm.begin(); iter != imm.end(); iter++)
00264 {
00265 clean_up(*iter);
00266 }
00267 imm.clear();
00268 }
00269
00270 else if (t == sched.minPriority() && imm.empty())
00271 {
00272 computeNextOutput();
00273 }
00274
00275 for (typename Bag<Event<X> >::iterator iter = input.begin();
00276 iter != input.end(); iter++)
00277 {
00278 Atomic<X>* amodel = (*iter).model->typeIsAtomic();
00279 if (amodel != NULL)
00280 {
00281 inject_event(amodel,(*iter).value);
00282 }
00283 else
00284 {
00285 route((*iter).model->typeIsNetwork(),(*iter).model,(*iter).value);
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294 for (typename Bag<Atomic<X>*>::iterator iter = imm.begin();
00295 iter != imm.end(); iter++)
00296 {
00297 exec_event(*iter,true,t);
00298 }
00299 for (typename Bag<Atomic<X>*>::iterator iter = activated.begin();
00300 iter != activated.end(); iter++)
00301 {
00302 exec_event(*iter,false,t);
00303 }
00310 if (model_func_eval_set.empty() == false)
00311 {
00312 while (!model_func_eval_set.empty())
00313 {
00314 Network<X>* network_model = *(model_func_eval_set.begin());
00315 getAllChildren(network_model,prev);
00316 if (network_model->model_transition() && network_model->getParent() != NULL)
00317 {
00318 model_func_eval_set.insert(network_model->getParent());
00319 }
00320 getAllChildren(network_model,next);
00321 model_func_eval_set.erase(network_model);
00322 }
00323
00324 set_assign_diff(added,next,prev);
00325
00326 set_assign_diff(removed,prev,next);
00327
00328
00329 next.clear();
00330 prev.clear();
00337 for (typename Bag<Devs<X>*>::iterator iter = added.begin();
00338 iter != added.end(); iter++)
00339 {
00340 schedule(*iter,t);
00341 }
00342
00343 added.clear();
00344
00345 for (typename Bag<Devs<X>*>::iterator iter = removed.begin();
00346 iter != removed.end(); iter++)
00347 {
00348 clean_up(*iter);
00349 unschedule_model(*iter);
00350 sorted_removed.insert(*iter);
00351 }
00352
00353 removed.clear();
00354
00355 while (!sorted_removed.empty())
00356 {
00357
00358 Devs<X>* model_to_remove = *(sorted_removed.begin());
00363 if (model_to_remove->typeIsNetwork() != NULL)
00364 {
00365 getAllChildren(model_to_remove->typeIsNetwork(),prev);
00366 for (typename Set<Devs<X>*>::iterator iter = prev.begin();
00367 iter != prev.end(); iter++)
00368 {
00369 sorted_removed.erase(*iter);
00370 }
00371 prev.clear();
00372 }
00373
00374 sorted_removed.erase(sorted_removed.begin());
00375
00376 delete model_to_remove;
00377 }
00378
00379 assert(prev.empty());
00380 assert(sorted_removed.empty());
00381 }
00382
00383
00384 for (typename Bag<Atomic<X>*>::iterator iter = imm.begin();
00385 iter != imm.end(); iter++)
00386 {
00387 clean_up(*iter);
00388 schedule(*iter,t);
00389 }
00390 for (typename Bag<Atomic<X>*>::iterator iter = activated.begin();
00391 iter != activated.end(); iter++)
00392 {
00393 clean_up(*iter);
00394 schedule(*iter,t);
00395 }
00396
00397 imm.clear();
00398 activated.clear();
00399 }
00400
00401 template <class X>
00402 void Simulator<X>::clean_up(Devs<X>* model)
00403 {
00404 Atomic<X>* amodel = model->typeIsAtomic();
00405 if (amodel != NULL)
00406 {
00407 amodel->active = false;
00408 if (amodel->x != NULL)
00409 {
00410 amodel->x->clear();
00411 io_pool.destroy_obj(amodel->x);
00412 amodel->x = NULL;
00413 }
00414 if (amodel->y != NULL)
00415 {
00416 amodel->gc_output(*(amodel->y));
00417 amodel->y->clear();
00418 io_pool.destroy_obj(amodel->y);
00419 amodel->y = NULL;
00420 }
00421 }
00422 else
00423 {
00424 Set<Devs<X>*> components;
00425 model->typeIsNetwork()->getComponents(components);
00426 for (typename Set<Devs<X>*>::iterator iter = components.begin();
00427 iter != components.end(); iter++)
00428 {
00429 clean_up(*iter);
00430 }
00431 }
00432 }
00433
00434 template <class X>
00435 void Simulator<X>::unschedule_model(Devs<X>* model)
00436 {
00437 if (model->typeIsAtomic() != NULL)
00438 {
00439 sched.schedule(model->typeIsAtomic(),DBL_MAX);
00440 imm.erase(model->typeIsAtomic());
00441 activated.erase(model->typeIsAtomic());
00442 }
00443 else
00444 {
00445 Set<Devs<X>*> components;
00446 model->typeIsNetwork()->getComponents(components);
00447 for (typename Set<Devs<X>*>::iterator iter = components.begin();
00448 iter != components.end(); iter++)
00449 {
00450 unschedule_model(*iter);
00451 }
00452 }
00453 }
00454
00455 template <class X>
00456 void Simulator<X>::schedule(Devs<X>* model, double t)
00457 {
00458 Atomic<X>* a = model->typeIsAtomic();
00459 if (a != NULL)
00460 {
00461 a->tL = t;
00462 double dt = a->ta();
00463 if (dt < 0.0)
00464 {
00465 exception err("Negative time advance",a);
00466 throw err;
00467 }
00468 if (dt == DBL_MAX)
00469 sched.schedule(a,DBL_MAX);
00470 else
00471 sched.schedule(a,t+dt);
00472 }
00473 else
00474 {
00475 Set<Devs<X>*> components;
00476 model->typeIsNetwork()->getComponents(components);
00477 typename Set<Devs<X>*>::iterator iter = components.begin();
00478 for (; iter != components.end(); iter++)
00479 {
00480 schedule(*iter,t);
00481 }
00482 }
00483 }
00484
00485 template <class X>
00486 void Simulator<X>::inject_event(Atomic<X>* model, X& value)
00487 {
00488 if (model->active == false)
00489 {
00490 model->active = true;
00491 activated.insert(model);
00492 }
00493 if (model->x == NULL)
00494 {
00495 model->x = io_pool.make_obj();
00496 }
00497 model->x->insert(value);
00498 }
00499
00500 template <class X>
00501 void Simulator<X>::route(Network<X>* parent, Devs<X>* src, X& x)
00502 {
00503
00504 if (parent != src)
00505 notify_output_listeners(src,x,sched.minPriority());
00506
00507 if (parent == NULL) return;
00508
00509 Bag<Event<X> >* recvs = recv_pool.make_obj();
00510 parent->route(x,src,*recvs);
00511
00512 Atomic<X>* amodel = NULL;
00513 typename Bag<Event<X> >::iterator recv_iter = recvs->begin();
00514 for (; recv_iter != recvs->end(); recv_iter++)
00515 {
00516
00517 if (src == (*recv_iter).model)
00518 {
00519 exception err("Model tried to influence self",src);
00520 throw err;
00521 }
00526 amodel = (*recv_iter).model->typeIsAtomic();
00527 if (amodel != NULL)
00528 {
00529
00530 if (lp == NULL || amodel->getProc() == lp->getID())
00531 inject_event(amodel,(*recv_iter).value);
00532
00533 else lp->notifyInput(amodel,(*recv_iter).value);
00534 }
00535
00536 else if ((*recv_iter).model == parent)
00537 {
00538 route(parent->getParent(),parent,(*recv_iter).value);
00539 }
00540
00541 else
00542 {
00543 route((*recv_iter).model->typeIsNetwork(),
00544 (*recv_iter).model,(*recv_iter).value);
00545 }
00546 }
00547 recvs->clear();
00548 recv_pool.destroy_obj(recvs);
00549 }
00550
00551 template <class X>
00552 void Simulator<X>::exec_event(Atomic<X>* model, bool internal, double t)
00553 {
00554
00555 if (model->x == NULL)
00556 {
00557 model->delta_int();
00558 }
00559 else if (internal)
00560 {
00561 model->delta_conf(*(model->x));
00562 }
00563 else
00564 {
00565 model->delta_ext(t-model->tL,*(model->x));
00566 }
00567
00568 notify_state_listeners(model,t);
00569
00570 if (model->model_transition() && model->getParent() != NULL)
00571 {
00572 model_func_eval_set.insert(model->getParent());
00573 }
00574 }
00575
00576 template <class X>
00577 void Simulator<X>::getAllChildren(Network<X>* model, Set<Devs<X>*>& s)
00578 {
00579 Set<Devs<X>*> tmp;
00580
00581 model->getComponents(tmp);
00582
00583 typename Set<Devs<X>*>::iterator iter;
00584 for (iter = tmp.begin(); iter != tmp.end(); iter++)
00585 {
00586 if ((*iter)->typeIsNetwork() != NULL)
00587 {
00588 getAllChildren((*iter)->typeIsNetwork(),s);
00589 }
00590 }
00591
00592 for (iter = tmp.begin(); iter != tmp.end(); iter++)
00593 {
00594 s.insert(*iter);
00595 }
00596 }
00597
00598 template <class X>
00599 Simulator<X>::~Simulator()
00600 {
00601
00602 typename Bag<Atomic<X>*>::iterator imm_iter;
00603 for (imm_iter = imm.begin(); imm_iter != imm.end(); imm_iter++)
00604 {
00605 clean_up(*imm_iter);
00606 }
00607 for (imm_iter = activated.begin(); imm_iter != activated.end(); imm_iter++)
00608 {
00609 clean_up(*imm_iter);
00610 }
00611 }
00612
00613 }
00614
00615 #endif