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.cpp -- The sc_signal<T> primitive channel class.
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG IS AT THE END OF THE FILE
27 *****************************************************************************/
28
29
30#include "sysc/communication/sc_communication_ids.h"
31#include "sysc/utils/sc_utils_ids.h"
32#include "sysc/communication/sc_signal.h"
33#include "sysc/datatypes/int/sc_signed.h"
34#include "sysc/datatypes/int/sc_unsigned.h"
35#include "sysc/datatypes/bit/sc_lv_base.h"
36#include "sysc/kernel/sc_reset.h"
37
38#include <sstream>
39
40using sc_dt::sc_lv_base;
41using sc_dt::sc_signed;
42using sc_dt::sc_unsigned;
43using sc_dt::int64;
44using sc_dt::uint64;
45
46namespace sc_core {
47
48// to avoid code bloat in sc_signal<T>
49
50void
51sc_signal_invalid_writer( sc_object* target, sc_object* first_writer,
52                          sc_object* second_writer, bool check_delta )
53{
54    if ( second_writer )
55    {
56        std::stringstream msg;
57
58        msg
59            << "\n signal "
60               "`" << target->name() << "' "
61               "(" << target->kind() << ")"
62            << "\n first driver "
63               "`" << first_writer->name() << "' "
64              " (" << first_writer->kind() << ")"
65            << "\n second driver "
66               "`" << second_writer->name() << "' "
67               "(" << second_writer->kind() << ")";
68
69        if( check_delta )
70        {
71            msg << "\n first conflicting write in delta cycle "
72                << sc_delta_count();
73        }
74        SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_,
75                         msg.str().c_str() );
76    }
77}
78
79bool
80sc_writer_policy_check_port::
81  check_port( sc_object* target, sc_port_base * port_, bool is_output )
82{
83    if ( is_output && sc_get_curr_simcontext()->write_check() )
84    {
85        // an out or inout port; only one can be connected
86        if( m_output != 0) {
87            sc_signal_invalid_writer( target, m_output, port_, false );
88            return false;
89        } else {
90            m_output = port_;
91        }
92    }
93    return true;
94}
95
96void sc_deprecated_get_data_ref()
97{
98    static bool warn_get_data_ref_deprecated=true;
99    if ( warn_get_data_ref_deprecated )
100    {
101        warn_get_data_ref_deprecated=false;
102	SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
103	    "get_data_ref() is deprecated, use read() instead" );
104    }
105}
106
107void sc_deprecated_get_new_value()
108{
109    static bool warn_new_value=true;
110    if ( warn_new_value )
111    {
112        warn_new_value=false;
113	SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
114	    "sc_signal<T>::get_new_value() is deprecated");
115    }
116}
117
118void sc_deprecated_trace()
119{
120    static bool warn_trace_deprecated=true;
121    if ( warn_trace_deprecated )
122    {
123        warn_trace_deprecated=false;
124	SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
125	    "sc_signal<T>::trace() is deprecated");
126    }
127}
128
129sc_event*
130sc_lazy_kernel_event( sc_event** ev, const char* name )
131{
132    if ( !*ev ) {
133        std::string kernel_name = SC_KERNEL_EVENT_PREFIX "_";
134        kernel_name.append( name );
135        *ev = new sc_event( kernel_name.c_str() );
136    }
137    return *ev;
138
139}
140
141// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
142
143template< sc_writer_policy POL >
144void
145sc_signal<bool,POL>::register_port( sc_port_base& port_,
146                                    const char* if_typename_ )
147{
148    bool is_output = std::string( if_typename_ ) == typeid(if_type).name();
149    if( !policy_type::check_port( this, &port_, is_output ) )
150       ((void)0); // fallback? error has been suppressed ...
151}
152
153
154// write the new value
155
156template< sc_writer_policy POL >
157void
158sc_signal<bool,POL>::write( const bool& value_ )
159{
160    bool value_changed = !( m_cur_val == value_ );
161    if ( !policy_type::check_write(this, value_changed) )
162        return;
163    m_new_val = value_;
164    if( value_changed ) {
165        request_update();
166    }
167}
168
169template< sc_writer_policy POL >
170inline
171void
172sc_signal<bool,POL>::print( ::std::ostream& os ) const
173{
174    os << m_cur_val;
175}
176
177template< sc_writer_policy POL >
178void
179sc_signal<bool,POL>::dump( ::std::ostream& os ) const
180{
181    os << "     name = " << name() << ::std::endl;
182    os << "    value = " << m_cur_val << ::std::endl;
183    os << "new value = " << m_new_val << ::std::endl;
184}
185
186
187template< sc_writer_policy POL >
188void
189sc_signal<bool,POL>::update()
190{
191    policy_type::update();
192    if( !( m_new_val == m_cur_val ) ) {
193        do_update();
194    }
195}
196
197template< sc_writer_policy POL >
198void
199sc_signal<bool,POL>::do_update()
200{
201    // order of execution below is important, the notify_processes() call
202    // must come after the update of m_cur_val for things to work properly!
203
204    m_cur_val = m_new_val;
205
206    if ( m_reset_p ) m_reset_p->notify_processes();
207
208    if ( m_change_event_p ) m_change_event_p->notify_next_delta();
209
210    sc_event* event_p = this->m_cur_val
211                      ? m_posedge_event_p : m_negedge_event_p;
212    if ( event_p ) event_p->notify_next_delta();
213
214    m_change_stamp = simcontext()->change_stamp();
215}
216
217// (edge) event methods
218
219template< sc_writer_policy POL >
220const sc_event&
221sc_signal<bool,POL>::value_changed_event() const
222{
223    return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event");
224}
225
226template< sc_writer_policy POL >
227const sc_event&
228sc_signal<bool,POL>::posedge_event() const
229{
230    return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event");
231}
232
233template< sc_writer_policy POL >
234const sc_event&
235sc_signal<bool,POL>::negedge_event() const
236{
237    return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event");
238}
239
240
241// reset support:
242
243template< sc_writer_policy POL >
244sc_reset*
245sc_signal<bool,POL>::is_reset() const
246{
247    sc_reset* result_p;
248    if ( !m_reset_p ) m_reset_p = new sc_reset( this );
249    result_p = m_reset_p;
250    return result_p;
251}
252
253// destructor
254
255template< sc_writer_policy POL >
256sc_signal<bool,POL>::~sc_signal()
257{
258    delete m_change_event_p;
259    delete m_negedge_event_p;
260    delete m_posedge_event_p;
261    delete m_reset_p;
262}
263
264// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
265
266template< sc_writer_policy POL >
267void
268sc_signal<sc_dt::sc_logic,POL>::register_port( sc_port_base& port_,
269                                               const char* if_typename_ )
270{
271    bool is_output = std::string( if_typename_ ) == typeid(if_type).name();
272    if( !policy_type::check_port( this, &port_, is_output ) )
273       ((void)0); // fallback? error has been suppressed ...
274}
275
276
277// write the new value
278
279template< sc_writer_policy POL >
280inline
281void
282sc_signal<sc_dt::sc_logic,POL>::write( const sc_dt::sc_logic& value_ )
283{
284    bool value_changed = !( m_cur_val == value_ );
285    if ( !policy_type::check_write(this, value_changed) )
286        return;
287
288    m_new_val = value_;
289    if( value_changed ) {
290        request_update();
291    }
292}
293
294template< sc_writer_policy POL >
295inline
296void
297sc_signal<sc_dt::sc_logic,POL>::print( ::std::ostream& os ) const
298{
299    os << m_cur_val;
300}
301
302template< sc_writer_policy POL >
303void
304sc_signal<sc_dt::sc_logic,POL>::dump( ::std::ostream& os ) const
305{
306    os << "     name = " << name() << ::std::endl;
307    os << "    value = " << m_cur_val << ::std::endl;
308    os << "new value = " << m_new_val << ::std::endl;
309}
310
311
312template< sc_writer_policy POL >
313void
314sc_signal<sc_dt::sc_logic,POL>::update()
315{
316    policy_type::update();
317    if( !( m_new_val == m_cur_val ) ) {
318        do_update();
319    }
320}
321
322template< sc_writer_policy POL >
323void
324sc_signal<sc_dt::sc_logic,POL>::do_update()
325{
326    m_cur_val = m_new_val;
327
328    if ( m_change_event_p ) m_change_event_p->notify_next_delta();
329
330    if( m_posedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_1) ) {
331        m_posedge_event_p->notify_next_delta();
332    }
333    else if( m_negedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_0) ) {
334        m_negedge_event_p->notify_next_delta();
335    }
336
337    m_change_stamp = simcontext()->change_stamp();
338}
339
340// (edge) event methods
341
342template< sc_writer_policy POL >
343const sc_event&
344sc_signal<sc_dt::sc_logic,POL>::value_changed_event() const
345{
346    return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event");
347}
348
349template< sc_writer_policy POL >
350const sc_event&
351sc_signal<sc_dt::sc_logic,POL>::posedge_event() const
352{
353    return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event");
354}
355
356template< sc_writer_policy POL >
357const sc_event&
358sc_signal<sc_dt::sc_logic,POL>::negedge_event() const
359{
360    return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event");
361}
362
363
364// template instantiations for writer policies
365
366template class sc_signal<bool,SC_ONE_WRITER>;
367template class sc_signal<bool,SC_MANY_WRITERS>;
368template class sc_signal<bool,SC_UNCHECKED_WRITERS>;
369
370template class sc_signal<sc_dt::sc_logic,SC_ONE_WRITER>;
371template class sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS>;
372template class sc_signal<sc_dt::sc_logic,SC_UNCHECKED_WRITERS>;
373
374} // namespace sc_core
375
376/*
377$Log: sc_signal.cpp,v $
378Revision 1.9  2011/08/26 20:45:42  acg
379 Andy Goodrich: moved the modification log to the end of the file to
380 eliminate source line number skew when check-ins are done.
381
382Revision 1.8  2011/02/18 20:23:45  acg
383 Andy Goodrich: Copyright update.
384
385Revision 1.7  2011/02/18 20:08:14  acg
386 Philipp A. Hartmann: addition of include for sstream for MSVC.
387
388Revision 1.6  2011/01/25 20:50:37  acg
389 Andy Goodrich: changes for IEEE 1666 2011.
390
391Revision 1.5  2010/12/07 19:50:36  acg
392 Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann.
393
394Revision 1.3  2007/04/09 21:59:49  acg
395 Andy Goodrich: fixed multiple write notification bug where writes
396 done outside the simulator were being treated as multiple writes.
397
398Revision 1.2  2007/04/02 17:24:01  acg
399 Andy Goodrich: added check for null writer pointers in sc_signal invalid
400 writer method.
401
402Revision 1.1.1.1  2006/12/15 20:20:04  acg
403SystemC 2.3
404
405Revision 1.7  2006/04/11 23:11:57  acg
406  Andy Goodrich: Changes for reset support that only includes
407  sc_cthread_process instances.
408
409Revision 1.6  2006/03/13 20:19:44  acg
410 Andy Goodrich: changed sc_event instances into pointers to sc_event instances
411 that are allocated as needed. This saves considerable storage for large
412 numbers of signals, etc.
413
414Revision 1.5  2006/01/25 00:31:11  acg
415 Andy Goodrich: Changed over to use a standard message id of
416 SC_ID_IEEE_1666_DEPRECATION for all deprecation messages.
417
418Revision 1.4  2006/01/24 20:46:32  acg
419Andy Goodrich: changes to eliminate use of deprecated features. For instance,
420using notify(SC_ZERO_TIME) in place of notify_delayed().
421
422Revision 1.3  2006/01/18 21:42:26  acg
423Andy Goodrich: Changes for check writer support, and tightening up sc_clock
424port usage.
425
426Revision 1.2  2006/01/03 23:18:26  acg
427Changed copyright to include 2006.
428
429Revision 1.1.1.1  2005/12/19 23:16:43  acg
430First check in of SystemC 2.1 into its own archive.
431
432Revision 1.14  2005/09/15 23:01:51  acg
433Added std:: prefix to appropriate methods and types to get around
434issues with the Edison Front End.
435
436Revision 1.13  2005/05/08 19:04:06  acg
437Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage.
438
439Revision 1.12  2005/04/04 00:15:51  acg
440Changes for directory name change to sys from systemc.
441Changes for sc_string going to std::string.
442Changes for sc_pvector going to std::vector.
443Changes for reference pools for bit and part selections.
444Changes for const sc_concatref support.
445
446Revision 1.10  2005/03/21 22:31:32  acg
447Changes to sc_core namespace.
448
449Revision 1.9  2004/09/27 21:02:54  acg
450Andy Goodrich - Forte Design Systems, Inc.
451   - Added a $Log comment so that CVS checkin comments will appear in
452     checked out source.
453
454*/
455
456// Taf!
457