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#include "messages.hh"
61
62namespace sc_gem5
63{
64
65// Goop for supporting sc_vector_iter, simplified from the Accellera version.
66
67#if __cplusplus >= 201103L
68
69using std::enable_if;
70using std::remove_const;
71using std::is_same;
72using std::is_const;
73
74#else
75
76template<bool Cond, typename T=void>
77struct enable_if
78{};
79
80template<typename T>
81struct enable_if<true, T>
82{
83    typedef T type;
84};
85
86template <typename T>
87struct remove_const
88{
89    typedef T type;
90};
91template <typename T>
92struct remove_const<const T>
93{
94    typedef T type;
95};
96
97template <typename T, typename U>
98struct is_same
99{
100    static const bool value = false;
101};
102template <typename T>
103struct is_same<T, T>
104{
105    static const bool value = true;
106};
107
108template <typename T>
109struct is_const
110{
111    static const bool value = false;
112};
113template <typename T>
114struct is_const<const T>
115{
116    static const bool value = true;
117};
118
119#endif
120
121template <typename CT, typename T>
122struct is_more_const
123{
124    static const bool value =
125        is_same<typename remove_const<CT>::type,
126                typename remove_const<T>::type>::value &&
127        is_const<CT>::value >= is_const<T>::value;
128};
129
130struct special_result
131{};
132
133template <typename T>
134struct remove_special_fptr
135{};
136
137template <typename T>
138struct remove_special_fptr<special_result & (*)(T)>
139{
140    typedef T type;
141};
142
143#define SC_RPTYPE_(Type) \
144    ::sc_gem5::remove_special_fptr< \
145        ::sc_gem5::special_result & (*) Type>::type::value
146
147#define SC_ENABLE_IF_(Cond) \
148    typename ::sc_gem5::enable_if<SC_RPTYPE_(Cond)>::type * = NULL
149
150} // namespace sc_gem5
151
152namespace sc_core
153{
154
155template <typename T, typename MT>
156class sc_vector_assembly;
157
158template <typename T>
159class sc_vector;
160
161template <typename T, typename MT>
162sc_vector_assembly<T, MT> sc_assemble_vector(
163        sc_vector<T> &, MT(T::* member_ptr));
164
165class sc_vector_base : public sc_object
166{
167  public:
168    typedef size_t size_type;
169
170    sc_vector_base(const char *_name) : sc_object(_name) {}
171
172    virtual const char *kind() const { return "sc_vector"; }
173    size_type size() const;
174    const std::vector<sc_object *> &get_elements() const;
175
176  protected:
177    std::vector<void *> objs;
178
179    // What's returned by get_elements, which really returns the elemenets
180    // which are also objects.
181    mutable std::vector<sc_object *> elements;
182
183    sc_object *implicitCast(sc_object *p) const { return p; }
184    sc_object *implicitCast(...) const
185    {
186        SC_REPORT_ERROR(SC_ID_VECTOR_NONOBJECT_ELEMENTS_, name());
187        return nullptr;
188    }
189    virtual sc_object *objectCast(void *) const = 0;
190
191    void checkIndex(size_type index) const;
192    void forceParent() const;
193    void unforceParent() const;
194
195    void reportEmpty(const char *kind_, bool empty_dest) const;
196};
197
198
199/*
200 * Non-standard iterator access adapters. Without using these, the classes as
201 * defined in the standard won't compile because of redundant bind() overloads.
202 */
203
204template <typename Element>
205class sc_direct_access
206{
207  public:
208    typedef Element ElementType;
209    typedef ElementType Type;
210    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
211
212    typedef sc_direct_access<ElementType> Policy;
213    typedef sc_direct_access<PlainType> NonConstPolicy;
214    typedef sc_direct_access<const PlainType> ConstPolicy;
215
216    sc_direct_access() {}
217    sc_direct_access(const NonConstPolicy &) {}
218
219    template <typename U>
220    sc_direct_access(const U &,
221        SC_ENABLE_IF_((
222            sc_gem5::is_more_const<
223                    ElementType, typename U::Policy::ElementType>
224        ))
225    )
226    {}
227
228    ElementType *
229    get(ElementType *this_) const
230    {
231        return this_;
232    }
233};
234
235template <typename Element, typename Access>
236class sc_member_access
237{
238  public:
239    template <typename, typename>
240    friend class sc_member_access;
241
242    typedef Element ElementType;
243    typedef Access AccessType;
244    typedef AccessType (ElementType::*MemberType);
245    typedef AccessType Type;
246    typedef typename sc_gem5::remove_const<AccessType>::type PlainType;
247    typedef typename sc_gem5::remove_const<ElementType>::type PlainElemType;
248
249    typedef sc_member_access<ElementType, AccessType> Policy;
250    typedef sc_member_access<PlainElemType, PlainType> NonConstPolicy;
251    typedef sc_member_access<const PlainElemType, const PlainType> ConstPolicy;
252
253    sc_member_access(MemberType ptr) : ptr_(ptr) {}
254    sc_member_access(const NonConstPolicy &other) : ptr_(other.ptr_) {}
255
256    AccessType *get(ElementType *this_) const { return &(this_->*ptr_); }
257
258  private:
259    MemberType ptr_;
260};
261
262template <typename Element,
263          typename AccessPolicy=sc_direct_access<Element> >
264class sc_vector_iter :
265        public std::iterator<std::random_access_iterator_tag,
266                             typename AccessPolicy::Type>,
267        private AccessPolicy
268{
269  private:
270    typedef Element ElementType;
271    typedef typename AccessPolicy::Policy Policy;
272    typedef typename AccessPolicy::NonConstPolicy NonConstPolicy;
273    typedef typename AccessPolicy::ConstPolicy ConstPolicy;
274    typedef typename Policy::Type AccessType;
275
276    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
277    typedef const PlainType ConstPlainType;
278    typedef typename sc_direct_access<PlainType>::ConstPolicy
279        ConstDirectPolicy;
280
281    friend class sc_vector<PlainType>;
282    template <typename, typename>
283    friend class sc_vector_assembly;
284    template <typename, typename>
285    friend class sc_vector_iter;
286
287    typedef std::iterator<std::random_access_iterator_tag, AccessType>
288        BaseType;
289    typedef sc_vector_iter ThisType;
290    typedef sc_vector<PlainType> VectorType;
291    typedef std::vector<void *> StorageType;
292
293    template <typename U>
294    struct SelectIter
295    {
296        typedef typename std::vector<void *>::iterator type;
297    };
298    template <typename U>
299    struct SelectIter<const U>
300    {
301        typedef typename std::vector<void *>::const_iterator type;
302    };
303    typedef typename SelectIter<ElementType>::type RawIterator;
304    typedef sc_vector_iter<ConstPlainType, ConstPolicy> ConstIterator;
305    typedef sc_vector_iter<ConstPlainType, ConstDirectPolicy>
306        ConstDirectIterator;
307
308    RawIterator it_;
309
310    sc_vector_iter(RawIterator it, Policy acc=Policy()) :
311        Policy(acc), it_(it)
312    {}
313
314    Policy const &get_policy() const { return *this; }
315
316  public:
317    // Conforms to Random Access Iterator category.
318    // See ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements]
319
320    typedef typename BaseType::difference_type difference_type;
321    typedef typename BaseType::reference reference;
322    typedef typename BaseType::pointer pointer;
323
324    sc_vector_iter() : Policy(), it_() {}
325
326    template <typename It>
327    sc_vector_iter(const It &it,
328        SC_ENABLE_IF_((
329            sc_gem5::is_more_const<
330                ElementType, typename It::Policy::ElementType>
331        ))
332    ) : Policy(it.get_policy()), it_(it.it_)
333    {}
334
335    ThisType &
336    operator ++ ()
337    {
338        ++it_;
339        return *this;
340    }
341    ThisType &
342    operator -- ()
343    {
344        --it_;
345        return *this;
346    }
347    ThisType
348    operator ++ (int)
349    {
350        ThisType old(*this);
351        ++it_;
352        return old;
353    }
354    ThisType
355    operator -- (int)
356    {
357        ThisType old(*this);
358        --it_;
359        return old;
360    }
361
362    ThisType
363    operator + (difference_type n) const
364    {
365        return ThisType(it_ + n, get_policy());
366    }
367    ThisType
368    operator - (difference_type n) const
369    {
370        return ThisType(it_ - n, get_policy());
371    }
372
373    ThisType &
374    operator += (difference_type n)
375    {
376        it_ += n;
377        return *this;
378    }
379
380    ThisType &
381    operator -= (difference_type n)
382    {
383        it_ -= n;
384        return *this;
385    }
386
387    bool
388    operator == (const ConstDirectIterator &other) const
389    {
390        return it_ == other.it_;
391    }
392    bool
393    operator != (const ConstDirectIterator &other) const
394    {
395        return it_ != other.it_;
396    }
397    bool
398    operator <= (const ConstDirectIterator &other) const
399    {
400        return it_ <= other.it_;
401    }
402    bool
403    operator >= (const ConstDirectIterator &other) const
404    {
405        return it_ >= other.it_;
406    }
407    bool
408    operator < (const ConstDirectIterator &other) const
409    {
410        return it_ < other.it_;
411    }
412    bool
413    operator > (const ConstDirectIterator &other) const
414    {
415        return it_ > other.it_;
416    }
417
418    reference
419    operator * () const
420    {
421        return *Policy::get(static_cast<ElementType *>((void *)*it_));
422    }
423    pointer
424    operator -> () const
425    {
426        return Policy::get(static_cast<ElementType *>((void *)*it_));
427    }
428    reference
429    operator [] (difference_type n) const
430    {
431        return *Policy::get(static_cast<ElementType *>((void *)it_[n]));
432    }
433
434    difference_type
435    operator - (ConstDirectIterator const &other) const
436    {
437        return it_ - other.it_;
438    }
439};
440
441template <typename T>
442class sc_vector : public sc_vector_base
443{
444  public:
445    using sc_vector_base::size_type;
446    typedef sc_vector_iter<T> iterator;
447    typedef sc_vector_iter<const T> const_iterator;
448
449    sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {}
450    explicit sc_vector(const char *_name) : sc_vector_base(_name) {}
451    sc_vector(const char *_name, size_type _size) : sc_vector_base(_name)
452    {
453        init(_size);
454    }
455    template <typename Creator>
456    sc_vector(const char *_name, size_type _size, Creator creator) :
457        sc_vector_base(_name)
458    {
459        init(_size, creator);
460    }
461    virtual ~sc_vector() { clear(); }
462
463    void
464    init(size_type _size)
465    {
466        init(_size, &sc_vector<T>::create_element);
467    }
468    static T *
469    create_element(const char *_name, size_type index)
470    {
471        return new T(_name);
472    }
473
474    template <typename Creator>
475    void
476    init(size_type _size, Creator creator)
477    {
478        forceParent();
479        try {
480            for (size_type i = 0; i < _size; i++) {
481                // XXX The name and scope of these objects needs to be handled
482                // specially.
483                T *p = creator(sc_gen_unique_name(basename()), i);
484                objs.push_back(p);
485            }
486        } catch (...) {
487            unforceParent();
488            clear();
489            throw;
490        }
491        unforceParent();
492    }
493
494    T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); }
495    const T &
496    operator [] (size_type index) const
497    {
498        return *static_cast<const T *>(objs[index]);
499    }
500
501    T &
502    at(size_type index)
503    {
504        this->checkIndex(index);
505        return *static_cast<T *>(objs[index]);
506    }
507    const T &
508    at(size_type index) const
509    {
510        this->checkIndex(index);
511        return *static_cast<const T *>(objs[index]);
512    }
513
514    iterator begin() { return objs.begin(); }
515    iterator end() { return objs.end(); }
516    const_iterator begin() const { return objs.begin(); }
517    const_iterator end() const { return objs.end(); }
518    const_iterator cbegin() const { return objs.begin(); }
519    const_iterator cend() const { return objs.end(); }
520
521    template <typename ContainerType, typename ArgumentType>
522    iterator
523    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
524    {
525        return bind(c.begin(), c.end());
526    }
527
528    template <typename BindableContainer>
529    iterator
530    bind(BindableContainer &c)
531    {
532        return bind(c.begin(), c.end());
533    }
534
535    template <typename BindableIterator>
536    iterator
537    bind(BindableIterator first, BindableIterator last)
538    {
539        return bind(first, last, this->begin());
540    }
541
542    template <typename BindableIterator>
543    iterator
544    bind(BindableIterator first, BindableIterator last, iterator from)
545    {
546        if (!size() || from == end() || first == last)
547            reportEmpty(kind(), from == end());
548
549        while (from != end() && first != last)
550            (*from++).bind(*first++);
551        return from;
552    }
553
554    template <typename ContainerType, typename ArgumentType>
555    iterator
556    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
557    {
558        return (*this)(c.begin(), c.end());
559    }
560
561    template <typename ArgumentContainer>
562    iterator
563    operator () (ArgumentContainer &c)
564    {
565        return (*this)(c.begin(), c.end());
566    }
567
568    template <typename ArgumentIterator>
569    iterator
570    operator () (ArgumentIterator first, ArgumentIterator last)
571    {
572        return (*this)(first, last, this->begin());
573    }
574
575    template <typename ArgumentIterator>
576    iterator
577    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
578    {
579        if (!size() || from == end() || first == last)
580            reportEmpty(kind(), from == end());
581
582        while (from != end() && first != last)
583            (*from++)(*first++);
584        return from;
585    }
586
587  private:
588    // Disabled
589    sc_vector(const sc_vector &);
590    sc_vector &operator = (const sc_vector &);
591
592    void
593    clear()
594    {
595        for (auto obj: objs)
596            delete static_cast<T *>(obj);
597    }
598
599    template <typename, typename>
600    friend class sc_vector_assembly;
601
602    sc_object *
603    objectCast(void *ptr) const
604    {
605        return implicitCast(static_cast<T *>(ptr));
606    }
607};
608
609template <typename T, typename MT>
610class sc_vector_assembly
611{
612  public:
613    friend sc_vector_assembly<T, MT> sc_assemble_vector<>(
614            sc_vector<T> &, MT (T::*));
615
616    typedef size_t size_type;
617    typedef sc_vector_iter<T, sc_member_access<T, MT> > iterator;
618    typedef sc_vector_iter<
619        const T, sc_member_access<const T, const MT> > const_iterator;
620    typedef MT (T::*MemberType);
621
622    sc_vector_assembly(const sc_vector_assembly &other) :
623        vec_(other.vec_), ptr_(other.ptr_)
624    {}
625
626    iterator begin() { return iterator(vec_->begin().it_, ptr_); }
627    iterator end() { return iterator(vec_->end().it_, ptr_); }
628
629    const_iterator
630    cbegin() const
631    {
632        return const_iterator(vec_->begin().it_, ptr_);
633    }
634    const_iterator
635    cend() const
636    {
637        return const_iterator(vec_->end().it_, ptr_);
638    }
639
640    const_iterator
641    begin() const
642    {
643        return const_iterator(vec_->begin().it_, ptr_);
644    }
645    const_iterator
646    end() const
647    {
648        return const_iterator(vec_->end().it_, ptr_);
649    }
650
651    size_type size() const { return vec_->size(); }
652
653    std::vector<sc_object *>
654    get_elements() const
655    {
656        std::vector<sc_object *> ret;
657        for (const_iterator it = begin(); it != end(); it++) {
658            sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it));
659
660            if (obj_ptr)
661                ret.push_back(obj_ptr);
662        }
663        return ret;
664    }
665
666    typename iterator::reference
667    operator [] (size_type i)
668    {
669        return (*vec_)[i].*ptr_;
670    }
671    typename const_iterator::reference
672    operator [] (size_type i) const
673    {
674        return (*vec_)[i].*ptr_;
675    }
676
677    typename iterator::reference
678    at(size_type i)
679    {
680        return vec_->at(i).*ptr_;
681    }
682    typename const_iterator::reference
683    at(size_type i) const
684    {
685        return vec_->at(i).*ptr_;
686    }
687
688    template <typename ContainerType, typename ArgumentType>
689    iterator
690    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
691    {
692        return bind(c.begin(), c.end());
693    }
694
695    template <typename BindableContainer>
696    iterator
697    bind(BindableContainer &c)
698    {
699        return bind(c.begin(), c.end());
700    }
701
702    template <typename BindableIterator>
703    iterator
704    bind(BindableIterator first, BindableIterator last)
705    {
706        return bind(first, last, this->begin());
707    }
708
709    template <typename BindableIterator>
710    iterator
711    bind(BindableIterator first, BindableIterator last, iterator from)
712    {
713        if (!size() || from == end() || first == last)
714            vec_->reportEmpty("sc_vector_assembly", from == end());
715
716        while (from != end() && first != last)
717            (*from++).bind(*first++);
718        return from;
719    }
720
721    template <typename BindableIterator>
722    iterator
723    bind(BindableIterator first, BindableIterator last,
724            typename sc_vector<T>::iterator from)
725    {
726        return bind(first, last, iterator(from.it_, ptr_));
727    }
728
729    template <typename ContainerType, typename ArgumentType>
730    iterator
731    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
732    {
733        return (*this)(c.begin(), c.end());
734    }
735
736    template <typename ArgumentContainer>
737    iterator
738    operator () (ArgumentContainer &c)
739    {
740        return (*this)(c.begin(), c.end());
741    }
742
743    template <typename ArgumentIterator>
744    iterator
745    operator () (ArgumentIterator first, ArgumentIterator last)
746    {
747        return (*this)(first, last, this->begin());
748    }
749
750    template <typename ArgumentIterator>
751    iterator
752    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
753    {
754        if (!size() || from == end() || first == last)
755            vec_->reportEmpty("sc_vector_assembly", from == end());
756
757        while (from != end() && first != last)
758            (*from++)(*first++);
759        return from;
760    }
761
762    template <typename ArgumentIterator>
763    iterator
764    operator () (ArgumentIterator first, ArgumentIterator last,
765                 typename sc_vector<T>::iterator from)
766    {
767        return (*this)(first, last, iterator(from.it_, ptr_));
768    }
769
770  private:
771    sc_vector_assembly(sc_vector<T> &v, MemberType ptr) :
772        vec_(&v), ptr_(ptr)
773    {}
774
775    sc_vector<T> *vec_;
776    MemberType ptr_;
777};
778
779template <typename T, typename MT>
780sc_vector_assembly<T, MT>
781sc_assemble_vector(sc_vector<T> &v, MT (T::*ptr))
782{
783    return sc_vector_assembly<T, MT>(v, ptr);
784}
785
786} // namespace sc_core
787
788#endif  //__SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
789