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 {
185 SC_REPORT_ERROR(
186 "(E808) sc_vector::get_elements called for element type "
187 "not derived from sc_object", name());
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 &) : sc_vector_base() {}
590 sc_vector &operator = (const sc_vector &) { return *this; }
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__