sc_context.hh revision 12853:e23d6f09069a
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 __SYSTEMC_EXT_DT_FX_SC_CONTEXT_HH__
59#define __SYSTEMC_EXT_DT_FX_SC_CONTEXT_HH__
60
61#include <map>
62
63#include "../../core/sc_process_handle.hh"
64#include "../../utils/sc_report_handler.hh"
65
66namespace sc_dt
67{
68
69// classes defined in this module
70class sc_without_context;
71template <class T>
72class sc_global;
73template <class T>
74class sc_context;
75
76
77// ----------------------------------------------------------------------------
78//  CLASS : sc_without_context
79//
80//  Empty class that is used for its type only.
81// ----------------------------------------------------------------------------
82
83class sc_without_context {};
84
85
86// ----------------------------------------------------------------------------
87//  TEMPLATE CLASS : sc_global
88//
89//  Template global variable class; singleton; co-routine safe.
90// ----------------------------------------------------------------------------
91
92template <class T>
93class sc_global
94{
95    sc_global();
96    void update();
97
98  public:
99    static sc_global<T>* instance();
100    const T*& value_ptr();
101
102  private:
103    static sc_global<T> *m_instance;
104
105    std::map<void *, const T *> m_map;
106    void *m_proc; // context (current process or NULL)
107    const T *m_value_ptr;
108};
109
110
111// ----------------------------------------------------------------------------
112//  ENUM : sc_context_begin
113//
114//  Enumeration of context begin options.
115// ----------------------------------------------------------------------------
116
117enum sc_context_begin
118{
119    SC_NOW,
120    SC_LATER
121};
122
123
124// ----------------------------------------------------------------------------
125//  CLASS : sc_context
126//
127//  Template context class; co-routine safe.
128// ----------------------------------------------------------------------------
129
130template <class T>
131class sc_context
132{
133    // disabled
134    sc_context(const sc_context<T> &);
135    void *operator new(std::size_t);
136
137  public:
138    explicit sc_context(const T &, sc_context_begin=SC_NOW);
139    ~sc_context();
140
141    void begin();
142    void end();
143
144    static const T &default_value();
145    const T &value() const;
146
147  private:
148    sc_context &operator = (const sc_context &) /* = delete */;
149
150    const T m_value;
151    const T *&m_def_value_ptr;
152    const T *m_old_value_ptr;
153};
154
155
156// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
157
158// ----------------------------------------------------------------------------
159//  TEMPLATE CLASS : sc_global
160//
161//  Template global variable class; singleton; co-routine safe.
162// ----------------------------------------------------------------------------
163
164template <class T>
165sc_global<T> *sc_global<T>::m_instance = 0;
166
167template <class T>
168inline sc_global<T>::sc_global() : m_map(),
169    // use &m_instance as unique "non-process" key (NULL denotes 'sc_main'
170    // context)
171    m_proc(&m_instance), m_value_ptr(0)
172{}
173
174
175template <class T>
176inline void
177sc_global<T>::update()
178{
179    void *p = (::sc_gem5::Process *)sc_core::sc_get_current_process_handle();
180    if (p != m_proc) {
181        const T *vp = m_map[p];
182        if (vp == 0) {
183            vp = new T(sc_without_context());
184            m_map.emplace(p, vp);
185        }
186        m_proc = p;
187        m_value_ptr = vp;
188    }
189}
190
191
192template <class T>
193inline sc_global<T> *
194sc_global<T>::instance()
195{
196    if (m_instance == 0) {
197        m_instance = new sc_global<T>;
198    }
199    return m_instance;
200}
201
202
203template <class T>
204inline const T *&
205sc_global<T>::value_ptr()
206{
207    update();
208    return m_value_ptr;
209}
210
211
212// ----------------------------------------------------------------------------
213//  CLASS : sc_context
214//
215//  Template context class; co-routine safe.
216// ----------------------------------------------------------------------------
217
218template <class T>
219inline sc_context<T>::sc_context(const T &value_, sc_context_begin begin_) :
220        m_value(value_),
221        m_def_value_ptr(sc_global<T>::instance()->value_ptr()),
222        m_old_value_ptr(0)
223{
224    if (begin_ == SC_NOW) {
225        m_old_value_ptr = m_def_value_ptr;
226        m_def_value_ptr = &m_value;
227    }
228}
229
230template <class T>
231inline sc_context<T>::~sc_context()
232{
233    if (m_old_value_ptr != 0) {
234        m_def_value_ptr = m_old_value_ptr;
235        m_old_value_ptr = 0;
236    }
237}
238
239
240template <class T>
241inline void
242sc_context<T>::begin()
243{
244    if (m_old_value_ptr == 0) {
245        m_old_value_ptr = m_def_value_ptr;
246        m_def_value_ptr = &m_value;
247    } else {
248        SC_REPORT_ERROR("context begin failed", 0);
249    }
250}
251
252template <class T>
253inline void
254sc_context<T>::end()
255{
256    if (m_old_value_ptr != 0) {
257        m_def_value_ptr = m_old_value_ptr;
258        m_old_value_ptr = 0;
259    } else {
260        SC_REPORT_ERROR("context end failed", 0);
261    }
262}
263
264
265template <class T>
266inline const T &
267sc_context<T>::default_value()
268{
269    return *sc_global<T>::instance()->value_ptr();
270}
271
272template <class T>
273inline const T &
274sc_context<T>::value() const
275{
276    return m_value;
277}
278
279} // namespace sc_dt
280
281#endif // __SYSTEMC_EXT_DT_FX_SC_CONTEXT_HH__
282