1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_signal.h -- The sc_signal<T> primitive channel class.
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG IS AT THE END OF THE FILE
27 *****************************************************************************/
28
29#ifndef SC_SIGNAL_H
30#define SC_SIGNAL_H
31
32#include "sysc/communication/sc_port.h"
33#include "sysc/communication/sc_prim_channel.h"
34#include "sysc/communication/sc_signal_ifs.h"
35#include "sysc/communication/sc_writer_policy.h"
36#include "sysc/kernel/sc_event.h"
37#include "sysc/kernel/sc_process.h"
38#include "sysc/kernel/sc_simcontext.h"
39#include "sysc/datatypes/bit/sc_logic.h"
40#include "sysc/tracing/sc_trace.h"
41#include <typeinfo>
42
43namespace sc_core {
44
45// to avoid code bloat in sc_signal<T>
46
47extern void sc_deprecated_get_data_ref();
48extern void sc_deprecated_get_new_value();
49extern void sc_deprecated_trace();
50extern sc_event * sc_lazy_kernel_event( sc_event**, const char* name );
51
52inline
53bool
54sc_writer_policy_check_write::check_write( sc_object* target, bool )
55{
56  sc_object* writer_p = sc_get_curr_simcontext()->get_current_writer();
57  if( SC_UNLIKELY_(m_writer_p == 0) ) {
58       m_writer_p = writer_p;
59  } else if( SC_UNLIKELY_(m_writer_p != writer_p && writer_p != 0) ) {
60       sc_signal_invalid_writer( target, m_writer_p, writer_p, m_check_delta );
61       // error has been suppressed, ignore check as well
62       // return false;
63  }
64  return true;
65}
66
67// ----------------------------------------------------------------------------
68//  CLASS : sc_signal<T>
69//
70//  The sc_signal<T> primitive channel class.
71// ----------------------------------------------------------------------------
72
73template< class T, sc_writer_policy POL /* = SC_DEFAULT_WRITER_POLICY */ >
74class sc_signal
75  : public    sc_signal_inout_if<T>
76  , public    sc_prim_channel
77  , protected sc_writer_policy_check<POL>
78{
79protected:
80    typedef sc_signal_inout_if<T>       if_type;
81    typedef sc_signal<T,POL>            this_type;
82    typedef sc_writer_policy_check<POL> policy_type;
83
84public: // constructors and destructor:
85
86    sc_signal()
87	: sc_prim_channel( sc_gen_unique_name( "signal" ) ),
88	  m_change_event_p( 0 ), m_cur_val( T() ),
89	  m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() )
90	{}
91
92    explicit sc_signal( const char* name_)
93	: sc_prim_channel( name_ ),
94	  m_change_event_p( 0 ), m_cur_val( T() ),
95	  m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() )
96    {}
97
98    sc_signal( const char* name_, const T& initial_value_ )
99      : sc_prim_channel( name_ )
100      , m_change_event_p( 0 )
101      , m_cur_val( initial_value_ )
102      , m_change_stamp( ~sc_dt::UINT64_ONE )
103      , m_new_val( initial_value_ )
104    {}
105
106    virtual ~sc_signal()
107	{
108	    delete m_change_event_p;
109	}
110
111
112    // interface methods
113
114    virtual void register_port( sc_port_base&, const char* );
115
116    virtual sc_writer_policy get_writer_policy() const
117      { return POL; }
118
119    // get the default event
120    virtual const sc_event& default_event() const
121      { return value_changed_event(); }
122
123    // get the value changed event
124    virtual const sc_event& value_changed_event() const
125    {
126        return *sc_lazy_kernel_event( &m_change_event_p
127                                    , "value_changed_event");
128    }
129
130
131    // read the current value
132    virtual const T& read() const
133	{ return m_cur_val; }
134
135    // get a reference to the current value (for tracing)
136    virtual const T& get_data_ref() const
137        { sc_deprecated_get_data_ref(); return m_cur_val; }
138
139
140    // was there an event?
141    virtual bool event() const
142        { return simcontext()->event_occurred(m_change_stamp); }
143
144    // write the new value
145    virtual void write( const T& );
146
147
148    // other methods
149
150    operator const T& () const
151	{ return read(); }
152
153
154    this_type& operator = ( const T& a )
155	{ write( a ); return *this; }
156
157    this_type& operator = ( const sc_signal_in_if<T>& a )
158	{ write( a.read() ); return *this; }
159
160    this_type& operator = ( const this_type& a )
161	{ write( a.read() ); return *this; }
162
163
164    const T& get_new_value() const
165        { sc_deprecated_get_new_value(); return m_new_val; }
166
167
168    void trace( sc_trace_file* tf ) const
169	{
170	    sc_deprecated_trace();
171#           ifdef DEBUG_SYSTEMC
172	        sc_trace( tf, read(), name() );
173#           else
174                if ( tf ) {}
175#	    endif
176	}
177
178
179    virtual void print( ::std::ostream& = ::std::cout ) const;
180    virtual void dump( ::std::ostream& = ::std::cout ) const;
181
182    virtual const char* kind() const
183        { return "sc_signal"; }
184
185protected:
186
187    virtual void update();
188            void do_update();
189
190protected:
191
192    mutable sc_event*  m_change_event_p;
193    T                  m_cur_val;
194    sc_dt::uint64      m_change_stamp;   // delta of last event
195    T                  m_new_val;
196
197private:
198
199    // disabled
200    sc_signal( const this_type& );
201};
202
203
204// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
205
206
207template< class T, sc_writer_policy POL >
208inline
209void
210sc_signal<T,POL>::register_port( sc_port_base& port_
211                               , const char* if_typename_ )
212{
213
214    bool is_output = std::string( if_typename_ ) == typeid(if_type).name();
215    if( !policy_type::check_port( this, &port_, is_output ) )
216       ((void)0); // fallback? error has been suppressed ...
217}
218
219
220// write the new value
221
222template< class T, sc_writer_policy POL >
223inline
224void
225sc_signal<T,POL>::write( const T& value_ )
226{
227    bool value_changed = !( m_cur_val == value_ );
228    if ( !policy_type::check_write(this, value_changed) )
229        return;
230
231    m_new_val = value_;
232    if( value_changed ) {
233        request_update();
234    }
235}
236
237
238template< class T, sc_writer_policy POL >
239inline
240void
241sc_signal<T,POL>::print( ::std::ostream& os ) const
242{
243    os << m_cur_val;
244}
245
246template< class T, sc_writer_policy POL >
247void
248sc_signal<T,POL>::dump( ::std::ostream& os ) const
249{
250    os << "     name = " << name() << ::std::endl;
251    os << "    value = " << m_cur_val << ::std::endl;
252    os << "new value = " << m_new_val << ::std::endl;
253}
254
255
256template< class T, sc_writer_policy POL >
257void
258sc_signal<T,POL>::update()
259{
260    policy_type::update();
261    if( !( m_new_val == m_cur_val ) ) {
262        do_update();
263    }
264}
265
266template< class T, sc_writer_policy POL >
267void
268sc_signal<T,POL>::do_update()
269{
270    m_cur_val = m_new_val;
271    if ( m_change_event_p ) m_change_event_p->notify_next_delta();
272    m_change_stamp = simcontext()->change_stamp();
273}
274
275// ----------------------------------------------------------------------------
276//  CLASS : sc_signal<bool>
277//
278//  Specialization of sc_signal<T> for type bool.
279// ----------------------------------------------------------------------------
280
281class sc_reset;
282
283template< sc_writer_policy POL >
284class sc_signal<bool,POL>
285  : public    sc_signal_inout_if<bool>
286  , public    sc_prim_channel
287  , protected sc_writer_policy_check<POL>
288{
289protected:
290    typedef sc_signal_inout_if<bool>    if_type;
291    typedef sc_signal<bool,POL>         this_type;
292    typedef sc_writer_policy_check<POL> policy_type;
293
294public: // constructors and destructor:
295
296    sc_signal()
297	: sc_prim_channel( sc_gen_unique_name( "signal" ) ),
298	  m_change_event_p( 0 ),
299          m_cur_val( false ),
300          m_change_stamp( ~sc_dt::UINT64_ONE ),
301	  m_negedge_event_p( 0 ),
302          m_new_val( false ),
303	  m_posedge_event_p( 0 ),
304          m_reset_p( 0 )
305	{}
306
307    explicit sc_signal( const char* name_ )
308	: sc_prim_channel( name_ ),
309	  m_change_event_p( 0 ),
310          m_cur_val( false ),
311          m_change_stamp( ~sc_dt::UINT64_ONE ),
312	  m_negedge_event_p( 0 ),
313          m_new_val( false ),
314	  m_posedge_event_p( 0 ),
315          m_reset_p( 0 )
316	{}
317
318    sc_signal( const char* name_, bool initial_value_ )
319      : sc_prim_channel( name_ )
320      , m_change_event_p( 0 )
321      , m_cur_val( initial_value_ )
322      , m_change_stamp( ~sc_dt::UINT64_ONE )
323      , m_negedge_event_p( 0 )
324      , m_new_val( initial_value_ )
325      , m_posedge_event_p( 0 )
326      , m_reset_p( 0 )
327    {}
328
329    virtual ~sc_signal();
330
331
332    // interface methods
333
334    virtual void register_port( sc_port_base&, const char* );
335
336    virtual sc_writer_policy get_writer_policy() const
337        { return POL; }
338
339    // get the default event
340    virtual const sc_event& default_event() const
341        { return value_changed_event(); }
342
343    // get the value changed event
344    virtual const sc_event& value_changed_event() const;
345
346    // get the positive edge event
347    virtual const sc_event& posedge_event() const;
348
349    // get the negative edge event
350    virtual const sc_event& negedge_event() const;
351
352
353    // read the current value
354    virtual const bool& read() const
355	{ return m_cur_val; }
356
357    // get a reference to the current value (for tracing)
358    virtual const bool& get_data_ref() const
359        { sc_deprecated_get_data_ref(); return m_cur_val; }
360
361
362    // was there a value changed event?
363    virtual bool event() const
364        { return simcontext()->event_occurred(m_change_stamp); }
365
366    // was there a positive edge event?
367    virtual bool posedge() const
368	{ return ( event() && m_cur_val ); }
369
370    // was there a negative edge event?
371    virtual bool negedge() const
372	{ return ( event() && ! m_cur_val ); }
373
374    // write the new value
375    virtual void write( const bool& );
376
377    // other methods
378
379    operator const bool& () const
380	{ return read(); }
381
382
383    this_type& operator = ( const bool& a )
384	{ write( a ); return *this; }
385
386    this_type& operator = ( const sc_signal_in_if<bool>& a )
387	{ write( a.read() ); return *this; }
388
389    this_type& operator = ( const this_type& a )
390	{ write( a.read() ); return *this; }
391
392
393    const bool& get_new_value() const
394	{ sc_deprecated_get_new_value(); return m_new_val; }
395
396
397    void trace( sc_trace_file* tf ) const
398	{
399	    sc_deprecated_trace();
400#           ifdef DEBUG_SYSTEMC
401	        sc_trace( tf, read(), name() );
402#           else
403                if ( tf ) {}
404#           endif
405	}
406
407
408    virtual void print( ::std::ostream& = ::std::cout ) const;
409    virtual void dump( ::std::ostream& = ::std::cout ) const;
410
411    virtual const char* kind() const
412        { return "sc_signal"; }
413
414protected:
415
416    virtual void update();
417            void do_update();
418
419    virtual bool is_clock() const { return false; }
420
421protected:
422    mutable sc_event* m_change_event_p;  // value change event if present.
423    bool              m_cur_val;         // current value of object.
424    sc_dt::uint64     m_change_stamp;    // delta of last event
425    mutable sc_event* m_negedge_event_p; // negative edge event if present.
426    bool              m_new_val;         // next value of object.
427    mutable sc_event* m_posedge_event_p; // positive edge event if present.
428    mutable sc_reset* m_reset_p;         // reset mechanism if present.
429
430private:
431
432    // reset creation
433    virtual sc_reset* is_reset() const;
434
435    // disabled
436    sc_signal( const this_type& );
437};
438
439
440// ----------------------------------------------------------------------------
441//  CLASS : sc_signal<sc_dt::sc_logic>
442//
443//  Specialization of sc_signal<T> for type sc_dt::sc_logic.
444// ----------------------------------------------------------------------------
445
446template< sc_writer_policy POL >
447class sc_signal<sc_dt::sc_logic,POL>
448  : public    sc_signal_inout_if<sc_dt::sc_logic>
449  , public    sc_prim_channel
450  , protected sc_writer_policy_check<POL>
451{
452protected:
453    typedef sc_signal_inout_if<sc_dt::sc_logic> if_type;
454    typedef sc_signal<sc_dt::sc_logic,POL>      this_type;
455    typedef sc_writer_policy_check<POL>         policy_type;
456
457public: // constructors and destructor:
458
459    sc_signal()
460	: sc_prim_channel( sc_gen_unique_name( "signal" ) ),
461	  m_change_event_p( 0 ),
462	  m_cur_val(),
463          m_change_stamp( ~sc_dt::UINT64_ONE ),
464	  m_negedge_event_p( 0 ),
465	  m_new_val(),
466	  m_posedge_event_p( 0 )
467	{}
468
469    explicit sc_signal( const char* name_ )
470	: sc_prim_channel( name_ ),
471	  m_change_event_p( 0 ),
472	  m_cur_val(),
473          m_change_stamp( ~sc_dt::UINT64_ONE ),
474	  m_negedge_event_p( 0 ),
475	  m_new_val(),
476	  m_posedge_event_p( 0 )
477	{}
478
479    sc_signal( const char* name_, sc_dt::sc_logic initial_value_ )
480      : sc_prim_channel( name_ )
481      , m_change_event_p( 0 )
482      , m_cur_val( initial_value_ )
483      , m_change_stamp( ~sc_dt::UINT64_ONE )
484      , m_negedge_event_p( 0 )
485      , m_new_val( initial_value_ )
486      , m_posedge_event_p( 0 )
487    {}
488
489    virtual ~sc_signal()
490	{
491	    delete m_change_event_p;
492	    delete m_negedge_event_p;
493	    delete m_posedge_event_p;
494	}
495
496
497    // interface methods
498
499    virtual void register_port( sc_port_base&, const char* );
500
501    virtual sc_writer_policy get_writer_policy() const
502        { return POL; }
503
504    // get the default event
505    virtual const sc_event& default_event() const
506        { return value_changed_event(); }
507
508    // get the value changed event
509    virtual const sc_event& value_changed_event() const;
510
511    // get the positive edge event
512    virtual const sc_event& posedge_event() const;
513
514    // get the negative edge event
515    virtual const sc_event& negedge_event() const;
516
517
518    // read the current value
519    virtual const sc_dt::sc_logic& read() const
520	{ return m_cur_val; }
521
522    // get a reference to the current value (for tracing)
523    virtual const sc_dt::sc_logic& get_data_ref() const
524        { sc_deprecated_get_data_ref(); return m_cur_val; }
525
526
527    // was there an event?
528    virtual bool event() const
529        { return simcontext()->event_occurred(m_change_stamp); }
530
531    // was there a positive edge event?
532    virtual bool posedge() const
533	{ return ( event() && m_cur_val == sc_dt::SC_LOGIC_1 ); }
534
535    // was there a negative edge event?
536    virtual bool negedge() const
537	{ return ( event() && m_cur_val == sc_dt::SC_LOGIC_0 ); }
538
539
540    // write the new value
541    virtual void write( const sc_dt::sc_logic& );
542
543
544    // other methods
545
546    operator const sc_dt::sc_logic& () const
547	{ return read(); }
548
549
550    this_type& operator = ( const sc_dt::sc_logic& a )
551	{ write( a ); return *this; }
552
553    this_type& operator = ( const sc_signal_in_if<sc_dt::sc_logic>& a )
554	{ write( a.read() ); return *this; }
555
556    this_type& operator = (const this_type& a)
557	{ write( a.read() ); return *this; }
558
559
560    const sc_dt::sc_logic& get_new_value() const
561        { sc_deprecated_get_new_value();  return m_new_val; }
562
563
564    void trace( sc_trace_file* tf ) const
565	{
566	    sc_deprecated_trace();
567#           ifdef DEBUG_SYSTEMC
568	        sc_trace( tf, read(), name() );
569#           else
570                if ( tf ) {}
571#           endif
572	}
573
574    virtual void print( ::std::ostream& = ::std::cout ) const;
575    virtual void dump( ::std::ostream& = ::std::cout ) const;
576
577    virtual const char* kind() const
578        { return "sc_signal"; }
579
580protected:
581
582    virtual void update();
583            void do_update();
584
585protected:
586
587    mutable sc_event* m_change_event_p;  // value change event if present.
588    sc_dt::sc_logic   m_cur_val;         // current value of object.
589    sc_dt::uint64     m_change_stamp;    // delta of last event
590    mutable sc_event* m_negedge_event_p; // negative edge event if present.
591    sc_dt::sc_logic   m_new_val;         // next value of object.
592    mutable sc_event* m_posedge_event_p; // positive edge event if present.
593
594private:
595
596    // disabled
597    sc_signal( const this_type& );
598};
599
600// ----------------------------------------------------------------------------
601
602template< typename T, sc_writer_policy POL >
603inline
604::std::ostream&
605operator << ( ::std::ostream& os, const sc_signal<T,POL>& a )
606{
607    return ( os << a.read() );
608}
609
610
611
612} // namespace sc_core
613
614/*****************************************************************************
615
616  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
617  changes you are making here.
618
619      Name, Affiliation, Date:
620  Description of Modification:
621
622 *****************************************************************************/
623//$Log: sc_signal.h,v $
624//Revision 1.16  2011/08/26 20:45:42  acg
625// Andy Goodrich: moved the modification log to the end of the file to
626// eliminate source line number skew when check-ins are done.
627//
628//Revision 1.15  2011/08/15 16:43:24  acg
629// Torsten Maehne: changes to remove unused argument warnings.
630//
631//Revision 1.14  2011/06/25 17:08:38  acg
632// Andy Goodrich: Jerome Cornet's changes to use libtool to build the
633// library.
634//
635//Revision 1.13  2011/04/13 02:59:09  acg
636// Andy Goodrich: made events internal to signals into kernel events.
637//
638//Revision 1.12  2011/04/08 18:22:46  acg
639// Philipp A. Hartmann: use the context of the primitive channel to get
640// the change stamp value.
641//
642//Revision 1.11  2011/04/05 20:48:09  acg
643// Andy Goodrich: changes to make sure that event(), posedge() and negedge()
644// only return true if the clock has not moved.
645//
646//Revision 1.10  2011/04/05 07:10:55  acg
647// Andy Goodrich: added line that I dropped in sc_signal<sc_dt::sc_logic>.
648//
649//Revision 1.9  2011/04/05 06:15:18  acg
650// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check.
651//
652//Revision 1.8  2011/03/23 16:17:22  acg
653// Andy Goodrich: hide the sc_events that are kernel related.
654//
655//Revision 1.7  2011/03/06 15:55:08  acg
656// Andy Goodrich: Changes for named events.
657//
658//Revision 1.6  2011/02/18 20:23:45  acg
659// Andy Goodrich: Copyright update.
660//
661//Revision 1.5  2011/02/07 19:16:50  acg
662// Andy Goodrich: changes for handling multiple writers.
663//
664//Revision 1.4  2011/01/25 20:50:37  acg
665// Andy Goodrich: changes for IEEE 1666 2011.
666//
667//Revision 1.3  2010/12/07 19:50:37  acg
668// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann.
669//
670//Revision 1.1.1.1  2006/12/15 20:20:04  acg
671//SystemC 2.3
672//
673//Revision 1.14  2006/05/08 17:52:47  acg
674// Andy Goodrich:
675//   (1) added David Long's forward declarations for friend functions,
676//       methods, and operators to keep the Microsoft compiler happy.
677//   (2) Added delta_count() method to sc_prim_channel for use by
678//       sc_signal so that the friend declaration in sc_simcontext.h
679//	   can be for a non-templated class (i.e., sc_prim_channel.)
680//
681//Revision 1.12  2006/04/11 23:11:57  acg
682//  Andy Goodrich: Changes for reset support that only includes
683//  sc_cthread_process instances.
684//
685//Revision 1.11  2006/03/13 20:19:44  acg
686// Andy Goodrich: changed sc_event instances into pointers to sc_event instances
687// that are allocated as needed. This saves considerable storage for large
688// numbers of signals, etc.
689//
690//Revision 1.10  2006/01/26 21:00:50  acg
691// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of
692// sc_event::notify_delayed()
693//
694//Revision 1.9  2006/01/24 20:45:41  acg
695//Andy Goodrich: converted notify_delayed() calls into notify_next_delta() calls
696//to eliminate deprecation warnings. notify_next_delta() is an implemenation-
697//dependent method of sc_event. It is simpler than notify_delayed(), and should
698//speed up simulation speeds.
699//
700//Revision 1.8  2006/01/19 19:18:25  acg
701//Andy Goodrich: eliminated check_writer in favor of inline code within the
702//write() method since we always execute the check_writer code even when
703//check writing is turned off.
704//
705//Revision 1.7  2006/01/19 00:30:57  acg
706//Andy Goodrich: Yet another implementation for disabling write checks on
707//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK,
708//that when set to DISABLE will turn off write checking.
709//
710//Revision 1.6  2006/01/18 21:42:26  acg
711//Andy Goodrich: Changes for check writer support, and tightening up sc_clock
712//port usage.
713//
714//Revision 1.5  2006/01/13 20:41:59  acg
715//Andy Goodrich: Changes to add port registration to the things that are
716//checked when SC_NO_WRITE_CHECK is not defined.
717//
718//Revision 1.4  2006/01/13 18:47:20  acg
719//Reversed sense of multiwriter signal check. It now defaults to ON unless the
720//user defines SC_NO_WRITE_CHEK before inclusion of the file.
721//
722//Revision 1.3  2006/01/03 23:18:26  acg
723//Changed copyright to include 2006.
724//
725//Revision 1.2  2005/12/20 21:58:18  acg
726//Removed Makefile.in, changed the event() methods to use sc_simcontext::event_occurred.
727//
728//Revision 1.1.1.1  2005/12/19 23:16:43  acg
729//First check in of SystemC 2.1 into its own archive.
730//
731//Revision 1.19  2005/09/15 23:01:51  acg
732//Added std:: prefix to appropriate methods and types to get around
733//issues with the Edison Front End.
734//
735//Revision 1.18  2005/06/10 22:43:55  acg
736//Added CVS change log annotation.
737//
738
739#endif
740
741// Taf!
742