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 // 12-Jan-2009 John Aynsley Bug fix. has_mm() and get_ref_count() should both be const 21 // 23-Mar-2009 John Aynsley Add method update_original_from() 22 // 20-Apr-2009 John Aynsley Bug fix for 64-bit machines: unsigned long int -> unsigned int 23 // 5-May-2011 JA and Philipp Hartmann Add tlm_gp_option, set_gp_option, get_gp_option 24 // 11-May-2011 John Aynsley Add run-time check to release() 25 26 27 #ifndef TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ 28 #define TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ 29 30 #include "sysc/kernel/sc_cmnhdr.h" // SC_API 31 #include "sysc/utils/sc_report.h" // sc_assert 32 #include "sysc/datatypes/int/sc_nbdefs.h" // sc_dt::uint64 33 34 #include "tlm_core/tlm_2/tlm_generic_payload/tlm_array.h" 35 36 #include <typeinfo> // std::type_info 37 38 namespace tlm { 39 40 class tlm_generic_payload; 41 42 class tlm_mm_interface { 43 public: 44 virtual void free(tlm_generic_payload*) = 0; ~tlm_mm_interface()45 virtual ~tlm_mm_interface() {} 46 }; 47 48 //--------------------------------------------------------------------------- 49 // Classes and helpers for the extension mechanism 50 //--------------------------------------------------------------------------- 51 // Helper function: 52 SC_API unsigned int max_num_extensions(); 53 54 // This class can be used for storing pointers to the extension classes, used 55 // in tlm_generic_payload: 56 class SC_API tlm_extension_base 57 { 58 public: 59 virtual tlm_extension_base* clone() const = 0; free()60 virtual void free() { delete this; } 61 virtual void copy_from(tlm_extension_base const &) = 0; 62 protected: ~tlm_extension_base()63 virtual ~tlm_extension_base() {} 64 static unsigned int register_extension(const std::type_info&); 65 }; 66 67 // Base class for all extension classes, derive your extension class in 68 // the following way: 69 // class my_extension : public tlm_extension<my_extension> { ... 70 // This triggers proper extension registration during C++ static 71 // contruction time. my_extension::ID will hold the unique index in the 72 // tlm_generic_payload::m_extensions array. 73 template <typename T> 74 class tlm_extension : public tlm_extension_base 75 { 76 public: 77 virtual tlm_extension_base* clone() const = 0; 78 virtual void copy_from(tlm_extension_base const &ext) = 0; ~tlm_extension()79 virtual ~tlm_extension() {} 80 const static unsigned int ID; 81 }; 82 83 template <typename T> 84 const unsigned int tlm_extension<T>::ID 85 = tlm_extension_base::register_extension(typeid(T)); 86 87 //--------------------------------------------------------------------------- 88 // enumeration types 89 //--------------------------------------------------------------------------- 90 enum tlm_command { 91 TLM_READ_COMMAND, 92 TLM_WRITE_COMMAND, 93 TLM_IGNORE_COMMAND 94 }; 95 96 enum tlm_response_status { 97 TLM_OK_RESPONSE = 1, 98 TLM_INCOMPLETE_RESPONSE = 0, 99 TLM_GENERIC_ERROR_RESPONSE = -1, 100 TLM_ADDRESS_ERROR_RESPONSE = -2, 101 TLM_COMMAND_ERROR_RESPONSE = -3, 102 TLM_BURST_ERROR_RESPONSE = -4, 103 TLM_BYTE_ENABLE_ERROR_RESPONSE = -5 104 }; 105 106 enum tlm_gp_option { 107 TLM_MIN_PAYLOAD, 108 TLM_FULL_PAYLOAD, 109 TLM_FULL_PAYLOAD_ACCEPTED 110 }; 111 112 #define TLM_BYTE_DISABLED 0x0 113 #define TLM_BYTE_ENABLED 0xff 114 115 //--------------------------------------------------------------------------- 116 // The generic payload class: 117 //--------------------------------------------------------------------------- 118 119 SC_API_TEMPLATE_DECL_ tlm_array<tlm_extension_base*>; 120 121 class SC_API tlm_generic_payload { 122 123 public: 124 //--------------- 125 // Constructors 126 //--------------- 127 128 // Default constructor 129 tlm_generic_payload(); 130 explicit tlm_generic_payload(tlm_mm_interface* mm); 131 acquire()132 void acquire() { sc_assert(m_mm != 0); m_ref_count++; } 133 release()134 void release() { 135 sc_assert(m_mm != 0 && m_ref_count > 0); 136 if (--m_ref_count==0) 137 m_mm->free(this); 138 } 139 get_ref_count()140 int get_ref_count() const { return m_ref_count; } 141 set_mm(tlm_mm_interface * mm)142 void set_mm(tlm_mm_interface* mm) { m_mm = mm; } has_mm()143 bool has_mm() const { return m_mm != 0; } 144 145 void reset(); 146 147 private: 148 //disabled copy ctor and assignment operator. 149 tlm_generic_payload(const tlm_generic_payload& x) /* = delete */; 150 tlm_generic_payload& operator= (const tlm_generic_payload& x) /* = delete */; 151 152 public: 153 // non-virtual deep-copying of the object 154 void deep_copy_from(const tlm_generic_payload & other); 155 156 // To update the state of the original generic payload from a deep copy 157 // Assumes that "other" was created from the original by calling deep_copy_from 158 // Argument use_byte_enable_on_read determines whether to use or ignores byte enables 159 // when copying back the data array on a read command 160 161 void update_original_from(const tlm_generic_payload & other, 162 bool use_byte_enable_on_read = true); 163 164 void update_extensions_from(const tlm_generic_payload & other); 165 166 // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager. 167 // normal and sticky extensions are freed and extension array cleared. 168 void free_all_extensions(); 169 170 //-------------- 171 // Destructor 172 //-------------- 173 virtual ~tlm_generic_payload(); 174 175 //---------------- 176 // API (including setters & getters) 177 //--------------- 178 179 // Command related method is_read()180 bool is_read() const {return (m_command == TLM_READ_COMMAND);} set_read()181 void set_read() {m_command = TLM_READ_COMMAND;} is_write()182 bool is_write() const {return (m_command == TLM_WRITE_COMMAND);} set_write()183 void set_write() {m_command = TLM_WRITE_COMMAND;} get_command()184 tlm_command get_command() const {return m_command;} set_command(const tlm_command command)185 void set_command(const tlm_command command) {m_command = command;} 186 187 // Address related methods get_address()188 sc_dt::uint64 get_address() const {return m_address;} set_address(const sc_dt::uint64 address)189 void set_address(const sc_dt::uint64 address) {m_address = address;} 190 191 // Data related methods get_data_ptr()192 unsigned char* get_data_ptr() const {return m_data;} set_data_ptr(unsigned char * data)193 void set_data_ptr(unsigned char* data) {m_data = data;} 194 195 // Transaction length (in bytes) related methods get_data_length()196 unsigned int get_data_length() const {return m_length;} set_data_length(const unsigned int length)197 void set_data_length(const unsigned int length) {m_length = length;} 198 199 // Response status related methods is_response_ok()200 bool is_response_ok() const {return (m_response_status > 0);} is_response_error()201 bool is_response_error() const {return (m_response_status <= 0);} get_response_status()202 tlm_response_status get_response_status() const {return m_response_status;} set_response_status(const tlm_response_status response_status)203 void set_response_status(const tlm_response_status response_status) 204 {m_response_status = response_status;} 205 std::string get_response_string() const; 206 207 // Streaming related methods get_streaming_width()208 unsigned int get_streaming_width() const {return m_streaming_width;} set_streaming_width(const unsigned int streaming_width)209 void set_streaming_width(const unsigned int streaming_width) {m_streaming_width = streaming_width; } 210 211 // Byte enable related methods get_byte_enable_ptr()212 unsigned char* get_byte_enable_ptr() const {return m_byte_enable;} set_byte_enable_ptr(unsigned char * byte_enable)213 void set_byte_enable_ptr(unsigned char* byte_enable){m_byte_enable = byte_enable;} get_byte_enable_length()214 unsigned int get_byte_enable_length() const {return m_byte_enable_length;} set_byte_enable_length(const unsigned int byte_enable_length)215 void set_byte_enable_length(const unsigned int byte_enable_length){m_byte_enable_length = byte_enable_length;} 216 217 // This is the "DMI-hint" a slave can set this to true if it 218 // wants to indicate that a DMI request would be supported: set_dmi_allowed(bool dmi_allowed)219 void set_dmi_allowed(bool dmi_allowed) { m_dmi = dmi_allowed; } is_dmi_allowed()220 bool is_dmi_allowed() const { return m_dmi; } 221 222 // Use full set of attributes in DMI/debug? get_gp_option()223 tlm_gp_option get_gp_option() const { return m_gp_option; } set_gp_option(const tlm_gp_option gp_opt)224 void set_gp_option( const tlm_gp_option gp_opt ) { m_gp_option = gp_opt; } 225 226 private: 227 228 /* --------------------------------------------------------------------- */ 229 /* Generic Payload attributes: */ 230 /* --------------------------------------------------------------------- */ 231 /* - m_command : Type of transaction. Three values supported: */ 232 /* - TLM_WRITE_COMMAND */ 233 /* - TLM_READ_COMMAND */ 234 /* - TLM_IGNORE_COMMAND */ 235 /* - m_address : Transaction base address (byte-addressing). */ 236 /* - m_data : When m_command = TLM_WRITE_COMMAND contains a */ 237 /* pointer to the data to be written in the target.*/ 238 /* When m_command = TLM_READ_COMMAND contains a */ 239 /* pointer where to copy the data read from the */ 240 /* target. */ 241 /* - m_length : Total number of bytes of the transaction. */ 242 /* - m_response_status : This attribute indicates whether an error has */ 243 /* occurred during the transaction. */ 244 /* Values supported are: */ 245 /* - TLM_OK_RESP */ 246 /* - TLM_INCOMPLETE_RESP */ 247 /* - TLM_GENERIC_ERROR_RESP */ 248 /* - TLM_ADDRESS_ERROR_RESP */ 249 /* - TLM_COMMAND_ERROR_RESP */ 250 /* - TLM_BURST_ERROR_RESP */ 251 /* - TLM_BYTE_ENABLE_ERROR_RESP */ 252 /* */ 253 /* - m_byte_enable : It can be used to create burst transfers where */ 254 /* the address increment between each beat is greater */ 255 /* than the word length of each beat, or to place */ 256 /* words in selected byte lanes of a bus. */ 257 /* - m_byte_enable_length : For a read or a write command, the target */ 258 /* interpret the byte enable length attribute as the */ 259 /* number of elements in the bytes enable array. */ 260 /* - m_streaming_width : */ 261 /* --------------------------------------------------------------------- */ 262 263 sc_dt::uint64 m_address; 264 tlm_command m_command; 265 unsigned char* m_data; 266 unsigned int m_length; 267 tlm_response_status m_response_status; 268 bool m_dmi; 269 unsigned char* m_byte_enable; 270 unsigned int m_byte_enable_length; 271 unsigned int m_streaming_width; 272 tlm_gp_option m_gp_option; 273 274 public: 275 276 /* --------------------------------------------------------------------- */ 277 /* Dynamic extension mechanism: */ 278 /* --------------------------------------------------------------------- */ 279 /* The extension mechanism is intended to enable initiator modules to */ 280 /* optionally and transparently add data fields to the */ 281 /* tlm_generic_payload. Target modules are free to check for extensions */ 282 /* and may or may not react to the data in the extension fields. The */ 283 /* definition of the extensions' semantics is solely in the */ 284 /* responsibility of the user. */ 285 /* */ 286 /* The following rules apply: */ 287 /* */ 288 /* - Every extension class must be derived from tlm_extension, e.g.: */ 289 /* class my_extension : public tlm_extension<my_extension> { ... } */ 290 /* */ 291 /* - A tlm_generic_payload object should be constructed after C++ */ 292 /* static initialization time. This way it is guaranteed that the */ 293 /* extension array is of sufficient size to hold all possible */ 294 /* extensions. Alternatively, the initiator module can enforce a valid */ 295 /* extension array size by calling the resize_extensions() method */ 296 /* once before the first transaction with the payload object is */ 297 /* initiated. */ 298 /* */ 299 /* - Initiators should use the the set_extension(e) or clear_extension(e)*/ 300 /* methods for manipulating the extension array. The type of the */ 301 /* argument must be a pointer to the specific registered extension */ 302 /* type (my_extension in the above example) and is used to */ 303 /* automatically locate the appropriate index in the array. */ 304 /* */ 305 /* - Targets can check for a specific extension by calling */ 306 /* get_extension(e). e will point to zero if the extension is not */ 307 /* present. */ 308 /* */ 309 /* --------------------------------------------------------------------- */ 310 311 // Stick the pointer to an extension into the vector, return the 312 // previous value: set_extension(T * ext)313 template <typename T> T* set_extension(T* ext) 314 { 315 return static_cast<T*>(set_extension(T::ID, ext)); 316 } 317 318 // non-templatized version with manual index: 319 tlm_extension_base* set_extension(unsigned int index, 320 tlm_extension_base* ext); 321 322 // Stick the pointer to an extension into the vector, return the 323 // previous value and schedule its release set_auto_extension(T * ext)324 template <typename T> T* set_auto_extension(T* ext) 325 { 326 return static_cast<T*>(set_auto_extension(T::ID, ext)); 327 } 328 329 // non-templatized version with manual index: 330 tlm_extension_base* set_auto_extension(unsigned int index, 331 tlm_extension_base* ext); 332 333 // Check for an extension, ext will point to 0 if not present get_extension(T * & ext)334 template <typename T> void get_extension(T*& ext) const 335 { 336 ext = get_extension<T>(); 337 } get_extension()338 template <typename T> T* get_extension() const 339 { 340 return static_cast<T*>(get_extension(T::ID)); 341 } 342 // Non-templatized version with manual index: 343 tlm_extension_base* get_extension(unsigned int index) const; 344 345 //this call just removes the extension from the txn but does not 346 // call free() or tells the MM to do so 347 // it return false if there was active MM so you are now in an unsafe situation 348 // recommended use: when 100% sure there is no MM clear_extension(const T * ext)349 template <typename T> void clear_extension(const T* ext) 350 { 351 clear_extension<T>(); 352 } 353 354 //this call just removes the extension from the txn but does not 355 // call free() or tells the MM to do so 356 // it return false if there was active MM so you are now in an unsafe situation 357 // recommended use: when 100% sure there is no MM clear_extension()358 template <typename T> void clear_extension() 359 { 360 clear_extension(T::ID); 361 } 362 363 //this call removes the extension from the txn and does 364 // call free() or tells the MM to do so when the txn is finally done 365 // recommended use: when not sure there is no MM release_extension(T * ext)366 template <typename T> void release_extension(T* ext) 367 { 368 release_extension<T>(); 369 } 370 371 //this call removes the extension from the txn and does 372 // call free() or tells the MM to do so when the txn is finally done 373 // recommended use: when not sure there is no MM release_extension()374 template <typename T> void release_extension() 375 { 376 release_extension(T::ID); 377 } 378 379 private: 380 // Non-templatized version with manual index 381 void clear_extension(unsigned int index); 382 // Non-templatized version with manual index 383 void release_extension(unsigned int index); 384 385 public: 386 // Make sure the extension array is large enough. Can be called once by 387 // an initiator module (before issuing the first transaction) to make 388 // sure that the extension array is of correct size. This is only needed 389 // if the initiator cannot guarantee that the generic payload object is 390 // allocated after C++ static construction time. 391 void resize_extensions(); 392 393 private: 394 tlm_array<tlm_extension_base*> m_extensions; 395 tlm_mm_interface* m_mm; 396 unsigned int m_ref_count; 397 }; 398 399 } // namespace tlm 400 401 402 #endif /* TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ */ 403