sc_vector.hh revision 13271
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