sc_vector.hh revision 13271:f001f9287ba3
1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*
21 * Copyright 2018 Google, Inc.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions are
25 * met: redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer;
27 * redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution;
30 * neither the name of the copyright holders nor the names of its
31 * contributors may be used to endorse or promote products derived from
32 * this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 *
46 * Authors: Gabe Black
47 */
48
49#ifndef __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
50#define __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
51
52#include <stdint.h>
53
54#include <exception>
55#include <iterator>
56#include <vector>
57
58#include "../core/sc_module.hh"
59#include "../core/sc_object.hh"
60
61namespace sc_gem5
62{
63
64// Goop for supporting sc_vector_iter, simplified from the Accellera version.
65
66#if __cplusplus >= 201103L
67
68using std::enable_if;
69using std::remove_const;
70using std::is_same;
71using std::is_const;
72
73#else
74
75template<bool Cond, typename T=void>
76struct enable_if
77{};
78
79template<typename T>
80struct enable_if<true, T>
81{
82    typedef T type;
83};
84
85template <typename T>
86struct remove_const
87{
88    typedef T type;
89};
90template <typename T>
91struct remove_const<const T>
92{
93    typedef T type;
94};
95
96template <typename T, typename U>
97struct is_same
98{
99    static const bool value = false;
100};
101template <typename T>
102struct is_same<T, T>
103{
104    static const bool value = true;
105};
106
107template <typename T>
108struct is_const
109{
110    static const bool value = false;
111};
112template <typename T>
113struct is_const<const T>
114{
115    static const bool value = true;
116};
117
118#endif
119
120template <typename CT, typename T>
121struct is_more_const
122{
123    static const bool value =
124        is_same<typename remove_const<CT>::type,
125                typename remove_const<T>::type>::value &&
126        is_const<CT>::value >= is_const<T>::value;
127};
128
129struct special_result
130{};
131
132template <typename T>
133struct remove_special_fptr
134{};
135
136template <typename T>
137struct remove_special_fptr<special_result & (*)(T)>
138{
139    typedef T type;
140};
141
142#define SC_RPTYPE_(Type) \
143    ::sc_gem5::remove_special_fptr< \
144        ::sc_gem5::special_result & (*) Type>::type::value
145
146#define SC_ENABLE_IF_(Cond) \
147    typename ::sc_gem5::enable_if<SC_RPTYPE_(Cond)>::type * = NULL
148
149} // namespace sc_gem5
150
151namespace sc_core
152{
153
154template <typename T, typename MT>
155class sc_vector_assembly;
156
157template <typename T>
158class sc_vector;
159
160template <typename T, typename MT>
161sc_vector_assembly<T, MT> sc_assemble_vector(
162        sc_vector<T> &, MT(T::* member_ptr));
163
164class sc_vector_base : public sc_object
165{
166  public:
167    typedef size_t size_type;
168
169    sc_vector_base(const char *_name) : sc_object(_name) {}
170
171    virtual const char *kind() const { return "sc_vector"; }
172    size_type size() const;
173    const std::vector<sc_object *> &get_elements() const;
174
175  protected:
176    std::vector<void *> objs;
177
178    // What's returned by get_elements, which really returns the elemenets
179    // which are also objects.
180    mutable std::vector<sc_object *> elements;
181
182    sc_object *implicitCast(sc_object *p) const { return p; }
183    sc_object *implicitCast(...) const
184    {
185        SC_REPORT_ERROR(
186                "(E808) sc_vector::get_elements called for element type "
187                "not derived from sc_object", name());
188        return nullptr;
189    }
190    virtual sc_object *objectCast(void *) const = 0;
191
192    void checkIndex(size_type index) const;
193    void forceParent() const;
194    void unforceParent() const;
195
196    void reportEmpty(const char *kind_, bool empty_dest) const;
197};
198
199
200/*
201 * Non-standard iterator access adapters. Without using these, the classes as
202 * defined in the standard won't compile because of redundant bind() overloads.
203 */
204
205template <typename Element>
206class sc_direct_access
207{
208  public:
209    typedef Element ElementType;
210    typedef ElementType Type;
211    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
212
213    typedef sc_direct_access<ElementType> Policy;
214    typedef sc_direct_access<PlainType> NonConstPolicy;
215    typedef sc_direct_access<const PlainType> ConstPolicy;
216
217    sc_direct_access() {}
218    sc_direct_access(const NonConstPolicy &) {}
219
220    template <typename U>
221    sc_direct_access(const U &,
222        SC_ENABLE_IF_((
223            sc_gem5::is_more_const<
224                    ElementType, typename U::Policy::ElementType>
225        ))
226    )
227    {}
228
229    ElementType *
230    get(ElementType *this_) const
231    {
232        return this_;
233    }
234};
235
236template <typename Element, typename Access>
237class sc_member_access
238{
239  public:
240    template <typename, typename>
241    friend class sc_member_access;
242
243    typedef Element ElementType;
244    typedef Access AccessType;
245    typedef AccessType (ElementType::*MemberType);
246    typedef AccessType Type;
247    typedef typename sc_gem5::remove_const<AccessType>::type PlainType;
248    typedef typename sc_gem5::remove_const<ElementType>::type PlainElemType;
249
250    typedef sc_member_access<ElementType, AccessType> Policy;
251    typedef sc_member_access<PlainElemType, PlainType> NonConstPolicy;
252    typedef sc_member_access<const PlainElemType, const PlainType> ConstPolicy;
253
254    sc_member_access(MemberType ptr) : ptr_(ptr) {}
255    sc_member_access(const NonConstPolicy &other) : ptr_(other.ptr_) {}
256
257    AccessType *get(ElementType *this_) const { return &(this_->*ptr_); }
258
259  private:
260    MemberType ptr_;
261};
262
263template <typename Element,
264          typename AccessPolicy=sc_direct_access<Element> >
265class sc_vector_iter :
266        public std::iterator<std::random_access_iterator_tag,
267                             typename AccessPolicy::Type>,
268        private AccessPolicy
269{
270  private:
271    typedef Element ElementType;
272    typedef typename AccessPolicy::Policy Policy;
273    typedef typename AccessPolicy::NonConstPolicy NonConstPolicy;
274    typedef typename AccessPolicy::ConstPolicy ConstPolicy;
275    typedef typename Policy::Type AccessType;
276
277    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
278    typedef const PlainType ConstPlainType;
279    typedef typename sc_direct_access<PlainType>::ConstPolicy
280        ConstDirectPolicy;
281
282    friend class sc_vector<PlainType>;
283    template <typename, typename>
284    friend class sc_vector_assembly;
285    template <typename, typename>
286    friend class sc_vector_iter;
287
288    typedef std::iterator<std::random_access_iterator_tag, AccessType>
289        BaseType;
290    typedef sc_vector_iter ThisType;
291    typedef sc_vector<PlainType> VectorType;
292    typedef std::vector<void *> StorageType;
293
294    template <typename U>
295    struct SelectIter
296    {
297        typedef typename std::vector<void *>::iterator type;
298    };
299    template <typename U>
300    struct SelectIter<const U>
301    {
302        typedef typename std::vector<void *>::const_iterator type;
303    };
304    typedef typename SelectIter<ElementType>::type RawIterator;
305    typedef sc_vector_iter<ConstPlainType, ConstPolicy> ConstIterator;
306    typedef sc_vector_iter<ConstPlainType, ConstDirectPolicy>
307        ConstDirectIterator;
308
309    RawIterator it_;
310
311    sc_vector_iter(RawIterator it, Policy acc=Policy()) :
312        Policy(acc), it_(it)
313    {}
314
315    Policy const &get_policy() const { return *this; }
316
317  public:
318    // Conforms to Random Access Iterator category.
319    // See ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements]
320
321    typedef typename BaseType::difference_type difference_type;
322    typedef typename BaseType::reference reference;
323    typedef typename BaseType::pointer pointer;
324
325    sc_vector_iter() : Policy(), it_() {}
326
327    template <typename It>
328    sc_vector_iter(const It &it,
329        SC_ENABLE_IF_((
330            sc_gem5::is_more_const<
331                ElementType, typename It::Policy::ElementType>
332        ))
333    ) : Policy(it.get_policy()), it_(it.it_)
334    {}
335
336    ThisType &
337    operator ++ ()
338    {
339        ++it_;
340        return *this;
341    }
342    ThisType &
343    operator -- ()
344    {
345        --it_;
346        return *this;
347    }
348    ThisType
349    operator ++ (int)
350    {
351        ThisType old(*this);
352        ++it_;
353        return old;
354    }
355    ThisType
356    operator -- (int)
357    {
358        ThisType old(*this);
359        --it_;
360        return old;
361    }
362
363    ThisType
364    operator + (difference_type n) const
365    {
366        return ThisType(it_ + n, get_policy());
367    }
368    ThisType
369    operator - (difference_type n) const
370    {
371        return ThisType(it_ - n, get_policy());
372    }
373
374    ThisType &
375    operator += (difference_type n)
376    {
377        it_ += n;
378        return *this;
379    }
380
381    ThisType &
382    operator -= (difference_type n)
383    {
384        it_ -= n;
385        return *this;
386    }
387
388    bool
389    operator == (const ConstDirectIterator &other) const
390    {
391        return it_ == other.it_;
392    }
393    bool
394    operator != (const ConstDirectIterator &other) const
395    {
396        return it_ != other.it_;
397    }
398    bool
399    operator <= (const ConstDirectIterator &other) const
400    {
401        return it_ <= other.it_;
402    }
403    bool
404    operator >= (const ConstDirectIterator &other) const
405    {
406        return it_ >= other.it_;
407    }
408    bool
409    operator < (const ConstDirectIterator &other) const
410    {
411        return it_ < other.it_;
412    }
413    bool
414    operator > (const ConstDirectIterator &other) const
415    {
416        return it_ > other.it_;
417    }
418
419    reference
420    operator * () const
421    {
422        return *Policy::get(static_cast<ElementType *>((void *)*it_));
423    }
424    pointer
425    operator -> () const
426    {
427        return Policy::get(static_cast<ElementType *>((void *)*it_));
428    }
429    reference
430    operator [] (difference_type n) const
431    {
432        return *Policy::get(static_cast<ElementType *>((void *)it_[n]));
433    }
434
435    difference_type
436    operator - (ConstDirectIterator const &other) const
437    {
438        return it_ - other.it_;
439    }
440};
441
442template <typename T>
443class sc_vector : public sc_vector_base
444{
445  public:
446    using sc_vector_base::size_type;
447    typedef sc_vector_iter<T> iterator;
448    typedef sc_vector_iter<const T> const_iterator;
449
450    sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {}
451    explicit sc_vector(const char *_name) : sc_vector_base(_name) {}
452    sc_vector(const char *_name, size_type _size) : sc_vector_base(_name)
453    {
454        init(_size);
455    }
456    template <typename Creator>
457    sc_vector(const char *_name, size_type _size, Creator creator) :
458        sc_vector_base(_name)
459    {
460        init(_size, creator);
461    }
462    virtual ~sc_vector() { clear(); }
463
464    void
465    init(size_type _size)
466    {
467        init(_size, &sc_vector<T>::create_element);
468    }
469    static T *
470    create_element(const char *_name, size_type index)
471    {
472        return new T(_name);
473    }
474
475    template <typename Creator>
476    void
477    init(size_type _size, Creator creator)
478    {
479        forceParent();
480        try {
481            for (size_type i = 0; i < _size; i++) {
482                // XXX The name and scope of these objects needs to be handled
483                // specially.
484                T *p = creator(sc_gen_unique_name(basename()), i);
485                objs.push_back(p);
486            }
487        } catch (...) {
488            unforceParent();
489            clear();
490            throw;
491        }
492        unforceParent();
493    }
494
495    T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); }
496    const T &
497    operator [] (size_type index) const
498    {
499        return *static_cast<const T *>(objs[index]);
500    }
501
502    T &
503    at(size_type index)
504    {
505        this->checkIndex(index);
506        return *static_cast<T *>(objs[index]);
507    }
508    const T &
509    at(size_type index) const
510    {
511        this->checkIndex(index);
512        return *static_cast<const T *>(objs[index]);
513    }
514
515    iterator begin() { return objs.begin(); }
516    iterator end() { return objs.end(); }
517    const_iterator begin() const { return objs.begin(); }
518    const_iterator end() const { return objs.end(); }
519    const_iterator cbegin() const { return objs.begin(); }
520    const_iterator cend() const { return objs.end(); }
521
522    template <typename ContainerType, typename ArgumentType>
523    iterator
524    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
525    {
526        return bind(c.begin(), c.end());
527    }
528
529    template <typename BindableContainer>
530    iterator
531    bind(BindableContainer &c)
532    {
533        return bind(c.begin(), c.end());
534    }
535
536    template <typename BindableIterator>
537    iterator
538    bind(BindableIterator first, BindableIterator last)
539    {
540        return bind(first, last, this->begin());
541    }
542
543    template <typename BindableIterator>
544    iterator
545    bind(BindableIterator first, BindableIterator last, iterator from)
546    {
547        if (!size() || from == end() || first == last)
548            reportEmpty(kind(), from == end());
549
550        while (from != end() && first != last)
551            (*from++).bind(*first++);
552        return from;
553    }
554
555    template <typename ContainerType, typename ArgumentType>
556    iterator
557    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
558    {
559        return (*this)(c.begin(), c.end());
560    }
561
562    template <typename ArgumentContainer>
563    iterator
564    operator () (ArgumentContainer &c)
565    {
566        return (*this)(c.begin(), c.end());
567    }
568
569    template <typename ArgumentIterator>
570    iterator
571    operator () (ArgumentIterator first, ArgumentIterator last)
572    {
573        return (*this)(first, last, this->begin());
574    }
575
576    template <typename ArgumentIterator>
577    iterator
578    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
579    {
580        if (!size() || from == end() || first == last)
581            reportEmpty(kind(), from == end());
582
583        while (from != end() && first != last)
584            (*from++)(*first++);
585        return from;
586    }
587
588  private:
589    // Disabled
590    sc_vector(const sc_vector &) : sc_vector_base() {}
591    sc_vector &operator = (const sc_vector &) { return *this; }
592
593    void
594    clear()
595    {
596        for (auto obj: objs)
597            delete static_cast<T *>(obj);
598    }
599
600    template <typename, typename>
601    friend class sc_vector_assembly;
602
603    sc_object *
604    objectCast(void *ptr) const
605    {
606        return implicitCast(static_cast<T *>(ptr));
607    }
608};
609
610template <typename T, typename MT>
611class sc_vector_assembly
612{
613  public:
614    friend sc_vector_assembly<T, MT> sc_assemble_vector<>(
615            sc_vector<T> &, MT (T::*));
616
617    typedef size_t size_type;
618    typedef sc_vector_iter<T, sc_member_access<T, MT> > iterator;
619    typedef sc_vector_iter<
620        const T, sc_member_access<const T, const MT> > const_iterator;
621    typedef MT (T::*MemberType);
622
623    sc_vector_assembly(const sc_vector_assembly &other) :
624        vec_(other.vec_), ptr_(other.ptr_)
625    {}
626
627    iterator begin() { return iterator(vec_->begin().it_, ptr_); }
628    iterator end() { return iterator(vec_->end().it_, ptr_); }
629
630    const_iterator
631    cbegin() const
632    {
633        return const_iterator(vec_->begin().it_, ptr_);
634    }
635    const_iterator
636    cend() const
637    {
638        return const_iterator(vec_->end().it_, ptr_);
639    }
640
641    const_iterator
642    begin() const
643    {
644        return const_iterator(vec_->begin().it_, ptr_);
645    }
646    const_iterator
647    end() const
648    {
649        return const_iterator(vec_->end().it_, ptr_);
650    }
651
652    size_type size() const { return vec_->size(); }
653
654    std::vector<sc_object *>
655    get_elements() const
656    {
657        std::vector<sc_object *> ret;
658        for (const_iterator it = begin(); it != end(); it++) {
659            sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it));
660
661            if (obj_ptr)
662                ret.push_back(obj_ptr);
663        }
664        return ret;
665    }
666
667    typename iterator::reference
668    operator [] (size_type i)
669    {
670        return (*vec_)[i].*ptr_;
671    }
672    typename const_iterator::reference
673    operator [] (size_type i) const
674    {
675        return (*vec_)[i].*ptr_;
676    }
677
678    typename iterator::reference
679    at(size_type i)
680    {
681        return vec_->at(i).*ptr_;
682    }
683    typename const_iterator::reference
684    at(size_type i) const
685    {
686        return vec_->at(i).*ptr_;
687    }
688
689    template <typename ContainerType, typename ArgumentType>
690    iterator
691    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
692    {
693        return bind(c.begin(), c.end());
694    }
695
696    template <typename BindableContainer>
697    iterator
698    bind(BindableContainer &c)
699    {
700        return bind(c.begin(), c.end());
701    }
702
703    template <typename BindableIterator>
704    iterator
705    bind(BindableIterator first, BindableIterator last)
706    {
707        return bind(first, last, this->begin());
708    }
709
710    template <typename BindableIterator>
711    iterator
712    bind(BindableIterator first, BindableIterator last, iterator from)
713    {
714        if (!size() || from == end() || first == last)
715            vec_->reportEmpty("sc_vector_assembly", from == end());
716
717        while (from != end() && first != last)
718            (*from++).bind(*first++);
719        return from;
720    }
721
722    template <typename BindableIterator>
723    iterator
724    bind(BindableIterator first, BindableIterator last,
725            typename sc_vector<T>::iterator from)
726    {
727        return bind(first, last, iterator(from.it_, ptr_));
728    }
729
730    template <typename ContainerType, typename ArgumentType>
731    iterator
732    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
733    {
734        return (*this)(c.begin(), c.end());
735    }
736
737    template <typename ArgumentContainer>
738    iterator
739    operator () (ArgumentContainer &c)
740    {
741        return (*this)(c.begin(), c.end());
742    }
743
744    template <typename ArgumentIterator>
745    iterator
746    operator () (ArgumentIterator first, ArgumentIterator last)
747    {
748        return (*this)(first, last, this->begin());
749    }
750
751    template <typename ArgumentIterator>
752    iterator
753    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
754    {
755        if (!size() || from == end() || first == last)
756            vec_->reportEmpty("sc_vector_assembly", from == end());
757
758        while (from != end() && first != last)
759            (*from++)(*first++);
760        return from;
761    }
762
763    template <typename ArgumentIterator>
764    iterator
765    operator () (ArgumentIterator first, ArgumentIterator last,
766                 typename sc_vector<T>::iterator from)
767    {
768        return (*this)(first, last, iterator(from.it_, ptr_));
769    }
770
771  private:
772    sc_vector_assembly(sc_vector<T> &v, MemberType ptr) :
773        vec_(&v), ptr_(ptr)
774    {}
775
776    sc_vector<T> *vec_;
777    MemberType ptr_;
778};
779
780template <typename T, typename MT>
781sc_vector_assembly<T, MT>
782sc_assemble_vector(sc_vector<T> &v, MT (T::*ptr))
783{
784    return sc_vector_assembly<T, MT>(v, ptr);
785}
786
787} // namespace sc_core
788
789#endif  //__SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
790