systemc: Rework how delayed sensitivities are handled.
authorGabe Black <gabeblack@google.com>
Sat, 15 Sep 2018 01:33:16 +0000 (18:33 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 9 Oct 2018 21:50:01 +0000 (21:50 +0000)
Make BindInfo into a more general purpose Port class which mirrors
sc_module and Module, sc_object and Object, etc. This tracks multiple
bindings internally, and also pending sensitivities. Keep a global
list of ports which are added in reverse order to match Accellera, and
which is iterated over to finalize binding and for phase callbacks.
This is as opposed to doing it one module at a time, and is to better
match Accellera's ordering for the regressions.

Also the sensitivity classes are now built with factory functions,
which gets around problems calling virtual functions from their
constructors or forgetting to having to have extra boilerplate each
place they're constructed.

The port class also now finalizes port or event finder sensitivities
when its binding is completed, unless it's already complete in which
case it does so immediately.

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

16 files changed:
src/systemc/core/SConscript
src/systemc/core/bindinfo.hh [deleted file]
src/systemc/core/kernel.cc
src/systemc/core/module.cc
src/systemc/core/port.cc [new file with mode: 0644]
src/systemc/core/port.hh [new file with mode: 0644]
src/systemc/core/process.cc
src/systemc/core/process.hh
src/systemc/core/sc_module.cc
src/systemc/core/sc_port.cc
src/systemc/core/sc_sensitive.cc
src/systemc/core/sc_spawn.cc
src/systemc/core/scheduler.cc
src/systemc/core/sensitivity.cc
src/systemc/core/sensitivity.hh
src/systemc/ext/core/sc_port.hh

index 1d291ef4dc81af2c88683af6925d9837ed7909aa..0aa59944df9f859e000c31cc40d2d682b110fc4e 100644 (file)
@@ -35,6 +35,7 @@ if env['USE_SYSTEMC']:
     Source('kernel.cc')
     Source('module.cc')
     Source('object.cc')
+    Source('port.cc')
     Source('process.cc')
     Source('process_types.cc')
     Source('python.cc')
diff --git a/src/systemc/core/bindinfo.hh b/src/systemc/core/bindinfo.hh
deleted file mode 100644 (file)
index 9e636a6..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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_BINDINFO_HH__
-#define __SYSTEMC_CORE_BINDINFO_HH__
-
-#include "systemc/ext/core/sc_interface.hh"
-
-namespace sc_gem5
-{
-
-class BindInfo
-{
-  public:
-    BindInfo(::sc_core::sc_interface *interface) :
-        interface(interface), port(nullptr)
-    {}
-
-    BindInfo(::sc_core::sc_port_base *port) :
-        interface(nullptr), port(port)
-    {}
-
-    ::sc_core::sc_interface *interface;
-    ::sc_core::sc_port_base *port;
-};
-
-} // namespace sc_gem5
-
-#endif // __SYSTEMC_CORE_BINDINFO_HH__
index ca99e19320d302f1659ef84faa77cda2451fd518..ff8e24e6a13e57350227181c241cb7047fcccf03 100644 (file)
@@ -32,6 +32,7 @@
 #include "base/logging.hh"
 #include "systemc/core/channel.hh"
 #include "systemc/core/module.hh"
+#include "systemc/core/port.hh"
 #include "systemc/core/scheduler.hh"
 
 namespace sc_gem5
@@ -75,6 +76,8 @@ Kernel::init()
         fatal("Simulation called sc_stop during elaboration.\n");
 
     status(::sc_core::SC_BEFORE_END_OF_ELABORATION);
+    for (auto p: allPorts)
+        p->sc_port_base()->before_end_of_elaboration();
     for (auto m: sc_gem5::allModules)
         m->beforeEndOfElaboration();
     for (auto c: sc_gem5::allChannels)
@@ -88,11 +91,12 @@ Kernel::regStats()
         return;
 
     try {
-        for (auto m: sc_gem5::allModules)
-            for (auto p: m->ports)
-                p->_gem5Finalize();
+        for (auto p: allPorts)
+            p->finalize();
 
         status(::sc_core::SC_END_OF_ELABORATION);
+        for (auto p: allPorts)
+            p->sc_port_base()->end_of_elaboration();
         for (auto m: sc_gem5::allModules)
             m->endOfElaboration();
         for (auto c: sc_gem5::allChannels)
@@ -117,6 +121,8 @@ Kernel::startup()
 
     try {
         status(::sc_core::SC_START_OF_SIMULATION);
+        for (auto p: allPorts)
+            p->sc_port_base()->start_of_simulation();
         for (auto m: sc_gem5::allModules)
             m->startOfSimulation();
         for (auto c: sc_gem5::allChannels)
@@ -147,6 +153,8 @@ Kernel::stopWork()
 {
     status(::sc_core::SC_END_OF_SIMULATION);
     try {
+        for (auto p: allPorts)
+            p->sc_port_base()->end_of_simulation();
         for (auto m: sc_gem5::allModules)
             m->endOfSimulation();
         for (auto c: sc_gem5::allChannels)
index dcd6faa53aa810706463d9d6c18881018cfda175..afc3bf24192e2889b0ec16a71920a29d963f60eb 100644 (file)
@@ -113,8 +113,6 @@ Module::beforeEndOfElaboration()
 {
     callbackModule(this);
     _sc_mod->before_end_of_elaboration();
-    for (auto p: ports)
-        p->before_end_of_elaboration();
     for (auto e: exports)
         e->before_end_of_elaboration();
     callbackModule(nullptr);
@@ -131,8 +129,6 @@ Module::endOfElaboration()
     }
     callbackModule(this);
     _sc_mod->end_of_elaboration();
-    for (auto p: ports)
-        p->end_of_elaboration();
     for (auto e: exports)
         e->end_of_elaboration();
     callbackModule(nullptr);
@@ -143,8 +139,6 @@ Module::startOfSimulation()
 {
     callbackModule(this);
     _sc_mod->start_of_simulation();
-    for (auto p: ports)
-        p->start_of_simulation();
     for (auto e: exports)
         e->start_of_simulation();
     callbackModule(nullptr);
@@ -155,8 +149,6 @@ Module::endOfSimulation()
 {
     callbackModule(this);
     _sc_mod->end_of_simulation();
-    for (auto p: ports)
-        p->end_of_simulation();
     for (auto e: exports)
         e->end_of_simulation();
     callbackModule(nullptr);
diff --git a/src/systemc/core/port.cc b/src/systemc/core/port.cc
new file mode 100644 (file)
index 0000000..af6ecd1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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/port.hh"
+
+#include "systemc/core/sensitivity.hh"
+
+namespace sc_gem5
+{
+
+void
+Port::finalizePort(StaticSensitivityPort *port)
+{
+    for (int i = 0; i < size(); i++)
+        port->addEvent(&getInterface(i)->default_event());
+}
+
+void
+Port::finalizeFinder(StaticSensitivityFinder *finder)
+{
+    for (int i = 0; i < size(); i++)
+        finder->addEvent(&finder->find(getInterface(i)));
+}
+
+void
+Port::sensitive(StaticSensitivityPort *port)
+{
+    if (finalized)
+        finalizePort(port);
+    else
+        sensitivities.push_back(new Sensitivity(port));
+}
+
+void
+Port::sensitive(StaticSensitivityFinder *finder)
+{
+    if (finalized)
+        finalizeFinder(finder);
+    else
+        sensitivities.push_back(new Sensitivity(finder));
+}
+
+void
+Port::finalize()
+{
+    if (finalized)
+        return;
+    finalized = true;
+
+    for (auto &b: bindings) {
+        if (b->interface) {
+            addInterface(b->interface);
+        } else {
+            b->port->_gem5Port->finalize();
+            addInterfaces(b->port);
+        }
+        delete b;
+    }
+
+    bindings.clear();
+
+    for (auto &s: sensitivities) {
+        if (s->port)
+            finalizePort(s->port);
+        else
+            finalizeFinder(s->finder);
+        delete s;
+    }
+
+    sensitivities.clear();
+}
+
+std::list<Port *> allPorts;
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/port.hh b/src/systemc/core/port.hh
new file mode 100644 (file)
index 0000000..15e7bbe
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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_PORT_HH__
+#define __SYSTEMC_CORE_PORT_HH__
+
+#include <list>
+#include <vector>
+
+#include "systemc/ext/core/sc_interface.hh"
+#include "systemc/ext/core/sc_port.hh"
+
+namespace sc_gem5
+{
+
+class StaticSensitivityPort;
+class StaticSensitivityFinder;
+
+class Port;
+
+extern std::list<Port *> allPorts;
+
+class Port
+{
+  private:
+    ::sc_core::sc_port_base *portBase;
+
+    bool finalized;
+    int _maxSize;
+    int _size;
+
+    void finalizePort(StaticSensitivityPort *port);
+    void finalizeFinder(StaticSensitivityFinder *finder);
+
+    void
+    addInterface(::sc_core::sc_interface *i)
+    {
+        _size++;
+        portBase->_gem5AddInterface(i);
+    }
+
+    void
+    addInterfaces(::sc_core::sc_port_base *pb)
+    {
+        for (int i = 0; i < pb->size(); i++)
+            addInterface(pb->_gem5Interface(i));
+    }
+
+    ::sc_core::sc_interface *
+    getInterface(int i)
+    {
+        return portBase->_gem5Interface(i);
+    }
+
+    struct Binding
+    {
+        explicit Binding(::sc_core::sc_interface *interface) :
+            interface(interface), port(nullptr)
+        {}
+
+        explicit Binding(::sc_core::sc_port_base *port) :
+            interface(nullptr), port(port)
+        {}
+
+        ::sc_core::sc_interface *interface;
+        ::sc_core::sc_port_base *port;
+    };
+
+    struct Sensitivity
+    {
+        Sensitivity(StaticSensitivityPort *port) :
+            port(port), finder(nullptr)
+        {}
+
+        Sensitivity(StaticSensitivityFinder *finder) :
+            port(nullptr), finder(finder)
+        {}
+
+        StaticSensitivityPort *port;
+        StaticSensitivityFinder *finder;
+    };
+
+    std::vector<Binding *> bindings;
+    std::vector<Sensitivity *> sensitivities;
+
+  public:
+    static Port *
+    fromPort(const ::sc_core::sc_port_base *pb)
+    {
+        return pb->_gem5Port;
+    }
+
+    ::sc_core::sc_port_base *sc_port_base() { return portBase; }
+
+    Port(::sc_core::sc_port_base *port_base, int max) :
+        portBase(port_base), finalized(false), _maxSize(max), _size(0)
+    {
+        allPorts.push_front(this);
+    }
+
+    void
+    bind(::sc_core::sc_interface *interface)
+    {
+        bindings.push_back(new Binding(interface));
+    }
+
+    void
+    bind(::sc_core::sc_port_base *port)
+    {
+        bindings.push_back(new Binding(port));
+    }
+
+    void sensitive(StaticSensitivityPort *port);
+    void sensitive(StaticSensitivityFinder *finder);
+
+    void finalize();
+
+    int size() { return _size; }
+    int maxSize() { return _maxSize; }
+};
+
+} // namespace sc_gem5
+
+#endif // __SYSTEMC_CORE_PORT_HH__
index e977713f49f6c4b621261703cb12bef5554a2054..45c01e916c83d665b8a2e5050a6910437cd3cdf2 100644 (file)
@@ -235,13 +235,6 @@ Process::syncResetOff(bool inc_kids)
     _syncReset = false;
 }
 
-void
-Process::finalize()
-{
-    for (auto s: staticSensitivities)
-        s->finalize();
-};
-
 void
 Process::run()
 {
@@ -276,8 +269,6 @@ Process::setDynamic(DynamicSensitivity *s)
         delete dynamicSensitivity;
     }
     dynamicSensitivity = s;
-    if (dynamicSensitivity)
-        dynamicSensitivity->finalize();
 }
 
 void
index 0a312e28e6dff9fa7f6cabc116cdcf48bd844e55..4266c2d7d57483cfe8c63662f89cf70195fa5dc6 100644 (file)
@@ -35,7 +35,6 @@
 #include <vector>
 
 #include "base/fiber.hh"
-#include "systemc/core/bindinfo.hh"
 #include "systemc/core/list.hh"
 #include "systemc/core/object.hh"
 #include "systemc/core/sched_event.hh"
@@ -96,8 +95,6 @@ class Process : public ::sc_core::sc_process_b, public ListNode
 
     void setStackSize(size_t size) { stackSize = size; }
 
-    void finalize();
-
     void run();
 
     void addStatic(StaticSensitivity *);
index 3e900f6583ee7b9494044a63eed7ed5e56dd7eac..32d1c979a3700d340eb0fde2039d48816a98276c 100644 (file)
@@ -505,7 +505,7 @@ next_trigger(const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
+    ::sc_gem5::newDynamicSensitivityEvent(p, &e);
 }
 
 void
@@ -513,7 +513,7 @@ next_trigger(const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
+    ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol);
 }
 
 void
@@ -521,7 +521,7 @@ next_trigger(const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
+    ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal);
 }
 
 void
@@ -543,7 +543,7 @@ next_trigger(const sc_time &t, const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
+    ::sc_gem5::newDynamicSensitivityEvent(p, &e);
 }
 
 void
@@ -557,7 +557,7 @@ next_trigger(const sc_time &t, const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
+    ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol);
 }
 
 void
@@ -571,7 +571,7 @@ next_trigger(const sc_time &t, const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
+    ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal);
 }
 
 void
@@ -616,7 +616,7 @@ wait(const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
+    ::sc_gem5::newDynamicSensitivityEvent(p, &e);
     sc_gem5::scheduler.yield();
 }
 
@@ -625,7 +625,7 @@ wait(const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
+    ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol);
     sc_gem5::scheduler.yield();
 }
 
@@ -634,7 +634,7 @@ wait(const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->cancelTimeout();
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
+    ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal);
     sc_gem5::scheduler.yield();
 }
 
@@ -658,7 +658,7 @@ wait(const sc_time &t, const sc_event &e)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
+    ::sc_gem5::newDynamicSensitivityEvent(p, &e);
     sc_gem5::scheduler.yield();
 }
 
@@ -673,7 +673,7 @@ wait(const sc_time &t, const sc_event_or_list &eol)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
+    ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol);
     sc_gem5::scheduler.yield();
 }
 
@@ -688,7 +688,7 @@ wait(const sc_time &t, const sc_event_and_list &eal)
 {
     sc_gem5::Process *p = sc_gem5::scheduler.current();
     p->setTimeout(t);
-    p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
+    ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal);
     sc_gem5::scheduler.yield();
 }
 
index c822e966e5c37cfdb5e60ed7fb300c2de9c63eee..52f66b70de2b5b17b50e66d02b95e85dfeb333fd 100644 (file)
@@ -28,8 +28,8 @@
  */
 
 #include "base/logging.hh"
-#include "systemc/core/bindinfo.hh"
 #include "systemc/core/module.hh"
+#include "systemc/core/port.hh"
 #include "systemc/core/scheduler.hh"
 #include "systemc/ext/core/sc_main.hh"
 #include "systemc/ext/core/sc_port.hh"
@@ -56,7 +56,7 @@ reportError(const char *id, const char *add_msg,
 }
 
 sc_port_base::sc_port_base(const char *name, int n, sc_port_policy p) :
-    sc_object(name), _maxSize(n), _size(0), finalized(false)
+    sc_object(name), _gem5Port(new ::sc_gem5::Port(this, n))
 {
     if (sc_is_running()) {
         reportError("(E110) insert port failed", "simulation running",
@@ -76,51 +76,21 @@ sc_port_base::sc_port_base(const char *name, int n, sc_port_policy p) :
     }
 }
 
-void
-sc_port_base::warn_unimpl(const char *func) const
-{
-    warn("%s not implemented.\n", func);
-}
-
-int sc_port_base::maxSize() const { return _maxSize; }
-int sc_port_base::size() const { return _size; }
-
-void
-sc_port_base::bind(sc_interface &i)
+sc_port_base::~sc_port_base()
 {
-    _gem5BindInfo.push_back(new ::sc_gem5::BindInfo(&i));
+    delete _gem5Port;
 }
 
 void
-sc_port_base::bind(sc_port_base &p)
+sc_port_base::warn_unimpl(const char *func) const
 {
-    _gem5BindInfo.push_back(new ::sc_gem5::BindInfo(&p));
+    warn("%s not implemented.\n", func);
 }
 
-void
-sc_port_base::_gem5Finalize()
-{
-    if (finalized)
-        return;
-    finalized = true;
+int sc_port_base::maxSize() const { return _gem5Port->maxSize(); }
+int sc_port_base::size() const { return _gem5Port->size(); }
 
-    for (auto &bi: _gem5BindInfo) {
-        if (bi->interface) {
-            _size++;
-            _gem5AddInterface(bi->interface);
-        } else {
-            sc_port_base *port = bi->port;
-            port->_gem5Finalize();
-            int size = port->size();
-            for (int i = 0; i < size; i++) {
-                _size++;
-                _gem5AddInterface(port->_gem5Interface(i));
-            }
-        }
-        delete bi;
-    }
-
-    _gem5BindInfo.clear();
-}
+void sc_port_base::bind(sc_interface &i) { _gem5Port->bind(&i); }
+void sc_port_base::bind(sc_port_base &p) { _gem5Port->bind(&p); }
 
 } // namespace sc_core
index 93b460a4bef7b40acf79368633f910240f3e31f6..b254f68615d91284f0e3036508c894a041706a39 100644 (file)
@@ -40,32 +40,28 @@ sc_sensitive::sc_sensitive() : currentProcess(nullptr) {}
 sc_sensitive &
 sc_sensitive::operator << (const sc_event &e)
 {
-    currentProcess->addStatic(
-            new sc_gem5::StaticSensitivityEvent(currentProcess, &e));
+    sc_gem5::newStaticSensitivityEvent(currentProcess, &e);
     return *this;
 }
 
 sc_sensitive &
 sc_sensitive::operator << (const sc_interface &i)
 {
-    currentProcess->addStatic(
-            new sc_gem5::StaticSensitivityInterface(currentProcess, &i));
+    sc_gem5::newStaticSensitivityInterface(currentProcess, &i);
     return *this;
 }
 
 sc_sensitive &
 sc_sensitive::operator << (const sc_port_base &b)
 {
-    currentProcess->addStatic(
-            new sc_gem5::StaticSensitivityPort(currentProcess, &b));
+    sc_gem5::newStaticSensitivityPort(currentProcess, &b);
     return *this;
 }
 
 sc_sensitive &
 sc_sensitive::operator << (sc_event_finder &f)
 {
-    currentProcess->addStatic(
-            new sc_gem5::StaticSensitivityFinder(currentProcess, &f));
+    sc_gem5::newStaticSensitivityFinder(currentProcess, &f);
     return *this;
 }
 
index 02f1fa6c9a1b4a10af6419729b8a92879c9a0c9e..8c936bfe9189526fbae115223ad2cea6e509958f 100644 (file)
@@ -70,19 +70,19 @@ spawnWork(ProcessFuncWrapper *func, const char *name,
 
     if (opts) {
         for (auto e: opts->_events)
-            proc->addStatic(new StaticSensitivityEvent(proc, e));
+            newStaticSensitivityEvent(proc, e);
 
         for (auto p: opts->_ports)
-            proc->addStatic(new StaticSensitivityPort(proc, p));
+            newStaticSensitivityPort(proc, p);
 
         for (auto e: opts->_exports)
-            proc->addStatic(new StaticSensitivityExport(proc, e));
+            newStaticSensitivityExport(proc, e);
 
         for (auto i: opts->_interfaces)
-            proc->addStatic(new StaticSensitivityInterface(proc, i));
+            newStaticSensitivityInterface(proc, i);
 
         for (auto f: opts->_finders)
-            proc->addStatic(new StaticSensitivityFinder(proc, f));
+            newStaticSensitivityFinder(proc, f);
     }
 
     if (opts && opts->_dontInitialize &&
index a0695a39552ceb35f2b61b14879074e1fefeaaa9..8a796bb5b82e17a16b0dac31f033907714090d61 100644 (file)
@@ -104,7 +104,6 @@ void
 Scheduler::initPhase()
 {
     for (Process *p = initList.getNext(); p; p = initList.getNext()) {
-        p->finalize();
         p->popListNode();
 
         if (p->dontInitialize()) {
@@ -141,8 +140,6 @@ void
 Scheduler::reg(Process *p)
 {
     if (initDone) {
-        // If we're past initialization, finalize static sensitivity.
-        p->finalize();
         // If not marked as dontInitialize, mark as ready.
         if (!p->dontInitialize())
             p->ready();
index 77aacb56aff9bbd534fcd16f8c1a7eddac726d29..740090cd9c69e31c740d6f45c4c7bb2cc16747f6 100644 (file)
@@ -30,6 +30,7 @@
 #include "systemc/core/sensitivity.hh"
 
 #include "systemc/core/event.hh"
+#include "systemc/core/port.hh"
 #include "systemc/core/scheduler.hh"
 #include "systemc/ext/core/sc_export.hh"
 #include "systemc/ext/core/sc_interface.hh"
 namespace sc_gem5
 {
 
+/*
+ * Common sensitivity interface.
+ */
+
 void
 Sensitivity::satisfy()
 {
@@ -53,6 +58,10 @@ Sensitivity::notify(Event *e)
 }
 
 
+/*
+ * Dynamic vs. static sensitivity.
+ */
+
 void
 DynamicSensitivity::addToEvent(const ::sc_core::sc_event *e)
 {
@@ -77,106 +86,139 @@ StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e)
     Event::getFromScEvent(e)->delSensitivity(this);
 }
 
+
+/*
+ * Static sensitivities.
+ */
+
 void
-StaticSensitivityInterface::finalize()
+newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e)
 {
-    event = &interface->default_event();
-    SensitivityEvent::finalize();
+    auto s = new StaticSensitivityEvent(p, e);
+    s->addToEvent(s->event);
+    p->addStatic(s);
 }
 
 void
-StaticSensitivityPort::finalize()
+newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i)
 {
-    for (int i = 0; i < port->size(); i++) {
-        const ::sc_core::sc_event *event =
-            &port->_gem5Interface(i)->default_event();
-        events.insert(event);
-        addToEvent(event);
-    }
+    auto s = new StaticSensitivityInterface(p, i);
+    s->addToEvent(s->event);
+    p->addStatic(s);
 }
 
 void
-StaticSensitivityExport::finalize()
+newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb)
 {
-    event = &exp->get_interface()->default_event();
-    SensitivityEvent::finalize();
+    auto s = new StaticSensitivityPort(p);
+    Port *port = Port::fromPort(pb);
+    port->sensitive(s);
+    p->addStatic(s);
 }
 
 void
-StaticSensitivityFinder::finalize()
+newStaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp)
 {
-    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);
-    }
+    auto s = new StaticSensitivityExport(p, exp);
+    s->addToEvent(s->event);
+    p->addStatic(s);
 }
 
-bool
-DynamicSensitivityEventOrList::notifyWork(Event *e)
+void
+newStaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f)
 {
-    events.erase(e->sc_event());
+    auto s = new StaticSensitivityFinder(p, f);
+    Port *port = Port::fromPort(f->port());
+    port->sensitive(s);
+    p->addStatic(s);
+}
 
-    // 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;
-}
+StaticSensitivityInterface::StaticSensitivityInterface(
+        Process *p, const sc_core::sc_interface *i) :
+    Sensitivity(p), StaticSensitivity(p),
+    SensitivityEvent(p, &i->default_event())
+{}
 
-DynamicSensitivityEventOrList::DynamicSensitivityEventOrList(
-        Process *p, const sc_core::sc_event_or_list *eol) :
-    Sensitivity(p), DynamicSensitivity(p), events(eol->events)
+StaticSensitivityExport::StaticSensitivityExport(
+        Process *p, const sc_core::sc_export_base *exp) :
+    Sensitivity(p), StaticSensitivity(p),
+    SensitivityEvent(p, &exp->get_interface()->default_event())
 {}
 
+const ::sc_core::sc_event &
+StaticSensitivityFinder::find(::sc_core::sc_interface *i)
+{
+    return finder->find_event(i);
+}
+
+
+/*
+ * Dynamic sensitivities.
+ */
+
 void
-DynamicSensitivityEventOrList::finalize()
+newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e)
 {
-    for (auto e: events)
-        addToEvent(e);
+    auto s = new DynamicSensitivityEvent(p, e);
+    s->addToEvent(s->event);
+    p->setDynamic(s);
 }
 
 void
-DynamicSensitivityEventOrList::clear()
+newDynamicSensitivityEventOrList(
+        Process *p, const sc_core::sc_event_or_list *eol)
+{
+    auto s = new DynamicSensitivityEventOrList(p, eol);
+    for (auto event: s->events)
+        s->addToEvent(event);
+    p->setDynamic(s);
+}
+
+void newDynamicSensitivityEventAndList(
+        Process *p, const sc_core::sc_event_and_list *eal)
 {
-    for (auto e: events)
-        delFromEvent(e);
+    auto s = new DynamicSensitivityEventAndList(p, eal);
+    for (auto event: s->events)
+        s->addToEvent(event);
+    p->setDynamic(s);
 }
 
+
+DynamicSensitivityEventOrList::DynamicSensitivityEventOrList(
+        Process *p, const sc_core::sc_event_or_list *eol) :
+    Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eol->events)
+{}
+
 bool
-DynamicSensitivityEventAndList::notifyWork(Event *e)
+DynamicSensitivityEventOrList::notifyWork(Event *e)
 {
     events.erase(e->sc_event());
 
-    // This sensitivity is satisfied if all events have triggered.
-    if (events.empty())
-        satisfy();
+    // 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;
 }
 
 DynamicSensitivityEventAndList::DynamicSensitivityEventAndList(
         Process *p, const sc_core::sc_event_and_list *eal) :
-    Sensitivity(p), DynamicSensitivity(p), events(eal->events)
+    Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eal->events)
 {}
 
-void
-DynamicSensitivityEventAndList::finalize()
+bool
+DynamicSensitivityEventAndList::notifyWork(Event *e)
 {
-    for (auto e: events)
-        addToEvent(e);
-}
+    events.erase(e->sc_event());
 
-void
-DynamicSensitivityEventAndList::clear()
-{
-    for (auto e: events)
-        delFromEvent(e);
+    // This sensitivity is satisfied if all events have triggered.
+    if (events.empty())
+        satisfy();
+
+    return true;
 }
 
 } // namespace sc_gem5
index f032630ec3f3d1bd0951b9b89fd62dad1c4e8b9b..b3f9a2e490c9cc2a7643f03f225ec8ec60845831 100644 (file)
@@ -79,7 +79,6 @@ class Sensitivity
     }
 
   public:
-    virtual void finalize() = 0;
     virtual void clear() = 0;
 
     void satisfy();
@@ -124,7 +123,7 @@ typedef std::vector<StaticSensitivity *> StaticSensitivities;
 
 
 /*
- * Sensitivity to events, which can be static or dynamic.
+ * Sensitivity to an event or events, which can be static or dynamic.
  */
 
 class SensitivityEvent : virtual public Sensitivity
@@ -137,19 +136,57 @@ class SensitivityEvent : virtual public Sensitivity
     {}
 
   public:
-    void finalize() override { addToEvent(event); }
     void clear() override { delFromEvent(event); }
 };
 
+class SensitivityEvents : virtual public Sensitivity
+{
+  protected:
+    std::set<const ::sc_core::sc_event *> events;
+
+    SensitivityEvents(Process *p) : Sensitivity(p) {}
+    SensitivityEvents(
+            Process *p, const std::set<const ::sc_core::sc_event *> &s) :
+        Sensitivity(p), events(s)
+    {}
+
+  public:
+    void
+    clear() override
+    {
+        for (auto event: events)
+            delFromEvent(event);
+    }
+
+    void
+    addEvent(const ::sc_core::sc_event *event)
+    {
+        events.insert(event);
+        addToEvent(event);
+    }
+};
+
 
 /*
  * Static sensitivities.
  */
 
+void newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e);
+void newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i);
+void newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb);
+void newStaticSensitivityExport(
+        Process *p, const sc_core::sc_export_base *exp);
+void newStaticSensitivityFinder(
+        Process *p, const sc_core::sc_event_finder *f);
+
+
 class StaticSensitivityEvent :
     public StaticSensitivity, public SensitivityEvent
 {
-  public:
+    friend void newStaticSensitivityEvent(
+            Process *p, const sc_core::sc_event *e);
+
+  protected:
     StaticSensitivityEvent(Process *p, const sc_core::sc_event *e) :
         Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p, e)
     {}
@@ -158,71 +195,50 @@ class StaticSensitivityEvent :
 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;
+    friend void newStaticSensitivityInterface(
+            Process *p, const sc_core::sc_interface *i);
+  protected:
+    StaticSensitivityInterface(Process *p, const sc_core::sc_interface *i);
 };
 
-class StaticSensitivityPort : public StaticSensitivity
+class StaticSensitivityPort :
+    public StaticSensitivity, public SensitivityEvents
 {
-  private:
-    const ::sc_core::sc_port_base *port;
-    std::set<const ::sc_core::sc_event *> events;
+    friend void newStaticSensitivityPort(
+            Process *p, const sc_core::sc_port_base *pb);
 
-  public:
-    StaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
-        Sensitivity(p), StaticSensitivity(p), port(pb)
+  protected:
+    StaticSensitivityPort(Process *p) :
+        Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p)
     {}
-
-    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)
-    {}
+    friend void newStaticSensitivityExport(
+            Process *p, const sc_core::sc_export_base *exp);
 
-    void finalize() override;
+    StaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp);
 };
 
-class StaticSensitivityFinder : public StaticSensitivity
+
+class StaticSensitivityFinder :
+    public StaticSensitivity, public SensitivityEvents
 {
   private:
-    const ::sc_core::sc_event_finder *finder;
-    std::set<const ::sc_core::sc_event *> events;
+    const sc_core::sc_event_finder *finder;
+
+    friend void newStaticSensitivityFinder(
+            Process *p, const sc_core::sc_event_finder *f);
 
-  public:
     StaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
-        Sensitivity(p), StaticSensitivity(p), finder(f)
+        Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p), finder(f)
     {}
 
-    void finalize() override;
-
-    void
-    clear() override
-    {
-        for (auto event: events)
-            delFromEvent(event);
-    }
+  public:
+    const ::sc_core::sc_event &find(::sc_core::sc_interface *i);
 };
 
 
@@ -230,48 +246,51 @@ class StaticSensitivityFinder : public StaticSensitivity
  * Dynamic sensitivities.
  */
 
+void newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e);
+void newDynamicSensitivityEventOrList(
+        Process *p, const sc_core::sc_event_or_list *eol);
+void newDynamicSensitivityEventAndList(
+        Process *p, const sc_core::sc_event_and_list *eal);
+
 class DynamicSensitivityEvent :
     public DynamicSensitivity, public SensitivityEvent
 {
-  public:
+  private:
+    friend void newDynamicSensitivityEvent(
+            Process *p, const sc_core::sc_event *e);
+
     DynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) :
         Sensitivity(p), DynamicSensitivity(p), SensitivityEvent(p, e)
     {}
 };
 
-class DynamicSensitivityEventOrList : public DynamicSensitivity
+class DynamicSensitivityEventOrList :
+    public DynamicSensitivity, public SensitivityEvents
 {
   private:
-    std::set<const ::sc_core::sc_event *> events;
-
-  protected:
-    bool notifyWork(Event *e) override;
+    friend void newDynamicSensitivityEventOrList(
+            Process *p, const sc_core::sc_event_or_list *eol);
 
-  public:
     DynamicSensitivityEventOrList(
             Process *p, const sc_core::sc_event_or_list *eol);
 
-    void finalize() override;
-    void clear() override;
+    bool notifyWork(Event *e) 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
+class DynamicSensitivityEventAndList :
+    public DynamicSensitivity, public SensitivityEvents
 {
   private:
-    std::set<const ::sc_core::sc_event *> events;
-
-  protected:
-    bool notifyWork(Event *e) override;
+    friend void newDynamicSensitivityEventAndList(
+            Process *p, const sc_core::sc_event_and_list *eal);
 
-  public:
     DynamicSensitivityEventAndList(
             Process *p, const sc_core::sc_event_and_list *eal);
 
-    void finalize() override;
-    void clear() override;
+    bool notifyWork(Event *e) override;
 };
 
 } // namespace sc_gem5
index de26f5ae5881e080322949cb1607c5e9b77433da..c9d436ec34ad2f4ac60a4bebe86ee92cc6e15612 100644 (file)
 namespace sc_gem5
 {
 
-class BindInfo;
-class Module;
-class StaticSensitivityPort;
-class StaticSensitivityFinder;
+class Port;
 
 };
 
@@ -62,6 +59,7 @@ class sc_port_base : public sc_object
 {
   public:
     sc_port_base(const char *name, int n, sc_port_policy p);
+    virtual ~sc_port_base();
 
     void warn_unimpl(const char *func) const;
 
@@ -87,19 +85,13 @@ class sc_port_base : public sc_object
     virtual void end_of_simulation() = 0;
 
   private:
-    friend class ::sc_gem5::StaticSensitivityPort;
-    friend class ::sc_gem5::StaticSensitivityFinder;
+    friend class ::sc_gem5::Port;
     friend class ::sc_gem5::Kernel;
 
-    void _gem5Finalize();
-
     virtual sc_interface *_gem5Interface(int n) const = 0;
     virtual void _gem5AddInterface(sc_interface *i) = 0;
 
-    std::vector<::sc_gem5::BindInfo *> _gem5BindInfo;
-    int _maxSize;
-    int _size;
-    bool finalized;
+    ::sc_gem5::Port *_gem5Port;
 };
 
 template <class IF>