dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_simulator.cpp
1 #include "scd_simulator.h"
2
3 #include <unistd.h>
4 #include <assert.h>
5
6 #include "systemc"
7
8 #include "scd_cont_man_master.h"
9 #include "scd_cont_man_slave.h"
10 #include "scd_init_listener.h"
11 #include "scd_logging.h"
12
13
14 scd_simulator::scd_simulator(const std::string& name,
15         const std::string &loc_host, uint16_t loc_port, bool master):
16     _name(name), _loc_host(loc_host), _loc_port(loc_port)
17 {
18     _poller = new scd_sock_poller;
19
20     if (master == SCD_MASTER)
21         _cont_man = new scd_cont_man_master(*this);
22     else
23         _cont_man = new scd_cont_man_slave(*this);
24
25     _chan_man = new scd_chan_man(*this);
26 }
27
28
29 scd_simulator::scd_simulator(const std::string& name, uint16_t loc_port,
30         bool master):
31     _name(name), _loc_host(""), _loc_port(loc_port)
32 {
33     _poller = new scd_sock_poller;
34
35     if (master == SCD_MASTER)
36         _cont_man = new scd_cont_man_master(*this);
37     else
38         _cont_man = new scd_cont_man_slave(*this);
39
40     _chan_man = new scd_chan_man(*this);
41 }
42
43
44 scd_simulator::~scd_simulator()
45 {
46     delete _chan_man;
47     delete _cont_man;
48     delete _poller;
49 }
50
51
52 const std::string& scd_simulator::get_name() const { return _name; }
53
54
55 scd_sock_poller& scd_simulator::get_poller() { return *_poller; }
56
57
58 scd_chan_man& scd_simulator::get_chan_man() { return *_chan_man; }
59
60
61 scd_cont_man& scd_simulator::get_cont_man() { return *_cont_man; }
62
63
64 bool scd_simulator::init()
65 {
66     scd_info("initialization start");
67
68     /* open port for incomming connections */
69     scd_init_listener listener(*this, _loc_host, _loc_port);
70     listener.listen();
71     
72     /* 
73      * init until the initialization failed or chan_man and cont_man are
74      * successfully initiated
75      */
76     while ( !_cont_man->failed() &&
77             ( !_chan_man->ready() || !_cont_man->active() )  )
78     {
79         // poll the sockets and execute callback handlers
80         _poller->process();
81
82         // connect channels
83         _chan_man->init_process();
84
85         // process state transitions
86         _cont_man->process();
87
88         /* as we might be waiting for a peer coming up we can not use
89          * a blocking poll as errors would always exist and the poller would
90          * wake up immediately
91          * => sleep some milliseconds
92          */
93         usleep(50);
94     }
95
96     listener.close();
97
98     if (_cont_man->failed())
99     {
100         scd_error("initialization failed");
101         return false;
102     }
103     else
104     {
105         scd_info("initialization done");
106         return true;
107     }
108
109 } // init()
110
111
112 bool scd_simulator::start()
113 {
114     scd_info("simulation start");
115
116     /* first delta cycle to initialize the SystemC scheduler
117      * else the _pending*() functions would fail */
118     sc_core::sc_start(sc_core::SC_ZERO_TIME);
119
120     while (_cont_man->active())
121     {
122         /* signalize the simulation state to the controller */
123         if (_pending())
124         {
125             if (_pending_now())
126             {
127                 // events in this time step
128                 _cont_man->set_busy();
129             }
130             else
131             {
132                 // signalize time step until next event
133                 sc_core::sc_time step;
134                 step = _next_time() - sc_core::sc_time_stamp();
135                 _cont_man->set_idle(step);
136             }
137         }
138         else
139             _cont_man->set_done();
140
141         // check for state changes
142         _cont_man->process();
143
144         /* run simulation if something to do and in right state */
145         if (_cont_man->busy())
146         {
147             // simulate one delta cycle
148             sc_core::sc_start(sc_core::SC_ZERO_TIME);
149
150             // check if we have to wait for new socket events
151             _chan_man->process();
152
153             // poll the sockets to induce transmissions
154             _poller->process();
155         }
156         else
157         {
158             if (_cont_man->advance_time())
159             {
160                 sc_core::sc_time step = _cont_man->get_time_step();
161                 // advance simulation time, nothing should actually be simulated
162                 sc_start(step);
163                 scd_info("time advanced by " + step.to_string() + " to "
164                         + sc_core::sc_time_stamp().to_string() );
165             }
166             else if ( _cont_man->active() )
167             {
168                 // wait for activity on sockets
169                 _poller->wait_process();
170             }
171         }
172
173     } // while simulation is running
174
175     /* simulation terminated */
176
177     if (_cont_man->failed())
178     {
179         scd_error("simulation failed");
180         return false;
181     }
182     else
183     {
184         scd_info("simulation done");
185         return true;
186     }
187
188 } // start()
189
190
191 /**
192  * Returns true if events exist at current simulation time.
193  */
194 bool scd_simulator::_pending_now()
195 {
196     return sc_core::sc_pending_activity_at_current_time();
197 }
198
199
200 /**
201  * Returns true if events exist at current or later simulation time.
202  */
203 bool scd_simulator::_pending()
204 {
205     sc_core::sc_time next = _next_time();
206     return ( (next != sc_core::SC_ZERO_TIME) || _pending_now() );
207 }
208
209
210 /**
211  * Returns the time of the next earliest timed event
212  * or SC_ZERO_TIME if no such event exists.
213  */
214 const sc_core::sc_time scd_simulator::_next_time()
215 {
216     return sc_core::sc_get_curr_simcontext()->next_time();
217 }
218