source: sources/src/sc_signal.h @ 64

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

Remplace USE_OPENMP with _OPENMP, the latter is automagically defined
by the compiler.

File size: 9.5 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
[27]18#include <iostream>
19#include <cstdlib>
[60]20#include <cstring>
[59]21#include <typeinfo> // for typeid
[52]22
[27]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
[1]30namespace sc_core {
31
32//
33#if ((__GNUC__ < 3) || (__GNUC_MINOR__ < 4))
[52]34    #define INLINE __attribute__((always_inline))
[1]35#else
[52]36    /* gcc3.4 doesn't support */ 
37    #define INLINE
[1]38#endif
39
[52]40
[1]41#define READ_SIGNAL(value_type_,pointer_) \
[52]42    ((value_type_ &) (*((value_type_ *) (pointer_))))
[1]43
[52]44///////////////////// DEPRECATED
[1]45// C ANSI-only since it is needed to link with extern "C"
46
[52]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
[1]52typedef tab_t base_type;
[52]53
[32]54struct pending_write_t {
[52]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    }
[1]61};
62
[52]63
[1]64// Check pending_writing to register
[52]65extern void pending_writing2register_clear();
66extern void pending_writing2register_record_and_check(const tab_t *);
[1]67
68// Pending write to register (simple stack)
[52]69typedef pending_write_t * pending_write_vector_t;
[60]70extern "C" int32_t * pending_write_vector_nb;
71extern "C" unsigned long long int total_assig;
[63]72#ifdef _OPENMP
[60]73#pragma omp threadprivate(pending_write_vector_nb, total_assig)
[62]74#endif
[1]75extern unsigned int pending_write_vector_capacity;
[60]76extern pending_write_vector_t pending_write_vector;
[63]77#ifdef _OPENMP
[60]78#pragma omp threadprivate(pending_write_vector)
[62]79#endif
[1]80
[52]81template < typename T >
[59]82inline void post_write(base_type * const pointer_, const T & value_) /*INLINE*/;
[52]83
84template < typename T >
[59]85inline void post_multiwrite(base_type * const pointer_, const T & value_) {
[52]86    size_t size = (sizeof(T) - 1) / sizeof(base_type);
87    size_t i = 0;
[59]88    const base_type * pvalue = (const base_type *) (void *) (&value_);
[52]89    do {
90        post_write(pointer_ + i, pvalue[i]);
91    } while (i++ < size);
[1]92}
[52]93
94template < typename T >
[59]95inline void post_write(base_type * const pointer_, const T & value_) {
[52]96    if (sizeof(T) > sizeof(base_type)) {
[59]97        post_multiwrite(pointer_, value_);
[52]98    }
99    else {
100#if defined(CONFIG_DEBUG)
[60]101        if (*pending_write_vector_nb >= pending_write_vector_capacity) {
[52]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        }
[1]107#endif
[60]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 !
[1]111
[52]112        // -> fix to use user-defined struct in sc_signal/sc_in/sc_out/sc_inout
[60]113        // pending_write_vector[(*pending_write_vector_nb)++].value = *((base_type*)&value_); => bug !
[1]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
[52]126
127inline bool is_posted_write() {
[60]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
[22]167
[52]168template < typename T >
169class sc_signal : public sc_signal_base {
[22]170
[52]171    private:
[59]172
[52]173    T val;
[60]174    T new_val;
[52]175    typedef T data_type;
176    typedef sc_signal < T > this_type;
[1]177
[52]178
179    ///////////
180    // Internal
181    public:
182    void init();
183    ///////////
184
185    void check_writer();
186
187    public:
188    // constructors, destructor
189    sc_signal() {
[59]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        }
[52]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
[60]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
[59]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    }
[52]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
[1]273};
274
[52]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)); 
[60]281#if 0
[59]282    val = (T) 0; /* The simulator initializes the signal/register to 0.    */
[60]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));
[62]287    memset(&new_val, 0, sizeof(new_val));
[60]288#endif
[1]289}
[52]290
291
[1]292// read the value
[52]293template < typename T >
294/*virtual*/ inline const T & sc_signal< T >::read() const {
[1]295#ifdef DUMP_READ
[59]296    std::cerr << "read " << READ_SIGNAL(const data_type, get_pointer()) << " on signal " << name() << "\n";
[1]297#endif
[59]298    // QM
299    return READ_SIGNAL(T, get_pointer());
[1]300}
301
[52]302
[1]303// write the new value
[52]304template < typename T >
305inline void sc_signal< T >::write(const data_type & value_) {
[60]306    if (sc_signal< T >::val == value_ && sc_signal< T >::new_val == value_) {
307        return;
308    }
[27]309#ifdef CONFIG_DEBUG
[52]310    if (get_pointer() == NULL) {
311        std::cerr << "Error : Unable to write into '" << name() << "'.";
312        exit(24032005);
313    }
[1]314#endif
315#ifdef DUMP_WRITE
[52]316    if (sc_signal< T >::read() == value_) {
317        return;
318    }
319    std::cerr << "write (posted) " << value_ << " on sc_signal (writing into register) '" << name() << "'\n";
[1]320#endif
[60]321    sc_signal<T>::new_val = value_;
[52]322    post_write(/*(tab_t*)&val*/ get_pointer(), value_);
[1]323}
324
325#undef INLINE
326#undef READ_SIGNAL
327
[52]328
[1]329} // end of namespace sc_core
330
331#endif /* __SC_SIGNAL_H__ */
332
[52]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.