| /***************************************************************************** | |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or | |
| more contributor license agreements. See the NOTICE file distributed | |
| with this work for additional information regarding copyright ownership. | |
| Accellera licenses this file to you under the Apache License, Version 2.0 | |
| (the "License"); you may not use this file except in compliance with the | |
| License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| implied. See the License for the specific language governing | |
| permissions and limitations under the License. | |
| *****************************************************************************/ | |
| /***************************************************************************** | |
| sc_vector.h - A vector of named (SystemC) objects (modules, ports, channels) | |
| Original Author: Philipp A. Hartmann, OFFIS | |
| CHANGE LOG AT END OF FILE | |
| *****************************************************************************/ | |
| #ifndef SC_VECTOR_H_INCLUDED_ | |
| #define SC_VECTOR_H_INCLUDED_ | |
| #include <vector> | |
| #include <iterator> | |
| #include <string> | |
| #include <algorithm> // std::swap | |
| #include "sysc/kernel/sc_object.h" | |
| #include <type_traits> | |
| //#define SC_VECTOR_HEADER_ONLY_ | |
| namespace sc_core { | |
| namespace sc_meta { | |
| using ::std::enable_if; | |
| using ::std::remove_const; | |
| using ::std::is_same; | |
| using ::std::is_const; | |
| template< typename CT, typename T > | |
| struct is_more_const { | |
| static constexpr bool value | |
| = ( is_same< typename remove_const<CT>::type | |
| , typename remove_const<T>::type | |
| >::value | |
| && ( is_const<CT>::value >= is_const<T>::value ) ); | |
| }; | |
| } // namespace sc_meta | |
| // forward declarations | |
| template< typename T > class sc_vector; | |
| template< typename T, typename MT > class sc_vector_assembly; | |
| template< typename T, typename MT > class sc_vector_iter; | |
| // implementation-defined | |
| template< typename Container, typename ArgumentIterator > | |
| typename Container::iterator | |
| sc_vector_do_bind( Container & cont | |
| , ArgumentIterator first | |
| , ArgumentIterator last | |
| , typename Container::iterator from ); | |
| // implementation-defined | |
| template< typename Container, typename ArgumentIterator > | |
| typename Container::iterator | |
| sc_vector_do_operator_paren( Container & cont | |
| , ArgumentIterator first | |
| , ArgumentIterator last | |
| , typename Container::iterator from ); | |
| class sc_vector_base | |
| : public sc_object | |
| { | |
| template<typename,typename> friend class sc_vector_assembly; | |
| template<typename,typename> friend class sc_vector_iter; | |
| public: | |
| typedef std::vector< void* > storage_type; | |
| typedef storage_type::size_type size_type; | |
| typedef storage_type::difference_type difference_type; | |
| const char * kind() const { return "sc_vector"; } | |
| std::vector<sc_object*> const & get_elements() const; | |
| size_type size() const | |
| { return vec_.size(); } | |
| protected: | |
| // begin implementation defined | |
| typedef storage_type::iterator iterator; | |
| typedef storage_type::const_iterator const_iterator; | |
| sc_vector_base(); | |
| sc_vector_base( const char* prefix ) | |
| : sc_object( prefix ) | |
| , vec_() | |
| , objs_vec_(0) | |
| {} | |
| ~sc_vector_base() | |
| { delete objs_vec_; } | |
| void * & at( size_type i ) | |
| { return vec_[i]; } | |
| void const * at( size_type i ) const | |
| { return vec_[i]; } | |
| void reserve( size_type n ) | |
| { vec_.reserve(n); } | |
| void clear() | |
| { vec_.clear(); } | |
| void push_back( void* item ) | |
| { vec_.push_back(item); } | |
| void check_index( size_type i ) const; | |
| bool check_init( size_type n ) const; | |
| static std::string make_name( const char* prefix, size_type index ); | |
| iterator begin() { return vec_.begin(); } | |
| iterator end() { return vec_.end(); } | |
| const_iterator begin() const { return vec_.begin(); } | |
| const_iterator end() const { return vec_.end(); } | |
| virtual sc_object* object_cast( void* ) const = 0; | |
| sc_object* implicit_cast( sc_object* p ) const { return p; } | |
| sc_object* implicit_cast( ... /* incompatible */ ) const; | |
| public: | |
| void report_empty_bind( const char* kind_, bool dst_range_ ) const; | |
| private: | |
| storage_type vec_; | |
| mutable std::vector< sc_object* >* objs_vec_; | |
| // disabled | |
| sc_vector_base( const sc_vector_base& ); | |
| sc_vector_base& operator=( const sc_vector_base& ); | |
| }; // sc_vector_base | |
| // iterator access adapters | |
| template< typename ElementType > | |
| struct sc_direct_access | |
| { | |
| typedef ElementType element_type; | |
| typedef element_type type; | |
| typedef typename sc_meta::remove_const<type>::type plain_type; | |
| typedef sc_direct_access< type > policy; | |
| typedef sc_direct_access< plain_type > non_const_policy; | |
| typedef sc_direct_access< const plain_type > const_policy; | |
| sc_direct_access(){} | |
| sc_direct_access( const non_const_policy& ) {} | |
| // convert from any policy to (const) direct policy | |
| template <typename U> | |
| sc_direct_access(const U&, | |
| typename sc_meta::enable_if<sc_meta::is_more_const< | |
| type, | |
| typename U::policy::element_type>::value>::type* = NULL) | |
| {} | |
| type* get( type* this_ ) const | |
| { return this_; } | |
| }; | |
| // iterator access adapters | |
| template< typename ElementType | |
| , typename AccessType > | |
| class sc_member_access | |
| { | |
| public: | |
| template< typename, typename > friend class sc_member_access; | |
| typedef ElementType element_type; | |
| typedef AccessType access_type; | |
| typedef access_type (ElementType::*member_type); | |
| typedef access_type type; | |
| typedef typename sc_meta::remove_const<type>::type plain_type; | |
| typedef typename sc_meta::remove_const<ElementType>::type plain_elem_type; | |
| typedef sc_member_access< element_type, access_type > policy; | |
| typedef sc_member_access< plain_elem_type, plain_type > | |
| non_const_policy; | |
| typedef sc_member_access< const plain_elem_type, const plain_type > | |
| const_policy; | |
| sc_member_access( member_type ptr ) | |
| : ptr_(ptr) {} | |
| sc_member_access( const non_const_policy& other ) | |
| : ptr_(other.ptr_) | |
| {} | |
| access_type * get( element_type* this_ ) const | |
| { return &(this_->*ptr_); } | |
| private: | |
| member_type ptr_; | |
| }; // sc_member_access | |
| template< typename ElementType | |
| , typename AccessPolicy = sc_direct_access<ElementType> > | |
| class sc_vector_iter | |
| : public std::iterator< std::random_access_iterator_tag | |
| , typename AccessPolicy::type > | |
| , private AccessPolicy | |
| { | |
| typedef ElementType element_type; | |
| typedef typename AccessPolicy::policy access_policy; | |
| typedef typename AccessPolicy::non_const_policy non_const_policy; | |
| typedef typename AccessPolicy::const_policy const_policy; | |
| typedef typename access_policy::type access_type; | |
| typedef typename sc_meta::remove_const<ElementType>::type plain_type; | |
| typedef const plain_type const_plain_type; | |
| friend class sc_vector< plain_type >; | |
| template< typename, typename > friend class sc_vector_assembly; | |
| template< typename, typename > friend class sc_vector_iter; | |
| typedef std::iterator< std::random_access_iterator_tag, access_type > base_type; | |
| typedef sc_vector_iter this_type; | |
| typedef sc_vector<plain_type> vector_type; | |
| typedef sc_vector_base::storage_type storage_type; | |
| // select correct base-type iterator | |
| template< typename U > struct select_iter | |
| { typedef typename storage_type::iterator type; }; | |
| template< typename U > struct select_iter< const U > | |
| { typedef typename storage_type::const_iterator type; }; | |
| typedef typename select_iter<ElementType>::type raw_iterator; | |
| typedef sc_vector_iter< const_plain_type, const_policy > const_iterator; | |
| // underlying vector iterator | |
| raw_iterator it_; | |
| sc_vector_iter( raw_iterator it, access_policy acc = access_policy() ) | |
| : access_policy(acc), it_(it) {} | |
| access_policy const & get_policy() const { return *this; } | |
| public: | |
| // interface for Random Access Iterator category, | |
| // see ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements] | |
| typedef typename base_type::difference_type difference_type; | |
| typedef typename base_type::reference reference; | |
| typedef typename base_type::pointer pointer; | |
| sc_vector_iter() : access_policy(), it_() {} | |
| // iterator conversions to more const, and/or direct iterators | |
| template< typename OtherElement, typename OtherPolicy > | |
| sc_vector_iter( const sc_vector_iter<OtherElement, OtherPolicy>& it | |
| , typename sc_meta::enable_if<sc_meta::is_more_const< | |
| element_type, | |
| typename OtherPolicy::element_type>::value>::type* = NULL) | |
| : access_policy( it.get_policy() ), it_( it.it_ ) | |
| {} | |
| // step | |
| this_type& operator++(){ ++it_; return *this; } | |
| this_type& operator--(){ --it_; return *this; } | |
| this_type operator++(int){ this_type old(*this); ++it_; return old; } | |
| this_type operator--(int){ this_type old(*this); --it_; return old; } | |
| // advance | |
| this_type operator+( difference_type n ) const | |
| { return this_type( it_ + n, get_policy()); } | |
| this_type operator-( difference_type n ) const | |
| { return this_type( it_ - n, get_policy()); } | |
| this_type& operator+=( difference_type n ) { it_+=n; return *this; } | |
| this_type& operator-=( difference_type n ) { it_-=n; return *this; } | |
| // relations | |
| bool operator== ( const this_type& that ) const { return it_ == that.it_; } | |
| bool operator!= ( const this_type& that ) const { return it_ != that.it_; } | |
| bool operator<= ( const this_type& that ) const { return it_ <= that.it_; } | |
| bool operator>= ( const this_type& that ) const { return it_ >= that.it_; } | |
| bool operator< ( const this_type& that ) const { return it_ < that.it_; } | |
| bool operator> ( const this_type& that ) const { return it_ > that.it_; } | |
| // dereference | |
| reference operator*() const | |
| { return *access_policy::get( static_cast<element_type*>(*it_) ); } | |
| pointer operator->() const | |
| { return access_policy::get( static_cast<element_type*>(*it_) ); } | |
| reference operator[]( difference_type n ) const | |
| { return *access_policy::get( static_cast<element_type*>(it_[n]) ); } | |
| // distance | |
| difference_type operator-( this_type const& that ) const | |
| { return it_-that.it_; } | |
| }; // sc_vector_iter | |
| template< typename T > | |
| class sc_vector | |
| : public sc_vector_base | |
| { | |
| typedef sc_vector_base base_type; | |
| typedef sc_vector<T> this_type; | |
| public: | |
| typedef T element_type; | |
| typedef sc_vector_iter< element_type > iterator; | |
| typedef sc_vector_iter< const element_type > const_iterator; | |
| sc_vector(){} | |
| explicit sc_vector( const char* prefix ) | |
| : base_type( prefix ) | |
| {} | |
| explicit sc_vector( const char* prefix, size_type n ) | |
| : base_type( prefix ) | |
| { init(n); } | |
| template< typename Creator > | |
| sc_vector( const char* prefix, size_type n, Creator creator ) | |
| : base_type( prefix ) | |
| { | |
| init( n, creator ); | |
| } | |
| virtual ~sc_vector(); | |
| element_type& operator[]( size_type i ) | |
| { return *static_cast<element_type*>( base_type::at(i) ); } | |
| element_type& at( size_type i ) | |
| { check_index(i); return (*this)[i]; } | |
| const element_type& operator[]( size_type i ) const | |
| { return *static_cast<element_type const *>( base_type::at(i) ); } | |
| const element_type& at( size_type i ) const | |
| { check_index(i); return (*this)[i]; } | |
| void init( size_type n ) | |
| { init( n, &this_type::create_element ); } | |
| template< typename Creator > | |
| void init( size_type n, Creator c ); | |
| static element_type * create_element( const char* prefix, size_type index ); | |
| iterator begin() { return base_type::begin(); } | |
| iterator end() { return base_type::end(); } | |
| const_iterator begin() const { return base_type::begin(); } | |
| const_iterator end() const { return base_type::end(); } | |
| const_iterator cbegin() const { return base_type::begin(); } | |
| const_iterator cend() const { return base_type::end(); } | |
| template< typename ContainerType, typename ArgumentType > | |
| iterator bind( sc_vector_assembly<ContainerType,ArgumentType> c ) | |
| { return bind( c.begin(), c.end() ); } | |
| template< typename BindableContainer > | |
| iterator bind( BindableContainer & c ) | |
| { return bind( c.begin(), c.end() ); } | |
| template< typename BindableIterator > | |
| iterator bind( BindableIterator first, BindableIterator last ) | |
| { return bind( first, last, this->begin() ); } | |
| template< typename BindableIterator > | |
| iterator bind( BindableIterator first, BindableIterator last | |
| , iterator from ) | |
| { return sc_vector_do_bind( *this, first, last, from ); } | |
| template< typename ContainerType, typename ArgumentType > | |
| iterator operator()( sc_vector_assembly<ContainerType,ArgumentType> c ) | |
| { return operator()( c.begin(), c.end() ); } | |
| template< typename ArgumentContainer > | |
| iterator operator()( ArgumentContainer & c ) | |
| { return operator()( c.begin(), c.end() ); } | |
| template< typename ArgumentIterator > | |
| iterator operator()( ArgumentIterator first, ArgumentIterator last ) | |
| { return operator()( first, last, this->begin() ); } | |
| template< typename ArgumentIterator > | |
| iterator operator()( ArgumentIterator first, ArgumentIterator last | |
| , iterator from ) | |
| { return sc_vector_do_operator_paren( *this, first, last, from ); } | |
| // member-wise access | |
| template< typename MT > | |
| sc_vector_assembly<T,MT> assemble( MT (T::*member_ptr) ) | |
| { return sc_vector_assembly<T,MT>( *this, member_ptr ); } | |
| protected: | |
| void clear(); | |
| virtual sc_object* object_cast( void* p ) const | |
| { return implicit_cast( static_cast<element_type*>(p) ); } | |
| }; | |
| template< typename T, typename MT > | |
| class sc_vector_assembly | |
| { | |
| template< typename U > friend class sc_vector; | |
| public: | |
| typedef sc_vector<T> base_type; | |
| typedef sc_vector_iter< T, sc_member_access<T, MT> > iterator; | |
| typedef sc_vector_iter< const T | |
| , sc_member_access<const T, const MT> > const_iterator; | |
| typedef T element_type; | |
| typedef MT access_type; | |
| typedef typename base_type::size_type size_type; | |
| typedef typename base_type::difference_type difference_type; | |
| typedef typename iterator::reference reference; | |
| typedef typename iterator::pointer pointer; | |
| typedef typename const_iterator::reference const_reference; | |
| typedef typename const_iterator::pointer const_pointer; | |
| typedef access_type (T::*member_type); | |
| const char* name() const { return vec_->name(); } | |
| const char* kind() const { return "sc_vector_assembly"; } | |
| iterator begin() | |
| { return iterator( (*vec_).begin().it_, ptr_ ); } | |
| iterator end() | |
| { return iterator( (*vec_).end().it_, ptr_ ); } | |
| const_iterator cbegin() const | |
| { return const_iterator( (*vec_).cbegin().it_, ptr_ ); } | |
| const_iterator cend() const | |
| { return const_iterator( (*vec_).cend().it_, ptr_ ); } | |
| const_iterator begin() const | |
| { return const_iterator( (*vec_).begin().it_, ptr_ ); } | |
| const_iterator end() const | |
| { return const_iterator( (*vec_).end().it_, ptr_ ); } | |
| size_type size() const { return vec_->size(); } | |
| const std::vector< sc_object* > & get_elements() const; | |
| reference operator[]( size_type idx ) | |
| { return (*vec_)[idx].*ptr_; } | |
| reference at( size_type idx ) | |
| { return vec_->at(idx).*ptr_; } | |
| const_reference operator[]( size_type idx ) const | |
| { return (*vec_)[idx].*ptr_; } | |
| const_reference at( size_type idx ) const | |
| { return vec_->at(idx).*ptr_; } | |
| template< typename ContainerType, typename ArgumentType > | |
| iterator bind( sc_vector_assembly<ContainerType,ArgumentType> c ) | |
| { return bind( c.begin(), c.end() ); } | |
| template< typename BindableContainer > | |
| iterator bind( BindableContainer & c ) | |
| { return bind( c.begin(), c.end() ); } | |
| template< typename BindableIterator > | |
| iterator bind( BindableIterator first, BindableIterator last ) | |
| { return bind( first, last, this->begin() ); } | |
| template< typename BindableIterator > | |
| iterator bind( BindableIterator first, BindableIterator last | |
| , iterator from ) | |
| { return sc_vector_do_bind( *this, first, last, from ); } | |
| template< typename BindableIterator > | |
| iterator bind( BindableIterator first, BindableIterator last | |
| , typename base_type::iterator from ) | |
| { return bind( first, last, iterator(from.it_, ptr_) ); } | |
| template< typename ContainerType, typename ArgumentType > | |
| iterator operator()( sc_vector_assembly<ContainerType,ArgumentType> c ) | |
| { return operator()( c.begin(), c.end() ); } | |
| template< typename ArgumentContainer > | |
| iterator operator()( ArgumentContainer & c ) | |
| { return operator()( c.begin(), c.end() ); } | |
| template< typename ArgumentIterator > | |
| iterator operator()( ArgumentIterator first, ArgumentIterator last ) | |
| { return operator()( first, last, this->begin() ); } | |
| template< typename ArgumentIterator > | |
| iterator operator()( ArgumentIterator first, ArgumentIterator last | |
| , iterator from ) | |
| { return sc_vector_do_operator_paren( *this, first, last, from ); } | |
| template< typename ArgumentIterator > | |
| iterator operator()( ArgumentIterator first, ArgumentIterator last | |
| , typename base_type::iterator from ) | |
| { return operator()( first, last, iterator(from.it_, ptr_) ); } | |
| sc_vector_assembly( const sc_vector_assembly & other ) | |
| : vec_( other.vec_ ) | |
| , ptr_( other.ptr_ ) | |
| , child_vec_(0) | |
| {} | |
| sc_vector_assembly& operator=( sc_vector_assembly other_copy ) | |
| { | |
| swap( other_copy ); | |
| return *this; | |
| } | |
| void swap( sc_vector_assembly & that ) | |
| { | |
| using std::swap; | |
| swap( vec_, that.vec_ ); | |
| swap( ptr_, that.ptr_ ); | |
| swap( child_vec_, that.child_vec_ ); | |
| } | |
| void report_empty_bind( const char* kind_, bool dst_empty_ ) const | |
| { vec_->report_empty_bind( kind_, dst_empty_ ); } | |
| ~sc_vector_assembly() | |
| { delete child_vec_; } | |
| private: | |
| sc_vector_assembly( base_type & v, member_type ptr ) | |
| : vec_(&v) | |
| , ptr_(ptr) | |
| , child_vec_(0) | |
| {} | |
| sc_object* object_cast( pointer p ) const | |
| { return vec_->implicit_cast( p ); } | |
| base_type * vec_; | |
| member_type ptr_; | |
| mutable std::vector< sc_object* >* child_vec_; | |
| }; | |
| template< typename T, typename MT > | |
| sc_vector_assembly<T,MT> | |
| sc_assemble_vector( sc_vector<T> & vec, MT (T::*ptr) ) | |
| { | |
| return vec.assemble( ptr ); | |
| } | |
| template< typename T > | |
| typename sc_vector<T>::element_type * | |
| sc_vector<T>::create_element( const char* name, size_type /* idx */ ) | |
| { | |
| return new T( name ); | |
| } | |
| template< typename T > | |
| template< typename Creator > | |
| void | |
| sc_vector<T>::init( size_type n, Creator c ) | |
| { | |
| if ( base_type::check_init(n) ) | |
| { | |
| base_type::reserve( n ); | |
| try | |
| { | |
| for ( size_type i = 0; i<n; ++i ) | |
| { | |
| // this workaround is needed for SystemC 2.2/2.3 sc_bind | |
| std::string name = make_name( basename(), i ); | |
| const char* cname = name.c_str(); | |
| void* p = c( cname, i ) ; // call Creator | |
| base_type::push_back(p); | |
| } | |
| } | |
| catch ( ... ) | |
| { | |
| clear(); | |
| throw; | |
| } | |
| } | |
| } | |
| template< typename T > | |
| void | |
| sc_vector<T>::clear() | |
| { | |
| size_type i = size(); | |
| while ( i --> 0 ) | |
| { | |
| delete &( (*this)[i] ); | |
| base_type::at(i) = 0; | |
| } | |
| base_type::clear(); | |
| } | |
| template< typename Container, typename ArgumentIterator > | |
| typename Container::iterator | |
| sc_vector_do_bind( Container & cont | |
| , ArgumentIterator first | |
| , ArgumentIterator last | |
| , typename Container::iterator from ) | |
| { | |
| typename Container::iterator end = cont.end(); | |
| if( !cont.size() || from == end || first == last ) | |
| cont.report_empty_bind( cont.kind(), from == end ); | |
| while( from!=end && first != last ) | |
| (*from++).bind( *first++ ); | |
| return from; | |
| } | |
| template< typename Container, typename ArgumentIterator > | |
| typename Container::iterator | |
| sc_vector_do_operator_paren( Container& cont | |
| , ArgumentIterator first | |
| , ArgumentIterator last | |
| , typename Container::iterator from ) | |
| { | |
| typename Container::iterator end = cont.end(); | |
| if( !cont.size() || from == end || first == last ) | |
| cont.report_empty_bind( cont.kind(), from == end ); | |
| while( from!=end && first != last ) | |
| (*from++)( *first++ ); | |
| return from; | |
| } | |
| template< typename T > | |
| sc_vector<T>::~sc_vector() | |
| { | |
| clear(); | |
| } | |
| template< typename T, typename MT > | |
| std::vector< sc_object* > const & | |
| sc_vector_assembly<T,MT>::get_elements() const | |
| { | |
| if( !child_vec_ ) | |
| child_vec_ = new std::vector< sc_object* >; | |
| if( child_vec_->size() || !size() ) | |
| return *child_vec_; | |
| child_vec_->reserve( size() ); | |
| for( const_iterator it=begin(); it != end(); ++it ) | |
| if( sc_object * obj = object_cast( const_cast<MT*>(&*it) ) ) | |
| child_vec_->push_back( obj ); | |
| return *child_vec_; | |
| } | |
| } // namespace sc_core | |
| #undef SC_RPTYPE_ | |
| #undef SC_ENABLE_IF_ | |
| // $Log: sc_vector.h,v $ | |
| // Revision 1.17 2011/08/26 20:46:20 acg | |
| // Andy Goodrich: moved the modification log to the end of the file to | |
| // eliminate source line number skew when check-ins are done. | |
| // | |
| // Revision 1.16 2011/07/25 10:21:17 acg | |
| // Andy Goodrich: check in aftermath of call to automake. | |
| // | |
| // Revision 1.15 2011/04/02 00:04:32 acg | |
| // Philipp A. Hartmann: fix distance from member iterators, and | |
| // add iterator conversions. | |
| // | |
| // Revision 1.14 2011/04/01 22:35:19 acg | |
| // Andy Goodrich: spelling fix. | |
| // | |
| // Revision 1.13 2011/03/28 13:03:09 acg | |
| // Andy Goodrich: Philipp's latest update. | |
| // | |
| // Revision 1.12 2011/03/23 16:16:28 acg | |
| // Philipp A. Hartmann: rebase implementation on void* | |
| // - supports virtual inheritance from sc_object again | |
| // - build up get_elements result on demand | |
| // - still requires element type to be derived from sc_object | |
| // | |
| // Revision 1.11 2011/02/19 16:46:36 acg | |
| // Andy Goodrich: finally get the update from Philipp correct! | |
| // | |
| #endif // SC_VECTOR_H_INCLUDED_ | |
| // Taf! |