source: sources/src/sc_signal.h @ 62

Last change on this file since 62 was 62, checked in by meunier, 7 years ago
  • Functional (or supposedly functional) OpenMP support configure must be run with --enable-use-omp and the topcell must define the USE_OPENMP flag before including the .h files of systemcass (if openmp enabled).
File size: 9.5 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 <iostream>
19#include <cstdlib>
20#include <cstring>
21#include <typeinfo> // for typeid
22
23#include "sc_fwd.h"
24#include "sc_nbdefs.h"
25#include "sc_time.h" // SC_ZERO_TIME
26#include "sc_object.h"
27#include "sc_interface.h"
28#include "internal_ext.h"
29
30namespace sc_core {
31
32//
33#if ((__GNUC__ < 3) || (__GNUC_MINOR__ < 4))
34    #define INLINE __attribute__((always_inline))
35#else
36    /* gcc3.4 doesn't support */ 
37    #define INLINE
38#endif
39
40
41#define READ_SIGNAL(value_type_,pointer_) \
42    ((value_type_ &) (*((value_type_ *) (pointer_))))
43
44///////////////////// DEPRECATED
45// C ANSI-only since it is needed to link with extern "C"
46
47extern void bind(sc_port_base &, sc_port_base &);
48extern void bind(sc_port_base &, sc_signal_base &);
49extern void bind(sc_signal_base & x);
50extern void bind(sc_port_base & x);
51
52typedef tab_t base_type;
53
54struct pending_write_t {
55    base_type * pointer;
56    base_type value;
57   
58    friend std::ostream & operator << (std::ostream & o, const pending_write_t & p) {
59        return o << "(pointer = " << p.pointer << "; value = " << p.value << ")\n";
60    }
61};
62
63
64// Check pending_writing to register
65extern void pending_writing2register_clear();
66extern void pending_writing2register_record_and_check(const tab_t *);
67
68// Pending write to register (simple stack)
69typedef pending_write_t * pending_write_vector_t;
70extern "C" int32_t * pending_write_vector_nb;
71extern "C" unsigned long long int total_assig;
72#ifdef USE_OPENMP
73#pragma omp threadprivate(pending_write_vector_nb, total_assig)
74#endif
75extern unsigned int pending_write_vector_capacity;
76extern pending_write_vector_t pending_write_vector;
77#ifdef USE_OPENMP
78#pragma omp threadprivate(pending_write_vector)
79#endif
80
81template < typename T >
82inline void post_write(base_type * const pointer_, const T & value_) /*INLINE*/;
83
84template < typename T >
85inline void post_multiwrite(base_type * const pointer_, const T & value_) {
86    size_t size = (sizeof(T) - 1) / sizeof(base_type);
87    size_t i = 0;
88    const base_type * pvalue = (const base_type *) (void *) (&value_);
89    do {
90        post_write(pointer_ + i, pvalue[i]);
91    } while (i++ < size);
92}
93
94template < typename T >
95inline void post_write(base_type * const pointer_, const T & value_) {
96    if (sizeof(T) > sizeof(base_type)) {
97        post_multiwrite(pointer_, value_);
98    }
99    else {
100#if defined(CONFIG_DEBUG)
101        if (*pending_write_vector_nb >= pending_write_vector_capacity) {
102            std::cerr << "Error : The array for posted writing on register is too small.\n";
103            std::cerr << "Up to 1 writing per register is allowed during a cycle.\n";
104            std::cerr << "Please check the hardware description.\n";
105            exit(-1);
106        }
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 !
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
126
127inline bool is_posted_write() {
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
167
168template < typename T >
169class 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 > &);
272
273};
274
275
276template < typename T >
277void sc_signal< T >::init() {
278    set_pointer((tab_t *) (void *) &val);
279    set_kind(kind_string);
280    sc_interface::init(sizeof(data_type)); 
281#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.      */
285#else
286    memset(&val, 0, sizeof(val));
287    memset(&new_val, 0, sizeof(new_val));
288#endif
289}
290
291
292// read the value
293template < typename T >
294/*virtual*/ inline const T & sc_signal< T >::read() const {
295#ifdef DUMP_READ
296    std::cerr << "read " << READ_SIGNAL(const data_type, get_pointer()) << " on signal " << name() << "\n";
297#endif
298    // QM
299    return READ_SIGNAL(T, get_pointer());
300}
301
302
303// write the new value
304template < typename T >
305inline void sc_signal< T >::write(const data_type & value_) {
306    if (sc_signal< T >::val == value_ && sc_signal< T >::new_val == value_) {
307        return;
308    }
309#ifdef CONFIG_DEBUG
310    if (get_pointer() == NULL) {
311        std::cerr << "Error : Unable to write into '" << name() << "'.";
312        exit(24032005);
313    }
314#endif
315#ifdef DUMP_WRITE
316    if (sc_signal< T >::read() == value_) {
317        return;
318    }
319    std::cerr << "write (posted) " << value_ << " on sc_signal (writing into register) '" << name() << "'\n";
320#endif
321    sc_signal<T>::new_val = value_;
322    post_write(/*(tab_t*)&val*/ get_pointer(), value_);
323}
324
325#undef INLINE
326#undef READ_SIGNAL
327
328
329} // end of namespace sc_core
330
331#endif /* __SC_SIGNAL_H__ */
332
333/*
334# Local Variables:
335# tab-width: 4;
336# c-basic-offset: 4;
337# c-file-offsets:((innamespace . 0)(inline-open . 0));
338# indent-tabs-mode: nil;
339# End:
340#
341# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
342*/
343
Note: See TracBrowser for help on using the repository browser.