systemc: Refactor sensitivities.
authorGabe Black <gabeblack@google.com>
Fri, 14 Sep 2018 07:04:22 +0000 (00:04 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 9 Oct 2018 21:49:30 +0000 (21:49 +0000)
Dynamic and Static sensitivities used to be represented by the same
classes, even though they're (almost) disjoint in how they worked. Also
timeouts, which can be used alongside dynamic sensitivities, were
handled by the sensitivities themselves. That meant that the
sensitivity mechanism had to mix in more types of behaviors,
increasing complexity. Also, the non-standard timed_out function
Accellera includes is harder to implement if the path for timeouts and
regular sensitivities are mixed together.

This change splits up dynamic and static sensitivities and splits out
timeouts. It also immitates the ordering Accellera uses when going
through sensitivities for an event. Static sensitivities are triggered
first in reverse order (why?), and then dynamic sensitivities are
triggered in what amounts to reverse order. To delete a sensitivity
which has been handled, it's swapped with the one in the last position,
and then the vector is truncated to drop it at the end. This has the
net effect of stirring the dynamic sensitivities, and isn't easily
immitated using a different approach, even if other approaches would
be more straightforward.

Double check addSensitivity for event.hh

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

12 files changed:
src/systemc/core/SConscript
src/systemc/core/event.cc
src/systemc/core/event.hh
src/systemc/core/process.cc
src/systemc/core/process.hh
src/systemc/core/sc_module.cc
src/systemc/core/sc_sensitive.cc
src/systemc/core/sc_spawn.cc
src/systemc/core/sensitivity.cc [new file with mode: 0644]
src/systemc/core/sensitivity.hh [new file with mode: 0644]
src/systemc/ext/core/sc_event.hh
src/systemc/ext/core/sc_port.hh

index 4814e6afa9209b52370a9f8b9cd41afbcbe3f721..1d291ef4dc81af2c88683af6925d9837ed7909aa 100644 (file)
@@ -40,6 +40,7 @@ if env['USE_SYSTEMC']:
     Source('python.cc')
     Source('scheduler.cc')
     Source('sched_event.cc')
+    Source('sensitivity.cc')
 
     Source('sc_attr.cc')
     Source('sc_event.cc')
index 61fa80c8bd9c0e18cf4a41d9750535a34eb14244..0daca12e13008d5f8a46e531b3c13051099554f3 100644 (file)
@@ -145,9 +145,18 @@ Event::notify()
     if (delayedNotify.scheduled())
         scheduler.deschedule(&delayedNotify);
 
-    auto local_sensitivities = sensitivities;
-    for (auto s: local_sensitivities)
+    for (auto s: staticSensitivities)
         s->notify(this);
+    DynamicSensitivities &ds = dynamicSensitivities;
+    int size = ds.size();
+    int pos = 0;
+    while (pos < size) {
+        if (ds[pos]->notify(this))
+            ds[pos] = ds[--size];
+        else
+            pos++;
+    }
+    ds.resize(size);
 }
 
 void
index c39053be8e5a08a7d295eb154b16ae9e9935a2d8..bb1d0a0d6182c6f8ac0ee1bf56ce73c0ad0f5a23 100644 (file)
@@ -37,7 +37,9 @@
 #include "sim/eventq.hh"
 #include "systemc/core/list.hh"
 #include "systemc/core/object.hh"
+#include "systemc/core/process.hh"
 #include "systemc/core/sched_event.hh"
+#include "systemc/core/sensitivity.hh"
 #include "systemc/ext/core/sc_prim.hh"
 #include "systemc/ext/core/sc_time.hh"
 
@@ -93,8 +95,40 @@ class Event
         return e->_gem5_event;
     }
 
-    void addSensitivity(Sensitivity *s) const { sensitivities.push_back(s); }
-    void delSensitivity(Sensitivity *s) const { sensitivities.remove(s); }
+    void
+    addSensitivity(StaticSensitivity *s) const
+    {
+        // Insert static sensitivities in reverse order to match Accellera's
+        // implementation.
+        staticSensitivities.insert(staticSensitivities.begin(), s);
+    }
+    void
+    delSensitivity(StaticSensitivity *s) const
+    {
+        for (auto &t: staticSensitivities) {
+            if (t == s) {
+                t = staticSensitivities.back();
+                staticSensitivities.pop_back();
+                break;
+            }
+        }
+    }
+    void
+    addSensitivity(DynamicSensitivity *s) const
+    {
+        dynamicSensitivities.push_back(s);
+    }
+    void
+    delSensitivity(DynamicSensitivity *s) const
+    {
+        for (auto &t: dynamicSensitivities) {
+            if (t == s) {
+                t = dynamicSensitivities.back();
+                dynamicSensitivities.pop_back();
+                break;
+            }
+        }
+    }
 
   private:
     sc_core::sc_event *_sc_event;
@@ -107,7 +141,8 @@ class Event
 
     ScEvent delayedNotify;
 
-    mutable std::list<Sensitivity *> sensitivities;
+    mutable StaticSensitivities staticSensitivities;
+    mutable DynamicSensitivities dynamicSensitivities;
 };
 
 extern Events topLevelEvents;
index 1c7a9d72ea33b0fd2c6063a7327eade7f71def33..e977713f49f6c4b621261703cb12bef5554a2054 100644 (file)
 namespace sc_gem5
 {
 
-SensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
-    Sensitivity(p), timeoutEvent([this]() { this->timeout(); })
-{
-    scheduler.schedule(&timeoutEvent, t);
-}
-
-SensitivityTimeout::~SensitivityTimeout()
-{
-    if (timeoutEvent.scheduled())
-        scheduler.deschedule(&timeoutEvent);
-}
-
-void
-SensitivityTimeout::timeout()
-{
-    notify();
-}
-
-SensitivityEvent::SensitivityEvent(
-        Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
-{
-    Event::getFromScEvent(event)->addSensitivity(this);
-}
-
-SensitivityEvent::~SensitivityEvent()
-{
-    Event::getFromScEvent(event)->delSensitivity(this);
-}
-
-SensitivityEventAndList::SensitivityEventAndList(
-        Process *p, const ::sc_core::sc_event_and_list *list) :
-    Sensitivity(p), list(list), count(0)
-{
-    for (auto e: list->events)
-        Event::getFromScEvent(e)->addSensitivity(this);
-}
-
-SensitivityEventAndList::~SensitivityEventAndList()
-{
-    for (auto e: list->events)
-        Event::getFromScEvent(e)->delSensitivity(this);
-}
-
-void
-SensitivityEventAndList::notifyWork(Event *e)
-{
-    e->delSensitivity(this);
-    count++;
-    if (count == list->events.size())
-        satisfy();
-}
-
-SensitivityEventOrList::SensitivityEventOrList(
-        Process *p, const ::sc_core::sc_event_or_list *list) :
-    Sensitivity(p), list(list)
-{
-    for (auto e: list->events)
-        Event::getFromScEvent(e)->addSensitivity(this);
-}
-
-SensitivityEventOrList::~SensitivityEventOrList()
-{
-    for (auto e: list->events)
-        Event::getFromScEvent(e)->delSensitivity(this);
-}
-
-void
-SensitivityTimeoutAndEventAndList::notifyWork(Event *e)
-{
-    if (e) {
-        // An event went off which must be part of the sc_event_and_list.
-        SensitivityEventAndList::notifyWork(e);
-    } else {
-        // There's no inciting event, so this must be a timeout.
-        satisfy(true);
-    }
-}
-
-
 class UnwindExceptionReset : public ::sc_core::sc_unwind_exception
 {
   public:
@@ -195,7 +116,7 @@ Process::disable(bool inc_kids)
         forEachKid([](Process *p) { p->disable(true); });
 
     if (!::sc_core::sc_allow_process_control_corners &&
-            dynamic_cast<SensitivityTimeout *>(dynamicSensitivity)) {
+            timeoutEvent.scheduled()) {
         std::string message("attempt to disable a thread with timeout wait: ");
         message += name();
         SC_REPORT_ERROR("Undefined process control interaction",
@@ -317,12 +238,8 @@ Process::syncResetOff(bool inc_kids)
 void
 Process::finalize()
 {
-    for (auto &s: pendingStaticSensitivities) {
-        s->finalize(staticSensitivities);
-        delete s;
-        s = nullptr;
-    }
-    pendingStaticSensitivities.clear();
+    for (auto s: staticSensitivities)
+        s->finalize();
 };
 
 void
@@ -346,26 +263,66 @@ Process::run()
 }
 
 void
-Process::addStatic(PendingSensitivity *s)
+Process::addStatic(StaticSensitivity *s)
 {
-    pendingStaticSensitivities.push_back(s);
+    staticSensitivities.push_back(s);
 }
 
 void
-Process::setDynamic(Sensitivity *s)
+Process::setDynamic(DynamicSensitivity *s)
 {
-    delete dynamicSensitivity;
+    if (dynamicSensitivity) {
+        dynamicSensitivity->clear();
+        delete dynamicSensitivity;
+    }
     dynamicSensitivity = s;
+    if (dynamicSensitivity)
+        dynamicSensitivity->finalize();
+}
+
+void
+Process::cancelTimeout()
+{
+    if (timeoutEvent.scheduled())
+        scheduler.deschedule(&timeoutEvent);
+}
+
+void
+Process::setTimeout(::sc_core::sc_time t)
+{
+    cancelTimeout();
+    scheduler.schedule(&timeoutEvent, t);
+}
+
+void
+Process::timeout()
+{
+    // A process is considered timed_out only if it was also waiting for an
+    // event but got a timeout instead.
+    _timedOut = (dynamicSensitivity != nullptr);
+
+    setDynamic(nullptr);
+    if (disabled())
+        return;
+
+    ready();
 }
 
 void
 Process::satisfySensitivity(Sensitivity *s)
 {
     // If there's a dynamic sensitivity and this wasn't it, ignore.
-    if (dynamicSensitivity && dynamicSensitivity != s)
+    if ((dynamicSensitivity || timeoutEvent.scheduled()) &&
+            dynamicSensitivity != s) {
         return;
+    }
 
-    setDynamic(nullptr);
+    _timedOut = false;
+    // This sensitivity should already be cleared by this point, or the event
+    // which triggered it will take care of it.
+    delete dynamicSensitivity;
+    dynamicSensitivity = nullptr;
+    cancelTimeout();
     ready();
 }
 
@@ -394,8 +351,9 @@ Process::lastReport(::sc_core::sc_report *report)
 ::sc_core::sc_report *Process::lastReport() const { return _lastReport.get(); }
 
 Process::Process(const char *name, ProcessFuncWrapper *func, bool internal) :
-    ::sc_core::sc_process_b(name), excWrapper(nullptr), func(func),
-    _internal(internal), _timedOut(false), _dontInitialize(false),
+    ::sc_core::sc_process_b(name), excWrapper(nullptr),
+    timeoutEvent([this]() { this->timeout(); }),
+    func(func), _internal(internal), _timedOut(false), _dontInitialize(false),
     _needsStart(true), _isUnwinding(false), _terminated(false),
     _suspended(false), _disabled(false), _syncReset(false), refCount(0),
     stackSize(::Fiber::DefaultStackSize), dynamicSensitivity(nullptr)
@@ -413,10 +371,12 @@ Process::terminate()
     _suspendedReady = false;
     _suspended = false;
     _syncReset = false;
-    delete dynamicSensitivity;
-    dynamicSensitivity = nullptr;
-    for (auto s: staticSensitivities)
+    clearDynamic();
+    cancelTimeout();
+    for (auto s: staticSensitivities) {
+        s->clear();
         delete s;
+    }
     staticSensitivities.clear();
 
     _terminatedEvent.notify();
index d399d7a3d4aabd3fa5743e8b950b832b24b43984..0a312e28e6dff9fa7f6cabc116cdcf48bd844e55 100644 (file)
 #include <vector>
 
 #include "base/fiber.hh"
-#include "sim/eventq.hh"
 #include "systemc/core/bindinfo.hh"
-#include "systemc/core/event.hh"
 #include "systemc/core/list.hh"
 #include "systemc/core/object.hh"
 #include "systemc/core/sched_event.hh"
+#include "systemc/core/sensitivity.hh"
 #include "systemc/ext/core/sc_event.hh"
-#include "systemc/ext/core/sc_export.hh"
-#include "systemc/ext/core/sc_interface.hh"
 #include "systemc/ext/core/sc_module.hh"
-#include "systemc/ext/core/sc_port.hh"
 #include "systemc/ext/core/sc_process_handle.hh"
-#include "systemc/ext/utils/sc_report.hh"
 
 namespace sc_core
 {
@@ -62,233 +57,6 @@ namespace sc_gem5
 class ScHalt
 {};
 
-class Sensitivity
-{
-  protected:
-    Process *process;
-
-  public:
-    Sensitivity(Process *p) : process(p) {}
-    virtual ~Sensitivity() {}
-
-    void satisfy(bool timedOut=false);
-
-    virtual void notifyWork(Event *e) { satisfy(); }
-    void notify(Event *e);
-    void notify() { notify(nullptr); }
-
-    const std::string name();
-};
-
-class SensitivityTimeout : virtual public Sensitivity
-{
-  private:
-    void timeout();
-    ScEvent timeoutEvent;
-
-  public:
-    SensitivityTimeout(Process *p, ::sc_core::sc_time t);
-    ~SensitivityTimeout();
-};
-
-class SensitivityEvent : virtual public Sensitivity
-{
-  private:
-    const ::sc_core::sc_event *event;
-
-  public:
-    SensitivityEvent(Process *p, const ::sc_core::sc_event *e);
-    ~SensitivityEvent();
-};
-
-//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
-//recreated. That works for dynamic sensitivities, but not for static.
-//Fortunately processes can't be statically sensitive to sc_event_and_lists.
-class SensitivityEventAndList : virtual public Sensitivity
-{
-  private:
-    const ::sc_core::sc_event_and_list *list;
-    int count;
-
-  public:
-    SensitivityEventAndList(
-            Process *p, const ::sc_core::sc_event_and_list *list);
-    ~SensitivityEventAndList();
-
-    void notifyWork(Event *e) override;
-};
-
-class SensitivityEventOrList : virtual public Sensitivity
-{
-  private:
-    const ::sc_core::sc_event_or_list *list;
-
-  public:
-    SensitivityEventOrList(
-            Process *p, const ::sc_core::sc_event_or_list *list);
-    ~SensitivityEventOrList();
-};
-
-// Combined sensitivities. These trigger when any of their parts do.
-
-class SensitivityTimeoutAndEvent :
-    public SensitivityTimeout, public SensitivityEvent
-{
-  public:
-    SensitivityTimeoutAndEvent(
-            Process *p, ::sc_core::sc_time t, const ::sc_core::sc_event *e) :
-        Sensitivity(p), SensitivityTimeout(p, t), SensitivityEvent(p, e)
-    {}
-
-    void notifyWork(Event *e) override { satisfy(e == nullptr); }
-};
-
-class SensitivityTimeoutAndEventAndList :
-    public SensitivityTimeout, public SensitivityEventAndList
-{
-  public:
-    SensitivityTimeoutAndEventAndList(
-            Process *p, ::sc_core::sc_time t,
-            const ::sc_core::sc_event_and_list *eal) :
-        Sensitivity(p), SensitivityTimeout(p, t),
-        SensitivityEventAndList(p, eal)
-    {}
-
-    void notifyWork(Event *e) override;
-};
-
-class SensitivityTimeoutAndEventOrList :
-    public SensitivityTimeout, public SensitivityEventOrList
-{
-  public:
-    SensitivityTimeoutAndEventOrList(
-            Process *p, ::sc_core::sc_time t,
-            const ::sc_core::sc_event_or_list *eol) :
-        Sensitivity(p), SensitivityTimeout(p, t),
-        SensitivityEventOrList(p, eol)
-    {}
-
-    void notifyWork(Event *e) override { satisfy(e == nullptr); }
-};
-
-typedef std::vector<Sensitivity *> Sensitivities;
-
-
-/*
- * Pending sensitivities. These are records of sensitivities to install later,
- * once all the information to configure them is available.
- */
-
-class PendingSensitivity
-{
-  protected:
-    Process *process;
-
-  public:
-    virtual void finalize(Sensitivities &s) = 0;
-    PendingSensitivity(Process *p) : process(p) {}
-    virtual ~PendingSensitivity() {}
-};
-
-class PendingSensitivityEvent : public PendingSensitivity
-{
-  private:
-    const sc_core::sc_event *event;
-
-  public:
-    PendingSensitivityEvent(Process *p, const sc_core::sc_event *e) :
-        PendingSensitivity(p), event(e) {}
-
-    void
-    finalize(Sensitivities &s) override
-    {
-        s.push_back(new SensitivityEvent(process, event));
-    }
-};
-
-class PendingSensitivityInterface : public PendingSensitivity
-{
-  private:
-    const sc_core::sc_interface *interface;
-
-  public:
-    PendingSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
-        PendingSensitivity(p), interface(i)
-    {}
-
-    void
-    finalize(Sensitivities &s) override
-    {
-        s.push_back(new SensitivityEvent(process,
-                                         &interface->default_event()));
-    }
-};
-
-class PendingSensitivityPort : public PendingSensitivity
-{
-  private:
-    const sc_core::sc_port_base *port;
-
-  public:
-    PendingSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
-        PendingSensitivity(p), port(pb)
-    {}
-
-    void
-    finalize(Sensitivities &s) override
-    {
-        for (int i = 0; i < port->size(); i++) {
-            const ::sc_core::sc_event *e =
-                &port->_gem5Interface(i)->default_event();
-            s.push_back(new SensitivityEvent(process, e));
-        }
-    }
-};
-
-class PendingSensitivityExport : public PendingSensitivity
-{
-  private:
-    const sc_core::sc_export_base *exp;
-
-  public:
-    PendingSensitivityExport(Process *p, const sc_core::sc_export_base *exp) :
-        PendingSensitivity(p), exp(exp)
-    {}
-
-    void
-    finalize(Sensitivities &s) override
-    {
-        s.push_back(new SensitivityEvent(process,
-                    &exp->get_interface()->default_event()));
-    }
-};
-
-class PendingSensitivityFinder : public PendingSensitivity
-{
-  private:
-    const sc_core::sc_event_finder *finder;
-
-  public:
-    PendingSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
-        PendingSensitivity(p), finder(f)
-    {}
-
-    void
-    finalize(Sensitivities &s) override
-    {
-        const ::sc_core::sc_port_base *port = finder->port();
-        int size = port->size();
-        for (int i = 0; i < size; i++) {
-            ::sc_core::sc_interface *interface = port->_gem5Interface(i);
-            const ::sc_core::sc_event *event = &finder->find_event(interface);
-            s.push_back(new SensitivityEvent(process, event));
-        }
-    }
-};
-
-typedef std::vector<PendingSensitivity *> PendingSensitivities;
-
-
 class Process : public ::sc_core::sc_process_b, public ListNode
 {
   public:
@@ -332,8 +100,13 @@ class Process : public ::sc_core::sc_process_b, public ListNode
 
     void run();
 
-    void addStatic(PendingSensitivity *);
-    void setDynamic(Sensitivity *);
+    void addStatic(StaticSensitivity *);
+    void setDynamic(DynamicSensitivity *);
+    void clearDynamic() { setDynamic(nullptr); }
+
+    ScEvent timeoutEvent;
+    void setTimeout(::sc_core::sc_time t);
+    void cancelTimeout();
 
     void satisfySensitivity(Sensitivity *);
 
@@ -349,7 +122,6 @@ class Process : public ::sc_core::sc_process_b, public ListNode
     bool hasStaticSensitivities() { return !staticSensitivities.empty(); }
     bool internal() { return _internal; }
     bool timedOut() { return _timedOut; }
-    void timedOut(bool to) { _timedOut = to; }
 
     bool dontInitialize() { return _dontInitialize; }
     void dontInitialize(bool di) { _dontInitialize = di; }
@@ -357,6 +129,8 @@ class Process : public ::sc_core::sc_process_b, public ListNode
     void joinWait(::sc_core::sc_join *join) { joinWaiters.push_back(join); }
 
   protected:
+    void timeout();
+
     Process(const char *name, ProcessFuncWrapper *func, bool internal=false);
 
     static Process *_newest;
@@ -365,8 +139,11 @@ class Process : public ::sc_core::sc_process_b, public ListNode
     {
         popListNode();
         delete func;
-        for (auto s: staticSensitivities)
+        for (auto s: staticSensitivities) {
+            s->clear();
             delete s;
+        }
+        clearDynamic();
     }
 
     ::sc_core::sc_event _resetEvent;
@@ -399,36 +176,14 @@ class Process : public ::sc_core::sc_process_b, public ListNode
 
     size_t stackSize;
 
-    Sensitivities staticSensitivities;
-    PendingSensitivities pendingStaticSensitivities;
-
-    Sensitivity *dynamicSensitivity;
+    StaticSensitivities staticSensitivities;
+    DynamicSensitivity *dynamicSensitivity;
 
     std::unique_ptr<::sc_core::sc_report> _lastReport;
 
     std::vector<::sc_core::sc_join *> joinWaiters;
 };
 
-inline void
-Sensitivity::satisfy(bool timedOut)
-{
-    process->timedOut(timedOut);
-    process->satisfySensitivity(this);
-}
-
-inline void
-Sensitivity::notify(Event *e)
-{
-    if (!process->disabled())
-        notifyWork(e);
-}
-
-inline const std::string
-Sensitivity::name()
-{
-    return std::string(process->name()) + ".timeout";
-}
-
 } // namespace sc_gem5
 
 #endif  //__SYSTEMC_CORE_PROCESS_HH__
index e695f7697c2bc9aa14b7904a388daa549a8113bd..3e900f6583ee7b9494044a63eed7ed5e56dd7eac 100644 (file)
@@ -496,35 +496,40 @@ void
 next_trigger()
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(nullptr);
+    p->cancelTimeout();
+    p->clearDynamic();
 }
 
 void
 next_trigger(const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEvent(p, &e));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
 }
 
 void
 next_trigger(const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEventOrList(p, &eol));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
 }
 
 void
 next_trigger(const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEventAndList(p, &eal));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
 }
 
 void
 next_trigger(const sc_time &t)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityTimeout(p, t));
+    p->setTimeout(t);
+    p->clearDynamic();
 }
 
 void
@@ -537,7 +542,8 @@ void
 next_trigger(const sc_time &t, const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityTimeoutAndEvent(p, t, &e));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
 }
 
 void
@@ -550,8 +556,8 @@ void
 next_trigger(const sc_time &t, const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(
-            new ::sc_gem5::SensitivityTimeoutAndEventOrList(p, t, &eol));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
 }
 
 void
@@ -564,8 +570,8 @@ void
 next_trigger(const sc_time &t, const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(
-            new ::sc_gem5::SensitivityTimeoutAndEventAndList(p, t, &eal));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
 }
 
 void
@@ -589,7 +595,8 @@ void
 wait()
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(nullptr);
+    p->cancelTimeout();
+    p->clearDynamic();
     sc_gem5::scheduler.yield();
 }
 
@@ -608,7 +615,8 @@ void
 wait(const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEvent(p, &e));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
     sc_gem5::scheduler.yield();
 }
 
@@ -616,7 +624,8 @@ void
 wait(const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEventOrList(p, &eol));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
     sc_gem5::scheduler.yield();
 }
 
@@ -624,7 +633,8 @@ void
 wait(const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityEventAndList(p, &eal));
+    p->cancelTimeout();
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
     sc_gem5::scheduler.yield();
 }
 
@@ -632,7 +642,8 @@ void
 wait(const sc_time &t)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityTimeout(p, t));
+    p->setTimeout(t);
+    p->clearDynamic();
     sc_gem5::scheduler.yield();
 }
 
@@ -646,7 +657,8 @@ void
 wait(const sc_time &t, const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(new ::sc_gem5::SensitivityTimeoutAndEvent(p, t, &e));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
     sc_gem5::scheduler.yield();
 }
 
@@ -660,8 +672,8 @@ void
 wait(const sc_time &t, const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(
-            new ::sc_gem5::SensitivityTimeoutAndEventOrList(p, t, &eol));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
     sc_gem5::scheduler.yield();
 }
 
@@ -675,8 +687,8 @@ void
 wait(const sc_time &t, const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
-    p->setDynamic(
-            new ::sc_gem5::SensitivityTimeoutAndEventAndList(p, t, &eal));
+    p->setTimeout(t);
+    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
     sc_gem5::scheduler.yield();
 }
 
index 25bc1bb085ece9638f2b40bac6db0cb40e35506e..93b460a4bef7b40acf79368633f910240f3e31f6 100644 (file)
@@ -41,7 +41,7 @@ sc_sensitive &
 sc_sensitive::operator << (const sc_event &e)
 {
     currentProcess->addStatic(
-            new sc_gem5::PendingSensitivityEvent(currentProcess, &e));
+            new sc_gem5::StaticSensitivityEvent(currentProcess, &e));
     return *this;
 }
 
@@ -49,7 +49,7 @@ sc_sensitive &
 sc_sensitive::operator << (const sc_interface &i)
 {
     currentProcess->addStatic(
-            new sc_gem5::PendingSensitivityInterface(currentProcess, &i));
+            new sc_gem5::StaticSensitivityInterface(currentProcess, &i));
     return *this;
 }
 
@@ -57,7 +57,7 @@ sc_sensitive &
 sc_sensitive::operator << (const sc_port_base &b)
 {
     currentProcess->addStatic(
-            new sc_gem5::PendingSensitivityPort(currentProcess, &b));
+            new sc_gem5::StaticSensitivityPort(currentProcess, &b));
     return *this;
 }
 
@@ -65,7 +65,7 @@ sc_sensitive &
 sc_sensitive::operator << (sc_event_finder &f)
 {
     currentProcess->addStatic(
-            new sc_gem5::PendingSensitivityFinder(currentProcess, &f));
+            new sc_gem5::StaticSensitivityFinder(currentProcess, &f));
     return *this;
 }
 
index 9e2b4c83a37c560b858f830afe772c26863ac83d..02f1fa6c9a1b4a10af6419729b8a92879c9a0c9e 100644 (file)
@@ -70,19 +70,19 @@ spawnWork(ProcessFuncWrapper *func, const char *name,
 
     if (opts) {
         for (auto e: opts->_events)
-            proc->addStatic(new PendingSensitivityEvent(proc, e));
+            proc->addStatic(new StaticSensitivityEvent(proc, e));
 
         for (auto p: opts->_ports)
-            proc->addStatic(new PendingSensitivityPort(proc, p));
+            proc->addStatic(new StaticSensitivityPort(proc, p));
 
         for (auto e: opts->_exports)
-            proc->addStatic(new PendingSensitivityExport(proc, e));
+            proc->addStatic(new StaticSensitivityExport(proc, e));
 
         for (auto i: opts->_interfaces)
-            proc->addStatic(new PendingSensitivityInterface(proc, i));
+            proc->addStatic(new StaticSensitivityInterface(proc, i));
 
         for (auto f: opts->_finders)
-            proc->addStatic(new PendingSensitivityFinder(proc, f));
+            proc->addStatic(new StaticSensitivityFinder(proc, f));
     }
 
     if (opts && opts->_dontInitialize &&
diff --git a/src/systemc/core/sensitivity.cc b/src/systemc/core/sensitivity.cc
new file mode 100644 (file)
index 0000000..77aacb5
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "systemc/core/sensitivity.hh"
+
+#include "systemc/core/event.hh"
+#include "systemc/core/scheduler.hh"
+#include "systemc/ext/core/sc_export.hh"
+#include "systemc/ext/core/sc_interface.hh"
+#include "systemc/ext/core/sc_port.hh"
+
+namespace sc_gem5
+{
+
+void
+Sensitivity::satisfy()
+{
+    process->satisfySensitivity(this);
+}
+
+bool
+Sensitivity::notify(Event *e)
+{
+    if (process->disabled())
+        return false;
+    return notifyWork(e);
+}
+
+
+void
+DynamicSensitivity::addToEvent(const ::sc_core::sc_event *e)
+{
+    Event::getFromScEvent(e)->addSensitivity(this);
+}
+
+void
+DynamicSensitivity::delFromEvent(const ::sc_core::sc_event *e)
+{
+    Event::getFromScEvent(e)->delSensitivity(this);
+}
+
+void
+StaticSensitivity::addToEvent(const ::sc_core::sc_event *e)
+{
+    Event::getFromScEvent(e)->addSensitivity(this);
+}
+
+void
+StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e)
+{
+    Event::getFromScEvent(e)->delSensitivity(this);
+}
+
+void
+StaticSensitivityInterface::finalize()
+{
+    event = &interface->default_event();
+    SensitivityEvent::finalize();
+}
+
+void
+StaticSensitivityPort::finalize()
+{
+    for (int i = 0; i < port->size(); i++) {
+        const ::sc_core::sc_event *event =
+            &port->_gem5Interface(i)->default_event();
+        events.insert(event);
+        addToEvent(event);
+    }
+}
+
+void
+StaticSensitivityExport::finalize()
+{
+    event = &exp->get_interface()->default_event();
+    SensitivityEvent::finalize();
+}
+
+void
+StaticSensitivityFinder::finalize()
+{
+    const ::sc_core::sc_port_base *port = finder->port();
+    int size = port->size();
+    for (int i = 0; i < size; i++) {
+        ::sc_core::sc_interface *interface = port->_gem5Interface(i);
+        const ::sc_core::sc_event *event = &finder->find_event(interface);
+        events.insert(event);
+        addToEvent(event);
+    }
+}
+
+bool
+DynamicSensitivityEventOrList::notifyWork(Event *e)
+{
+    events.erase(e->sc_event());
+
+    // All the other events need this deleted from their lists since this
+    // sensitivity has been satisfied without them triggering.
+    for (auto le: events)
+        delFromEvent(le);
+
+    satisfy();
+    return true;
+}
+
+DynamicSensitivityEventOrList::DynamicSensitivityEventOrList(
+        Process *p, const sc_core::sc_event_or_list *eol) :
+    Sensitivity(p), DynamicSensitivity(p), events(eol->events)
+{}
+
+void
+DynamicSensitivityEventOrList::finalize()
+{
+    for (auto e: events)
+        addToEvent(e);
+}
+
+void
+DynamicSensitivityEventOrList::clear()
+{
+    for (auto e: events)
+        delFromEvent(e);
+}
+
+bool
+DynamicSensitivityEventAndList::notifyWork(Event *e)
+{
+    events.erase(e->sc_event());
+
+    // This sensitivity is satisfied if all events have triggered.
+    if (events.empty())
+        satisfy();
+
+    return true;
+}
+
+DynamicSensitivityEventAndList::DynamicSensitivityEventAndList(
+        Process *p, const sc_core::sc_event_and_list *eal) :
+    Sensitivity(p), DynamicSensitivity(p), events(eal->events)
+{}
+
+void
+DynamicSensitivityEventAndList::finalize()
+{
+    for (auto e: events)
+        addToEvent(e);
+}
+
+void
+DynamicSensitivityEventAndList::clear()
+{
+    for (auto e: events)
+        delFromEvent(e);
+}
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/sensitivity.hh b/src/systemc/core/sensitivity.hh
new file mode 100644 (file)
index 0000000..f032630
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SYSTEMC_CORE_SENSITIVITY_HH__
+#define __SYSTEMC_CORE_SENSITIVITY_HH__
+
+#include <set>
+#include <vector>
+
+#include "sim/eventq.hh"
+#include "systemc/core/sched_event.hh"
+#include "systemc/ext/core/sc_module.hh"
+
+namespace sc_core
+{
+
+class sc_event;
+class sc_event_and_list;
+class sc_event_or_list;
+class sc_event_finder;
+class sc_export_base;
+class sc_interface;
+class sc_port_base;
+
+} // namespace sc_core
+
+namespace sc_gem5
+{
+
+class Process;
+class Event;
+
+/*
+ * Common sensitivity interface.
+ */
+
+class Sensitivity
+{
+  protected:
+    Process *process;
+
+    Sensitivity(Process *p) : process(p) {}
+    virtual ~Sensitivity() {}
+
+    virtual void addToEvent(const ::sc_core::sc_event *e) = 0;
+    virtual void delFromEvent(const ::sc_core::sc_event *e) = 0;
+
+    virtual bool
+    notifyWork(Event *e)
+    {
+        satisfy();
+        return true;
+    }
+
+  public:
+    virtual void finalize() = 0;
+    virtual void clear() = 0;
+
+    void satisfy();
+    bool notify(Event *e);
+
+    virtual bool dynamic() = 0;
+};
+
+
+/*
+ * Dynamic vs. static sensitivity.
+ */
+
+class DynamicSensitivity : virtual public Sensitivity
+{
+  protected:
+    DynamicSensitivity(Process *p) : Sensitivity(p) {}
+
+    void addToEvent(const ::sc_core::sc_event *e) override;
+    void delFromEvent(const ::sc_core::sc_event *e) override;
+
+  public:
+    bool dynamic() override { return true; }
+};
+
+typedef std::vector<DynamicSensitivity *> DynamicSensitivities;
+
+
+class StaticSensitivity : virtual public Sensitivity
+{
+  protected:
+    StaticSensitivity(Process *p) : Sensitivity(p) {}
+
+    void addToEvent(const ::sc_core::sc_event *e) override;
+    void delFromEvent(const ::sc_core::sc_event *e) override;
+
+  public:
+    bool dynamic() override { return false; }
+};
+
+typedef std::vector<StaticSensitivity *> StaticSensitivities;
+
+
+/*
+ * Sensitivity to events, which can be static or dynamic.
+ */
+
+class SensitivityEvent : virtual public Sensitivity
+{
+  protected:
+    const ::sc_core::sc_event *event;
+
+    SensitivityEvent(Process *p, const ::sc_core::sc_event *e=nullptr) :
+        Sensitivity(p), event(e)
+    {}
+
+  public:
+    void finalize() override { addToEvent(event); }
+    void clear() override { delFromEvent(event); }
+};
+
+
+/*
+ * Static sensitivities.
+ */
+
+class StaticSensitivityEvent :
+    public StaticSensitivity, public SensitivityEvent
+{
+  public:
+    StaticSensitivityEvent(Process *p, const sc_core::sc_event *e) :
+        Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p, e)
+    {}
+};
+
+class StaticSensitivityInterface :
+    public StaticSensitivity, public SensitivityEvent
+{
+  private:
+    const sc_core::sc_interface *interface;
+
+  public:
+    StaticSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
+        Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p), interface(i)
+    {}
+
+    void finalize() override;
+};
+
+class StaticSensitivityPort : public StaticSensitivity
+{
+  private:
+    const ::sc_core::sc_port_base *port;
+    std::set<const ::sc_core::sc_event *> events;
+
+  public:
+    StaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
+        Sensitivity(p), StaticSensitivity(p), port(pb)
+    {}
+
+    void finalize() override;
+
+    void
+    clear() override
+    {
+        for (auto event: events)
+            delFromEvent(event);
+    }
+};
+
+class StaticSensitivityExport :
+    public StaticSensitivity, public SensitivityEvent
+{
+  private:
+    const sc_core::sc_export_base *exp;
+
+  public:
+    StaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp) :
+        Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p), exp(exp)
+    {}
+
+    void finalize() override;
+};
+
+class StaticSensitivityFinder : public StaticSensitivity
+{
+  private:
+    const ::sc_core::sc_event_finder *finder;
+    std::set<const ::sc_core::sc_event *> events;
+
+  public:
+    StaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
+        Sensitivity(p), StaticSensitivity(p), finder(f)
+    {}
+
+    void finalize() override;
+
+    void
+    clear() override
+    {
+        for (auto event: events)
+            delFromEvent(event);
+    }
+};
+
+
+/*
+ * Dynamic sensitivities.
+ */
+
+class DynamicSensitivityEvent :
+    public DynamicSensitivity, public SensitivityEvent
+{
+  public:
+    DynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) :
+        Sensitivity(p), DynamicSensitivity(p), SensitivityEvent(p, e)
+    {}
+};
+
+class DynamicSensitivityEventOrList : public DynamicSensitivity
+{
+  private:
+    std::set<const ::sc_core::sc_event *> events;
+
+  protected:
+    bool notifyWork(Event *e) override;
+
+  public:
+    DynamicSensitivityEventOrList(
+            Process *p, const sc_core::sc_event_or_list *eol);
+
+    void finalize() override;
+    void clear() override;
+};
+
+//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
+//recreated. That works for dynamic sensitivities, but not for static.
+//Fortunately processes can't be statically sensitive to sc_event_and_lists.
+class DynamicSensitivityEventAndList : public DynamicSensitivity
+{
+  private:
+    std::set<const ::sc_core::sc_event *> events;
+
+  protected:
+    bool notifyWork(Event *e) override;
+
+  public:
+    DynamicSensitivityEventAndList(
+            Process *p, const sc_core::sc_event_and_list *eal);
+
+    void finalize() override;
+    void clear() override;
+};
+
+} // namespace sc_gem5
+
+#endif  //__SYSTEMC_CORE_SENSITIVITY_HH__
index e9748cb9508d55d82133d0f675e0359f8e0a7dd2..f70951d6a42712fe53279c96b2cfe1108d16a5eb 100644 (file)
@@ -41,8 +41,8 @@ namespace sc_gem5
 {
 
 class Event;
-class SensitivityEventAndList;
-class SensitivityEventOrList;
+class DynamicSensitivityEventAndList;
+class DynamicSensitivityEventOrList;
 
 }
 
@@ -116,7 +116,7 @@ class sc_event_and_list
 
   private:
     friend class sc_event_and_expr;
-    friend class sc_gem5::SensitivityEventAndList;
+    friend class sc_gem5::DynamicSensitivityEventAndList;
 
     explicit sc_event_and_list(bool auto_delete);
 
@@ -148,7 +148,7 @@ class sc_event_or_list
 
   private:
     friend class sc_event_or_expr;
-    friend class sc_gem5::SensitivityEventOrList;
+    friend class sc_gem5::DynamicSensitivityEventOrList;
 
     explicit sc_event_or_list(bool auto_delete);
 
index 88745cc2ef0f97a56218278c20dc9610273ebe60..de26f5ae5881e080322949cb1607c5e9b77433da 100644 (file)
@@ -41,8 +41,8 @@ namespace sc_gem5
 
 class BindInfo;
 class Module;
-class PendingSensitivityPort;
-class PendingSensitivityFinder;
+class StaticSensitivityPort;
+class StaticSensitivityFinder;
 
 };
 
@@ -87,8 +87,8 @@ class sc_port_base : public sc_object
     virtual void end_of_simulation() = 0;
 
   private:
-    friend class ::sc_gem5::PendingSensitivityPort;
-    friend class ::sc_gem5::PendingSensitivityFinder;
+    friend class ::sc_gem5::StaticSensitivityPort;
+    friend class ::sc_gem5::StaticSensitivityFinder;
     friend class ::sc_gem5::Kernel;
 
     void _gem5Finalize();