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