systemc: Implement most of sc_fifo and its interfaces.
authorGabe Black <gabeblack@google.com>
Tue, 28 Aug 2018 05:37:27 +0000 (22:37 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 3 Oct 2018 00:11:33 +0000 (00:11 +0000)
There are still some bugs since the output of the tests don't all
match, but more tests pass and fewer abort.

Change-Id: I37f84d65c4a8a43357c98282096e39b9401fc1dd
Reviewed-on: https://gem5-review.googlesource.com/c/12275
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/ext/channel/sc_fifo.hh
src/systemc/ext/channel/sc_fifo_in.hh
src/systemc/ext/channel/sc_fifo_out.hh

index 8cf2124b771d26a097ea2862049de1bd42599815..4fe7046131a3236932a49bd00103482c3da2ee09 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__
 #define __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__
 
+#include <list>
+
 #include "../core/sc_module.hh" // for sc_gen_unique_name
 #include "../core/sc_prim.hh"
 #include "sc_fifo_in_if.hh"
@@ -50,11 +52,12 @@ class sc_fifo : public sc_fifo_in_if<T>,
   public:
     explicit sc_fifo(int size=16) :
             sc_fifo_in_if<T>(), sc_fifo_out_if<T>(),
-            sc_prim_channel(sc_gen_unique_name("fifo"))
+            sc_prim_channel(sc_gen_unique_name("fifo")),
+            _size(size), _readsHappened(false)
     {}
     explicit sc_fifo(const char *name, int size=16) :
             sc_fifo_in_if<T>(), sc_fifo_out_if<T>(),
-            sc_prim_channel(name)
+            sc_prim_channel(name), _size(size), _readsHappened(false)
     {}
     virtual ~sc_fifo() {}
 
@@ -65,76 +68,84 @@ class sc_fifo : public sc_fifo_in_if<T>,
     }
 
     virtual void
-    read(T &)
+    read(T &t)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        while (num_available() == 0)
+            sc_core::wait(_dataWriteEvent);
+        _readsHappened = true;
+        t = _entries.front();
+        _entries.pop_front();
+        request_update();
     }
     virtual T
     read()
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(T *)nullptr;
+        T t;
+        read(t);
+        return t;
     }
     virtual bool
-    nb_read(T &)
+    nb_read(T &t)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return false;
-    }
-    operator T()
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(T *)nullptr;
+        if (num_available()) {
+            read(t);
+            return true;
+        } else {
+            return false;
+        }
     }
+    operator T() { return read(); }
 
     virtual void
-    write(const T &)
+    write(const T &t)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        while (num_free() == 0)
+            sc_core::wait(_dataReadEvent);
+        _pending.emplace_back(t);
+        request_update();
     }
     virtual bool
-    nb_write(const T&)
+    nb_write(const T &t)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return false;
+        if (num_free()) {
+            write(t);
+            return true;
+        } else {
+            return false;
+        }
     }
     sc_fifo<T> &
-    operator = (const T &)
+    operator = (const T &t)
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        write(t);
         return *this;
     }
 
     virtual const sc_event &
     data_written_event() const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const sc_event *)nullptr;
+        return _dataWriteEvent;
     }
     virtual const sc_event &
     data_read_event() const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const sc_event *)nullptr;
+        return _dataReadEvent;
     }
 
-    virtual int
-    num_available() const
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return 0;
-    }
+    virtual int num_available() const { return _entries.size(); }
     virtual int
     num_free() const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return 0;
+        return _size - _entries.size() - _pending.size();
     }
 
     virtual void
-    print(std::ostream & =std::cout) const
+    print(std::ostream &os=std::cout) const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        for (typename ::std::list<T>::iterator pos = _entries.begin();
+                pos != _entries.end(); pos++) {
+            os << *pos << ::std::endl;
+        }
     }
     virtual void
     dump(std::ostream & =std::cout) const
@@ -147,7 +158,15 @@ class sc_fifo : public sc_fifo_in_if<T>,
     virtual void
     update()
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
+        if (!_pending.empty()) {
+            _dataWriteEvent.notify(SC_ZERO_TIME);
+            _entries.insert(_entries.end(), _pending.begin(), _pending.end());
+            _pending.clear();
+        }
+        if (_readsHappened) {
+            _readsHappened = false;
+            _dataReadEvent.notify(SC_ZERO_TIME);
+        }
     }
 
   private:
@@ -156,6 +175,14 @@ class sc_fifo : public sc_fifo_in_if<T>,
             sc_fifo_in_if<T>(), sc_fifo_in_if<T>(), sc_prim_channel()
     {}
     sc_fifo &operator = (const sc_fifo<T> &) { return *this; }
+
+    sc_event _dataReadEvent;
+    sc_event _dataWriteEvent;
+
+    int _size;
+    mutable std::list<T> _entries;
+    mutable std::list<T> _pending;
+    bool _readsHappened;
 };
 
 template <class T>
index 0952d77d10242dd64a29462334c7edc72979a5c6..541d1fcaa9ec00ecb6f3c499a4a7b5adbd65d862 100644 (file)
@@ -30,6 +30,7 @@
 #ifndef __SYSTEMC_EXT_CHANNEL_SC_FIFO_IN_HH__
 #define __SYSTEMC_EXT_CHANNEL_SC_FIFO_IN_HH__
 
+#include "../core/sc_event.hh"
 #include "../core/sc_port.hh"
 #include "sc_fifo_in_if.hh"
 #include "warn_unimpl.hh"
@@ -44,72 +45,59 @@ template <class T>
 class sc_fifo_in : public sc_port<sc_fifo_in_if<T>, 0>
 {
   public:
-    sc_fifo_in() : sc_port<sc_fifo_in_if<T>, 0>() {}
-    explicit sc_fifo_in(const char *name) : sc_port<sc_fifo_in_if<T>, 0>(name)
+    sc_fifo_in() : sc_port<sc_fifo_in_if<T>, 0>(),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
+    {}
+    explicit sc_fifo_in(const char *name) :
+        sc_port<sc_fifo_in_if<T>, 0>(name),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     virtual ~sc_fifo_in() {}
 
     // Deprecated binding constructors.
     explicit sc_fifo_in(const sc_fifo_in_if<T> &interface) :
-        sc_port<sc_fifo_in_if<T>, 0>(interface)
+        sc_port<sc_fifo_in_if<T>, 0>(interface),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     sc_fifo_in(const char *name, const sc_fifo_in_if<T> &interface) :
-        sc_port<sc_fifo_in_if<T>, 0>(name, interface)
+        sc_port<sc_fifo_in_if<T>, 0>(name, interface),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     explicit sc_fifo_in(sc_port_b<sc_fifo_in_if<T> > &parent) :
-        sc_port<sc_fifo_in_if<T>, 0>(parent)
+        sc_port<sc_fifo_in_if<T>, 0>(parent),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     sc_fifo_in(const char *name, sc_port_b<sc_fifo_in_if<T> > &parent) :
-        sc_port<sc_fifo_in_if<T>, 0>(name, parent)
+        sc_port<sc_fifo_in_if<T>, 0>(name, parent),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     explicit sc_fifo_in(sc_port<sc_fifo_in_if<T>, 0> &parent) :
-        sc_port<sc_fifo_in_if<T>, 0>(parent)
+        sc_port<sc_fifo_in_if<T>, 0>(parent),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
     sc_fifo_in(const char *name, sc_port<sc_fifo_in_if<T>, 0> &parent) :
-        sc_port<sc_fifo_in_if<T>, 0>(name, parent)
+        sc_port<sc_fifo_in_if<T>, 0>(name, parent),
+        _dataWrittenFinder(*this, &sc_fifo_in_if<T>::data_written_event)
     {}
 
-    void
-    read(T &)
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-    }
-    T
-    read()
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(T *)nullptr;
-    }
-    bool
-    nb_read(T &)
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return false;
-    }
+    void read(T &t) { (*this)->read(t); }
+    T read() { return (*this)->read(); }
+    bool nb_read(T &t) { return (*this)->nb_read(t); }
     const sc_event &
     data_written_event() const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const sc_event *)nullptr;
-    }
-    sc_event_finder &
-    data_written() const
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(sc_event_finder *)nullptr;
-    }
-    int
-    num_available() const
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return 0;
+        return (*this)->data_written_event();
     }
+    sc_event_finder &data_written() const { return _dataWrittenFinder; }
+    int num_available() const { return (*this)->num_available(); }
     virtual const char *kind() const { return "sc_fifo_in"; }
 
   private:
     // Disabled
     sc_fifo_in(const sc_fifo_in<T> &) : sc_port<sc_fifo_in_if<T>, 0>() {}
     sc_fifo_in<T> &operator = (const sc_fifo_in<T> &) { return *this; }
+
+    mutable sc_event_finder_t<sc_fifo_in_if<T> > _dataWrittenFinder;
 };
 
 } // namespace sc_core
index af2f6efe5790d381d98fe9231b53c7cc9615a21b..52840305bc52f7cce9c74e40190ad0625bb9f530 100644 (file)
@@ -44,67 +44,58 @@ template <class T>
 class sc_fifo_out : public sc_port<sc_fifo_out_if<T>, 0>
 {
   public:
-    sc_fifo_out() : sc_port<sc_fifo_out_if<T>, 0>() {}
+    sc_fifo_out() : sc_port<sc_fifo_out_if<T>, 0>(),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
+    {}
     explicit sc_fifo_out(const char *name) :
-            sc_port<sc_fifo_out_if<T>, 0>(name)
+            sc_port<sc_fifo_out_if<T>, 0>(name),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     virtual ~sc_fifo_out() {}
 
     // Deprecated binding constructors.
     explicit sc_fifo_out(const sc_fifo_out_if<T> &interface) :
-        sc_port<sc_fifo_out_if<T>, 0>(interface)
+        sc_port<sc_fifo_out_if<T>, 0>(interface),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     sc_fifo_out(const char *name, const sc_fifo_out_if<T> &interface) :
-        sc_port<sc_fifo_out_if<T>, 0>(name, interface)
+        sc_port<sc_fifo_out_if<T>, 0>(name, interface),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     explicit sc_fifo_out(sc_port_b<sc_fifo_out_if<T> > &parent) :
-        sc_port<sc_fifo_out_if<T>, 0>(parent)
+        sc_port<sc_fifo_out_if<T>, 0>(parent),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     sc_fifo_out(const char *name, sc_port_b<sc_fifo_out_if<T> > &parent) :
-        sc_port<sc_fifo_out_if<T>, 0>(name, parent)
+        sc_port<sc_fifo_out_if<T>, 0>(name, parent),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     explicit sc_fifo_out(sc_port<sc_fifo_out_if<T>, 0> &parent) :
-        sc_port<sc_fifo_out_if<T>, 0>(parent)
+        sc_port<sc_fifo_out_if<T>, 0>(parent),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
     sc_fifo_out(const char *name, sc_port<sc_fifo_out_if<T>, 0> &parent) :
-        sc_port<sc_fifo_out_if<T>, 0>(name, parent)
+        sc_port<sc_fifo_out_if<T>, 0>(name, parent),
+        _dataReadFinder(*this, &sc_fifo_out_if<T>::data_read_event)
     {}
 
-    void
-    write(const T &)
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-    }
-    bool
-    nb_write(const T &)
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return false;
-    }
+    void write(const T &t) { (*this)->write(t); }
+    bool nb_write(const T &t) { return (*this)->nb_write(t); }
     const sc_event &
     data_read_event() const
     {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const sc_event *)nullptr;
-    }
-    sc_event_finder &
-    data_read() const
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(sc_event_finder *)nullptr;
-    }
-    int
-    num_free() const
-    {
-        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
-        return 0;
+        return (*this)->data_read_event();
     }
+    sc_event_finder &data_read() const { return _dataReadFinder; }
+    int num_free() const { return (*this)->num_free(); }
     virtual const char *kind() const { return "sc_fifo_out"; }
 
   private:
     // Disabled
     sc_fifo_out(const sc_fifo_out<T> &) : sc_port<sc_fifo_out_if<T>, 0>() {}
     sc_fifo_out<T> &operator = (const sc_fifo_out<T> &) { return *this; }
+
+    mutable sc_event_finder_t<sc_fifo_out_if<T> > _dataReadFinder;
 };
 
 } // namespace sc_core