systemc: Implement the sc_signal_rv channel and ports.
authorGabe Black <gabeblack@google.com>
Sat, 15 Sep 2018 22:24:28 +0000 (15:24 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 9 Oct 2018 21:52:42 +0000 (21:52 +0000)
Change-Id: Id1a3fd2ded224bbe94a4a65e0acf34a3547aedcc
Reviewed-on: https://gem5-review.googlesource.com/c/12813
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/ext/channel/sc_in_rv.hh
src/systemc/ext/channel/sc_inout_rv.hh
src/systemc/ext/channel/sc_out_rv.hh
src/systemc/ext/channel/sc_signal_rv.hh
src/systemc/tests/systemc/communication/sc_signal_rv/test02/expected_returncode [new file with mode: 0644]
src/systemc/tests/systemc/communication/sc_signal_rv/test03/expected_returncode [new file with mode: 0644]

index eca2c0c7e189dabba369f4348371c9f65561cc5c..278b95864c56949a68bd7303916dfc9b30cbda63 100644 (file)
 #ifndef __SYSTEMC_EXT_CHANNEL_SC_IN_RV_HH__
 #define __SYSTEMC_EXT_CHANNEL_SC_IN_RV_HH__
 
+#include <sstream>
+
 #include "sc_in.hh"
+#include "sc_signal_rv.hh"
 
 namespace sc_dt
 {
@@ -51,7 +54,18 @@ class sc_in_rv : public sc_in<sc_dt::sc_lv<W>>
     explicit sc_in_rv(const char *name) : sc_in<sc_dt::sc_lv<W>>(name) {}
     virtual ~sc_in_rv() {};
 
-    virtual void end_of_elaboration() {}
+    virtual void
+    end_of_elaboration()
+    {
+        sc_in<sc_dt::sc_lv<W> >::end_of_elaboration();
+        if (!dynamic_cast<sc_signal_rv<W> *>(this->get_interface())) {
+            std::ostringstream ss;
+            ss << "port '" << this->name() << "' (" << this->kind() << ")";
+            SC_REPORT_ERROR(
+                    "(E117) resolved port not bound to resolved signal",
+                    ss.str().c_str());
+        }
+    }
 
     virtual const char *kind() const { return "sc_in_rv"; }
 
index f231d9311898ff8188f7254654bc19f59f083d5a..5ff9d105e64587ae894006dea1574d744c9c2714 100644 (file)
 #ifndef __SYSTEMC_EXT_CHANNEL_SC_INOUT_RV_HH__
 #define __SYSTEMC_EXT_CHANNEL_SC_INOUT_RV_HH__
 
+#include <sstream>
+
 #include "../core/sc_port.hh"
 #include "sc_signal_in_if.hh"
 #include "sc_signal_inout_if.hh"
+#include "sc_signal_rv.hh"
 #include "warn_unimpl.hh"
 
 namespace sc_dt
@@ -55,37 +58,48 @@ class sc_inout_rv : public sc_inout<sc_dt::sc_lv<W>>
     virtual ~sc_inout_rv() {}
 
     sc_inout_rv<W> &
-    operator = (const sc_dt::sc_lv<W> &)
+    operator = (const sc_dt::sc_lv<W> &l)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(l);
         return *this;
     }
     sc_inout_rv<W> &
-    operator = (const sc_signal_in_if<sc_dt::sc_lv<W>> &)
+    operator = (const sc_signal_in_if<sc_dt::sc_lv<W>> &i)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(i.read());
         return *this;
     }
     sc_inout_rv<W> &
-    operator = (const sc_port<sc_signal_in_if<sc_dt::sc_lv<W>>, 1> &)
+    operator = (const sc_port<sc_signal_in_if<sc_dt::sc_lv<W>>, 1> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
     sc_inout_rv<W> &
-    operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_lv<W>>, 1> &)
+    operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_lv<W>>, 1> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
     sc_inout_rv<W> &
-    operator = (const sc_inout_rv<W> &)
+    operator = (const sc_inout_rv<W> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
 
-    virtual void end_of_elaboration() {};
+    virtual void
+    end_of_elaboration()
+    {
+        sc_inout<sc_dt::sc_lv<W> >::end_of_elaboration();
+        if (!dynamic_cast<sc_signal_rv<W> *>(this->get_interface())) {
+            std::ostringstream ss;
+            ss << this->name() << " (" << this->kind() << ")";
+            SC_REPORT_ERROR(
+                    "(E117) resolved port not bound to resolved signal",
+                    ss.str().c_str());
+        }
+    }
 
     virtual const char *kind() const { return "sc_inout_rv"; }
 };
index af5b05526fab327b6bac4af05c12af327d96956e..ace1f05c5ef2045e808e8a155b0438d6db7920eb 100644 (file)
@@ -56,33 +56,33 @@ class sc_out_rv : public sc_inout_rv<W>
     virtual ~sc_out_rv() {};
 
     sc_out_rv<W> &
-    operator = (const sc_dt::sc_lv<W> &)
+    operator = (const sc_dt::sc_lv<W> &l)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(l);
         return *this;
     }
     sc_out_rv<W> &
-    operator = (const sc_signal_in_if<sc_dt::sc_lv<W>> &)
+    operator = (const sc_signal_in_if<sc_dt::sc_lv<W>> &i)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(i.read());
         return *this;
     }
     sc_out_rv<W> &
-    operator = (const sc_port<sc_signal_in_if<sc_dt::sc_lv<W>>, 1> &)
+    operator = (const sc_port<sc_signal_in_if<sc_dt::sc_lv<W>>, 1> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
     sc_out_rv<W> &
-    operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_lv<W>>, 1> &)
+    operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_lv<W>>, 1> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
     sc_out_rv<W> &
-    operator = (const sc_out_rv<W> &)
+    operator = (const sc_out_rv<W> &p)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        (*this)->write(p->read());
         return *this;
     }
 
index 723c2b45d0148500a8c149d8865b34d97f0b45ba..d333da05277465d7d9553b9022d2345baed70e04 100644 (file)
@@ -31,6 +31,9 @@
 #define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_RV_HH__
 
 #include "../core/sc_module.hh" // for sc_gen_unique_name
+#include "../core/scheduler.hh"
+#include "../dt/bit/sc_logic.hh"
+#include "../dt/bit/sc_lv.hh"
 #include "sc_signal.hh"
 #include "warn_unimpl.hh"
 
@@ -66,20 +69,29 @@ class sc_signal_rv : public sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS>
     }
 
     virtual void
-    write(const sc_dt::sc_lv<W> &)
+    write(const sc_dt::sc_lv<W> &l)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        ::sc_gem5::Process *p = ::sc_gem5::scheduler.current();
+
+        auto it = inputs.find(p);
+        if (it == inputs.end()) {
+            inputs.emplace(p, l);
+            this->request_update();
+        } else if (it->second != l) {
+            it->second = l;
+            this->request_update();
+        }
     }
     sc_signal_rv<W> &
-    operator = (const sc_dt::sc_lv<W> &)
+    operator = (const sc_dt::sc_lv<W> &l)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        write(l);
         return *this;
     }
     sc_signal_rv<W> &
-    operator = (const sc_signal_rv<W> &)
+    operator = (const sc_signal_rv<W> &r)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        write(r.read());
         return *this;
     }
 
@@ -89,7 +101,28 @@ class sc_signal_rv : public sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS>
     virtual void
     update()
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        using sc_dt::Log_0;
+        using sc_dt::Log_1;
+        using sc_dt::Log_Z;
+        using sc_dt::Log_X;
+        static sc_dt::sc_logic_value_t merge_table[4][4] = {
+            { Log_0, Log_X, Log_0, Log_X },
+            { Log_X, Log_1, Log_1, Log_X },
+            { Log_0, Log_1, Log_Z, Log_X },
+            { Log_X, Log_X, Log_X, Log_X }
+        };
+
+        // Resolve the inputs, and give the result to the underlying
+        // signal class.
+        for (int i = 0; i < W; i++) {
+            sc_dt::sc_logic_value_t bit = Log_Z;
+            for (auto &input: inputs)
+                bit = merge_table[bit][input.second.get_bit(i)];
+            this->m_new_val.set_bit(i, bit);
+        }
+
+        // Ask the signal to update it's value.
+        sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS>::update();
     }
 
   private:
@@ -97,6 +130,8 @@ class sc_signal_rv : public sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS>
     sc_signal_rv(const sc_signal_rv<W> &) :
             sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS>()
     {}
+
+    std::map<::sc_gem5::Process *, sc_dt::sc_lv<W> > inputs;
 };
 
 } // namespace sc_core
diff --git a/src/systemc/tests/systemc/communication/sc_signal_rv/test02/expected_returncode b/src/systemc/tests/systemc/communication/sc_signal_rv/test02/expected_returncode
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/src/systemc/tests/systemc/communication/sc_signal_rv/test03/expected_returncode b/src/systemc/tests/systemc/communication/sc_signal_rv/test03/expected_returncode
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1