Changeset 65 for sources/src/sc_signal.h


Ignore:
Timestamp:
Oct 23, 2019, 12:53:07 PM (5 years ago)
Author:
bouyer
Message:

Various performance improvements for the parallel systemcass: cache-aligned
data structures, write only when needed, disable some unneeded barriers.

Fix bug in the non-openmp case: a pointer was not initialized

various style updates

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sources/src/sc_signal.h

    r63 r65  
    1616
    1717// Define registers writing method
     18#include <string.h>
    1819#include <iostream>
    1920#include <cstdlib>
     
    6869// Pending write to register (simple stack)
    6970typedef pending_write_t * pending_write_vector_t;
    70 extern "C" int32_t * pending_write_vector_nb;
     71extern "C" int32_t *pending_write_vector_nb;
    7172extern "C" unsigned long long int total_assig;
    7273#ifdef _OPENMP
    73 #pragma omp threadprivate(pending_write_vector_nb, total_assig)
     74#pragma omp threadprivate (pending_write_vector_nb,total_assig)
    7475#endif
    7576extern unsigned int pending_write_vector_capacity;
     77
    7678extern pending_write_vector_t pending_write_vector;
    7779#ifdef _OPENMP
    78 #pragma omp threadprivate(pending_write_vector)
    79 #endif
    80 
    81 template < typename T >
    82 inline void post_write(base_type * const pointer_, const T & value_) /*INLINE*/;
     80#pragma omp threadprivate (pending_write_vector)
     81#endif
     82
     83template <typename T>
     84inline void post_write (base_type *const pointer_,
     85                        const T          value_) /*INLINE*/;
    8386
    8487template < typename T >
     
    9396
    9497template < typename T >
    95 inline void post_write(base_type * const pointer_, const T & value_) {
     98inline void post_write(base_type * const pointer_, const T value_) {
    9699    if (sizeof(T) > sizeof(base_type)) {
    97100        post_multiwrite(pointer_, value_);
     
    105108            exit(-1);
    106109        }
    107 #endif
    108         pending_write_vector[*pending_write_vector_nb].pointer = pointer_;
    109         // pending_write_vector[(*pending_write_vector_nb)++].value = *(reinterpret_cast<const base_type*const>(&value_)); => bug !
    110         pending_write_vector[(*pending_write_vector_nb)++].value = value_; // => bug avec blues !
    111 
    112         // -> fix to use user-defined struct in sc_signal/sc_in/sc_out/sc_inout
    113         // pending_write_vector[(*pending_write_vector_nb)++].value = *((base_type*)&value_); => bug !
     110#endif // CONFIG_DEBUG
     111        sc_core::pending_write_vector[*pending_write_vector_nb].pointer = pointer_;
     112        sc_core::pending_write_vector[(*pending_write_vector_nb)++].value = value_;
     113
    114114#if 0
    115115        std::cerr << "posted write : ptr = " << pointer_ << ", val = " << value_ << "\n";
     
    124124}
    125125
    126 
    127 inline bool is_posted_write() {
    128     return *pending_write_vector_nb > 0;
     126inline bool is_posted_write ()
     127{
     128  return *pending_write_vector_nb > 0;
    129129}
    130130
     
    165165};
    166166
    167 
    168 template < typename T >
    169 class sc_signal : public sc_signal_base {
    170 
    171     private:
    172 
    173     T val;
    174     T new_val;
    175     typedef T data_type;
    176     typedef sc_signal < T > this_type;
    177 
    178 
    179     ///////////
    180     // Internal
    181     public:
    182     void init();
    183     ///////////
    184 
    185     void check_writer();
    186 
    187     public:
    188     // constructors, destructor
    189     sc_signal() {
    190         if (typeid(data_type) == typeid(double) || typeid(data_type) == typeid(float)) {
    191             std::cerr << "Error: SystemCASS does not support sc_signal<T> with T of type " << typeid(data_type).name() << std::endl;
    192             exit(1);
    193         }
    194         init();
    195     }
    196 
    197     explicit sc_signal(const char * name_) : sc_signal_base(name_) {
    198         init();
    199     }
    200 
    201     /*virtual*/ ~sc_signal() {}
    202     /*virtual*/ inline const data_type & read() const INLINE;
    203     /*virtual*/ inline void write(const data_type &) /*INLINE*/;
    204 
    205     inline operator const data_type & () const { return this->read(); }
    206 
    207     inline this_type & operator = (const data_type & a) {
    208         sc_signal< T >::write(a);
    209         return *this;
    210     }
    211 
    212     inline this_type & operator = (const sc_signal < T > & a) {
    213         sc_signal< T >::write(a.read());
    214         return *this;
    215     }
    216 
    217     inline this_type & operator += (const data_type & a) {
    218         sc_signal< T >::write(read() + a);
    219         return *this;
    220     }
    221 
    222     inline this_type & operator += (const sc_signal < T > & a) {
    223         sc_signal< T >::write(read() + a.read());
    224         return *this;
    225     }
    226 
    227     inline void * operator new (size_t size, size_t align) {
    228         void * p;
    229         const size_t nsize = (size + align - 1) & ~(align - 1);
    230         if (nsize < size) {
    231             std::cerr << "sc_signal new() alignement doesn't work (" <<
    232                 nsize << " < " << size << ")" << std::endl;
    233             abort();
    234         }
    235 
    236         if (posix_memalign(&p, align, nsize) == 0) {
    237             return p;
    238         }
    239         else {
    240             return NULL;
    241         }
    242     }
    243 
    244     inline void * operator new (size_t size) {
    245         return malloc(size);
    246     }
    247 
    248     inline void * operator new (size_t size, void * p) {
    249         return p;
    250     }
    251 
    252     const data_type & get_new_value() const {
    253         // Warning: untested and doesn't support variable size
    254         unsigned int i = 0;
    255         for (i = 0; i < pending_write_vector_capacity; i++) {
    256             if (pending_write_vector[i].pointer == get_pointer()) {
    257                 return pending_write_vector[i].value;
    258             }
    259         }
    260         return val;
    261     }
    262 
    263     //  void trace (sc_trace_file * tf) const;
    264     /*
    265     virtual void print(std::ostream & o) const { o << *this; }
    266     virtual void dump(std::ostream & o) const { o << *this; }
    267     */
    268 
    269     private:
    270     // disabled
    271     sc_signal(const sc_signal < T > &);
     167template <typename T>
     168class sc_signal : public sc_signal_base
     169{
     170private:
     171  T val;
     172  T new_val;
     173  typedef T                data_type;
     174  typedef sc_signal < T >  this_type;
     175
     176  ///////////
     177  // Internal
     178public: void init ();
     179  ///////////
     180
     181  //  virtual void update ();
     182  void check_writer ();
     183public:
     184  // constructors, destructor
     185  sc_signal ()
     186  { init (); }
     187  explicit sc_signal (const char *name_): sc_signal_base(name_)
     188  { init (); }
     189  /*virtual */~ sc_signal ()
     190  {}
     191  // methods
     192  /*
     193  virtual void register_port (sc_port_base &, const char *)
     194  {}
     195  virtual const sc_event & default_event () const
     196  {}
     197  virtual const sc_event & value_changed_event () const
     198  {}
     199  */
     200  /*virtual*/ inline const data_type & read () const INLINE;
     201/*
     202  virtual const T & get_data_ref () const
     203  {}
     204  virtual bool event () const
     205  {}
     206  */
     207  /*virtual*/ inline void write (const data_type &) /*INLINE*/;
     208  inline operator const data_type & () const
     209  { return this->read(); }
     210  inline this_type& operator = (const data_type & a)
     211  { sc_signal<T>::write (a); return *this; }
     212  inline this_type& operator = (const sc_signal < T > &a)
     213  { sc_signal<T>::write (a.read()); return *this; }
     214  inline this_type& operator += (const data_type & a)
     215  { sc_signal<T>::write (read() + a); return *this; }
     216  inline this_type& operator += (const sc_signal < T > &a)
     217  { sc_signal<T>::write (read()+a.read()); return *this; }
     218  inline void * operator new (size_t size, size_t align)
     219  {
     220    void *p;
     221    const size_t nsize = (size + align - 1) & ~(align -1);
     222    if (nsize < size) {
     223        std::cerr << "sc_signal new() alignement doesn't work (" <<
     224            nsize << " < " << size << ")" << std::endl;
     225        abort();
     226    }
     227
     228    if (posix_memalign(&p, align, nsize) == 0)
     229        return p;
     230    else
     231        return NULL;
     232  }
     233  inline void * operator new (size_t size)
     234  {
     235    return malloc(size);
     236  }
     237  inline void * operator new (size_t size, void *p)
     238  {
     239    return p;
     240  }
     241
     242  const data_type & get_new_value () const;
     243//  void trace (sc_trace_file * tf) const;
     244  /*
     245        virtual void print (std::ostream &o) const
     246  { o << *this; }
     247  virtual void dump (std::ostream &o) const
     248  { o << *this; }
     249        */
     250private:
     251  // disabled
     252  sc_signal (const sc_signal < T > &);
    272253
    273254};
    274255
    275 
    276 template < typename T >
    277 void sc_signal< T >::init() {
    278     set_pointer((tab_t *) (void *) &val);
    279     set_kind(kind_string);
    280     sc_interface::init(sizeof(data_type));
     256template <typename T>
     257void
     258sc_signal<T>::init()
     259{
     260        set_pointer ((tab_t*)(void*)&val);
     261  set_kind    (kind_string);
     262  sc_interface::init (sizeof (data_type));
    281263#if 0
    282     val = (T) 0; /* The simulator initializes the signal/register to 0.    */
    283                  /* However, hardware initialization still has to be done. */
    284                  /* This kind of initialization is for trace diffing.      */
     264  val = 0; /* The simulator initializes the signal/register to 0.    */
     265           /* However, hardware initialization still has to be done. */
     266           /* This kind of initialization is for trace diffing.      */
    285267#else
    286     memset(&val, 0, sizeof(val));
    287     memset(&new_val, 0, sizeof(new_val));
    288 #endif
    289 }
    290 
     268   memset(&val, 0, sizeof(val));
     269   memset(&new_val, 0, sizeof(new_val));
     270#endif
     271}
    291272
    292273// read the value
     
    307288        return;
    308289    }
     290  if (sc_signal<T>::val == value_ && sc_signal<T>::new_val == value_)
     291    return;
    309292#ifdef CONFIG_DEBUG
    310293    if (get_pointer() == NULL) {
     
    319302    std::cerr << "write (posted) " << value_ << " on sc_signal (writing into register) '" << name() << "'\n";
    320303#endif
    321     sc_signal<T>::new_val = value_;
    322     post_write(/*(tab_t*)&val*/ get_pointer(), value_);
     304  sc_signal<T>::new_val = value_;
     305  post_write (/*(tab_t*)&val*/ get_pointer(), value_);
    323306}
    324307
Note: See TracChangeset for help on using the changeset viewer.