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#include <cstring> // std::memcpy et.al. 21#include <map> 22#include <systemc> 23#include <tlm>
| 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#include <cstring> // std::memcpy et.al. 21#include <map> 22#include <systemc> 23#include <tlm>
|
56 { 57 type_map::const_iterator it = ids_.find(type); 58 59 if (it == ids_.end()) { 60 // New extension - generate/store ID. 61 type_map::value_type v(type, static_cast<key_type>(ids_.size())); 62 ids_.insert(v); 63 return v.second; 64 } 65 return it->second; 66 } 67 68 static unsigned int 69 max_num_extensions() 70 { 71 return (instance_) ? instance().ids_.size() : 0; 72 } 73 74 private: 75 static tlm_extension_registry *instance_; 76 type_map ids_; 77 tlm_extension_registry() {} 78 79}; 80 81tlm_extension_registry *tlm_extension_registry::instance_ = NULL; 82 83} // anonymous namespace 84 85unsigned int 86max_num_extensions() 87{ 88 return tlm_extension_registry::max_num_extensions(); 89} 90 91unsigned int 92tlm_extension_base::register_extension(const std::type_info &type) 93{ 94 return tlm_extension_registry::instance().register_extension(type); 95} 96 97//--------------------------------------------------------------------------- 98// The generic payload class: 99//--------------------------------------------------------------------------- 100 101tlm_generic_payload::tlm_generic_payload() : m_address(0), 102 m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 103 m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 104 m_byte_enable_length(0), m_streaming_width(0), 105 m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(0), 106 m_ref_count(0) 107{} 108 109tlm_generic_payload::tlm_generic_payload(tlm_mm_interface *mm): m_address(0), 110 m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 111 m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 112 m_byte_enable_length(0), m_streaming_width(0), 113 m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(mm), 114 m_ref_count(0) 115{} 116 117void 118tlm_generic_payload::reset() 119{ 120 // Should the other members be reset too? 121 m_gp_option = TLM_MIN_PAYLOAD; 122 m_extensions.free_entire_cache(); 123}; 124 125// Non-virtual deep-copying of the object. 126void 127tlm_generic_payload::deep_copy_from(const tlm_generic_payload &other) 128{ 129 m_command = other.get_command(); 130 m_address = other.get_address(); 131 m_length = other.get_data_length(); 132 m_response_status = other.get_response_status(); 133 m_byte_enable_length = other.get_byte_enable_length(); 134 m_streaming_width = other.get_streaming_width(); 135 m_gp_option = other.get_gp_option(); 136 m_dmi = other.is_dmi_allowed(); 137 138 // Deep copy data. 139 // There must be enough space in the target transaction! 140 if (m_data && other.m_data) { 141 std::memcpy(m_data, other.m_data, m_length); 142 } 143 // Deep copy byte enables. 144 // There must be enough space in the target transaction! 145 if (m_byte_enable && other.m_byte_enable) { 146 std::memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length); 147 } 148 // Deep copy extensions (sticky and non-sticky). 149 if (m_extensions.size() < other.m_extensions.size()) { 150 m_extensions.expand(other.m_extensions.size()); 151 } 152 for (unsigned int i = 0; i < other.m_extensions.size(); i++) { 153 if (other.m_extensions[i]) { 154 // Original has extension i. 155 if (!m_extensions[i]) { 156 // We don't: clone. 157 tlm_extension_base *ext = other.m_extensions[i]->clone(); 158 if (ext) { // Extension may not be clonable. 159 if (has_mm()) { 160 // mm can take care of removing cloned extensions. 161 set_auto_extension(i, ext); 162 } else { 163 // no mm, user will call free_all_extensions(). 164 set_extension(i, ext); 165 } 166 } 167 } else { 168 // We already have such extension. Copy original over it. 169 m_extensions[i]->copy_from(*other.m_extensions[i]); 170 } 171 } 172 } 173} 174 175// To update the state of the original generic payload from a deep copy. 176// Assumes that "other" was created from the original by calling 177// deep_copy_from. Argument use_byte_enable_on_read determines whether to use 178// or ignores byte enables when copying back the data array on a read command. 179 180void 181tlm_generic_payload::update_original_from( 182 const tlm_generic_payload &other, bool use_byte_enable_on_read) 183{ 184 // Copy back extensions that are present on the original. 185 update_extensions_from(other); 186 187 // Copy back the response status and DMI hint attributes. 188 m_response_status = other.get_response_status(); 189 m_dmi = other.is_dmi_allowed(); 190 191 // Copy back the data array for a read command only deep_copy_from allowed 192 // null pointers, and so will we. 193 // We assume the arrays are the same size. 194 // We test for equal pointers in case the original and the copy share the 195 // same array. 196 197 if (is_read() && m_data && other.m_data && m_data != other.m_data) { 198 if (m_byte_enable && use_byte_enable_on_read) { 199 if (m_byte_enable_length == 8 && m_length % 8 == 0) { 200 // Optimized implementation copies 64-bit words by masking. 201 for (unsigned int i = 0; i < m_length; i += 8) { 202 typedef sc_dt::uint64 *u; 203 *reinterpret_cast<u>(&m_data[i]) &= 204 ~*reinterpret_cast<u>(m_byte_enable); 205 *reinterpret_cast<u>(&m_data[i]) |= 206 *reinterpret_cast<u>(&other.m_data[i]) & 207 *reinterpret_cast<u>(m_byte_enable); 208 } 209 } else if (m_byte_enable_length == 4 && m_length % 4 == 0) { 210 // Optimized implementation copies 32-bit words by masking. 211 for (unsigned int i = 0; i < m_length; i += 4) { 212 typedef unsigned int *u; 213 *reinterpret_cast<u>(&m_data[i]) &= 214 ~*reinterpret_cast<u>(m_byte_enable); 215 *reinterpret_cast<u>(&m_data[i]) |= 216 *reinterpret_cast<u>(&other.m_data[i]) & 217 *reinterpret_cast<u>(m_byte_enable); 218 } 219 } else { 220 // Unoptimized implementation. 221 for (unsigned int i = 0; i < m_length; i++) { 222 if (m_byte_enable[i % m_byte_enable_length]) 223 m_data[i] = other.m_data[i]; 224 } 225 } 226 } else { 227 std::memcpy(m_data, other.m_data, m_length); 228 } 229 } 230} 231 232void 233tlm_generic_payload::update_extensions_from(const tlm_generic_payload &other) 234{ 235 // Deep copy extensions that are already present. 236 sc_assert(m_extensions.size() <= other.m_extensions.size()); 237 for (unsigned int i = 0; i < m_extensions.size(); i++) { 238 if (other.m_extensions[i]) { 239 // Original has extension i. 240 if (m_extensions[i]) { 241 // We have it too. Copy. 242 m_extensions[i]->copy_from(*other.m_extensions[i]); 243 } 244 } 245 } 246} 247 248// Free all extensions. Useful when reusing a cloned transaction that doesn't 249// have memory manager. Normal and sticky extensions are freed and extension 250// array cleared. 251void 252tlm_generic_payload::free_all_extensions() 253{ 254 m_extensions.free_entire_cache(); 255 for (unsigned int i = 0; i < m_extensions.size(); i++) { 256 if (m_extensions[i]) { 257 m_extensions[i]->free(); 258 m_extensions[i] = 0; 259 } 260 } 261} 262 263tlm_generic_payload::~tlm_generic_payload() 264{ 265 for (unsigned int i = 0; i < m_extensions.size(); i++) { 266 if (m_extensions[i]) 267 m_extensions[i]->free(); 268 } 269} 270 271//---------------- 272// API (including setters & getters) 273//--------------- 274 275std::string 276tlm_generic_payload::get_response_string() const 277{ 278 switch (m_response_status) { 279 case TLM_OK_RESPONSE: 280 return "TLM_OK_RESPONSE"; 281 case TLM_INCOMPLETE_RESPONSE: 282 return "TLM_INCOMPLETE_RESPONSE"; 283 case TLM_GENERIC_ERROR_RESPONSE: 284 return "TLM_GENERIC_ERROR_RESPONSE"; 285 case TLM_ADDRESS_ERROR_RESPONSE: 286 return "TLM_ADDRESS_ERROR_RESPONSE"; 287 case TLM_COMMAND_ERROR_RESPONSE: 288 return "TLM_COMMAND_ERROR_RESPONSE"; 289 case TLM_BURST_ERROR_RESPONSE: 290 return "TLM_BURST_ERROR_RESPONSE"; 291 case TLM_BYTE_ENABLE_ERROR_RESPONSE: 292 return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; 293 } 294 return "TLM_UNKNOWN_RESPONSE"; 295} 296 297/* --------------------------------------------------------------------- */ 298/* Dynamic extension mechanism: */ 299/* --------------------------------------------------------------------- */ 300 301tlm_extension_base * 302tlm_generic_payload::set_extension(unsigned int index, tlm_extension_base *ext) 303{ 304 sc_assert(index < m_extensions.size()); 305 tlm_extension_base *tmp = m_extensions[index]; 306 m_extensions[index] = ext; 307 return tmp; 308} 309 310tlm_extension_base * 311tlm_generic_payload::set_auto_extension( 312 unsigned int index, tlm_extension_base *ext) 313{ 314 sc_assert(index < m_extensions.size()); 315 tlm_extension_base *tmp = m_extensions[index]; 316 m_extensions[index] = ext; 317 if (!tmp) 318 m_extensions.insert_in_cache(&m_extensions[index]); 319 sc_assert(m_mm != 0); 320 return tmp; 321} 322 323tlm_extension_base * 324tlm_generic_payload::get_extension(unsigned int index) const 325{ 326 sc_assert(index < m_extensions.size()); 327 return m_extensions[index]; 328} 329 330void 331tlm_generic_payload::clear_extension(unsigned int index) 332{ 333 sc_assert(index < m_extensions.size()); 334 m_extensions[index] = static_cast<tlm_extension_base *>(0); 335} 336 337void 338tlm_generic_payload::release_extension(unsigned int index) 339{ 340 sc_assert(index < m_extensions.size()); 341 if (m_mm) { 342 m_extensions.insert_in_cache(&m_extensions[index]); 343 } else { 344 m_extensions[index]->free(); 345 m_extensions[index] = static_cast<tlm_extension_base *>(nullptr); 346 } 347} 348 349void 350tlm_generic_payload::resize_extensions() 351{ 352 m_extensions.expand(max_num_extensions()); 353} 354 355} // namespace tlm
| 55 { 56 type_map::const_iterator it = ids_.find(type); 57 58 if (it == ids_.end()) { 59 // New extension - generate/store ID. 60 type_map::value_type v(type, static_cast<key_type>(ids_.size())); 61 ids_.insert(v); 62 return v.second; 63 } 64 return it->second; 65 } 66 67 static unsigned int 68 max_num_extensions() 69 { 70 return (instance_) ? instance().ids_.size() : 0; 71 } 72 73 private: 74 static tlm_extension_registry *instance_; 75 type_map ids_; 76 tlm_extension_registry() {} 77 78}; 79 80tlm_extension_registry *tlm_extension_registry::instance_ = NULL; 81 82} // anonymous namespace 83 84unsigned int 85max_num_extensions() 86{ 87 return tlm_extension_registry::max_num_extensions(); 88} 89 90unsigned int 91tlm_extension_base::register_extension(const std::type_info &type) 92{ 93 return tlm_extension_registry::instance().register_extension(type); 94} 95 96//--------------------------------------------------------------------------- 97// The generic payload class: 98//--------------------------------------------------------------------------- 99 100tlm_generic_payload::tlm_generic_payload() : m_address(0), 101 m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 102 m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 103 m_byte_enable_length(0), m_streaming_width(0), 104 m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(0), 105 m_ref_count(0) 106{} 107 108tlm_generic_payload::tlm_generic_payload(tlm_mm_interface *mm): m_address(0), 109 m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 110 m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 111 m_byte_enable_length(0), m_streaming_width(0), 112 m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(mm), 113 m_ref_count(0) 114{} 115 116void 117tlm_generic_payload::reset() 118{ 119 // Should the other members be reset too? 120 m_gp_option = TLM_MIN_PAYLOAD; 121 m_extensions.free_entire_cache(); 122}; 123 124// Non-virtual deep-copying of the object. 125void 126tlm_generic_payload::deep_copy_from(const tlm_generic_payload &other) 127{ 128 m_command = other.get_command(); 129 m_address = other.get_address(); 130 m_length = other.get_data_length(); 131 m_response_status = other.get_response_status(); 132 m_byte_enable_length = other.get_byte_enable_length(); 133 m_streaming_width = other.get_streaming_width(); 134 m_gp_option = other.get_gp_option(); 135 m_dmi = other.is_dmi_allowed(); 136 137 // Deep copy data. 138 // There must be enough space in the target transaction! 139 if (m_data && other.m_data) { 140 std::memcpy(m_data, other.m_data, m_length); 141 } 142 // Deep copy byte enables. 143 // There must be enough space in the target transaction! 144 if (m_byte_enable && other.m_byte_enable) { 145 std::memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length); 146 } 147 // Deep copy extensions (sticky and non-sticky). 148 if (m_extensions.size() < other.m_extensions.size()) { 149 m_extensions.expand(other.m_extensions.size()); 150 } 151 for (unsigned int i = 0; i < other.m_extensions.size(); i++) { 152 if (other.m_extensions[i]) { 153 // Original has extension i. 154 if (!m_extensions[i]) { 155 // We don't: clone. 156 tlm_extension_base *ext = other.m_extensions[i]->clone(); 157 if (ext) { // Extension may not be clonable. 158 if (has_mm()) { 159 // mm can take care of removing cloned extensions. 160 set_auto_extension(i, ext); 161 } else { 162 // no mm, user will call free_all_extensions(). 163 set_extension(i, ext); 164 } 165 } 166 } else { 167 // We already have such extension. Copy original over it. 168 m_extensions[i]->copy_from(*other.m_extensions[i]); 169 } 170 } 171 } 172} 173 174// To update the state of the original generic payload from a deep copy. 175// Assumes that "other" was created from the original by calling 176// deep_copy_from. Argument use_byte_enable_on_read determines whether to use 177// or ignores byte enables when copying back the data array on a read command. 178 179void 180tlm_generic_payload::update_original_from( 181 const tlm_generic_payload &other, bool use_byte_enable_on_read) 182{ 183 // Copy back extensions that are present on the original. 184 update_extensions_from(other); 185 186 // Copy back the response status and DMI hint attributes. 187 m_response_status = other.get_response_status(); 188 m_dmi = other.is_dmi_allowed(); 189 190 // Copy back the data array for a read command only deep_copy_from allowed 191 // null pointers, and so will we. 192 // We assume the arrays are the same size. 193 // We test for equal pointers in case the original and the copy share the 194 // same array. 195 196 if (is_read() && m_data && other.m_data && m_data != other.m_data) { 197 if (m_byte_enable && use_byte_enable_on_read) { 198 if (m_byte_enable_length == 8 && m_length % 8 == 0) { 199 // Optimized implementation copies 64-bit words by masking. 200 for (unsigned int i = 0; i < m_length; i += 8) { 201 typedef sc_dt::uint64 *u; 202 *reinterpret_cast<u>(&m_data[i]) &= 203 ~*reinterpret_cast<u>(m_byte_enable); 204 *reinterpret_cast<u>(&m_data[i]) |= 205 *reinterpret_cast<u>(&other.m_data[i]) & 206 *reinterpret_cast<u>(m_byte_enable); 207 } 208 } else if (m_byte_enable_length == 4 && m_length % 4 == 0) { 209 // Optimized implementation copies 32-bit words by masking. 210 for (unsigned int i = 0; i < m_length; i += 4) { 211 typedef unsigned int *u; 212 *reinterpret_cast<u>(&m_data[i]) &= 213 ~*reinterpret_cast<u>(m_byte_enable); 214 *reinterpret_cast<u>(&m_data[i]) |= 215 *reinterpret_cast<u>(&other.m_data[i]) & 216 *reinterpret_cast<u>(m_byte_enable); 217 } 218 } else { 219 // Unoptimized implementation. 220 for (unsigned int i = 0; i < m_length; i++) { 221 if (m_byte_enable[i % m_byte_enable_length]) 222 m_data[i] = other.m_data[i]; 223 } 224 } 225 } else { 226 std::memcpy(m_data, other.m_data, m_length); 227 } 228 } 229} 230 231void 232tlm_generic_payload::update_extensions_from(const tlm_generic_payload &other) 233{ 234 // Deep copy extensions that are already present. 235 sc_assert(m_extensions.size() <= other.m_extensions.size()); 236 for (unsigned int i = 0; i < m_extensions.size(); i++) { 237 if (other.m_extensions[i]) { 238 // Original has extension i. 239 if (m_extensions[i]) { 240 // We have it too. Copy. 241 m_extensions[i]->copy_from(*other.m_extensions[i]); 242 } 243 } 244 } 245} 246 247// Free all extensions. Useful when reusing a cloned transaction that doesn't 248// have memory manager. Normal and sticky extensions are freed and extension 249// array cleared. 250void 251tlm_generic_payload::free_all_extensions() 252{ 253 m_extensions.free_entire_cache(); 254 for (unsigned int i = 0; i < m_extensions.size(); i++) { 255 if (m_extensions[i]) { 256 m_extensions[i]->free(); 257 m_extensions[i] = 0; 258 } 259 } 260} 261 262tlm_generic_payload::~tlm_generic_payload() 263{ 264 for (unsigned int i = 0; i < m_extensions.size(); i++) { 265 if (m_extensions[i]) 266 m_extensions[i]->free(); 267 } 268} 269 270//---------------- 271// API (including setters & getters) 272//--------------- 273 274std::string 275tlm_generic_payload::get_response_string() const 276{ 277 switch (m_response_status) { 278 case TLM_OK_RESPONSE: 279 return "TLM_OK_RESPONSE"; 280 case TLM_INCOMPLETE_RESPONSE: 281 return "TLM_INCOMPLETE_RESPONSE"; 282 case TLM_GENERIC_ERROR_RESPONSE: 283 return "TLM_GENERIC_ERROR_RESPONSE"; 284 case TLM_ADDRESS_ERROR_RESPONSE: 285 return "TLM_ADDRESS_ERROR_RESPONSE"; 286 case TLM_COMMAND_ERROR_RESPONSE: 287 return "TLM_COMMAND_ERROR_RESPONSE"; 288 case TLM_BURST_ERROR_RESPONSE: 289 return "TLM_BURST_ERROR_RESPONSE"; 290 case TLM_BYTE_ENABLE_ERROR_RESPONSE: 291 return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; 292 } 293 return "TLM_UNKNOWN_RESPONSE"; 294} 295 296/* --------------------------------------------------------------------- */ 297/* Dynamic extension mechanism: */ 298/* --------------------------------------------------------------------- */ 299 300tlm_extension_base * 301tlm_generic_payload::set_extension(unsigned int index, tlm_extension_base *ext) 302{ 303 sc_assert(index < m_extensions.size()); 304 tlm_extension_base *tmp = m_extensions[index]; 305 m_extensions[index] = ext; 306 return tmp; 307} 308 309tlm_extension_base * 310tlm_generic_payload::set_auto_extension( 311 unsigned int index, tlm_extension_base *ext) 312{ 313 sc_assert(index < m_extensions.size()); 314 tlm_extension_base *tmp = m_extensions[index]; 315 m_extensions[index] = ext; 316 if (!tmp) 317 m_extensions.insert_in_cache(&m_extensions[index]); 318 sc_assert(m_mm != 0); 319 return tmp; 320} 321 322tlm_extension_base * 323tlm_generic_payload::get_extension(unsigned int index) const 324{ 325 sc_assert(index < m_extensions.size()); 326 return m_extensions[index]; 327} 328 329void 330tlm_generic_payload::clear_extension(unsigned int index) 331{ 332 sc_assert(index < m_extensions.size()); 333 m_extensions[index] = static_cast<tlm_extension_base *>(0); 334} 335 336void 337tlm_generic_payload::release_extension(unsigned int index) 338{ 339 sc_assert(index < m_extensions.size()); 340 if (m_mm) { 341 m_extensions.insert_in_cache(&m_extensions[index]); 342 } else { 343 m_extensions[index]->free(); 344 m_extensions[index] = static_cast<tlm_extension_base *>(nullptr); 345 } 346} 347 348void 349tlm_generic_payload::resize_extensions() 350{ 351 m_extensions.expand(max_num_extensions()); 352} 353 354} // namespace tlm
|