scc  2024.06
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
30 namespace tlm {
32 namespace scc {
33 
34 struct tlm_gp_mm : public tlm_extension<tlm_gp_mm> {
35  virtual ~tlm_gp_mm() {}
36 
37  void copy_from(ATTR_UNUSED tlm_extension_base const& from) override {
38  // No need to copy, because this extension is used for memory handling for tlm generic payload data.
39  // The copy operation of the data is therefore handled by the tlm functions deep_copy_from and update_original_from.
40  }
41 
42  tlm_gp_mm* clone() const override { return tlm_gp_mm::create(data_size); }
43 
44  size_t const data_size;
45  uint8_t* const data_ptr;
46  uint8_t* const be_ptr;
47 
48  static tlm_gp_mm* create(size_t sz, bool be = false);
49 
50  template <typename TYPES = tlm_base_protocol_types>
51  static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type& gp, bool be = false) {
52  return add_data_ptr(sz, &gp, be);
53  }
54  template <typename TYPES = tlm_base_protocol_types>
55  static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type* gp, bool be = false);
56 
57 protected:
58  tlm_gp_mm(size_t sz, uint8_t* data_ptr, uint8_t* be_ptr)
59  : data_size(sz)
60  , data_ptr(data_ptr)
61  , be_ptr(be_ptr) {}
62 };
63 
64 template <size_t SZ, bool BE = false> struct tlm_gp_mm_t : public tlm_gp_mm {
65 
66  friend tlm_gp_mm;
67 
68  virtual ~tlm_gp_mm_t() {}
69 
70  void free() override { util::pool_allocator<sizeof(tlm_gp_mm_t<SZ, BE>)>::get().free(this); }
71 
72 protected:
73  tlm_gp_mm_t(size_t sz)
74  : tlm_gp_mm(sz, data, BE ? be : nullptr) {}
75  uint8_t data[SZ];
76  uint8_t be[BE ? SZ : 0];
77 };
78 
79 struct tlm_gp_mm_v : public tlm_gp_mm {
80 
81  friend tlm_gp_mm;
82 
83  virtual ~tlm_gp_mm_v() { delete data_ptr; }
84 
85 protected:
86  tlm_gp_mm_v(size_t sz)
87  : tlm_gp_mm(sz, new uint8_t[sz], nullptr) {}
88 };
89 
90 inline tlm_gp_mm* tlm::scc::tlm_gp_mm::create(size_t sz, bool be) {
91  if(sz > 4096) {
92  return new tlm_gp_mm_v(sz);
93  } else if(sz > 1024) {
94  if(be) {
95  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, true>)>::get().allocate()) tlm_gp_mm_t<4096, true>(sz);
96  } else {
97  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, false>)>::get().allocate()) tlm_gp_mm_t<4096, false>(sz);
98  }
99  } else if(sz > 256) {
100  if(be) {
101  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, true>)>::get().allocate()) tlm_gp_mm_t<1024, true>(sz);
102  } else {
103  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, false>)>::get().allocate()) tlm_gp_mm_t<1024, false>(sz);
104  }
105  } else if(sz > 64) {
106  if(be) {
107  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, true>)>::get().allocate()) tlm_gp_mm_t<256, true>(sz);
108  } else {
109  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, false>)>::get().allocate()) tlm_gp_mm_t<256, false>(sz);
110  }
111  } else if(sz > 16) {
112  if(be) {
113  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, true>)>::get().allocate()) tlm_gp_mm_t<64, true>(sz);
114  } else {
115  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, false>)>::get().allocate()) tlm_gp_mm_t<64, false>(sz);
116  }
117  } else if(be) {
118  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, true>)>::get().allocate()) tlm_gp_mm_t<16, true>(sz);
119  } else {
120  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, false>)>::get().allocate()) tlm_gp_mm_t<16, false>(sz);
121  }
122 }
123 
124 template <typename TYPES>
125 inline typename TYPES::tlm_payload_type* tlm::scc::tlm_gp_mm::add_data_ptr(size_t sz, typename TYPES::tlm_payload_type* gp, bool be) {
126  auto* ext = create(sz, be);
127  gp->set_auto_extension(ext);
128  gp->set_data_ptr(ext->data_ptr);
129  gp->set_data_length(sz);
130  gp->set_byte_enable_ptr(ext->be_ptr);
131  if(be)
132  gp->set_byte_enable_length(sz);
133  return gp;
134 }
135 
136 template <typename EXT> struct tlm_ext_mm : public EXT {
137 
138  friend tlm_gp_mm;
139 
140  ~tlm_ext_mm() {}
141 
142  void free() override { util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().free(this); }
143 
144  EXT* clone() const override { return create(*this); }
145 
146  template <typename... Args> static EXT* create(Args... args) {
147  return new(util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().allocate()) tlm_ext_mm<EXT>(args...);
148  }
149 
150 protected:
151  template <typename... Args>
152  tlm_ext_mm(Args... args)
153  : EXT(args...) {}
154 };
155 template <typename TYPES> struct tlm_mm_traits { using mm_if_type = tlm::tlm_mm_interface; };
163 template <typename TYPES, bool CLEANUP_DATA, typename BASE> class tlm_mm_t : public BASE {
164  using payload_type = typename TYPES::tlm_payload_type;
165  using payload_base = typename tlm_mm_traits<TYPES>::payload_base;
166  static_assert(!std::is_base_of<tlm::tlm_generic_payload, typename TYPES::tlm_payload_type>::value, "Using cxs::tlm_network_cxs_types");
167 
168 public:
169  tlm_mm_t()
170  : allocator(util::pool_allocator<sizeof(payload_type)>::get()) {}
171 
172  tlm_mm_t(const tlm_mm_t&) = delete;
173 
174  tlm_mm_t(tlm_mm_t&&) = delete;
175 
176  tlm_mm_t& operator=(const tlm_mm_t& other) = delete;
177 
178  tlm_mm_t& operator=(tlm_mm_t&& other) = delete;
179 
180  ~tlm_mm_t() = default;
185  payload_type* allocate() {
186  auto* ptr = allocator.allocate(sc_core::sc_time_stamp().value());
187  return new(ptr) payload_type(this);
188  }
193  template <typename PEXT> payload_type* allocate() {
194  auto* ptr = allocate();
195  ptr->set_auto_extension(new PEXT);
196  return ptr;
197  }
202  void free(payload_base* trans) {
203  trans->~payload_base();
204  allocator.free(trans);
205  }
206 
207 private:
208  util::pool_allocator<sizeof(payload_type)>& allocator;
209 };
210 
211 template <typename TYPES, bool CLEANUP_DATA> class tlm_mm_t<TYPES, CLEANUP_DATA, tlm::tlm_mm_interface> : public tlm::tlm_mm_interface {
212  using payload_type = typename TYPES::tlm_payload_type;
213 
214 public:
215  tlm_mm_t()
216  : allocator(util::pool_allocator<sizeof(payload_type)>::get()) {}
217 
218  tlm_mm_t(const tlm_mm_t&) = delete;
219 
220  tlm_mm_t(tlm_mm_t&&) = delete;
221 
222  tlm_mm_t& operator=(const tlm_mm_t& other) = delete;
223 
224  tlm_mm_t& operator=(tlm_mm_t&& other) = delete;
225 
226  ~tlm_mm_t() = default;
231  payload_type* allocate() {
232  auto* ptr = allocator.allocate(sc_core::sc_time_stamp().value());
233  return new(ptr) payload_type(this);
234  }
239  template <typename PEXT> payload_type* allocate() {
240  auto* ptr = allocate();
241  ptr->set_auto_extension(new PEXT);
242  return ptr;
243  }
248  payload_type* allocate(size_t sz, bool be = false) { return sz ? tlm_gp_mm::add_data_ptr(sz, allocate(), be) : allocate(); }
254  template <typename PEXT> payload_type* allocate(size_t sz, bool be = false) {
255  auto* ptr = allocate(sz, be);
256  ptr->set_auto_extension(tlm_ext_mm<PEXT>::create());
257  return ptr;
258  }
263  void free(tlm::tlm_generic_payload* trans) {
264  if(CLEANUP_DATA && !trans->get_extension<tlm_gp_mm>()) {
265  if(trans->get_data_ptr())
266  delete[] trans->get_data_ptr();
267  if(trans->get_byte_enable_ptr())
268  delete[] trans->get_byte_enable_ptr();
269  }
270  trans->set_data_ptr(nullptr);
271  trans->set_byte_enable_ptr(nullptr);
272  trans->reset();
273  trans->~tlm_generic_payload();
274  allocator.free(trans);
275  }
276 
277 private:
278  util::pool_allocator<sizeof(payload_type)>& allocator;
279 };
280 
281 template <typename TYPES = tlm_base_protocol_types, bool CLEANUP_DATA = true>
282 struct tlm_mm
283 : public tlm_mm_t<TYPES, CLEANUP_DATA,
284  typename std::conditional<std::is_base_of<tlm::tlm_generic_payload, typename TYPES::tlm_payload_type>::value,
285  tlm::tlm_mm_interface, typename tlm_mm_traits<TYPES>::mm_if_type>::type> {
290  static tlm_mm& get();
291 };
292 
293 template <typename TYPES, bool CLEANUP_DATA> inline tlm_mm<TYPES, CLEANUP_DATA>& tlm_mm<TYPES, CLEANUP_DATA>::get() {
294  static tlm_mm<TYPES, CLEANUP_DATA> mm;
295  return mm;
296 }
297 } // namespace scc
298 } // namespace tlm
299 
300 #endif /* _TLM_TLM_MM_H_ */
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:231
void free(tlm::tlm_generic_payload *trans)
return the extension into the memory pool (removing the extensions)
Definition: tlm_mm.h:263
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:254
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:248
payload_type * allocate()
get a tlm_payload_type with registered extension
Definition: tlm_mm.h:239
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:185
payload_type * allocate()
get a tlm_payload_type with registered extension
Definition: tlm_mm.h:193
void free(payload_base *trans)
return the extension into the memory pool (removing the extensions)
Definition: tlm_mm.h:202
a generic pool allocator singleton not being MT-safe
void free(void *p)
pit the memory back into the pool
SCC TLM utilities.
SystemC TLM.
Definition: cxs_tlm.h:69
a tlm memory manager
Definition: tlm_mm.h:285
static tlm_mm & get()
accessor function of the singleton
Definition: tlm_mm.h:293