diff options
Diffstat (limited to 'ext/systemc/src/sysc/utils/sc_vector.h')
-rw-r--r-- | ext/systemc/src/sysc/utils/sc_vector.h | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/utils/sc_vector.h b/ext/systemc/src/sysc/utils/sc_vector.h new file mode 100644 index 000000000..2afbaf45e --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_vector.h @@ -0,0 +1,724 @@ +/***************************************************************************** + + 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! |