scc 2025.09
SystemC components library
tlm_mm.h
1/*******************************************************************************
2 * Copyright 2020 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_MM_H_
18#define _TLM_TLM_MM_H_
19
20#include <tlm>
21#include <type_traits>
22#include <util/pool_allocator.h>
23
24// #if defined(MSVC)
25#define ATTR_UNUSED
26// #else
27// #define ATTR_UNUSED __attribute__((unused))
28// #endif
30namespace tlm {
32namespace scc {
41struct tlm_gp_mm : public tlm_extension<tlm_gp_mm> {
42 virtual ~tlm_gp_mm() {}
43
44 void copy_from(ATTR_UNUSED tlm_extension_base const& from) override {
45 // No need to copy, because this extension is used for memory handling for tlm generic payload data.
46 // The copy operation of the data is therefore handled by the tlm functions deep_copy_from and update_original_from.
47 }
48
49 tlm_gp_mm* clone() const override { return tlm_gp_mm::create(data_size); }
50
51 size_t const data_size;
52 uint8_t* const data_ptr;
53 uint8_t* const be_ptr;
54
55 static tlm_gp_mm* create(size_t sz, bool be = false);
56
57 template <typename TYPES = tlm_base_protocol_types>
58 static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type& gp, bool be = false) {
59 return add_data_ptr(sz, &gp, be);
60 }
61 template <typename TYPES = tlm_base_protocol_types>
62 static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type* gp, bool be = false);
63
64protected:
65 tlm_gp_mm(size_t sz, uint8_t* data_ptr, uint8_t* be_ptr)
66 : data_size(sz)
67 , data_ptr(data_ptr)
68 , be_ptr(be_ptr) {}
69};
70
77template <size_t SZ, bool BE = false> struct tlm_gp_mm_t : public tlm_gp_mm {
78
79 friend tlm_gp_mm;
83 virtual ~tlm_gp_mm_t() {}
87 void free() override { util::pool_allocator<sizeof(tlm_gp_mm_t<SZ, BE>)>::get().free(this); }
88
89protected:
90 tlm_gp_mm_t(size_t sz)
91 : tlm_gp_mm(sz, data, BE ? be : nullptr) {}
92 uint8_t data[SZ];
93 uint8_t be[BE ? SZ : 0];
94};
95
96struct tlm_gp_mm_v : public tlm_gp_mm {
97
98 friend tlm_gp_mm;
99
100 virtual ~tlm_gp_mm_v() { delete data_ptr; }
101
102protected:
103 tlm_gp_mm_v(size_t sz)
104 : tlm_gp_mm(sz, new uint8_t[sz], nullptr) {}
105};
106
114inline tlm_gp_mm* tlm::scc::tlm_gp_mm::create(size_t sz, bool be) {
115 if(sz > 4096) {
116 return new tlm_gp_mm_v(sz);
117 } else if(sz > 1024) {
118 if(be) {
119 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, true>)>::get().allocate()) tlm_gp_mm_t<4096, true>(sz);
120 } else {
121 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, false>)>::get().allocate()) tlm_gp_mm_t<4096, false>(sz);
122 }
123 } else if(sz > 256) {
124 if(be) {
125 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, true>)>::get().allocate()) tlm_gp_mm_t<1024, true>(sz);
126 } else {
127 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, false>)>::get().allocate()) tlm_gp_mm_t<1024, false>(sz);
128 }
129 } else if(sz > 64) {
130 if(be) {
131 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, true>)>::get().allocate()) tlm_gp_mm_t<256, true>(sz);
132 } else {
133 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, false>)>::get().allocate()) tlm_gp_mm_t<256, false>(sz);
134 }
135 } else if(sz > 16) {
136 if(be) {
137 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, true>)>::get().allocate()) tlm_gp_mm_t<64, true>(sz);
138 } else {
139 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, false>)>::get().allocate()) tlm_gp_mm_t<64, false>(sz);
140 }
141 } else if(be) {
142 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, true>)>::get().allocate()) tlm_gp_mm_t<16, true>(sz);
143 } else {
144 return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, false>)>::get().allocate()) tlm_gp_mm_t<16, false>(sz);
145 }
146}
147
155template <typename TYPES>
156inline typename TYPES::tlm_payload_type* tlm::scc::tlm_gp_mm::add_data_ptr(size_t sz, typename TYPES::tlm_payload_type* gp, bool be) {
157 auto* ext = create(sz, be);
158 gp->set_auto_extension(ext);
159 gp->set_data_ptr(ext->data_ptr);
160 gp->set_data_length(sz);
161 gp->set_byte_enable_ptr(ext->be_ptr);
162 if(be)
163 gp->set_byte_enable_length(sz);
164 return gp;
165}
166
169template <typename EXT> struct tlm_ext_mm : public EXT {
170
171 friend tlm_gp_mm;
172
173 ~tlm_ext_mm() {}
174
175 void free() override { util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().free(this); }
176
177 EXT* clone() const override { return create(*this); }
178
179 template <typename... Args> static EXT* create(Args... args) {
180 return new(util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().allocate()) tlm_ext_mm<EXT>(args...);
181 }
182
183protected:
184 template <typename... Args>
185 tlm_ext_mm(Args... args)
186 : EXT(args...) {}
187};
188template <typename TYPES> struct tlm_mm_traits { using mm_if_type = tlm::tlm_mm_interface; };
196template <typename TYPES, bool CLEANUP_DATA, typename BASE> class tlm_mm_t : public BASE {
197 using payload_type = typename TYPES::tlm_payload_type;
198 using payload_base = typename tlm_mm_traits<TYPES>::payload_base;
199 static_assert(!std::is_base_of<tlm::tlm_generic_payload, typename TYPES::tlm_payload_type>::value, "Using cxs::tlm_network_cxs_types");
200
201public:
202 tlm_mm_t()
203 : allocator(util::pool_allocator<sizeof(payload_type)>::get()) {}
204
205 tlm_mm_t(const tlm_mm_t&) = delete;
206
207 tlm_mm_t(tlm_mm_t&&) = delete;
208
209 tlm_mm_t& operator=(const tlm_mm_t& other) = delete;
210
211 tlm_mm_t& operator=(tlm_mm_t&& other) = delete;
212
213 ~tlm_mm_t() = default;
218 payload_type* allocate() {
219 auto* ptr = allocator.allocate(sc_core::sc_time_stamp().value());
220 return new(ptr) payload_type(this);
221 }
222
226 template <typename PEXT> payload_type* allocate() {
227 auto* ptr = allocate();
228 ptr->set_auto_extension(new PEXT);
229 return ptr;
230 }
231
235 void free(payload_base* trans) {
236 trans->~payload_base();
237 allocator.free(trans);
238 }
239
240private:
241 util::pool_allocator<sizeof(payload_type)>& allocator;
242};
243
250template <typename TYPES, bool CLEANUP_DATA> class tlm_mm_t<TYPES, CLEANUP_DATA, tlm::tlm_mm_interface> : public tlm::tlm_mm_interface {
251 using payload_type = typename TYPES::tlm_payload_type;
252
253public:
254 tlm_mm_t()
255 : allocator(util::pool_allocator<sizeof(payload_type)>::get()) {}
256
257 tlm_mm_t(const tlm_mm_t&) = delete;
258
259 tlm_mm_t(tlm_mm_t&&) = delete;
260
261 tlm_mm_t& operator=(const tlm_mm_t& other) = delete;
262
263 tlm_mm_t& operator=(tlm_mm_t&& other) = delete;
264
265 ~tlm_mm_t() = default;
270 payload_type* allocate() {
271 auto* ptr = allocator.allocate(sc_core::sc_time_stamp().value());
272 return new(ptr) payload_type(this);
273 }
274
278 template <typename PEXT> payload_type* allocate() {
279 auto* ptr = allocate();
280 ptr->set_auto_extension(new PEXT);
281 return ptr;
282 }
283
287 payload_type* allocate(size_t sz, bool be = false) { return sz ? tlm_gp_mm::add_data_ptr(sz, allocate(), be) : allocate(); }
293 template <typename PEXT> payload_type* allocate(size_t sz, bool be = false) {
294 auto* ptr = allocate(sz, be);
295 ptr->set_auto_extension(tlm_ext_mm<PEXT>::create());
296 return ptr;
297 }
298
302 void free(tlm::tlm_generic_payload* trans) {
303 if(CLEANUP_DATA && !trans->get_extension<tlm_gp_mm>()) {
304 if(trans->get_data_ptr())
305 delete[] trans->get_data_ptr();
306 if(trans->get_byte_enable_ptr())
307 delete[] trans->get_byte_enable_ptr();
308 }
309 trans->set_data_ptr(nullptr);
310 trans->set_byte_enable_ptr(nullptr);
311 trans->reset();
312 trans->~tlm_generic_payload();
313 allocator.free(trans);
314 }
315
316private:
317 util::pool_allocator<sizeof(payload_type)>& allocator;
318};
319
326template <typename TYPES = tlm_base_protocol_types, bool CLEANUP_DATA = true>
327struct tlm_mm
328: public tlm_mm_t<TYPES, CLEANUP_DATA,
329 typename std::conditional<std::is_base_of<tlm::tlm_generic_payload, typename TYPES::tlm_payload_type>::value,
330 tlm::tlm_mm_interface, typename tlm_mm_traits<TYPES>::mm_if_type>::type> {
335 static tlm_mm& get();
336};
337
338template <typename TYPES, bool CLEANUP_DATA> inline tlm_mm<TYPES, CLEANUP_DATA>& tlm_mm<TYPES, CLEANUP_DATA>::get() {
340 return mm;
341}
342} // namespace scc
343} // namespace tlm
344
345#endif /* _TLM_TLM_MM_H_ */
payload_type * allocate(size_t sz, bool be=false)
get a plain tlm_payload_type without extensions but initialized data and byte enable
Definition tlm_mm.h:287
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition tlm_mm.h:270
void free(tlm::tlm_generic_payload *trans)
return the extension into the memory pool (removing the extensions)
Definition tlm_mm.h:302
payload_type * allocate()
get a tlm_payload_type with registered extension
Definition tlm_mm.h:278
payload_type * allocate(size_t sz, bool be=false)
get a tlm_payload_type with registered extension and initialize data pointer
Definition tlm_mm.h:293
void free(payload_base *trans)
return the extension into the memory pool (removing the extensions)
Definition tlm_mm.h:235
payload_type * allocate()
get a tlm_payload_type with registered extension
Definition tlm_mm.h:226
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition tlm_mm.h:218
a generic pool allocator singleton not being MT-safe
void free(void *p)
pit the memory back into the pool
SCC TLM utilities.
Definition axis_tlm.h:56
SystemC TLM.
Definition dmi_mgr.h:19
Creates a new tlm_gp_mm object with fixed size.
Definition tlm_mm.h:77
virtual ~tlm_gp_mm_t()
Definition tlm_mm.h:83
void free() override
Definition tlm_mm.h:87
Memory management for TLM generic payload data.
Definition tlm_mm.h:41
static tlm_gp_mm * create(size_t sz, bool be=false)
Creates a new tlm_gp_mm object with a dynamically allocated buffer.
Definition tlm_mm.h:114
a tlm memory manager
Definition tlm_mm.h:330
static tlm_mm & get()
accessor function of the singleton
Definition tlm_mm.h:338