systemc: Implement most of sc_object.
authorGabe Black <gabeblack@google.com>
Fri, 22 Jun 2018 21:19:44 +0000 (14:19 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 5 Sep 2018 06:01:39 +0000 (06:01 +0000)
To avoid making it hard to change sc_object's implementation in the
future, this change keeps most of the data members out of sc_object and
keeps them in a seperate Object which is managed independently but
still matches to the sc_objects one to one.

This change also moves away from the SystemC/sc_gem5 namespace pair in
favor of sc_gem5. Having two namespaces with classes, etc, living in
both was complicating things. Having to use a namespace that doesn't
fit in one scheme or the other isn't great, but it's the lesser of two
evils.

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

src/systemc/core/SConscript
src/systemc/core/module.cc
src/systemc/core/module.hh
src/systemc/core/object.cc [new file with mode: 0644]
src/systemc/core/object.hh [new file with mode: 0644]
src/systemc/core/sc_module_name.cc
src/systemc/core/sc_object.cc
src/systemc/ext/core/sc_object.hh

index 2cf410eaeee376c90a2b537fb463b03ce69a96ae..a07c026830a6658ee51ce9f337a65d92d6d0e7a4 100644 (file)
@@ -32,6 +32,7 @@ if env['USE_SYSTEMC']:
 
     Source('kernel.cc')
     Source('module.cc')
+    Source('object.cc')
 
     Source('sc_attr.cc')
     Source('sc_event.cc')
index 97a4a9ffabd1e8f7300df360fa020585cb7f20bb..3b7e922e334a48e00ae94d54821dcd5f0d263e40 100644 (file)
 
 #include "systemc/core/module.hh"
 
+#include <cassert>
 #include <list>
 
 #include "base/logging.hh"
 
-namespace SystemC
+namespace sc_gem5
 {
 
 namespace
 {
 
 std::list<Module *> _modules;
-
-Module *_top_module = nullptr;
+Module *_new_module;
 
 } // anonymous namespace
 
+Module::Module(const char *name) : _name(name), _sc_mod(nullptr), _obj(nullptr)
+{
+    panic_if(_new_module, "Previous module not finished.\n");
+    _new_module = this;
+}
+
 void
-Module::push()
+Module::finish(Object *this_obj)
 {
-    if (!_top_module)
-        _top_module = this;
+    assert(!_obj);
+    _obj = this_obj;
     _modules.push_back(this);
+    _new_module = nullptr;
 }
 
 void
 Module::pop()
 {
-    panic_if(_modules.size(), "Popping from empty module list.\n");
+    panic_if(!_modules.size(), "Popping from empty module list.\n");
     panic_if(_modules.back() != this,
             "Popping module which isn't at the end of the module list.\n");
+    panic_if(_new_module, "Pop with unfinished module.\n");
+    _modules.pop_back();
+}
+
+Module *
+currentModule()
+{
+    if (_modules.empty())
+        return nullptr;
+    return _modules.back();
 }
 
 Module *
-topModule()
+newModule()
 {
-    return _top_module;
+    return _new_module;
 }
 
-} // namespace SystemC
+} // namespace sc_gem5
index 56e125ee6cfb7917f9e4e8c4d73a8e6fc9bb58a7..3734e633f9d1e0ec389dc749b537e141d88f645f 100644 (file)
 #ifndef __SYSTEMC_CORE_MODULE_HH__
 #define __SYSTEMC_CORE_MODULE_HH__
 
-namespace SystemC
+#include <cassert>
+
+#include "systemc/core/object.hh"
+#include "systemc/ext/core/sc_module.hh"
+
+namespace sc_gem5
 {
 
 class Module
 {
   private:
     const char *_name;
+    sc_core::sc_module *_sc_mod;
+    Object *_obj;
 
   public:
-    Module(const char *name) : _name(name) {}
 
-    const char *name() { return _name; }
+    Module(const char *name);
+    void finish(Object *this_obj);
 
-    void push();
-    void pop();
-};
+    const char *name() const { return _name; }
 
-extern Module *topModule();
+    sc_core::sc_module *
+    sc_mod() const
+    {
+        assert(_sc_mod);
+        return _sc_mod;
+    }
 
-} // namespace SystemC
+    void
+    sc_mod(sc_core::sc_module *sc_mod)
+    {
+        assert(!_sc_mod);
+        _sc_mod = sc_mod;
+    }
 
-namespace sc_gem5
-{
+    Object *
+    obj()
+    {
+        assert(_obj);
+        return _obj;
+    }
+
+    void pop();
+};
 
-using SystemC::Module;
+Module *currentModule();
+Module *newModule();
 
 } // namespace sc_gem5
 
diff --git a/src/systemc/core/object.cc b/src/systemc/core/object.cc
new file mode 100644 (file)
index 0000000..8d2b735
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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/object.hh"
+
+#include "base/logging.hh"
+#include "systemc/core/module.hh"
+
+namespace sc_gem5
+{
+
+namespace
+{
+
+ObjectsIt
+findObjectIn(Objects &objects, const std::string &name)
+{
+    ObjectsIt it;
+    for (it = objects.begin(); it != objects.end(); it++)
+        if (!strcmp((*it)->name(), name.c_str()))
+            break;
+
+    return it;
+}
+
+void
+addObject(Objects *objects, sc_core::sc_object *object)
+{
+    objects->emplace(objects->end(), object);
+}
+
+void
+popObject(Objects *objects, const std::string &name)
+{
+    ObjectsIt it = findObjectIn(*objects, name);
+    assert(it != objects->end());
+    std::swap(objects->back(), *it);
+    objects->pop_back();
+}
+
+} // anonymous namespace
+
+Object::Object(sc_core::sc_object *sc_obj) : Object(sc_obj, "object") {}
+
+Object::Object(sc_core::sc_object *sc_obj, const char *obj_name) :
+    sc_obj(sc_obj), _basename(obj_name), parent(nullptr)
+{
+    if (_basename == "")
+        _basename = "object";
+
+    Module *p = currentModule();
+
+    Module *n = newModule();
+    if (n) {
+        // We are a module in the process of being constructed.
+        n->finish(this);
+    }
+
+    if (p) {
+        // We're "within" a parent module, ie we're being created while its
+        // constructor is running.
+        parent = p->obj()->sc_obj;
+        addObject(&parent->_gem5_object->children, sc_obj);
+    } else if (false /* TODO Check if a process is running */) {
+        // The process is our parent.
+    } else {
+        // We're a top level object.
+        addObject(&topLevelObjects, sc_obj);
+    }
+
+    addObject(&allObjects, sc_obj);
+
+    _name = _basename;
+    sc_core::sc_object *sc_p = parent;
+    while (sc_p) {
+        _name = std::string(sc_p->basename()) + std::string(".") + _name;
+        sc_p = get_parent_object();
+    }
+}
+
+Object::Object(sc_core::sc_object *sc_obj, const Object &arg) :
+    Object(sc_obj, arg._basename.c_str())
+{}
+
+Object &
+Object::operator = (const Object &)
+{
+    return *this;
+}
+
+Object::~Object()
+{
+    panic_if(!children.empty(), "Parent object still has children.\n");
+
+    if (parent)
+        popObject(&parent->_gem5_object->children, _name);
+    else
+        popObject(&topLevelObjects, _name);
+    popObject(&allObjects, _name);
+}
+
+const char *
+Object::name() const
+{
+    return _name.c_str();
+}
+
+const char *
+Object::basename() const
+{
+    return _basename.c_str();
+}
+
+void
+Object::print(std::ostream &out) const
+{
+    out << name();
+}
+
+void
+Object::dump(std::ostream &out) const
+{
+    out << "name = " << name() << "\n";
+    out << "kind = " << sc_obj->kind() << "\n";
+}
+
+const std::vector<sc_core::sc_object *> &
+Object::get_child_objects() const
+{
+    return children;
+}
+
+const std::vector<sc_core::sc_event *> &
+Object::get_child_events() const
+{
+    return events;
+}
+
+sc_core::sc_object *Object::get_parent_object() const
+{
+    return parent;
+}
+
+bool
+Object::add_attribute(sc_core::sc_attr_base &attr)
+{
+    return cltn.push_back(&attr);
+}
+
+sc_core::sc_attr_base *
+Object::get_attribute(const std::string &attr)
+{
+    return cltn[attr];
+}
+
+sc_core::sc_attr_base *
+Object::remove_attribute(const std::string &attr)
+{
+    return cltn.remove(attr);
+}
+
+void
+Object::remove_all_attributes()
+{
+    cltn.remove_all();
+}
+
+int
+Object::num_attributes() const
+{
+    return cltn.size();
+}
+
+sc_core::sc_attr_cltn &
+Object::attr_cltn()
+{
+    return cltn;
+}
+
+const sc_core::sc_attr_cltn &
+Object::attr_cltn() const
+{
+    return cltn;
+}
+
+sc_core::sc_simcontext *
+Object::simcontext() const
+{
+    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    return nullptr;
+}
+
+
+Objects topLevelObjects;
+Objects allObjects;
+
+const std::vector<sc_core::sc_object *> &
+getTopLevelScObjects()
+{
+    return topLevelObjects;
+}
+
+sc_core::sc_object *
+findObject(const char *name, const Objects &objects)
+{
+    ObjectsIt it = findObjectIn(allObjects, name);
+    return it == allObjects.end() ? nullptr : *it;
+}
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/object.hh b/src/systemc/core/object.hh
new file mode 100644 (file)
index 0000000..93c5e8f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_OBJECT_HH__
+#define __SYSTEMC_CORE_OBJECT_HH__
+
+#include <string>
+#include <vector>
+
+#include "systemc/ext/core/sc_attr.hh"
+#include "systemc/ext/core/sc_object.hh"
+
+namespace sc_gem5
+{
+
+class Object;
+
+typedef std::vector<sc_core::sc_object *> Objects;
+typedef std::vector<sc_core::sc_event *> Events;
+typedef Objects::iterator ObjectsIt;
+
+class Object
+{
+  public:
+    Object(sc_core::sc_object *sc_obj);
+    Object(sc_core::sc_object *sc_obj, const char *);
+    Object(sc_core::sc_object *sc_obj, const Object &);
+    Object &operator = (const Object &);
+
+    virtual ~Object();
+
+    /*
+     * sc_object methods.
+     */
+    const char *name() const;
+    const char *basename() const;
+
+    void print(std::ostream & =std::cout) const;
+    void dump(std::ostream & =std::cout) const;
+
+    const std::vector<sc_core::sc_object *> &get_child_objects() const;
+    const std::vector<sc_core::sc_event *> &get_child_events() const;
+    sc_core::sc_object *get_parent_object() const;
+
+    bool add_attribute(sc_core::sc_attr_base &);
+    sc_core::sc_attr_base *get_attribute(const std::string &);
+    sc_core::sc_attr_base *remove_attribute(const std::string &);
+    void remove_all_attributes();
+    int num_attributes() const;
+    sc_core::sc_attr_cltn &attr_cltn();
+    const sc_core::sc_attr_cltn &attr_cltn() const;
+
+    sc_core::sc_simcontext *simcontext() const;
+
+  private:
+    sc_core::sc_object *sc_obj;
+
+    std::string _basename;
+    std::string _name;
+
+    Objects children;
+    Events events;
+    sc_core::sc_object *parent;
+    ObjectsIt parentIt;
+
+    sc_core::sc_attr_cltn cltn;
+};
+
+extern Objects topLevelObjects;
+extern Objects allObjects;
+
+sc_core::sc_object *findObject(
+        const char *name, const Objects &objects=topLevelObjects);
+
+} // namespace sc_gem5
+
+#endif  //__SYSTEMC_CORE_OBJECT_HH__
index b55e50001c0fa39e3271e748aef0b461dd0f9563..ca568e2ad9186f99e9550367414102ef36199bbb 100644 (file)
@@ -36,10 +36,8 @@ namespace sc_core
 {
 
 sc_module_name::sc_module_name(const char *name) :
-    _name(name), _gem5_module(new SystemC::Module(name)), _on_the_stack(true)
-{
-    _gem5_module->push();
-}
+    _name(name), _gem5_module(new sc_gem5::Module(name)), _on_the_stack(true)
+{}
 
 sc_module_name::sc_module_name(const sc_module_name &other) :
     _name(other._name), _gem5_module(other._gem5_module), _on_the_stack(false)
index b6883443addab3f76a40d53ebf8f2a1212530d9a..c2e27610b48ba1e8630a7c7c024f388ea00a88b3 100644 (file)
  * Authors: Gabe Black
  */
 
+#include <vector>
+
 #include "base/logging.hh"
+#include "systemc/core/object.hh"
 #include "systemc/ext/core/sc_object.hh"
 
 namespace sc_core
 {
 
-const char *
-sc_object::name() const
+namespace
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return "sc_object";
-}
+
+std::vector<sc_object *> top_level_objects;
+
+} // anonymous namespace
 
 const char *
-sc_object::basename() const
+sc_object::name() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return "sc_object";
+    return _gem5_object->name();
 }
 
 const char *
-sc_object::kind() const
+sc_object::basename() const
 {
-    return "sc_object";
+    return _gem5_object->basename();
 }
 
 void
 sc_object::print(std::ostream &out) const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_object->print(out);
 }
 
 void
 sc_object::dump(std::ostream &out) const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_object->dump(out);
 }
 
 const std::vector<sc_object *> &
 sc_object::get_child_objects() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const std::vector<sc_object *> *)nullptr;
+    return _gem5_object->get_child_objects();
 }
 
 const std::vector<sc_event *> &
 sc_object::get_child_events() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const std::vector<sc_event *> *)nullptr;
+    return _gem5_object->get_child_events();
 }
 
 sc_object *
 sc_object::get_parent_object() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return NULL;
+    return _gem5_object->get_parent_object();
 }
 
 bool
-sc_object::add_attribute(sc_attr_base &)
+sc_object::add_attribute(sc_attr_base &attr)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return false;
+    return _gem5_object->add_attribute(attr);
 }
 
 sc_attr_base *
-sc_object::get_attribute(const std::string &)
+sc_object::get_attribute(const std::string &name)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return NULL;
+    return _gem5_object->get_attribute(name);
 }
 
 sc_attr_base *
-sc_object::remove_attribute(const std::string &)
+sc_object::remove_attribute(const std::string &name)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return NULL;
+    return _gem5_object->remove_attribute(name);
 }
 
 void
 sc_object::remove_all_attributes()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    return _gem5_object->remove_all_attributes();
 }
 
 int
 sc_object::num_attributes() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return 0;
+    return _gem5_object->num_attributes();
 }
 
 sc_attr_cltn &
 sc_object::attr_cltn()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(sc_attr_cltn *)NULL;
+    return _gem5_object->attr_cltn();
 }
 
 const sc_attr_cltn &
 sc_object::attr_cltn() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(sc_attr_cltn *)NULL;
+    return _gem5_object->attr_cltn();
 }
 
 sc_simcontext *
 sc_object::simcontext() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return nullptr;
+    return _gem5_object->simcontext();
 }
 
 sc_object::sc_object()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_object = new sc_gem5::Object(this);
 }
 
 sc_object::sc_object(const char *name)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_object = new sc_gem5::Object(this, name);
 }
 
-sc_object::sc_object(const sc_object &arg)
+sc_object::sc_object(const sc_object &other)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_object = new sc_gem5::Object(this, *other._gem5_object);
 }
 
 sc_object &
-sc_object::operator = (const sc_object &)
+sc_object::operator = (const sc_object &other)
 {
+    *_gem5_object = *other._gem5_object;
     return *this;
 }
 
 sc_object::~sc_object()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    delete _gem5_object;
 }
 
 const std::vector<sc_object *> &
 sc_get_top_level_objects()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const std::vector<sc_object *> *)nullptr;
+    return sc_gem5::topLevelObjects;
 }
 
 sc_object *
-sc_find_object(const char *)
+sc_find_object(const char *name)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return NULL;
+    return sc_gem5::findObject(name);
 }
 
 } // namespace sc_core
index 653df874ed13a0c889a8b69e753c7a22846e09b9..2dcc7faa72f3715a1fb6f8a05775893a43d138f9 100644 (file)
 #include <string>
 #include <vector>
 
+namespace sc_gem5
+{
+
+class Object;
+
+} // namespace sc_gem5
+
 namespace sc_core
 {
 
@@ -48,7 +55,7 @@ class sc_object
     const char *name() const;
     const char *basename() const;
 
-    virtual const char *kind() const;
+    virtual const char *kind() const { return "sc_object"; }
 
     virtual void print(std::ostream & =std::cout) const;
     virtual void dump(std::ostream & =std::cout) const;
@@ -66,8 +73,7 @@ class sc_object
     const sc_attr_cltn &attr_cltn() const;
 
     // Deprecated
-    sc_simcontext *
-    simcontext() const;
+    sc_simcontext *simcontext() const;
 
   protected:
     sc_object();
@@ -75,6 +81,10 @@ class sc_object
     sc_object(const sc_object &);
     sc_object &operator = (const sc_object &);
     virtual ~sc_object();
+
+  private:
+    friend class sc_gem5::Object;
+    sc_gem5::Object *_gem5_object;
 };
 
 const std::vector<sc_object *> &sc_get_top_level_objects();