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_context.h -
23
24  Original Author: Martin Janssen, Synopsys, Inc.
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36 *****************************************************************************/
37
38// $Log: sc_context.h,v $
39// Revision 1.2  2011/08/24 22:05:43  acg
40//  Torsten Maehne: initialization changes to remove warnings.
41//
42// Revision 1.1.1.1  2006/12/15 20:20:04  acg
43// SystemC 2.3
44//
45// Revision 1.5  2006/05/26 20:36:52  acg
46//  Andy Goodrich: added a using for sc_core::default_ptr_hash_fn to keep HP
47//  aCC happy.
48//
49// Revision 1.4  2006/03/21 00:00:31  acg
50//   Andy Goodrich: changed name of sc_get_current_process_base() to be
51//   sc_get_current_process_b() since its returning an sc_process_b instance.
52//
53// Revision 1.3  2006/01/13 18:53:57  acg
54// Andy Goodrich: added $Log command so that CVS comments are reproduced in
55// the source.
56//
57
58#ifndef SC_CONTEXT_H
59#define SC_CONTEXT_H
60
61
62#include "sysc/datatypes/fx/sc_fx_ids.h"
63#include "sysc/kernel/sc_simcontext.h"
64#include "sysc/utils/sc_hash.h"
65
66
67namespace sc_core {
68	class sc_process_b;
69}
70
71using sc_core::default_ptr_hash_fn; // To keep HP aCC happy.
72
73namespace sc_dt
74{
75
76// classes defined in this module
77class sc_without_context;
78template <class T> class sc_global;
79template <class T> class sc_context;
80
81
82// ----------------------------------------------------------------------------
83//  CLASS : sc_without_context
84//
85//  Empty class that is used for its type only.
86// ----------------------------------------------------------------------------
87
88class sc_without_context {};
89
90
91// ----------------------------------------------------------------------------
92//  TEMPLATE CLASS : sc_global
93//
94//  Template global variable class; singleton; co-routine safe.
95// ----------------------------------------------------------------------------
96
97template <class T>
98class sc_global
99{
100
101    sc_global();
102
103    void update();
104
105public:
106
107    static sc_global<T>* instance();
108
109    const T*& value_ptr();
110
111private:
112    static sc_global<T>* m_instance;
113
114    sc_core::sc_phash<void*,const T*> m_map;
115    void*                             m_proc; // context (current process or NULL)
116    const T*                          m_value_ptr;
117
118};
119
120
121// ----------------------------------------------------------------------------
122//  ENUM : sc_context_begin
123//
124//  Enumeration of context begin options.
125// ----------------------------------------------------------------------------
126
127enum sc_context_begin
128{
129    SC_NOW,
130    SC_LATER
131};
132
133
134// ----------------------------------------------------------------------------
135//  CLASS : sc_context
136//
137//  Template context class; co-routine safe.
138// ----------------------------------------------------------------------------
139
140template <class T>
141class sc_context
142{
143    // disabled
144    sc_context( const sc_context<T>& );
145    void* operator new( std::size_t );
146
147public:
148
149    explicit sc_context( const T&, sc_context_begin = SC_NOW );
150    ~sc_context();
151
152    void begin();
153    void end();
154
155    static const T& default_value();
156    const T& value() const;
157
158private:
159
160    const T   m_value;
161    const T*& m_def_value_ptr;
162    const T*  m_old_value_ptr;
163};
164
165
166// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
167
168// ----------------------------------------------------------------------------
169//  TEMPLATE CLASS : sc_global
170//
171//  Template global variable class; singleton; co-routine safe.
172// ----------------------------------------------------------------------------
173
174template <class T>
175sc_global<T>* sc_global<T>::m_instance = 0;
176
177template <class T>
178inline
179sc_global<T>::sc_global()
180  : m_map()
181  // use &m_instance as unique "non-process" key (NULL denotes 'sc_main' context)
182  , m_proc( &m_instance )
183  , m_value_ptr( 0 )
184{}
185
186
187template <class T>
188inline
189void
190sc_global<T>::update()
191{
192    void* p = sc_core::sc_get_current_process_b();
193    if( p != m_proc )
194    {
195        const T* vp = m_map[p];
196        if( vp == 0 )
197        {
198            vp = new T( sc_without_context() );
199            m_map.insert( p, vp );
200        }
201        m_proc = p;
202        m_value_ptr = vp;
203    }
204}
205
206
207template <class T>
208inline
209sc_global<T>*
210sc_global<T>::instance()
211{
212    if( m_instance == 0 )
213    {
214        m_instance = new sc_global<T>;
215    }
216    return m_instance;
217}
218
219
220template <class T>
221inline
222const T*&
223sc_global<T>::value_ptr()
224{
225    update();
226    return m_value_ptr;
227}
228
229
230// ----------------------------------------------------------------------------
231//  CLASS : sc_context
232//
233//  Template context class; co-routine safe.
234// ----------------------------------------------------------------------------
235
236template <class T>
237inline
238sc_context<T>::sc_context( const T& value_, sc_context_begin begin )
239: m_value( value_ ),
240  m_def_value_ptr( sc_global<T>::instance()->value_ptr() ),
241  m_old_value_ptr( 0 )
242{
243    if( begin == SC_NOW )
244    {
245	m_old_value_ptr = m_def_value_ptr;
246	m_def_value_ptr = &m_value;
247    }
248}
249
250template <class T>
251inline
252sc_context<T>::~sc_context()
253{
254    if( m_old_value_ptr != 0 )
255    {
256        m_def_value_ptr = m_old_value_ptr;
257	m_old_value_ptr = 0;
258    }
259}
260
261
262template <class T>
263inline
264void
265sc_context<T>::begin()
266{
267    if( m_old_value_ptr == 0 )
268    {
269	m_old_value_ptr = m_def_value_ptr;
270	m_def_value_ptr = &m_value;
271    }
272    else
273    {
274        SC_REPORT_ERROR( sc_core::SC_ID_CONTEXT_BEGIN_FAILED_, 0 );
275    }
276}
277
278template <class T>
279inline
280void
281sc_context<T>::end()
282{
283    if( m_old_value_ptr != 0 )
284    {
285        m_def_value_ptr = m_old_value_ptr;
286	m_old_value_ptr = 0;
287    }
288    else
289    {
290        SC_REPORT_ERROR( sc_core::SC_ID_CONTEXT_END_FAILED_, 0 );
291    }
292}
293
294
295template <class T>
296inline
297const T&
298sc_context<T>::default_value()
299{
300    return *sc_global<T>::instance()->value_ptr();
301}
302
303template <class T>
304inline
305const T&
306sc_context<T>::value() const
307{
308    return m_value;
309}
310
311} // namespace sc_dt
312
313
314#endif
315
316// Taf!
317