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
Line 
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\------------------------------------------------------------*/
13
14#ifndef __SC_SIGNAL_H__
15#define __SC_SIGNAL_H__
16
17// Define registers writing method
18#include <string.h>
19#include <iostream>
20#include <cstdlib>
21#include <cstring>
22#include <typeinfo> // for typeid
23
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
31namespace sc_core {
32
33//
34#if ((__GNUC__ < 3) || (__GNUC_MINOR__ < 4))
35    #define INLINE __attribute__((always_inline))
36#else
37    /* gcc3.4 doesn't support */ 
38    #define INLINE
39#endif
40
41
42#define READ_SIGNAL(value_type_,pointer_) \
43    ((value_type_ &) (*((value_type_ *) (pointer_))))
44
45///////////////////// DEPRECATED
46// C ANSI-only since it is needed to link with extern "C"
47
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
53typedef tab_t base_type;
54
55struct pending_write_t {
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    }
62};
63
64
65// Check pending_writing to register
66extern void pending_writing2register_clear();
67extern void pending_writing2register_record_and_check(const tab_t *);
68
69// Pending write to register (simple stack)
70typedef pending_write_t * pending_write_vector_t;
71extern "C" int32_t *pending_write_vector_nb;
72extern "C" unsigned long long int total_assig;
73#ifdef _OPENMP
74#pragma omp threadprivate (pending_write_vector_nb,total_assig)
75#endif
76extern unsigned int pending_write_vector_capacity;
77
78extern pending_write_vector_t pending_write_vector;
79#ifdef _OPENMP
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*/;
86
87template < typename T >
88inline void post_multiwrite(base_type * const pointer_, const T & value_) {
89    size_t size = (sizeof(T) - 1) / sizeof(base_type);
90    size_t i = 0;
91    const base_type * pvalue = (const base_type *) (void *) (&value_);
92    do {
93        post_write(pointer_ + i, pvalue[i]);
94    } while (i++ < size);
95}
96
97template < typename T >
98inline void post_write(base_type * const pointer_, const T value_) {
99    if (sizeof(T) > sizeof(base_type)) {
100        post_multiwrite(pointer_, value_);
101    }
102    else {
103#if defined(CONFIG_DEBUG)
104        if (*pending_write_vector_nb >= pending_write_vector_capacity) {
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        }
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
114#if 0
115        std::cerr << "posted write : ptr = " << pointer_ << ", val = " << value_ << "\n";
116#endif
117#if 0 
118        // introduce bug on using trace functions
119        if (value_ == READ_SIGNAL(T,pointer_)) {
120            return;
121        }
122#endif
123    }
124}
125
126inline bool is_posted_write ()
127{
128  return *pending_write_vector_nb > 0;
129}
130
131
132extern "C" void update(void);
133
134
135// ----------------------------------------------------------------------------
136//  CLASS : sc_signal_base
137//
138//  The sc_signal_base<T> primitive channel class.
139// ----------------------------------------------------------------------------
140
141class sc_signal_base : public sc_object, public sc_interface {
142
143    //////
144    // Internal
145    friend class sc_clock;
146    friend class sc_port_base;
147    void init();
148    //////
149
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
165};
166
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 > &);
253
254};
255
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)); 
263#if 0
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.      */
267#else
268   memset(&val, 0, sizeof(val));
269   memset(&new_val, 0, sizeof(new_val));
270#endif
271}
272
273// read the value
274template < typename T >
275/*virtual*/ inline const T & sc_signal< T >::read() const {
276#ifdef DUMP_READ
277    std::cerr << "read " << READ_SIGNAL(const data_type, get_pointer()) << " on signal " << name() << "\n";
278#endif
279    // QM
280    return READ_SIGNAL(T, get_pointer());
281}
282
283
284// write the new value
285template < typename T >
286inline void sc_signal< T >::write(const data_type & value_) {
287    if (sc_signal< T >::val == value_ && sc_signal< T >::new_val == value_) {
288        return;
289    }
290  if (sc_signal<T>::val == value_ && sc_signal<T>::new_val == value_)
291    return;
292#ifdef CONFIG_DEBUG
293    if (get_pointer() == NULL) {
294        std::cerr << "Error : Unable to write into '" << name() << "'.";
295        exit(24032005);
296    }
297#endif
298#ifdef DUMP_WRITE
299    if (sc_signal< T >::read() == value_) {
300        return;
301    }
302    std::cerr << "write (posted) " << value_ << " on sc_signal (writing into register) '" << name() << "'\n";
303#endif
304  sc_signal<T>::new_val = value_;
305  post_write (/*(tab_t*)&val*/ get_pointer(), value_);
306}
307
308#undef INLINE
309#undef READ_SIGNAL
310
311
312} // end of namespace sc_core
313
314#endif /* __SC_SIGNAL_H__ */
315
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.