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