dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_simulator.cpp
diff --git a/dol/src/dol/visitor/hdsd/scd/scd_simulator.cpp b/dol/src/dol/visitor/hdsd/scd/scd_simulator.cpp
new file mode 100644 (file)
index 0000000..86c2196
--- /dev/null
@@ -0,0 +1,218 @@
+#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();
+}
+