systemc: Implement sc_vector.
authorGabe Black <gabeblack@google.com>
Mon, 1 Oct 2018 08:22:39 +0000 (01:22 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 16 Oct 2018 00:42:21 +0000 (00:42 +0000)
Change-Id: I3cf096c4432fdf310fa1279da32620d5c9f57b5d
Reviewed-on: https://gem5-review.googlesource.com/c/13197
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/ext/utils/sc_vector.hh
src/systemc/utils/sc_vector.cc

index fea49c29674b5609c65369808709a2850c0b819a..f005751d5d822e340dac1f4135596680c2b3eb97 100644 (file)
@@ -1,3 +1,22 @@
+/*****************************************************************************
+
+  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+  more contributor license agreements.  See the NOTICE file distributed
+  with this work for additional information regarding copyright ownership.
+  Accellera licenses this file to you under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with the
+  License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+  implied.  See the License for the specific language governing
+  permissions and limitations under the License.
+
+ *****************************************************************************/
+
 /*
  * Copyright 2018 Google, Inc.
  *
@@ -36,8 +55,8 @@
 #include <iterator>
 #include <vector>
 
+#include "../core/sc_module.hh"
 #include "../core/sc_object.hh"
-#include "warn_unimpl.hh"
 
 namespace sc_gem5
 {
@@ -147,9 +166,34 @@ class sc_vector_base : public sc_object
   public:
     typedef size_t size_type;
 
+    sc_vector_base(const char *_name) : sc_object(_name) {}
+
     virtual const char *kind() const { return "sc_vector"; }
     size_type size() const;
     const std::vector<sc_object *> &get_elements() const;
+
+  protected:
+    std::vector<void *> objs;
+
+    // What's returned by get_elements, which really returns the elemenets
+    // which are also objects.
+    mutable std::vector<sc_object *> elements;
+
+    sc_object *implicitCast(sc_object *p) const { return p; }
+    sc_object *implicitCast(...) const
+    {
+        SC_REPORT_ERROR(
+                "(E808) sc_vector::get_elements called for element type "
+                "not derived from sc_object", name());
+        return nullptr;
+    }
+    virtual sc_object *objectCast(void *) const = 0;
+
+    void checkIndex(size_type index) const;
+    void forceParent() const;
+    void unforceParent() const;
+
+    void reportEmpty(const char *kind_, bool empty_dest) const;
 };
 
 
@@ -403,177 +447,164 @@ class sc_vector : public sc_vector_base
     typedef sc_vector_iter<T> iterator;
     typedef sc_vector_iter<const T> const_iterator;
 
-    sc_vector() : sc_vector_base()
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    }
-    explicit sc_vector(const char *) : sc_vector_base()
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    }
-    sc_vector(const char *, size_type) : sc_vector_base()
+    sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {}
+    explicit sc_vector(const char *_name) : sc_vector_base(_name) {}
+    sc_vector(const char *_name, size_type _size) : sc_vector_base(_name)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
+        init(_size);
     }
     template <typename Creator>
-    sc_vector(const char *, size_type, Creator) : sc_vector_base()
+    sc_vector(const char *_name, size_type _size, Creator creator) :
+        sc_vector_base(_name)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
+        init(_size, creator);
     }
-    virtual ~sc_vector() {}
+    virtual ~sc_vector() { clear(); }
 
     void
-    init(size_type)
+    init(size_type _size)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
+        init(_size, &sc_vector<T>::create_element);
     }
     static T *
-    create_element(const char *, size_type)
+    create_element(const char *_name, size_type index)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return nullptr;
+        return new T(_name);
     }
 
     template <typename Creator>
     void
-    init(size_type, Creator)
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    }
-
-    T &
-    operator [] (size_type)
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(T *)nullptr;
-    }
+    init(size_type _size, Creator creator)
+    {
+        forceParent();
+        try {
+            for (size_type i = 0; i < _size; i++) {
+                // XXX The name and scope of these objects needs to be handled
+                // specially.
+                T *p = creator(sc_gen_unique_name(basename()), i);
+                objs.push_back(p);
+            }
+        } catch (...) {
+            unforceParent();
+            clear();
+            throw;
+        }
+        unforceParent();
+    }
+
+    T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); }
     const T &
-    operator [] (size_type) const
+    operator [] (size_type index) const
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const T *)nullptr;
+        return *static_cast<const T *>(objs[index]);
     }
 
     T &
-    at(size_type)
+    at(size_type index)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(T *)nullptr;
+        this->checkIndex(index);
+        return *static_cast<T *>(objs[index]);
     }
     const T &
-    at(size_type) const
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(const T *)nullptr;
-    }
-
-    iterator
-    begin()
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
-    }
-    iterator
-    end()
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
-    }
-
-    const_iterator
-    begin() const
+    at(size_type index) const
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return const_iterator();
-    }
-    const_iterator
-    end() const
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return const_iterator();
+        this->checkIndex(index);
+        return *static_cast<const T *>(objs[index]);
     }
 
-    const_iterator
-    cbegin() const
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return const_iterator();
-    }
-    const_iterator
-    cend() const
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return const_iterator();
-    }
+    iterator begin() { return objs.begin(); }
+    iterator end() { return objs.end(); }
+    const_iterator begin() const { return objs.begin(); }
+    const_iterator end() const { return objs.end(); }
+    const_iterator cbegin() const { return objs.begin(); }
+    const_iterator cend() const { return objs.end(); }
 
     template <typename ContainerType, typename ArgumentType>
     iterator
-    bind(sc_vector_assembly<ContainerType, ArgumentType>)
+    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return bind(c.begin(), c.end());
     }
 
     template <typename BindableContainer>
     iterator
-    bind(BindableContainer &)
+    bind(BindableContainer &c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return bind(c.begin(), c.end());
     }
 
     template <typename BindableIterator>
     iterator
-    bind(BindableIterator, BindableIterator)
+    bind(BindableIterator first, BindableIterator last)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return bind(first, last, this->begin());
     }
 
     template <typename BindableIterator>
     iterator
-    bind(BindableIterator, BindableIterator, iterator)
+    bind(BindableIterator first, BindableIterator last, iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        if (!size() || from == end() || first == last)
+            reportEmpty(kind(), from == end());
+
+        while (from != end() && first != last)
+            (*from++).bind(*first++);
+        return from;
     }
 
     template <typename ContainerType, typename ArgumentType>
     iterator
     operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return (*this)(c.begin(), c.end());
     }
 
     template <typename ArgumentContainer>
     iterator
-    operator () (ArgumentContainer &)
+    operator () (ArgumentContainer &c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return (*this)(c.begin(), c.end());
     }
 
     template <typename ArgumentIterator>
     iterator
-    operator () (ArgumentIterator, ArgumentIterator)
+    operator () (ArgumentIterator first, ArgumentIterator last)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        return (*this)(first, last, this->begin());
     }
 
     template <typename ArgumentIterator>
     iterator
-    operator () (ArgumentIterator, ArgumentIterator, iterator)
+    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return iterator();
+        if (!size() || from == end() || first == last)
+            reportEmpty(kind(), from == end());
+
+        while (from != end() && first != last)
+            (*from++)(*first++);
+        return from;
     }
 
   private:
     // Disabled
     sc_vector(const sc_vector &) : sc_vector_base() {}
     sc_vector &operator = (const sc_vector &) { return *this; }
+
+    void
+    clear()
+    {
+        for (auto obj: objs)
+            delete static_cast<T *>(obj);
+    }
+
+    template <typename, typename>
+    friend class sc_vector_assembly;
+
+    sc_object *
+    objectCast(void *ptr) const
+    {
+        return implicitCast(static_cast<T *>(ptr));
+    }
 };
 
 template <typename T, typename MT>
@@ -589,10 +620,9 @@ class sc_vector_assembly
         const T, sc_member_access<const T, const MT> > const_iterator;
     typedef MT (T::*MemberType);
 
-    sc_vector_assembly(const sc_vector_assembly &)
-    {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    }
+    sc_vector_assembly(const sc_vector_assembly &other) :
+        vec_(other.vec_), ptr_(other.ptr_)
+    {}
 
     iterator begin() { return iterator(vec_->begin().it_, ptr_); }
     iterator end() { return iterator(vec_->end().it_, ptr_); }
@@ -624,8 +654,14 @@ class sc_vector_assembly
     std::vector<sc_object *>
     get_elements() const
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return *(std::vector<sc_object *> *)nullptr;
+        std::vector<sc_object *> ret;
+        for (const_iterator it = begin(); it != end(); it++) {
+            sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it));
+
+            if (obj_ptr)
+                ret.push_back(obj_ptr);
+        }
+        return ret;
     }
 
     typename iterator::reference
@@ -652,83 +688,84 @@ class sc_vector_assembly
 
     template <typename ContainerType, typename ArgumentType>
     iterator
-    bind(sc_vector_assembly<ContainerType, ArgumentType>)
+    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return bind(c.begin(), c.end());
     }
 
     template <typename BindableContainer>
     iterator
-    bind(BindableContainer &)
+    bind(BindableContainer &c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return bind(c.begin(), c.end());
     }
 
     template <typename BindableIterator>
     iterator
-    bind(BindableIterator, BindableIterator)
+    bind(BindableIterator first, BindableIterator last)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return bind(first, last, this->begin());
     }
 
     template <typename BindableIterator>
     iterator
-    bind(BindableIterator, BindableIterator, iterator)
+    bind(BindableIterator first, BindableIterator last, iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        if (!size() || from == end() || first == last)
+            vec_->reportEmpty("sc_vector_assembly", from == end());
+
+        while (from != end() && first != last)
+            (*from++).bind(*first++);
+        return from;
     }
 
     template <typename BindableIterator>
     iterator
-    bind(BindableIterator, BindableIterator, typename sc_vector<T>::iterator)
+    bind(BindableIterator first, BindableIterator last,
+            typename sc_vector<T>::iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return bind(first, last, iterator(from.it_, ptr_));
     }
 
     template <typename ContainerType, typename ArgumentType>
     iterator
-    operator () (sc_vector_assembly<ContainerType, ArgumentType>)
+    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return (*this)(c.begin(), c.end());
     }
 
     template <typename ArgumentContainer>
     iterator
-    operator () (ArgumentContainer &)
+    operator () (ArgumentContainer &c)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return (*this)(c.begin(), c.end());
     }
 
     template <typename ArgumentIterator>
     iterator
-    operator () (ArgumentIterator, ArgumentIterator)
+    operator () (ArgumentIterator first, ArgumentIterator last)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return (*this)(first, last, this->begin());
     }
 
     template <typename ArgumentIterator>
     iterator
-    operator () (ArgumentIterator, ArgumentIterator, iterator)
+    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        if (!size() || from == end() || first == last)
+            vec_->reportEmpty("sc_vector_assembly", from == end());
+
+        while (from != end() && first != last)
+            (*from++)(*first++);
+        return from;
     }
 
     template <typename ArgumentIterator>
     iterator
-    operator () (ArgumentIterator, ArgumentIterator,
-                 typename sc_vector<T>::iterator)
+    operator () (ArgumentIterator first, ArgumentIterator last,
+                 typename sc_vector<T>::iterator from)
     {
-        sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-        return begin();
+        return (*this)(first, last, iterator(from.it_, ptr_));
     }
 
   private:
index ed59b734f2d358c64aaa018b03fbcdd383ef9779..985253995f61a03dd0f02663013f7460af0c03d9 100644 (file)
@@ -1,3 +1,22 @@
+/*****************************************************************************
+
+  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+  more contributor license agreements.  See the NOTICE file distributed
+  with this work for additional information regarding copyright ownership.
+  Accellera licenses this file to you under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with the
+  License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+  implied.  See the License for the specific language governing
+  permissions and limitations under the License.
+
+ *****************************************************************************/
+
 /*
  * Copyright 2018 Google, Inc.
  *
  * Authors: Gabe Black
  */
 
+#include <sstream>
+
+#include "base/cprintf.hh"
+#include "systemc/core/object.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
 #include "systemc/ext/utils/sc_vector.hh"
 
 namespace sc_core
 {
 
-sc_vector_base::size_type
-sc_vector_base::size() const
-{
-    sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    return 0;
-}
+sc_vector_base::size_type sc_vector_base::size() const { return objs.size(); }
 
 const std::vector<sc_object *> &
 sc_vector_base::get_elements() const
 {
-    sc_utils_warn_unimpl(__PRETTY_FUNCTION__);
-    return *(const std::vector<sc_object *> *)nullptr;
+    elements.clear();
+    for (auto ptr: objs) {
+        sc_object *obj_ptr = objectCast(ptr);
+        if (obj_ptr)
+            elements.push_back(obj_ptr);
+    }
+    return elements;
+}
+
+void
+sc_vector_base::checkIndex(size_type index) const
+{
+    if (index >= size()) {
+        std::ostringstream ss;
+        ccprintf(ss, "%s[%d] >= size() = %d", name(), index, size());
+        SC_REPORT_ERROR("(E5) out of bounds", ss.str().c_str());
+        sc_abort();
+    }
+}
+
+void
+sc_vector_base::forceParent() const
+{
+    sc_gem5::pushParentObj(get_parent_object());
+}
+
+void
+sc_vector_base::unforceParent() const
+{
+    sc_gem5::popParentObj();
+}
+
+void
+sc_vector_base::reportEmpty(const char *kind_, bool empty_dest) const
+{
+    std::ostringstream ss;
+
+    ss << "target `" << name() << "' " << "(" << kind_ << ") ";
+
+    if (!size())
+        ss << "not initialised yet";
+    else if (empty_dest)
+        ss << "empty range given";
+    else
+        ss << "empty destination range given";
+
+    SC_REPORT_WARNING("(W807) sc_vector::bind called with empty range",
+            ss.str().c_str());
 }
 
 } // namespace sc_core