scc  2022.4.0
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 <util/pool_allocator.h>
22 
23 //#if defined(MSVC)
24 #define ATTR_UNUSED
25 //#else
26 //#define ATTR_UNUSED __attribute__((unused))
27 //#endif
29 namespace tlm {
31 namespace scc {
32 
33 struct tlm_gp_mm : public tlm_extension<tlm_gp_mm> {
34  virtual ~tlm_gp_mm() {}
35 
36  void copy_from(ATTR_UNUSED tlm_extension_base const& from) override {
37  // No need to copy, because this extension is used for memory handling for tlm generic payload data.
38  // The copy operation of the data is therefore handled by the tlm functions deep_copy_from and update_original_from.
39  }
40 
41  tlm_gp_mm* clone() const override { return tlm_gp_mm::create(data_size); }
42 
43  size_t const data_size;
44  uint8_t* const data_ptr;
45  uint8_t* const be_ptr;
46 
47  static tlm_gp_mm* create(size_t sz, bool be = false);
48 
49  template <typename TYPES = tlm_base_protocol_types>
50  static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type& gp, bool be = false) {
51  return add_data_ptr(sz, &gp, be);
52  }
53  template <typename TYPES = tlm_base_protocol_types>
54  static typename TYPES::tlm_payload_type* add_data_ptr(size_t sz, typename TYPES::tlm_payload_type* gp, bool be = false);
55 
56 protected:
57  tlm_gp_mm(size_t sz, uint8_t* data_ptr, uint8_t* be_ptr)
58  : data_size(sz)
59  , data_ptr(data_ptr)
60  , be_ptr(be_ptr) {}
61 };
62 
63 template <size_t SZ, bool BE = false> struct tlm_gp_mm_t : public tlm_gp_mm {
64 
65  friend tlm_gp_mm;
66 
67  virtual ~tlm_gp_mm_t() {}
68 
69  void free() override { util::pool_allocator<sizeof(tlm_gp_mm_t<SZ, BE>)>::get().free(this); }
70 
71 protected:
72  tlm_gp_mm_t(size_t sz)
73  : tlm_gp_mm(sz, data, BE ? be : nullptr) {}
74  uint8_t data[SZ];
75  uint8_t be[BE ? SZ : 0];
76 };
77 
78 struct tlm_gp_mm_v : public tlm_gp_mm {
79 
80  friend tlm_gp_mm;
81 
82  virtual ~tlm_gp_mm_v() { delete data_ptr; }
83 
84 protected:
85  tlm_gp_mm_v(size_t sz)
86  : tlm_gp_mm(sz, new uint8_t[sz], nullptr) {}
87 };
88 
89 inline tlm_gp_mm* tlm::scc::tlm_gp_mm::create(size_t sz, bool be) {
90  if(sz > 4096) {
91  return new tlm_gp_mm_v(sz);
92  } else if(sz > 1024) {
93  if(be) {
94  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, true>)>::get().allocate()) tlm_gp_mm_t<4096, true>(sz);
95  } else {
96  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<4096, false>)>::get().allocate()) tlm_gp_mm_t<4096, false>(sz);
97  }
98  } else if(sz > 256) {
99  if(be) {
100  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, true>)>::get().allocate()) tlm_gp_mm_t<1024, true>(sz);
101  } else {
102  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<1024, false>)>::get().allocate()) tlm_gp_mm_t<1024, false>(sz);
103  }
104  } else if(sz > 64) {
105  if(be) {
106  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, true>)>::get().allocate()) tlm_gp_mm_t<256, true>(sz);
107  } else {
108  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<256, false>)>::get().allocate()) tlm_gp_mm_t<256, false>(sz);
109  }
110  } else if(sz > 16) {
111  if(be) {
112  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, true>)>::get().allocate()) tlm_gp_mm_t<64, true>(sz);
113  } else {
114  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<64, false>)>::get().allocate()) tlm_gp_mm_t<64, false>(sz);
115  }
116  } else if(be) {
117  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, true>)>::get().allocate()) tlm_gp_mm_t<16, true>(sz);
118  } else {
119  return new(util::pool_allocator<sizeof(tlm_gp_mm_t<16, false>)>::get().allocate()) tlm_gp_mm_t<16, false>(sz);
120  }
121 }
122 
123 template <typename TYPES>
124 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) {
125  auto* ext = create(sz, be);
126  gp->set_auto_extension(ext);
127  gp->set_data_ptr(ext->data_ptr);
128  gp->set_data_length(sz);
129  gp->set_byte_enable_ptr(ext->be_ptr);
130  if(be)
131  gp->set_byte_enable_length(sz);
132  return gp;
133 }
134 
135 template <typename EXT> struct tlm_ext_mm : public EXT {
136 
137  friend tlm_gp_mm;
138 
139  ~tlm_ext_mm() {}
140 
141  void free() override { util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().free(this); }
142 
143  EXT* clone() const override { return create(*this); }
144 
145  template <typename... Args> static EXT* create(Args... args) {
146  return new(util::pool_allocator<sizeof(tlm_ext_mm<EXT>)>::get().allocate()) tlm_ext_mm<EXT>(args...);
147  }
148 
149 protected:
150  template <typename... Args>
151  tlm_ext_mm(Args... args)
152  : EXT(args...) {}
153 };
161 template <typename TYPES = tlm_base_protocol_types, bool CLEANUP_DATA = true> class tlm_mm : public tlm::tlm_mm_interface {
162  using payload_type = typename TYPES::tlm_payload_type;
163 
164 public:
169  static tlm_mm& get();
170 
171  tlm_mm()
172  : allocator(util::pool_allocator<sizeof(payload_type)>::get()) {}
173 
174  tlm_mm(const tlm_mm&) = delete;
175 
176  tlm_mm(tlm_mm&&) = delete;
177 
178  tlm_mm& operator=(const tlm_mm& other) = delete;
179 
180  tlm_mm& operator=(tlm_mm&& other) = delete;
181 
182  ~tlm_mm() = default;
187  payload_type* allocate();
192  template <typename PEXT> payload_type* allocate() {
193  auto* ptr = allocate();
194  ptr->set_auto_extension(new PEXT);
195  return ptr;
196  }
201  payload_type* allocate(size_t sz, bool be = false);
207  template <typename PEXT> payload_type* allocate(size_t sz, bool be = false) {
208  auto* ptr = allocate(sz, be);
209  ptr->set_auto_extension(tlm_ext_mm<PEXT>::create());
210  return ptr;
211  }
216  void free(tlm::tlm_generic_payload* trans) override;
217 
218 private:
219  util::pool_allocator<sizeof(payload_type)>& allocator;
220 };
221 
222 template <typename TYPES, bool CLEANUP_DATA> inline tlm_mm<TYPES, CLEANUP_DATA>& tlm_mm<TYPES, CLEANUP_DATA>::get() {
223  static tlm_mm<TYPES, CLEANUP_DATA> mm;
224  return mm;
225 }
226 
227 template <typename TYPES, bool CLEANUP_DATA>
228 inline typename tlm_mm<TYPES, CLEANUP_DATA>::payload_type* tlm_mm<TYPES, CLEANUP_DATA>::allocate() {
229  auto* ptr = allocator.allocate(sc_core::sc_time_stamp().value());
230  return new(ptr) payload_type(this);
231 }
232 
233 template <typename TYPES, bool CLEANUP_DATA>
234 inline typename tlm_mm<TYPES, CLEANUP_DATA>::payload_type* tlm_mm<TYPES, CLEANUP_DATA>::allocate(size_t sz, bool be) {
235  return sz ? tlm_gp_mm::add_data_ptr(sz, allocate(), be) : allocate();
236 }
237 
238 template <typename TYPES, bool CLEANUP_DATA> void tlm_mm<TYPES, CLEANUP_DATA>::free(tlm::tlm_generic_payload* trans) {
239  if(CLEANUP_DATA && !trans->get_extension<tlm_gp_mm>()) {
240  if(trans->get_data_ptr())
241  delete[] trans->get_data_ptr();
242  trans->set_data_ptr(nullptr);
243  if(trans->get_byte_enable_ptr())
244  delete[] trans->get_byte_enable_ptr();
245  trans->set_byte_enable_ptr(nullptr);
246  }
247  trans->reset();
248  trans->~tlm_generic_payload();
249  allocator.free(trans);
250 }
251 
252 } // namespace scc
253 } // namespace tlm
254 
255 #endif /* _TLM_TLM_MM_H_ */
a tlm memory manager
Definition: tlm_mm.h:161
payload_type * allocate()
get a tlm_payload_type with registered extension
Definition: tlm_mm.h:192
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:228
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:207
void free(tlm::tlm_generic_payload *trans) override
return the extension into the memory pool (removing the extensions)
Definition: tlm_mm.h:238
static tlm_mm & get()
accessor function of the singleton
Definition: tlm_mm.h:222
a generic pool allocator singleton not being MT-safe
void free(void *p)
pit the memory back into the pool
SCC SystemC utilities.
SystemC TLM.