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