scc 2025.09
SystemC components library
tlm_signal_gp.h
1/*******************************************************************************
2 * Copyright 2018-2022 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17#ifndef _TLM_TLM_SIGNAL_GP_H_
18#define _TLM_TLM_SIGNAL_GP_H_
19
20#include <deque>
21#ifdef CWR_SYSTEMC
22#include <tlm_h/tlm_generic_payload/tlm_gp.h>
23#else
24#include <tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h>
25#endif
26
28namespace tlm {
30namespace scc {
31
33
35public:
36 virtual void free(tlm_generic_payload_base*) = 0;
37 virtual ~tlm_base_mm_interface() {}
38};
39
40struct tlm_generic_payload_base {
41 tlm_generic_payload_base()
42 : tlm_generic_payload_base(nullptr) {}
43
44 explicit tlm_generic_payload_base(tlm_base_mm_interface* mm)
45 : m_extensions(max_num_extensions())
46 , m_mm(mm)
47 , m_ref_count(0){};
48
49 virtual ~tlm_generic_payload_base() {
50 for(unsigned int i = 0; i < m_extensions.size(); i++)
51 if(m_extensions[i])
52 m_extensions[i]->free();
53 }
54
55 void reset() { m_extensions.free_entire_cache(); }
56
57 void acquire() {
58 sc_assert(m_mm != 0);
59 m_ref_count++;
60 }
61
62 void release() {
63 sc_assert(m_mm != 0 && m_ref_count > 0);
64 if(--m_ref_count == 0)
65 m_mm->free(this);
66 }
67
68 int get_ref_count() const { return m_ref_count; }
69
70 void set_mm(tlm_base_mm_interface* mm) { m_mm = mm; }
71 bool has_mm() const { return m_mm != 0; }
72
73 void copy_extensions_from(const tlm_generic_payload_base& other);
74
75 void update_extensions_from(const tlm_generic_payload_base& other);
76 // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager.
77 // normal and sticky extensions are freed and extension array cleared.
78 void free_all_extensions();
79 // Stick the pointer to an extension into the vector, return the
80 // previous value:
81 template <typename T> T* set_extension(T* ext) { return static_cast<T*>(set_extension(T::ID, ext)); }
82
83 // non-templatized version with manual index:
84 tlm_extension_base* set_extension(unsigned int index, tlm_extension_base* ext);
85
86 // Stick the pointer to an extension into the vector, return the
87 // previous value and schedule its release
88 template <typename T> T* set_auto_extension(T* ext) { return static_cast<T*>(set_auto_extension(T::ID, ext)); }
89
90 // non-templatized version with manual index:
91 tlm_extension_base* set_auto_extension(unsigned int index, tlm_extension_base* ext);
92
93 // Check for an extension, ext will point to 0 if not present
94 template <typename T> void get_extension(T*& ext) const { ext = get_extension<T>(); }
95 template <typename T> T* get_extension() const { return static_cast<T*>(get_extension(T::ID)); }
96 // Non-templatized version with manual index:
97 tlm_extension_base* get_extension(unsigned int index) const;
98
99 // this call just removes the extension from the txn but does not
100 // call free() or tells the MM to do so
101 // it return false if there was active MM so you are now in an unsafe situation
102 // recommended use: when 100% sure there is no MM
103 template <typename T> void clear_extension(const T* ext) { clear_extension<T>(); }
104
105 // this call just removes the extension from the txn but does not
106 // call free() or tells the MM to do so
107 // it return false if there was active MM so you are now in an unsafe situation
108 // recommended use: when 100% sure there is no MM
109 template <typename T> void clear_extension() { clear_extension(T::ID); }
110
111 // this call removes the extension from the txn and does
112 // call free() or tells the MM to do so when the txn is finally done
113 // recommended use: when not sure there is no MM
114 template <typename T> void release_extension(T* ext) { release_extension<T>(); }
115
116 // this call removes the extension from the txn and does
117 // call free() or tells the MM to do so when the txn is finally done
118 // recommended use: when not sure there is no MM
119 template <typename T> void release_extension() { release_extension(T::ID); }
120
121private:
122 // Non-templatized version with manual index
123 void clear_extension(unsigned int index);
124 // Non-templatized version with manual index
125 void release_extension(unsigned int index);
126
127public:
128 // Make sure the extension array is large enough. Can be called once by
129 // an initiator module (before issuing the first transaction) to make
130 // sure that the extension array is of correct size. This is only needed
131 // if the initiator cannot guarantee that the generic payload object is
132 // allocated after C++ static construction time.
133 void resize_extensions();
134
135private:
136 tlm_array<tlm_extension_base*> m_extensions;
138 unsigned int m_ref_count;
139};
140
141template <typename SIG = bool> struct tlm_signal_gp : public tlm_generic_payload_base {
142
143 tlm_signal_gp();
144
145 explicit tlm_signal_gp(tlm_base_mm_interface* mm);
146
147 tlm_signal_gp(const tlm_signal_gp<SIG>& x) = delete;
148 tlm_signal_gp<SIG>& operator=(const tlm_signal_gp<SIG>& x) = delete;
149
150 //--------------
151 // Destructor
152 //--------------
153 virtual ~tlm_signal_gp(){};
154 // non-virtual deep-copying of the object
155
156 void deep_copy_from(const tlm_signal_gp& other);
157
158 tlm_command get_command() const { return m_command; }
159 void set_command(const tlm_command command) { m_command = command; }
160
161 SIG get_value() const { return m_value; }
162 void set_value(const SIG value) { m_value = value; }
163
164 // Response status related methods
165 bool is_response_ok() const { return (m_response_status > 0); }
166 bool is_response_error() const { return (m_response_status <= 0); }
167 tlm_response_status get_response_status() const { return m_response_status; }
168 void set_response_status(const tlm_response_status response_status) { m_response_status = response_status; }
169 std::string get_response_string() const;
170
171 struct gp_mm : public tlm_base_mm_interface {
172 tlm_signal_gp<SIG>* create() {
173 if(pool.size()) {
174 auto ret = pool.front();
175 pool.pop_front();
176 return ret;
177 } else
178 return new tlm_signal_gp<SIG>(this);
179 }
180 void free(tlm_generic_payload_base* gp) override {
181 auto t = dynamic_cast<tlm_signal_gp<SIG>*>(gp);
182 t->free_all_extensions();
183 pool.push_back(t);
184 }
185 ~gp_mm() {
186 for(auto n : pool)
187 delete n;
188 }
189
190 private:
191 std::deque<tlm_signal_gp<SIG>*> pool;
192 };
193
194 static tlm_signal_gp<SIG>* create() {
195 static thread_local gp_mm mm;
196 return mm.create();
197 }
198
199protected:
200 tlm_command m_command;
201 SIG m_value;
202 tlm_response_status m_response_status;
203
204public:
205};
206
207template <typename SIG>
208inline tlm_signal_gp<SIG>::tlm_signal_gp()
209: tlm_generic_payload_base()
210, m_command(TLM_IGNORE_COMMAND)
211, m_response_status(TLM_OK_RESPONSE) {}
212
213template <typename SIG>
214inline tlm_signal_gp<SIG>::tlm_signal_gp(tlm_base_mm_interface* mm)
215: tlm_generic_payload_base(mm)
216, m_command(TLM_IGNORE_COMMAND)
217, m_response_status(TLM_OK_RESPONSE) {}
218
219inline void tlm_generic_payload_base::free_all_extensions() {
220 m_extensions.free_entire_cache();
221 for(unsigned int i = 0; i < m_extensions.size(); i++) {
222 if(m_extensions[i]) {
223 m_extensions[i]->free();
224 m_extensions[i] = 0;
225 }
226 }
227}
228
229template <typename SIG> void tlm_signal_gp<SIG>::deep_copy_from(const tlm_signal_gp& other) {
230 m_command = other.get_command();
231 m_response_status = other.get_response_status();
232 m_value = other.get_value();
233 copy_extensions_from(other);
234}
235
236template <typename SIG> std::string tlm_signal_gp<SIG>::get_response_string() const {
237 switch(m_response_status) {
238 case TLM_OK_RESPONSE:
239 return "TLM_OK_RESPONSE";
240 case TLM_INCOMPLETE_RESPONSE:
241 return "TLM_INCOMPLETE_RESPONSE";
242 case TLM_GENERIC_ERROR_RESPONSE:
243 return "TLM_GENERIC_ERROR_RESPONSE";
244 case TLM_ADDRESS_ERROR_RESPONSE:
245 return "TLM_ADDRESS_ERROR_RESPONSE";
246 case TLM_COMMAND_ERROR_RESPONSE:
247 return "TLM_COMMAND_ERROR_RESPONSE";
248 case TLM_BURST_ERROR_RESPONSE:
249 return "TLM_BURST_ERROR_RESPONSE";
250 case TLM_BYTE_ENABLE_ERROR_RESPONSE:
251 return "TLM_BYTE_ENABLE_ERROR_RESPONSE";
252 }
253 return "TLM_UNKNOWN_RESPONSE";
254}
255
256inline tlm_extension_base* tlm_generic_payload_base::set_extension(unsigned int index, tlm_extension_base* ext) {
257 sc_assert(index < m_extensions.size());
258 tlm_extension_base* tmp = m_extensions[index];
259 m_extensions[index] = ext;
260 return tmp;
261}
262
263inline tlm_extension_base* tlm_generic_payload_base::set_auto_extension(unsigned int index, tlm_extension_base* ext) {
264 sc_assert(index < m_extensions.size());
265 tlm_extension_base* tmp = m_extensions[index];
266 m_extensions[index] = ext;
267 if(!tmp)
268 m_extensions.insert_in_cache(&m_extensions[index]);
269 sc_assert(m_mm != 0);
270 return tmp;
271}
272
273inline tlm_extension_base* tlm_generic_payload_base::get_extension(unsigned int index) const {
274 sc_assert(index < m_extensions.size());
275 return m_extensions[index];
276}
277
278inline void tlm_generic_payload_base::clear_extension(unsigned int index) {
279 sc_assert(index < m_extensions.size());
280 m_extensions[index] = static_cast<tlm_extension_base*>(0);
281}
282
283inline void tlm_generic_payload_base::release_extension(unsigned int index) {
284 sc_assert(index < m_extensions.size());
285 if(m_mm) {
286 m_extensions.insert_in_cache(&m_extensions[index]);
287 } else {
288 m_extensions[index]->free();
289 m_extensions[index] = static_cast<tlm_extension_base*>(0);
290 }
291}
292
293inline void tlm_generic_payload_base::update_extensions_from(const tlm_generic_payload_base& other) {
294 // deep copy extensions that are already present
295 sc_assert(m_extensions.size() <= other.m_extensions.size());
296 for(unsigned int i = 0; i < m_extensions.size(); i++) {
297 if(other.m_extensions[i]) { // original has extension i
298 if(m_extensions[i]) { // We have it too. copy.
299 m_extensions[i]->copy_from(*other.m_extensions[i]);
300 }
301 }
302 }
303}
304
305inline void tlm_generic_payload_base::copy_extensions_from(const tlm_generic_payload_base& other) {
306 // deep copy extensions (sticky and non-sticky)
307 if(m_extensions.size() < other.m_extensions.size())
308 m_extensions.expand(other.m_extensions.size());
309 for(unsigned int i = 0; i < other.m_extensions.size(); i++) {
310 if(other.m_extensions[i]) { // original has extension i
311 if(!m_extensions[i]) { // We don't: clone.
312 tlm_extension_base* ext = other.m_extensions[i]->clone();
313 if(ext) { // extension may not be clonable.
314 if(has_mm()) { // mm can take care of removing cloned extensions
315 set_auto_extension(i, ext);
316 } else { // no mm, user will call free_all_extensions().
317 set_extension(i, ext);
318 }
319 }
320 } else { // We already have such extension. Copy original over it.
321 m_extensions[i]->copy_from(*other.m_extensions[i]);
322 }
323 }
324 }
325}
326
327inline void tlm_generic_payload_base::resize_extensions() { m_extensions.expand(max_num_extensions()); }
328} // namespace scc
329} // namespace tlm
330#endif /* _TLM_TLM_SIGNAL_GP_H_ */
SCC TLM utilities.
Definition axis_tlm.h:56
SystemC TLM.
Definition dmi_mgr.h:19