Deleted Added
sdiff udiff text old ( 13271:f001f9287ba3 ) new ( 13322:7391057615bd )
full compact
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__