source: sources/src/sc_signal.h @ 65

Last change on this file since 65 was 65, checked in by bouyer, 5 years ago

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 size: 8.7 KB
RevLine 
[1]1/*------------------------------------------------------------\
2|                                                             |
3| Tool    :                  systemcass                       |
4|                                                             |
5| File    :                   sc_signal.h                     |
6|                                                             |
7| Author  :                 Buchmann Richard                  |
8|                           Taktak Sami                       |
9|                                                             |
10| Date    :                   09_07_2004                      |
11|                                                             |
12\------------------------------------------------------------*/
[52]13
[1]14#ifndef __SC_SIGNAL_H__
15#define __SC_SIGNAL_H__
16
17// Define registers writing method
[65]18#include <string.h>
[27]19#include <iostream>
20#include <cstdlib>
[60]21#include <cstring>
[59]22#include <typeinfo> // for typeid
[52]23
[27]24#include "sc_fwd.h"
25#include "sc_nbdefs.h"
26#include "sc_time.h" // SC_ZERO_TIME
27#include "sc_object.h"
28#include "sc_interface.h"
29#include "internal_ext.h"
30
[1]31namespace sc_core {
32
33//
34#if ((__GNUC__ < 3) || (__GNUC_MINOR__ < 4))
[52]35    #define INLINE __attribute__((always_inline))
[1]36#else
[52]37    /* gcc3.4 doesn't support */ 
38    #define INLINE
[1]39#endif
40
[52]41
[1]42#define READ_SIGNAL(value_type_,pointer_) \
[52]43    ((value_type_ &) (*((value_type_ *) (pointer_))))
[1]44
[52]45///////////////////// DEPRECATED
[1]46// C ANSI-only since it is needed to link with extern "C"
47
[52]48extern void bind(sc_port_base &, sc_port_base &);
49extern void bind(sc_port_base &, sc_signal_base &);
50extern void bind(sc_signal_base & x);
51extern void bind(sc_port_base & x);
52
[1]53typedef tab_t base_type;
[52]54
[32]55struct pending_write_t {
[52]56    base_type * pointer;
57    base_type value;
58   
59    friend std::ostream & operator << (std::ostream & o, const pending_write_t & p) {
60        return o << "(pointer = " << p.pointer << "; value = " << p.value << ")\n";
61    }
[1]62};
63
[52]64
[1]65// Check pending_writing to register
[52]66extern void pending_writing2register_clear();
67extern void pending_writing2register_record_and_check(const tab_t *);
[1]68
69// Pending write to register (simple stack)
[52]70typedef pending_write_t * pending_write_vector_t;
[65]71extern "C" int32_t *pending_write_vector_nb;
[60]72extern "C" unsigned long long int total_assig;
[63]73#ifdef _OPENMP
[65]74#pragma omp threadprivate (pending_write_vector_nb,total_assig)
[62]75#endif
[1]76extern unsigned int pending_write_vector_capacity;
[65]77
[60]78extern pending_write_vector_t pending_write_vector;
[63]79#ifdef _OPENMP
[65]80#pragma omp threadprivate (pending_write_vector)
[62]81#endif
[1]82
[65]83template <typename T>
84inline void post_write (base_type *const pointer_,
85                        const T          value_) /*INLINE*/;
[52]86
87template < typename T >
[59]88inline void post_multiwrite(base_type * const pointer_, const T & value_) {
[52]89    size_t size = (sizeof(T) - 1) / sizeof(base_type);
90    size_t i = 0;
[59]91    const base_type * pvalue = (const base_type *) (void *) (&value_);
[52]92    do {
93        post_write(pointer_ + i, pvalue[i]);
94    } while (i++ < size);
[1]95}
[52]96
97template < typename T >
[65]98inline void post_write(base_type * const pointer_, const T value_) {
[52]99    if (sizeof(T) > sizeof(base_type)) {
[59]100        post_multiwrite(pointer_, value_);
[52]101    }
102    else {
103#if defined(CONFIG_DEBUG)
[60]104        if (*pending_write_vector_nb >= pending_write_vector_capacity) {
[52]105            std::cerr << "Error : The array for posted writing on register is too small.\n";
106            std::cerr << "Up to 1 writing per register is allowed during a cycle.\n";
107            std::cerr << "Please check the hardware description.\n";
108            exit(-1);
109        }
[65]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_;
[1]113
114#if 0
[52]115        std::cerr << "posted write : ptr = " << pointer_ << ", val = " << value_ << "\n";
[1]116#endif
117#if 0 
[52]118        // introduce bug on using trace functions
119        if (value_ == READ_SIGNAL(T,pointer_)) {
120            return;
121        }
[1]122#endif
[52]123    }
[1]124}
125
[65]126inline bool is_posted_write ()
127{
128  return *pending_write_vector_nb > 0;
[1]129}
130
131
[52]132extern "C" void update(void);
133
134
[1]135// ----------------------------------------------------------------------------
136//  CLASS : sc_signal_base
137//
138//  The sc_signal_base<T> primitive channel class.
139// ----------------------------------------------------------------------------
140
[52]141class sc_signal_base : public sc_object, public sc_interface {
[1]142
[52]143    //////
144    // Internal
145    friend class sc_clock;
146    friend class sc_port_base;
147    void init();
148    //////
[1]149
[52]150
151    public: 
152    // LRM (?)
153    //virtual const sc_event /*&*/ default_event() const;
154    static const char * const kind_string;
155    //virtual const char * kind() const;
156
157   
158
159    public:
160    sc_signal_base();
161    sc_signal_base(const char * name_);
162    sc_signal_base(const char * name_, void *);
163    ~sc_signal_base();
164
[1]165};
166
[65]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;
[22]175
[65]176  ///////////
177  // Internal
178public: void init ();
179  ///////////
[22]180
[65]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();
[52]226    }
227
[65]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  }
[52]241
[65]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 > &);
[52]253
[1]254};
255
[65]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)); 
[60]263#if 0
[65]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.      */
[60]267#else
[65]268   memset(&val, 0, sizeof(val));
269   memset(&new_val, 0, sizeof(new_val));
[60]270#endif
[1]271}
[52]272
[1]273// read the value
[52]274template < typename T >
275/*virtual*/ inline const T & sc_signal< T >::read() const {
[1]276#ifdef DUMP_READ
[59]277    std::cerr << "read " << READ_SIGNAL(const data_type, get_pointer()) << " on signal " << name() << "\n";
[1]278#endif
[59]279    // QM
280    return READ_SIGNAL(T, get_pointer());
[1]281}
282
[52]283
[1]284// write the new value
[52]285template < typename T >
286inline void sc_signal< T >::write(const data_type & value_) {
[60]287    if (sc_signal< T >::val == value_ && sc_signal< T >::new_val == value_) {
288        return;
289    }
[65]290  if (sc_signal<T>::val == value_ && sc_signal<T>::new_val == value_)
291    return;
[27]292#ifdef CONFIG_DEBUG
[52]293    if (get_pointer() == NULL) {
294        std::cerr << "Error : Unable to write into '" << name() << "'.";
295        exit(24032005);
296    }
[1]297#endif
298#ifdef DUMP_WRITE
[52]299    if (sc_signal< T >::read() == value_) {
300        return;
301    }
302    std::cerr << "write (posted) " << value_ << " on sc_signal (writing into register) '" << name() << "'\n";
[1]303#endif
[65]304  sc_signal<T>::new_val = value_;
305  post_write (/*(tab_t*)&val*/ get_pointer(), value_);
[1]306}
307
308#undef INLINE
309#undef READ_SIGNAL
310
[52]311
[1]312} // end of namespace sc_core
313
314#endif /* __SC_SIGNAL_H__ */
315
[52]316/*
317# Local Variables:
318# tab-width: 4;
319# c-basic-offset: 4;
320# c-file-offsets:((innamespace . 0)(inline-open . 0));
321# indent-tabs-mode: nil;
322# End:
323#
324# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
325*/
326
Note: See TracBrowser for help on using the repository browser.