--- /dev/null
+#include "scd_simulator.h"
+
+#include <unistd.h>
+#include <assert.h>
+
+#include "systemc"
+
+#include "scd_cont_man_master.h"
+#include "scd_cont_man_slave.h"
+#include "scd_init_listener.h"
+#include "scd_logging.h"
+
+
+scd_simulator::scd_simulator(const std::string& name,
+ const std::string &loc_host, uint16_t loc_port, bool master):
+ _name(name), _loc_host(loc_host), _loc_port(loc_port)
+{
+ _poller = new scd_sock_poller;
+
+ if (master == SCD_MASTER)
+ _cont_man = new scd_cont_man_master(*this);
+ else
+ _cont_man = new scd_cont_man_slave(*this);
+
+ _chan_man = new scd_chan_man(*this);
+}
+
+
+scd_simulator::scd_simulator(const std::string& name, uint16_t loc_port,
+ bool master):
+ _name(name), _loc_host(""), _loc_port(loc_port)
+{
+ _poller = new scd_sock_poller;
+
+ if (master == SCD_MASTER)
+ _cont_man = new scd_cont_man_master(*this);
+ else
+ _cont_man = new scd_cont_man_slave(*this);
+
+ _chan_man = new scd_chan_man(*this);
+}
+
+
+scd_simulator::~scd_simulator()
+{
+ delete _chan_man;
+ delete _cont_man;
+ delete _poller;
+}
+
+
+const std::string& scd_simulator::get_name() const { return _name; }
+
+
+scd_sock_poller& scd_simulator::get_poller() { return *_poller; }
+
+
+scd_chan_man& scd_simulator::get_chan_man() { return *_chan_man; }
+
+
+scd_cont_man& scd_simulator::get_cont_man() { return *_cont_man; }
+
+
+bool scd_simulator::init()
+{
+ scd_info("initialization start");
+
+ /* open port for incomming connections */
+ scd_init_listener listener(*this, _loc_host, _loc_port);
+ listener.listen();
+
+ /*
+ * init until the initialization failed or chan_man and cont_man are
+ * successfully initiated
+ */
+ while ( !_cont_man->failed() &&
+ ( !_chan_man->ready() || !_cont_man->active() ) )
+ {
+ // poll the sockets and execute callback handlers
+ _poller->process();
+
+ // connect channels
+ _chan_man->init_process();
+
+ // process state transitions
+ _cont_man->process();
+
+ /* as we might be waiting for a peer coming up we can not use
+ * a blocking poll as errors would always exist and the poller would
+ * wake up immediately
+ * => sleep some milliseconds
+ */
+ usleep(50);
+ }
+
+ listener.close();
+
+ if (_cont_man->failed())
+ {
+ scd_error("initialization failed");
+ return false;
+ }
+ else
+ {
+ scd_info("initialization done");
+ return true;
+ }
+
+} // init()
+
+
+bool scd_simulator::start()
+{
+ scd_info("simulation start");
+
+ /* first delta cycle to initialize the SystemC scheduler
+ * else the _pending*() functions would fail */
+ sc_core::sc_start(sc_core::SC_ZERO_TIME);
+
+ while (_cont_man->active())
+ {
+ /* signalize the simulation state to the controller */
+ if (_pending())
+ {
+ if (_pending_now())
+ {
+ // events in this time step
+ _cont_man->set_busy();
+ }
+ else
+ {
+ // signalize time step until next event
+ sc_core::sc_time step;
+ step = _next_time() - sc_core::sc_time_stamp();
+ _cont_man->set_idle(step);
+ }
+ }
+ else
+ _cont_man->set_done();
+
+ // check for state changes
+ _cont_man->process();
+
+ /* run simulation if something to do and in right state */
+ if (_cont_man->busy())
+ {
+ // simulate one delta cycle
+ sc_core::sc_start(sc_core::SC_ZERO_TIME);
+
+ // check if we have to wait for new socket events
+ _chan_man->process();
+
+ // poll the sockets to induce transmissions
+ _poller->process();
+ }
+ else
+ {
+ if (_cont_man->advance_time())
+ {
+ sc_core::sc_time step = _cont_man->get_time_step();
+ // advance simulation time, nothing should actually be simulated
+ sc_start(step);
+ scd_info("time advanced by " + step.to_string() + " to "
+ + sc_core::sc_time_stamp().to_string() );
+ }
+ else if ( _cont_man->active() )
+ {
+ // wait for activity on sockets
+ _poller->wait_process();
+ }
+ }
+
+ } // while simulation is running
+
+ /* simulation terminated */
+
+ if (_cont_man->failed())
+ {
+ scd_error("simulation failed");
+ return false;
+ }
+ else
+ {
+ scd_info("simulation done");
+ return true;
+ }
+
+} // start()
+
+
+/**
+ * Returns true if events exist at current simulation time.
+ */
+bool scd_simulator::_pending_now()
+{
+ return sc_core::sc_pending_activity_at_current_time();
+}
+
+
+/**
+ * Returns true if events exist at current or later simulation time.
+ */
+bool scd_simulator::_pending()
+{
+ sc_core::sc_time next = _next_time();
+ return ( (next != sc_core::SC_ZERO_TIME) || _pending_now() );
+}
+
+
+/**
+ * Returns the time of the next earliest timed event
+ * or SC_ZERO_TIME if no such event exists.
+ */
+const sc_core::sc_time scd_simulator::_next_time()
+{
+ return sc_core::sc_get_curr_simcontext()->next_time();
+}
+