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