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_ports.h -- The sc_signal<T> port classes.
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG APPEARS AT THE END OF THE FILE
27 *****************************************************************************/
28
29#ifndef SC_SIGNAL_PORTS_H
30#define SC_SIGNAL_PORTS_H
31
32
33#include "sysc/communication/sc_event_finder.h"
34#include "sysc/communication/sc_port.h"
35#include "sysc/communication/sc_signal_ifs.h"
36#include "sysc/datatypes/bit/sc_logic.h"
37#include "sysc/tracing/sc_trace.h"
38
39#if ! defined( SC_DISABLE_VIRTUAL_BIND )
40#  define SC_VIRTUAL_ virtual
41#else
42#  define SC_VIRTUAL_ /* non-virtual */
43#endif
44
45namespace sc_core {
46
47// ----------------------------------------------------------------------------
48//  STRUCT : sc_trace_params
49//
50//  Struct for storing the trace file and object name of an sc_trace call.
51//  FOR INTERNAL USE ONLY!
52// ----------------------------------------------------------------------------
53
54extern void sc_deprecated_add_trace();
55
56struct sc_trace_params
57{
58    sc_trace_file*        tf;
59    std::string      name;
60
61    sc_trace_params( sc_trace_file* tf_, const std::string& name_ )
62	: tf( tf_ ), name( name_ )
63	{}
64};
65
66
67typedef std::vector<sc_trace_params*> sc_trace_params_vec;
68
69
70// ----------------------------------------------------------------------------
71//  CLASS : sc_in<T>
72//
73//  The sc_signal<T> input port class.
74// ----------------------------------------------------------------------------
75
76template <class T>
77class sc_in
78: public sc_port<sc_signal_in_if<T>,1,SC_ONE_OR_MORE_BOUND>
79{
80public:
81
82    // typedefs
83
84    typedef T                                             data_type;
85
86    typedef sc_signal_in_if<data_type>                    if_type;
87    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>       base_type;
88    typedef sc_in<data_type>                              this_type;
89    typedef typename base_type::port_type                 base_port_type;
90
91    typedef if_type                                       in_if_type;
92    typedef base_type                                     in_port_type;
93    typedef sc_signal_inout_if<data_type>                 inout_if_type;
94    typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type;
95
96public:
97
98    // constructors
99
100    sc_in()
101	: base_type(), m_traces( 0 ),
102	  m_change_finder_p(0)
103	{}
104
105    explicit sc_in( const char* name_ )
106	: base_type( name_ ), m_traces( 0 ),
107	  m_change_finder_p(0)
108	{}
109
110    explicit sc_in( const in_if_type& interface_ )
111        : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
112	  m_change_finder_p(0)
113        {}
114
115    sc_in( const char* name_, const in_if_type& interface_ )
116	: base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
117	  m_change_finder_p(0)
118	{}
119
120    explicit sc_in( in_port_type& parent_ )
121	: base_type( parent_ ), m_traces( 0 ),
122	  m_change_finder_p(0)
123	{}
124
125    sc_in( const char* name_, in_port_type& parent_ )
126	: base_type( name_, parent_ ), m_traces( 0 ),
127	  m_change_finder_p(0)
128	{}
129
130    explicit sc_in( inout_port_type& parent_ )
131	: base_type(), m_traces( 0 ),
132	  m_change_finder_p(0)
133	{ sc_port_base::bind( parent_ ); }
134
135    sc_in( const char* name_, inout_port_type& parent_ )
136	: base_type( name_ ), m_traces( 0 ),
137	  m_change_finder_p(0)
138	{ sc_port_base::bind( parent_ ); }
139
140    sc_in( this_type& parent_ )
141	: base_type( parent_ ), m_traces( 0 ),
142	  m_change_finder_p(0)
143	{}
144
145    sc_in( const char* name_, this_type& parent_ )
146	: base_type( name_, parent_ ), m_traces( 0 ),
147	  m_change_finder_p(0)
148	{}
149
150
151    // destructor
152
153    virtual ~sc_in()
154	{
155	    remove_traces();
156	    delete m_change_finder_p;
157	}
158
159
160    // bind to in interface
161
162    SC_VIRTUAL_ void bind( const in_if_type& interface_ )
163	{ sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); }
164
165    SC_VIRTUAL_ void bind( in_if_type& interface_ )
166	{ this->bind( CCAST<const in_if_type&>( interface_ ) ); }
167
168    void operator () ( const in_if_type& interface_ )
169	{ this->bind( interface_ ); }
170
171
172    // bind to parent in port
173
174    SC_VIRTUAL_ void bind( in_port_type& parent_ )
175        { sc_port_base::bind( parent_ ); }
176
177    void operator () ( in_port_type& parent_ )
178        { this->bind( parent_ ); }
179
180
181    // bind to parent inout port
182
183    SC_VIRTUAL_ void bind( inout_port_type& parent_ )
184	{ sc_port_base::bind( parent_ ); }
185
186    void operator () ( inout_port_type& parent_ )
187	{ this->bind( parent_ ); }
188
189
190    // interface access shortcut methods
191
192    // get the default event
193
194    const sc_event& default_event() const
195	{ return (*this)->default_event(); }
196
197
198    // get the value changed event
199
200    const sc_event& value_changed_event() const
201	{ return (*this)->value_changed_event(); }
202
203
204    // read the current value
205
206    const data_type& read() const
207	{ return (*this)->read(); }
208
209    operator const data_type& () const
210	{ return (*this)->read(); }
211
212
213    // was there a value changed event?
214
215    bool event() const
216	{ return (*this)->event(); }
217
218
219    // (other) event finder method(s)
220
221    sc_event_finder& value_changed() const
222    {
223        if ( !m_change_finder_p )
224	{
225	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
226	        *this, &in_if_type::value_changed_event );
227	}
228	return *m_change_finder_p;
229    }
230
231
232    // called when elaboration is done
233    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
234    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
235
236    virtual void end_of_elaboration();
237
238    virtual const char* kind() const
239        { return "sc_in"; }
240
241
242    void add_trace( sc_trace_file*, const std::string& ) const;
243
244    // called by sc_trace
245    void add_trace_internal( sc_trace_file*, const std::string& ) const;
246
247protected:
248
249    void remove_traces() const;
250
251    mutable sc_trace_params_vec* m_traces;
252
253protected:
254
255    // called by pbind (for internal use only)
256    virtual int vbind( sc_interface& );
257    virtual int vbind( sc_port_base& );
258
259    // implement virtual base_type port-binding function
260    //  - avoids warnings on some compilers
261    //  - should only be called, when using sc_port_b explicitly
262    //  - errors are detected during elaboration
263
264    SC_VIRTUAL_ void bind( base_port_type& parent_ )
265        { sc_port_base::bind( parent_ ); }
266
267
268private:
269  mutable sc_event_finder* m_change_finder_p;
270
271private:
272
273    // disabled
274    sc_in( const this_type& );
275    this_type& operator = ( const this_type& );
276
277#ifdef __GNUC__
278    // Needed to circumvent a problem in the g++-2.95.2 compiler:
279    // This unused variable forces the compiler to instantiate
280    // an object of T template so an implicit conversion from
281    // read() to a C++ intrinsic data type will work.
282    static data_type dummy;
283#endif
284};
285
286template<typename T>
287::std::ostream& operator << ( ::std::ostream& os, const sc_in<T>& a )
288{
289    return os << a->read();
290}
291
292// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
293
294
295// called when elaboration is done
296
297template <class T>
298inline
299void
300sc_in<T>::end_of_elaboration()
301{
302    if( m_traces != 0 ) {
303	for( int i = 0; i < (int)m_traces->size(); ++ i ) {
304	    sc_trace_params* p = (*m_traces)[i];
305	    in_if_type* iface = DCAST<in_if_type*>( this->get_interface() );
306	    sc_trace( p->tf, iface->read(), p->name );
307	}
308	remove_traces();
309    }
310}
311
312
313// called by sc_trace
314
315template <class T>
316inline
317void
318sc_in<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_ )
319const
320{
321    if( tf_ != 0 ) {
322	if( m_traces == 0 ) {
323	    m_traces = new sc_trace_params_vec;
324	}
325	m_traces->push_back( new sc_trace_params( tf_, name_ ) );
326    }
327}
328
329template <class T>
330inline
331void
332sc_in<T>::add_trace( sc_trace_file* tf_, const std::string& name_ )
333const
334{
335    sc_deprecated_add_trace();
336    add_trace_internal(tf_, name_);
337}
338
339template <class T>
340inline
341void
342sc_in<T>::remove_traces() const
343{
344    if( m_traces != 0 ) {
345	for( int i = (int)m_traces->size() - 1; i >= 0; -- i ) {
346	    delete (*m_traces)[i];
347	}
348	delete m_traces;
349	m_traces = 0;
350    }
351}
352
353
354// called by pbind (for internal use only)
355
356template <class T>
357inline
358int
359sc_in<T>::vbind( sc_interface& interface_ )
360{
361    return sc_port_b<if_type>::vbind( interface_ );
362}
363
364template <class T>
365inline
366int
367sc_in<T>::vbind( sc_port_base& parent_ )
368{
369    in_port_type* in_parent = DCAST<in_port_type*>( &parent_ );
370    if( in_parent != 0 ) {
371	sc_port_base::bind( *in_parent );
372	return 0;
373    }
374    inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ );
375    if( inout_parent != 0 ) {
376	sc_port_base::bind( *inout_parent );
377	return 0;
378    }
379    // type mismatch
380    return 2;
381}
382
383
384// ----------------------------------------------------------------------------
385//  CLASS : sc_in<bool>
386//
387//  Specialization of sc_in<T> for type bool.
388// ----------------------------------------------------------------------------
389
390template <>
391class sc_in<bool> :
392    public sc_port<sc_signal_in_if<bool>,1,SC_ONE_OR_MORE_BOUND>
393{
394public:
395
396    // typedefs
397
398    typedef bool                                           data_type;
399
400    typedef sc_signal_in_if<data_type>                     if_type;
401    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>        base_type;
402    typedef sc_in<data_type>                               this_type;
403    typedef /* typename */ base_type::port_type            base_port_type;
404
405    typedef if_type                                        in_if_type;
406    typedef base_type                                      in_port_type;
407    typedef sc_signal_inout_if<data_type>                  inout_if_type;
408    typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND>  inout_port_type;
409
410public:
411
412    // constructors
413
414    sc_in()
415	: base_type(), m_traces( 0 ), m_change_finder_p(0),
416	  m_neg_finder_p(0), m_pos_finder_p(0)
417	{}
418
419    explicit sc_in( const char* name_ )
420	: base_type( name_ ), m_traces( 0 ), m_change_finder_p(0),
421	  m_neg_finder_p(0), m_pos_finder_p(0)
422	{}
423
424    explicit sc_in( const in_if_type& interface_ )
425	: base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
426	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
427	{}
428
429    sc_in( const char* name_, const in_if_type& interface_ )
430	: base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
431	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
432	{}
433
434    explicit sc_in( in_port_type& parent_ )
435	: base_type( parent_ ), m_traces( 0 ),
436	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
437	{}
438
439    sc_in( const char* name_, in_port_type& parent_ )
440	: base_type( name_, parent_ ), m_traces( 0 ),
441	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
442	{}
443
444    explicit sc_in( inout_port_type& parent_ )
445	: base_type(), m_traces( 0 ),
446	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
447	{ sc_port_base::bind( parent_ ); }
448
449    sc_in( const char* name_, inout_port_type& parent_ )
450	: base_type( name_ ), m_traces( 0 ),
451	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
452	{ sc_port_base::bind( parent_ ); }
453
454    sc_in( this_type& parent_ )
455	: base_type( parent_ ), m_traces( 0 ),
456	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
457	{}
458
459#if defined(TESTING)
460    sc_in( const this_type& parent_ )
461	: base_type( *(in_if_type*)parent_.get_interface() ) , m_traces( 0 ),
462	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
463	{}
464#endif
465
466    sc_in( const char* name_, this_type& parent_ )
467	: base_type( name_, parent_ ), m_traces( 0 ),
468	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
469	{}
470
471
472    // destructor
473
474    virtual ~sc_in()
475	{
476	    remove_traces();
477	    delete m_change_finder_p;
478	    delete m_neg_finder_p;
479	    delete m_pos_finder_p;
480	}
481
482
483    // bind to in interface
484
485    SC_VIRTUAL_ void bind( const in_if_type& interface_ )
486	{ sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); }
487
488    SC_VIRTUAL_ void bind( in_if_type& interface_ )
489	{ this->bind( CCAST<const in_if_type&>( interface_ ) ); }
490
491    void operator () ( const in_if_type& interface_ )
492	{ this->bind( interface_ ); }
493
494
495    // bind to parent in port
496
497    SC_VIRTUAL_ void bind( in_port_type& parent_ )
498        { sc_port_base::bind( parent_ ); }
499
500    void operator () ( in_port_type& parent_ )
501        { this->bind( parent_ ); }
502
503
504    // bind to parent inout port
505
506    SC_VIRTUAL_ void bind( inout_port_type& parent_ )
507	{ sc_port_base::bind( parent_ ); }
508
509    void operator () ( inout_port_type& parent_ )
510	{ this->bind( parent_ ); }
511
512
513    // interface access shortcut methods
514
515    // get the default event
516
517    const sc_event& default_event() const
518	{ return (*this)->default_event(); }
519
520
521    // get the value changed event
522
523    const sc_event& value_changed_event() const
524	{ return (*this)->value_changed_event(); }
525
526    // get the positive edge event
527
528    const sc_event& posedge_event() const
529	{ return (*this)->posedge_event(); }
530
531    // get the negative edge event
532
533    const sc_event& negedge_event() const
534	{ return (*this)->negedge_event(); }
535
536
537    // read the current value
538
539    const data_type& read() const
540	{ return (*this)->read(); }
541
542    operator const data_type& () const
543	{ return (*this)->read(); }
544
545
546    // use for positive edge sensitivity
547
548    sc_event_finder& pos() const
549    {
550        if ( !m_pos_finder_p )
551	{
552	    m_pos_finder_p = new sc_event_finder_t<in_if_type>(
553	        *this, &in_if_type::posedge_event );
554	}
555	return *m_pos_finder_p;
556    }
557
558    // use for negative edge sensitivity
559
560    sc_event_finder& neg() const
561    {
562        if ( !m_neg_finder_p )
563	{
564	    m_neg_finder_p = new sc_event_finder_t<in_if_type>(
565	        *this, &in_if_type::negedge_event );
566	}
567	return *m_neg_finder_p;
568    }
569
570
571    // was there a value changed event?
572
573    bool event() const
574	{ return (*this)->event(); }
575
576    // was there a positive edge event?
577
578    bool posedge() const
579        { return (*this)->posedge(); }
580
581    // was there a negative edge event?
582
583    bool negedge() const
584        { return (*this)->negedge(); }
585
586    // (other) event finder method(s)
587
588    sc_event_finder& value_changed() const
589    {
590        if ( !m_change_finder_p )
591	{
592	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
593	        *this, &in_if_type::value_changed_event );
594	}
595	return *m_change_finder_p;
596    }
597
598
599    // called when elaboration is done
600    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
601    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
602
603    virtual void end_of_elaboration();
604
605    virtual const char* kind() const
606        { return "sc_in"; }
607
608
609    void add_trace( sc_trace_file*, const std::string& ) const;
610
611    // called by sc_trace
612    void add_trace_internal( sc_trace_file*, const std::string& ) const;
613
614protected:
615
616    void remove_traces() const;
617
618    mutable sc_trace_params_vec* m_traces;
619
620protected:
621
622    // called by pbind (for internal use only)
623    virtual int vbind( sc_interface& );
624    virtual int vbind( sc_port_base& );
625
626    // implement virtual base_type port-binding function
627    //  - avoids warnings on some compilers
628    //  - should only be called, when using sc_port_b explicitly
629    //  - errors are detected during elaboration
630
631    SC_VIRTUAL_ void bind( base_port_type& parent_ )
632        { sc_port_base::bind( parent_ ); }
633
634private:
635  mutable sc_event_finder* m_change_finder_p;
636  mutable sc_event_finder* m_neg_finder_p;
637  mutable sc_event_finder* m_pos_finder_p;
638
639private:
640
641    // disabled
642#if defined(TESTING)
643#else
644    sc_in( const this_type& );
645#endif
646    this_type& operator = ( const this_type& );
647
648#ifdef __GNUC__
649    // Needed to circumvent a problem in the g++-2.95.2 compiler:
650    // This unused variable forces the compiler to instantiate
651    // an object of T template so an implicit conversion from
652    // read() to a C++ intrinsic data type will work.
653    static data_type dummy;
654#endif
655};
656
657
658// ----------------------------------------------------------------------------
659//  CLASS : sc_in<sc_dt::sc_logic>
660//
661//  Specialization of sc_in<T> for type sc_dt::sc_logic.
662// ----------------------------------------------------------------------------
663
664template <>
665class sc_in<sc_dt::sc_logic>
666: public sc_port<sc_signal_in_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND>
667{
668public:
669
670    // typedefs
671
672    typedef sc_dt::sc_logic                               data_type;
673
674    typedef sc_signal_in_if<data_type>                    if_type;
675    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>       base_type;
676    typedef sc_in<data_type>                              this_type;
677    typedef /* typename */ base_type::port_type           base_port_type;
678
679    typedef if_type                                       in_if_type;
680    typedef base_type                                     in_port_type;
681    typedef sc_signal_inout_if<data_type>                 inout_if_type;
682    typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type;
683
684public:
685
686    // constructors
687
688    sc_in()
689	: base_type(), m_traces( 0 ),
690	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
691	{}
692
693    explicit sc_in( const char* name_ )
694	: base_type( name_ ), m_traces( 0 ),
695	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
696	{}
697
698    explicit sc_in( const in_if_type& interface_ )
699	: base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
700	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
701	{}
702
703    sc_in( const char* name_, const in_if_type& interface_ )
704	: base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ),
705	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
706	{}
707
708    explicit sc_in( in_port_type& parent_ )
709	: base_type( parent_ ), m_traces( 0 ),
710	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
711	{}
712
713    sc_in( const char* name_, in_port_type& parent_ )
714	: base_type( name_, parent_ ), m_traces( 0 ),
715	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
716	{}
717
718    explicit sc_in( inout_port_type& parent_ )
719	: base_type(), m_traces( 0 ),
720	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
721	{ sc_port_base::bind( parent_ ); }
722
723    sc_in( const char* name_, inout_port_type& parent_ )
724	: base_type( name_ ), m_traces( 0 ),
725	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
726	{ sc_port_base::bind( parent_ ); }
727
728    sc_in( this_type& parent_ )
729	: base_type( parent_ ), m_traces( 0 ),
730	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
731	{}
732
733    sc_in( const char* name_, this_type& parent_ )
734	: base_type( name_, parent_ ), m_traces( 0 ),
735	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
736	{}
737
738
739    // destructor
740
741    virtual ~sc_in()
742	{
743	    remove_traces();
744	    delete m_change_finder_p;
745	    delete m_neg_finder_p;
746	    delete m_pos_finder_p;
747	}
748
749
750    // bind to in interface
751
752    SC_VIRTUAL_ void bind( const in_if_type& interface_ )
753	{ sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); }
754
755    SC_VIRTUAL_ void bind( in_if_type& interface_ )
756	{ this->bind( CCAST<const in_if_type&>( interface_ ) ); }
757
758    void operator () ( const in_if_type& interface_ )
759	{ this->bind( interface_ ); }
760
761
762    // bind to parent in port
763
764    SC_VIRTUAL_ void bind( in_port_type& parent_ )
765        { sc_port_base::bind( parent_ ); }
766
767    void operator () ( in_port_type& parent_ )
768        { this->bind( parent_ ); }
769
770
771    // bind to parent inout port
772
773    SC_VIRTUAL_ void bind( inout_port_type& parent_ )
774	{ sc_port_base::bind( parent_ ); }
775
776    void operator () ( inout_port_type& parent_ )
777	{ this->bind( parent_ ); }
778
779
780    // interface access shortcut methods
781
782    // get the default event
783
784    const sc_event& default_event() const
785	{ return (*this)->default_event(); }
786
787
788    // get the value changed event
789
790    const sc_event& value_changed_event() const
791	{ return (*this)->value_changed_event(); }
792
793    // get the positive edge event
794
795    const sc_event& posedge_event() const
796	{ return (*this)->posedge_event(); }
797
798    // get the negative edge event
799
800    const sc_event& negedge_event() const
801	{ return (*this)->negedge_event(); }
802
803
804    // read the current value
805
806    const data_type& read() const
807	{ return (*this)->read(); }
808
809    operator const data_type& () const
810	{ return (*this)->read(); }
811
812
813    // use for positive edge sensitivity
814
815    sc_event_finder& pos() const
816    {
817        if ( !m_pos_finder_p )
818	{
819	    m_pos_finder_p = new sc_event_finder_t<in_if_type>(
820	        *this, &in_if_type::posedge_event );
821	}
822	return *m_pos_finder_p;
823    }
824
825    // use for negative edge sensitivity
826
827    sc_event_finder& neg() const
828    {
829        if ( !m_neg_finder_p )
830	{
831	    m_neg_finder_p = new sc_event_finder_t<in_if_type>(
832	        *this, &in_if_type::negedge_event );
833	}
834	return *m_neg_finder_p;
835    }
836
837
838    // was there a value changed event?
839
840    bool event() const
841	{ return (*this)->event(); }
842
843    // was there a positive edge event?
844
845    bool posedge() const
846        { return (*this)->posedge(); }
847
848    // was there a negative edge event?
849
850    bool negedge() const
851        { return (*this)->negedge(); }
852
853    // (other) event finder method(s)
854
855    sc_event_finder& value_changed() const
856    {
857        if ( !m_change_finder_p )
858	{
859	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
860	        *this, &in_if_type::value_changed_event );
861	}
862	return *m_change_finder_p;
863    }
864
865
866    // called when elaboration is done
867    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
868    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
869
870    virtual void end_of_elaboration();
871
872    virtual const char* kind() const
873        { return "sc_in"; }
874
875
876    void add_trace( sc_trace_file*, const std::string& ) const;
877
878    // called by sc_trace
879    void add_trace_internal( sc_trace_file*, const std::string& ) const;
880
881protected:
882
883    void remove_traces() const;
884
885    mutable sc_trace_params_vec* m_traces;
886
887protected:
888
889    // called by pbind (for internal use only)
890    virtual int vbind( sc_interface& );
891    virtual int vbind( sc_port_base& );
892
893    // implement virtual base_type port-binding function
894    //  - avoids warnings on some compilers
895    //  - should only be called, when using sc_port_b explicitly
896    //  - errors are detected during elaboration
897
898    SC_VIRTUAL_ void bind( base_port_type& parent_ )
899        { sc_port_base::bind( parent_ ); }
900
901private:
902  mutable sc_event_finder* m_change_finder_p;
903  mutable sc_event_finder* m_neg_finder_p;
904  mutable sc_event_finder* m_pos_finder_p;
905
906private:
907
908    // disabled
909    sc_in( const this_type& );
910    this_type& operator = ( const this_type& );
911
912#ifdef __GNUC__
913    // Needed to circumvent a problem in the g++-2.95.2 compiler:
914    // This unused variable forces the compiler to instantiate
915    // an object of T template so an implicit conversion from
916    // read() to a C++ intrinsic data type will work.
917    static data_type dummy;
918#endif
919};
920
921
922// ----------------------------------------------------------------------------
923//  CLASS : sc_inout<T>
924//
925//  The sc_signal<T> input/output port class.
926// ----------------------------------------------------------------------------
927
928template <class T>
929class sc_inout
930: public sc_port<sc_signal_inout_if<T>,1,SC_ONE_OR_MORE_BOUND>
931{
932public:
933
934    // typedefs
935
936    typedef T                                          data_type;
937
938    typedef sc_signal_inout_if<data_type>              if_type;
939    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>    base_type;
940    typedef sc_inout<data_type>                        this_type;
941
942    typedef sc_signal_in_if<data_type>                 in_if_type;
943    typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type;
944    typedef if_type                                    inout_if_type;
945    typedef base_type                                  inout_port_type;
946
947public:
948
949    // constructors
950
951    sc_inout()
952	: base_type(), m_init_val( 0 ), m_traces( 0 ),
953	  m_change_finder_p(0)
954	{}
955
956    explicit sc_inout( const char* name_ )
957	: base_type( name_ ), m_init_val( 0 ), m_traces( 0 ),
958	  m_change_finder_p(0)
959	{}
960
961    explicit sc_inout( inout_if_type& interface_ )
962	: base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ),
963	  m_change_finder_p(0)
964	{}
965
966    sc_inout( const char* name_, inout_if_type& interface_ )
967	: base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ),
968	  m_change_finder_p(0)
969	{}
970
971    explicit sc_inout( inout_port_type& parent_ )
972	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
973	  m_change_finder_p(0)
974	{}
975
976    sc_inout( const char* name_, inout_port_type& parent_ )
977	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
978	  m_change_finder_p(0)
979	{}
980
981    sc_inout( this_type& parent_ )
982	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
983	  m_change_finder_p(0)
984	{}
985
986    sc_inout( const char* name_, this_type& parent_ )
987	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
988	  m_change_finder_p(0)
989	{}
990
991
992    // destructor
993
994    virtual ~sc_inout();
995
996
997    // interface access shortcut methods
998
999    // get the default event
1000
1001    const sc_event& default_event() const
1002	{ return (*this)->default_event(); }
1003
1004
1005    // get the value changed event
1006
1007    const sc_event& value_changed_event() const
1008	{ return (*this)->value_changed_event(); }
1009
1010
1011    // read the current value
1012
1013    const data_type& read() const
1014	{ return (*this)->read(); }
1015
1016    operator const data_type& () const
1017	{ return (*this)->read(); }
1018
1019
1020    // was there a value changed event?
1021
1022    bool event() const
1023	{ return (*this)->event(); }
1024
1025
1026    // write the new value
1027
1028    void write( const data_type& value_ )
1029	{ (*this)->write( value_ ); }
1030
1031    this_type& operator = ( const data_type& value_ )
1032	{ (*this)->write( value_ ); return *this; }
1033
1034    this_type& operator = ( const in_if_type& interface_ )
1035	{ (*this)->write( interface_.read() ); return *this; }
1036
1037    this_type& operator = ( const in_port_type& port_ )
1038	{ (*this)->write( port_->read() ); return *this; }
1039
1040    this_type& operator = ( const inout_port_type& port_ )
1041	{ (*this)->write( port_->read() ); return *this; }
1042
1043    this_type& operator = ( const this_type& port_ )
1044	{ (*this)->write( port_->read() ); return *this; }
1045
1046
1047    // set initial value (can also be called when port is not bound yet)
1048
1049    void initialize( const data_type& value_ );
1050
1051    void initialize( const in_if_type& interface_ )
1052	{ initialize( interface_.read() ); }
1053
1054
1055    // called when elaboration is done
1056    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
1057    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
1058
1059    virtual void end_of_elaboration();
1060
1061
1062    // (other) event finder method(s)
1063
1064    sc_event_finder& value_changed() const
1065    {
1066        if ( !m_change_finder_p )
1067	{
1068	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
1069	        *this, &in_if_type::value_changed_event );
1070	}
1071	return *m_change_finder_p;
1072    }
1073
1074    virtual const char* kind() const
1075        { return "sc_inout"; }
1076
1077protected:
1078
1079    data_type* m_init_val;
1080
1081public:
1082
1083    // called by sc_trace
1084    void add_trace_internal( sc_trace_file*, const std::string& ) const;
1085
1086    void add_trace( sc_trace_file*, const std::string& ) const;
1087
1088protected:
1089
1090    void remove_traces() const;
1091
1092    mutable sc_trace_params_vec* m_traces;
1093
1094private:
1095  mutable sc_event_finder* m_change_finder_p;
1096
1097private:
1098
1099    // disabled
1100    sc_inout( const this_type& );
1101
1102#ifdef __GNUC__
1103    // Needed to circumvent a problem in the g++-2.95.2 compiler:
1104    // This unused variable forces the compiler to instantiate
1105    // an object of T template so an implicit conversion from
1106    // read() to a C++ intrinsic data type will work.
1107    static data_type dummy;
1108#endif
1109};
1110
1111template<typename T>
1112::std::ostream& operator << ( ::std::ostream& os, const sc_inout<T>& a )
1113{
1114    return os << a->read();
1115}
1116
1117// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
1118
1119
1120// destructor
1121
1122template <class T>
1123inline
1124sc_inout<T>::~sc_inout()
1125{
1126    delete m_change_finder_p;
1127    delete m_init_val;
1128    remove_traces();
1129}
1130
1131
1132// set initial value (can also be called when port is not bound yet)
1133
1134template <class T>
1135inline
1136void
1137sc_inout<T>::initialize( const data_type& value_ )
1138{
1139    inout_if_type* iface = DCAST<inout_if_type*>( this->get_interface() );
1140    if( iface != 0 ) {
1141	iface->write( value_ );
1142    } else {
1143	if( m_init_val == 0 ) {
1144	    m_init_val = new data_type;
1145	}
1146	*m_init_val = value_;
1147    }
1148}
1149
1150
1151// called when elaboration is done
1152
1153template <class T>
1154inline
1155void
1156sc_inout<T>::end_of_elaboration()
1157{
1158    if( m_init_val != 0 ) {
1159	write( *m_init_val );
1160	delete m_init_val;
1161	m_init_val = 0;
1162    }
1163    if( m_traces != 0 ) {
1164	for( int i = 0; i < (int)m_traces->size(); ++ i ) {
1165	    sc_trace_params* p = (*m_traces)[i];
1166	    in_if_type* iface = DCAST<in_if_type*>( this->get_interface() );
1167	    sc_trace( p->tf, iface->read(), p->name );
1168	}
1169	remove_traces();
1170    }
1171}
1172
1173
1174// called by sc_trace
1175
1176template <class T>
1177inline
1178void
1179sc_inout<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_)
1180const
1181{
1182    if( tf_ != 0 ) {
1183	    if( m_traces == 0 ) {
1184	        m_traces = new sc_trace_params_vec;
1185	    }
1186	    m_traces->push_back( new sc_trace_params( tf_, name_ ) );
1187    }
1188}
1189
1190template <class T>
1191inline
1192void
1193sc_inout<T>::add_trace( sc_trace_file* tf_, const std::string& name_) const
1194{
1195    sc_deprecated_add_trace();
1196    add_trace_internal(tf_, name_);
1197}
1198
1199template <class T>
1200inline
1201void
1202sc_inout<T>::remove_traces() const
1203{
1204    if( m_traces != 0 ) {
1205		for( int i = m_traces->size() - 1; i >= 0; -- i ) {
1206	        delete (*m_traces)[i];
1207		}
1208		delete m_traces;
1209		m_traces = 0;
1210    }
1211}
1212
1213
1214// ----------------------------------------------------------------------------
1215//  CLASS : sc_inout<bool>
1216//
1217//  Specialization of sc_inout<T> for type bool.
1218// ----------------------------------------------------------------------------
1219
1220template <>
1221class sc_inout<bool> :
1222    public sc_port<sc_signal_inout_if<bool>,1,SC_ONE_OR_MORE_BOUND>
1223{
1224public:
1225
1226    // typedefs
1227
1228    typedef bool                                       data_type;
1229
1230    typedef sc_signal_inout_if<data_type>              if_type;
1231    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>    base_type;
1232    typedef sc_inout<data_type>                        this_type;
1233
1234    typedef sc_signal_in_if<data_type>                 in_if_type;
1235    typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type;
1236    typedef if_type                                    inout_if_type;
1237    typedef base_type                                  inout_port_type;
1238
1239public:
1240
1241    // constructors
1242
1243    sc_inout()
1244	: base_type(), m_init_val( 0 ), m_traces( 0 ),
1245	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1246	{}
1247
1248    explicit sc_inout( const char* name_ )
1249	: base_type( name_ ), m_init_val( 0 ), m_traces( 0 ),
1250	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1251	{}
1252
1253    explicit sc_inout( inout_if_type& interface_ )
1254	: base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ),
1255	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1256	{}
1257
1258    sc_inout( const char* name_, inout_if_type& interface_ )
1259	: base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ),
1260	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1261	{}
1262
1263    explicit sc_inout( inout_port_type& parent_ )
1264	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
1265	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1266	{}
1267
1268    sc_inout( const char* name_, inout_port_type& parent_ )
1269	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
1270	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1271	{}
1272
1273    sc_inout( this_type& parent_ )
1274	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
1275	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1276	{}
1277
1278    sc_inout( const char* name_, this_type& parent_ )
1279	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
1280	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1281	{}
1282
1283
1284    // destructor
1285
1286    virtual ~sc_inout();
1287
1288
1289    // interface access shortcut methods
1290
1291    // get the default event
1292
1293    const sc_event& default_event() const
1294	{ return (*this)->default_event(); }
1295
1296
1297    // get the value changed event
1298
1299    const sc_event& value_changed_event() const
1300	{ return (*this)->value_changed_event(); }
1301
1302    // get the positive edge event
1303
1304    const sc_event& posedge_event() const
1305	{ return (*this)->posedge_event(); }
1306
1307    // get the negative edge event
1308
1309    const sc_event& negedge_event() const
1310	{ return (*this)->negedge_event(); }
1311
1312
1313    // read the current value
1314
1315    const data_type& read() const
1316	{ return (*this)->read(); }
1317
1318    operator const data_type& () const
1319	{ return (*this)->read(); }
1320
1321
1322    // use for positive edge sensitivity
1323
1324    sc_event_finder& pos() const
1325    {
1326        if ( !m_pos_finder_p )
1327	{
1328	    m_pos_finder_p = new sc_event_finder_t<in_if_type>(
1329	        *this, &in_if_type::posedge_event );
1330	}
1331	return *m_pos_finder_p;
1332    }
1333
1334    // use for negative edge sensitivity
1335
1336    sc_event_finder& neg() const
1337    {
1338        if ( !m_neg_finder_p )
1339	{
1340	    m_neg_finder_p = new sc_event_finder_t<in_if_type>(
1341	        *this, &in_if_type::negedge_event );
1342	}
1343	return *m_neg_finder_p;
1344    }
1345
1346
1347    // was there a value changed event?
1348
1349    bool event() const
1350	{ return (*this)->event(); }
1351
1352    // was there a positive edge event?
1353
1354    bool posedge() const
1355        { return (*this)->posedge(); }
1356
1357    // was there a negative edge event?
1358
1359    bool negedge() const
1360        { return (*this)->negedge(); }
1361
1362    // write the new value
1363
1364    void write( const data_type& value_ )
1365	{ (*this)->write( value_ ); }
1366
1367    this_type& operator = ( const data_type& value_ )
1368	{ (*this)->write( value_ ); return *this; }
1369
1370    this_type& operator = ( const in_if_type& interface_ )
1371	{ (*this)->write( interface_.read() ); return *this; }
1372
1373    this_type& operator = ( const in_port_type& port_ )
1374	{ (*this)->write( port_->read() ); return *this; }
1375
1376    this_type& operator = ( const inout_port_type& port_ )
1377	{ (*this)->write( port_->read() ); return *this; }
1378
1379    this_type& operator = ( const this_type& port_ )
1380	{ (*this)->write( port_->read() ); return *this; }
1381
1382
1383    // set initial value (can also be called when port is not bound yet)
1384
1385    void initialize( const data_type& value_ );
1386
1387    void initialize( const in_if_type& interface_ )
1388	{ initialize( interface_.read() ); }
1389
1390
1391    // called when elaboration is done
1392    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
1393    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
1394
1395    virtual void end_of_elaboration();
1396
1397
1398    // (other) event finder method(s)
1399
1400    sc_event_finder& value_changed() const
1401    {
1402        if ( !m_change_finder_p )
1403	{
1404	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
1405	        *this, &in_if_type::value_changed_event );
1406	}
1407	return *m_change_finder_p;
1408    }
1409
1410    virtual const char* kind() const
1411        { return "sc_inout"; }
1412
1413protected:
1414
1415    data_type* m_init_val;
1416
1417public:
1418
1419    // called by sc_trace
1420    void add_trace_internal( sc_trace_file*, const std::string& ) const;
1421
1422    void add_trace( sc_trace_file*, const std::string& ) const;
1423
1424protected:
1425
1426    void remove_traces() const;
1427
1428    mutable sc_trace_params_vec* m_traces;
1429
1430private:
1431  mutable sc_event_finder* m_change_finder_p;
1432  mutable sc_event_finder* m_neg_finder_p;
1433  mutable sc_event_finder* m_pos_finder_p;
1434
1435private:
1436
1437    // disabled
1438    sc_inout( const this_type& );
1439
1440#ifdef __GNUC__
1441    // Needed to circumvent a problem in the g++-2.95.2 compiler:
1442    // This unused variable forces the compiler to instantiate
1443    // an object of T template so an implicit conversion from
1444    // read() to a C++ intrinsic data type will work.
1445    static data_type dummy;
1446#endif
1447};
1448
1449
1450// ----------------------------------------------------------------------------
1451//  CLASS : sc_inout<sc_dt::sc_logic>
1452//
1453//  Specialization of sc_inout<T> for type sc_dt::sc_logic.
1454// ----------------------------------------------------------------------------
1455
1456template <>
1457class sc_inout<sc_dt::sc_logic>
1458: public sc_port<sc_signal_inout_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND>
1459{
1460public:
1461
1462    // typedefs
1463
1464    typedef sc_dt::sc_logic                            data_type;
1465
1466    typedef sc_signal_inout_if<data_type>              if_type;
1467    typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND>    base_type;
1468    typedef sc_inout<data_type>                        this_type;
1469
1470    typedef sc_signal_in_if<data_type>                 in_if_type;
1471    typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type;
1472    typedef if_type                                    inout_if_type;
1473    typedef base_type                                  inout_port_type;
1474
1475public:
1476
1477    // constructors
1478
1479    sc_inout()
1480	: base_type(), m_init_val( 0 ), m_traces( 0 ),
1481	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1482	{}
1483
1484    explicit sc_inout( const char* name_ )
1485	: base_type( name_ ), m_init_val( 0 ), m_traces( 0 ),
1486	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1487	{}
1488
1489    explicit sc_inout( inout_if_type& interface_ )
1490	: base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ),
1491	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1492	{}
1493
1494    sc_inout( const char* name_, inout_if_type& interface_ )
1495	: base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ),
1496	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1497	{}
1498
1499    explicit sc_inout( inout_port_type& parent_ )
1500	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
1501	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1502	{}
1503
1504    sc_inout( const char* name_, inout_port_type& parent_ )
1505	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
1506	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1507	{}
1508
1509    sc_inout( this_type& parent_ )
1510	: base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ),
1511	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1512	{}
1513
1514    sc_inout( const char* name_, this_type& parent_ )
1515	: base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ),
1516	  m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0)
1517	{}
1518
1519
1520    // destructor
1521
1522    virtual ~sc_inout();
1523
1524
1525    // interface access shortcut methods
1526
1527    // get the default event
1528
1529    const sc_event& default_event() const
1530	{ return (*this)->default_event(); }
1531
1532
1533    // get the value changed event
1534
1535    const sc_event& value_changed_event() const
1536	{ return (*this)->value_changed_event(); }
1537
1538    // get the positive edge event
1539
1540    const sc_event& posedge_event() const
1541	{ return (*this)->posedge_event(); }
1542
1543    // get the negative edge event
1544
1545    const sc_event& negedge_event() const
1546	{ return (*this)->negedge_event(); }
1547
1548
1549    // read the current value
1550
1551    const data_type& read() const
1552	{ return (*this)->read(); }
1553
1554    operator const data_type& () const
1555	{ return (*this)->read(); }
1556
1557
1558    // use for positive edge sensitivity
1559
1560    sc_event_finder& pos() const
1561    {
1562        if ( !m_pos_finder_p )
1563	{
1564	    m_pos_finder_p = new sc_event_finder_t<in_if_type>(
1565	        *this, &in_if_type::posedge_event );
1566	}
1567	return *m_pos_finder_p;
1568    }
1569
1570    // use for negative edge sensitivity
1571
1572    sc_event_finder& neg() const
1573    {
1574        if ( !m_neg_finder_p )
1575	{
1576	    m_neg_finder_p = new sc_event_finder_t<in_if_type>(
1577	        *this, &in_if_type::negedge_event );
1578	}
1579	return *m_neg_finder_p;
1580    }
1581
1582
1583    // was there a value changed event?
1584
1585    bool event() const
1586	{ return (*this)->event(); }
1587
1588    // was there a positive edge event?
1589
1590    bool posedge() const
1591        { return (*this)->posedge(); }
1592
1593    // was there a negative edge event?
1594
1595    bool negedge() const
1596        { return (*this)->negedge(); }
1597
1598    // write the new value
1599
1600    void write( const data_type& value_ )
1601	{ (*this)->write( value_ ); }
1602
1603    this_type& operator = ( const data_type& value_ )
1604	{ (*this)->write( value_ ); return *this; }
1605
1606    this_type& operator = ( const in_if_type& interface_ )
1607	{ (*this)->write( interface_.read() ); return *this; }
1608
1609    this_type& operator = ( const in_port_type& port_ )
1610	{ (*this)->write( port_->read() ); return *this; }
1611
1612    this_type& operator = ( const inout_port_type& port_ )
1613	{ (*this)->write( port_->read() ); return *this; }
1614
1615    this_type& operator = ( const this_type& port_ )
1616	{ (*this)->write( port_->read() ); return *this; }
1617
1618
1619    // set initial value (can also be called when port is not bound yet)
1620
1621    void initialize( const data_type& value_ );
1622
1623    void initialize( const in_if_type& interface_ )
1624	{ initialize( interface_.read() ); }
1625
1626
1627    // called when elaboration is done
1628    /*  WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */
1629    /*  MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */
1630
1631    virtual void end_of_elaboration();
1632
1633
1634    // (other) event finder method(s)
1635
1636    sc_event_finder& value_changed() const
1637    {
1638        if ( !m_change_finder_p )
1639	{
1640	    m_change_finder_p = new sc_event_finder_t<in_if_type>(
1641	        *this, &in_if_type::value_changed_event );
1642	}
1643        return *m_change_finder_p;
1644    }
1645
1646    virtual const char* kind() const
1647        { return "sc_inout"; }
1648
1649protected:
1650
1651    data_type* m_init_val;
1652
1653public:
1654
1655    // called by sc_trace
1656    void add_trace_internal( sc_trace_file*, const std::string& ) const;
1657
1658    void add_trace( sc_trace_file*, const std::string& ) const;
1659
1660protected:
1661
1662    void remove_traces() const;
1663
1664    mutable sc_trace_params_vec* m_traces;
1665
1666private:
1667  mutable sc_event_finder* m_change_finder_p;
1668  mutable sc_event_finder* m_neg_finder_p;
1669  mutable sc_event_finder* m_pos_finder_p;
1670
1671private:
1672
1673    // disabled
1674    sc_inout( const this_type& );
1675
1676#ifdef __GNUC__
1677    // Needed to circumvent a problem in the g++-2.95.2 compiler:
1678    // This unused variable forces the compiler to instantiate
1679    // an object of T template so an implicit conversion from
1680    // read() to a C++ intrinsic data type will work.
1681    static data_type dummy;
1682#endif
1683};
1684
1685
1686// ----------------------------------------------------------------------------
1687//  CLASS : sc_out<T>
1688//
1689//  The sc_signal<T> output port class.
1690// ----------------------------------------------------------------------------
1691
1692// sc_out can also read from its port, hence no difference with sc_inout.
1693// For debugging reasons, a class is provided instead of a define.
1694
1695template <class T>
1696class sc_out
1697: public sc_inout<T>
1698{
1699public:
1700
1701    // typedefs
1702
1703    typedef T                                   data_type;
1704
1705    typedef sc_out<data_type>                   this_type;
1706    typedef sc_inout<data_type>                 base_type;
1707
1708    typedef typename base_type::in_if_type      in_if_type;
1709    typedef typename base_type::in_port_type    in_port_type;
1710    typedef typename base_type::inout_if_type   inout_if_type;
1711    typedef typename base_type::inout_port_type inout_port_type;
1712
1713public:
1714
1715    // constructors
1716
1717    sc_out()
1718	: base_type()
1719	{}
1720
1721    explicit sc_out( const char* name_ )
1722	: base_type( name_ )
1723	{}
1724
1725    explicit sc_out( inout_if_type& interface_ )
1726	: base_type( interface_ )
1727	{}
1728
1729    sc_out( const char* name_, inout_if_type& interface_ )
1730	: base_type( name_, interface_ )
1731	{}
1732
1733    explicit sc_out( inout_port_type& parent_ )
1734	: base_type( parent_ )
1735	{}
1736
1737    sc_out( const char* name_, inout_port_type& parent_ )
1738	: base_type( name_, parent_ )
1739	{}
1740
1741    sc_out( this_type& parent_ )
1742	: base_type( parent_ )
1743	{}
1744
1745    sc_out( const char* name_, this_type& parent_ )
1746	: base_type( name_, parent_ )
1747	{}
1748
1749
1750    // destructor (does nothing)
1751
1752    virtual ~sc_out()
1753	{}
1754
1755
1756    // write the new value
1757
1758    this_type& operator = ( const data_type& value_ )
1759	{ (*this)->write( value_ ); return *this; }
1760
1761    this_type& operator = ( const in_if_type& interface_ )
1762	{ (*this)->write( interface_.read() ); return *this; }
1763
1764    this_type& operator = ( const in_port_type& port_ )
1765	{ (*this)->write( port_->read() ); return *this; }
1766
1767    this_type& operator = ( const inout_port_type& port_ )
1768	{ (*this)->write( port_->read() ); return *this; }
1769
1770    this_type& operator = ( const this_type& port_ )
1771	{ (*this)->write( port_->read() ); return *this; }
1772
1773    virtual const char* kind() const
1774        { return "sc_out"; }
1775
1776private:
1777
1778    // disabled
1779    sc_out( const this_type& );
1780};
1781
1782
1783// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
1784
1785
1786// ----------------------------------------------------------------------------
1787//  FUNCTION : sc_trace
1788// ----------------------------------------------------------------------------
1789
1790template <class T>
1791inline
1792void
1793sc_trace(sc_trace_file* tf, const sc_in<T>& port, const std::string& name)
1794{
1795    const sc_signal_in_if<T>* iface = 0;
1796    if (sc_get_curr_simcontext()->elaboration_done() )
1797    {
1798	iface = DCAST<const sc_signal_in_if<T>*>( port.get_interface() );
1799    }
1800
1801    if ( iface )
1802	sc_trace( tf, iface->read(), name );
1803    else
1804	port.add_trace_internal( tf, name );
1805}
1806
1807template <class T>
1808inline
1809void
1810sc_trace( sc_trace_file* tf, const sc_inout<T>& port,
1811    const std::string& name )
1812{
1813    const sc_signal_in_if<T>* iface = 0;
1814    if (sc_get_curr_simcontext()->elaboration_done() )
1815    {
1816	iface =DCAST<const sc_signal_in_if<T>*>( port.get_interface() );
1817    }
1818
1819    if ( iface )
1820	sc_trace( tf, iface->read(), name );
1821    else
1822	port.add_trace_internal( tf, name );
1823}
1824
1825} // namespace sc_core
1826
1827#undef SC_VIRTUAL_
1828
1829/*****************************************************************************
1830
1831  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
1832  changes you are making here.
1833
1834      Name, Affiliation, Date:  Jason Elbaum, Motorola, Inc., 2001-11-12
1835  Description of Modification:  Added a static, private, otherwise
1836                                unused data member to the sc_in
1837                                and sc_inout classes to address
1838                                a bug in the GNU compiler *only*.
1839                                This works around a bug in g++ 2.95.2
1840                                regarding implicit casting from a
1841                                templated class to a C++ intrinsic type.
1842
1843 *****************************************************************************/
1844//$Log: sc_signal_ports.h,v $
1845//Revision 1.10  2011/08/29 18:04:32  acg
1846// Philipp A. Hartmann: miscellaneous clean ups.
1847//
1848//Revision 1.9  2011/08/26 20:45:43  acg
1849// Andy Goodrich: moved the modification log to the end of the file to
1850// eliminate source line number skew when check-ins are done.
1851//
1852//Revision 1.8  2011/08/07 19:08:01  acg
1853// Andy Goodrich: moved logs to end of file so line number synching works
1854// better between versions.
1855//
1856//Revision 1.7  2011/08/07 18:53:09  acg
1857// Philipp A. Hartmann: add virtual instances of the bind function for
1858// base classes to eliminate warning messages for clang platforms.
1859//
1860//Revision 1.6  2011/04/02 00:03:23  acg
1861// Andy Goodrich: catch the other bind()'s that I missed in Philipp's update.
1862//
1863//Revision 1.5  2011/04/01 22:33:31  acg
1864// Philipp A. Harmann: Use const interface signature to implement non-const
1865// interface signature for virtual bind(...).
1866//
1867//Revision 1.4  2011/03/30 16:46:10  acg
1868// Andy Goodrich: added a signature and removed a virtual specification
1869// to eliminate warnings with certain compilers.
1870//
1871//Revision 1.3  2011/02/18 20:23:45  acg
1872// Andy Goodrich: Copyright update.
1873//
1874//Revision 1.2  2011/01/20 16:52:15  acg
1875// Andy Goodrich: changes for IEEE 1666 2011.
1876//
1877//Revision 1.1.1.1  2006/12/15 20:20:04  acg
1878//SystemC 2.3
1879//
1880//Revision 1.11  2006/04/18 23:36:50  acg
1881// Andy Goodrich: made add_trace_internal public until I can figure out
1882// how to do a friend specification for sc_trace in an environment where
1883// there are partial template and full template specifications for its
1884// arguments.
1885//
1886//Revision 1.10  2006/04/18 18:01:26  acg
1887// Andy Goodrich: added an add_trace_internal() method to the various port
1888// classes so that sc_trace has something to call that won't emit an
1889// IEEE 1666 deprecation message.
1890//
1891//Revision 1.9  2006/03/13 20:19:44  acg
1892// Andy Goodrich: changed sc_event instances into pointers to sc_event instances
1893// that are allocated as needed. This saves considerable storage for large
1894// numbers of signals, etc.
1895//
1896//Revision 1.8  2006/02/02 23:42:37  acg
1897// Andy Goodrich: implemented a much better fix to the sc_event_finder
1898// proliferation problem. This new version allocates only a single event
1899// finder for each port for each type of event, e.g., pos(), neg(), and
1900// value_change(). The event finder persists as long as the port does,
1901// which is what the LRM dictates. Because only a single instance is
1902// allocated for each event type per port there is not a potential
1903// explosion of storage as was true in the 2.0.1/2.1 versions.
1904//
1905//Revision 1.7  2006/02/02 21:38:12  acg
1906// Andy Goodrich: fix to the comment log.
1907//
1908//Revision 1.4  2006/01/24 20:46:32  acg
1909//Andy Goodrich: changes to eliminate use of deprecated features. For instance,
1910//using notify(SC_ZERO_TIME) in place of notify_delayed().
1911//
1912//Revision 1.3  2006/01/13 18:47:42  acg
1913//Added $Log command so that CVS comments are reproduced in the source.
1914//
1915//Revision 1.2  2006/01/03 23:18:26  acg
1916//Changed copyright to include 2006.
1917//
1918//Revision 1.1.1.1  2005/12/19 23:16:43  acg
1919//First check in of SystemC 2.1 into its own archive.
1920//
1921//Revision 1.18  2005/09/15 23:01:52  acg
1922//Added std:: prefix to appropriate methods and types to get around
1923//issues with the Edison Front End.
1924//
1925//Revision 1.17  2005/06/10 22:43:55  acg
1926//Added CVS change log annotation.
1927//
1928
1929#endif
1930
1931// Taf!
1932