00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef __TLM_GP_H__
00024 #define __TLM_GP_H__
00025
00026 #include <systemc>
00027 #include "tlm_array.h"
00028
00029 namespace tlm {
00030
00031 class
00032 tlm_generic_payload;
00033
00034 class tlm_mm_interface {
00035 public:
00036 virtual void free(tlm_generic_payload*) = 0;
00037 virtual ~tlm_mm_interface() {}
00038 };
00039
00040
00041
00042
00043
00044 inline unsigned int max_num_extensions(bool increment=false)
00045 {
00046 static unsigned int max_num = 0;
00047 if (increment) ++max_num;
00048 return max_num;
00049 }
00050
00051
00052
00053 class tlm_extension_base
00054 {
00055 public:
00056 virtual tlm_extension_base* clone() const = 0;
00057 virtual void free() { delete this; }
00058 virtual void copy_from(tlm_extension_base const &) = 0;
00059 protected:
00060 virtual ~tlm_extension_base() {}
00061 static unsigned int register_extension()
00062 {
00063 return (max_num_extensions(true) - 1);
00064 };
00065 };
00066
00067
00068
00069
00070
00071
00072
00073 template <typename T>
00074 class tlm_extension : public tlm_extension_base
00075 {
00076 public:
00077 virtual tlm_extension_base* clone() const = 0;
00078 virtual void copy_from(tlm_extension_base const &ext) = 0;
00079 virtual ~tlm_extension() {}
00080 const static unsigned int ID;
00081 };
00082
00083 template <typename T>
00084 const
00085 unsigned int tlm_extension<T>::ID = tlm_extension_base::register_extension();
00086
00087
00088
00089
00090 enum tlm_command {
00091 TLM_READ_COMMAND,
00092 TLM_WRITE_COMMAND,
00093 TLM_IGNORE_COMMAND
00094 };
00095
00096 enum tlm_response_status {
00097 TLM_OK_RESPONSE = 1,
00098 TLM_INCOMPLETE_RESPONSE = 0,
00099 TLM_GENERIC_ERROR_RESPONSE = -1,
00100 TLM_ADDRESS_ERROR_RESPONSE = -2,
00101 TLM_COMMAND_ERROR_RESPONSE = -3,
00102 TLM_BURST_ERROR_RESPONSE = -4,
00103 TLM_BYTE_ENABLE_ERROR_RESPONSE = -5
00104 };
00105
00106 #define TLM_BYTE_DISABLED 0x0
00107 #define TLM_BYTE_ENABLED 0xff
00108
00109
00110
00111
00112 class tlm_generic_payload {
00113
00114 public:
00115
00116
00117
00118
00119
00120 tlm_generic_payload()
00121 : m_address(0)
00122 , m_command(TLM_IGNORE_COMMAND)
00123 , m_data(0)
00124 , m_length(0)
00125 , m_response_status(TLM_INCOMPLETE_RESPONSE)
00126 , m_dmi(false)
00127 , m_byte_enable(0)
00128 , m_byte_enable_length(0)
00129 , m_streaming_width(0)
00130 , m_extensions(max_num_extensions())
00131 , m_mm(0)
00132 , m_ref_count(0)
00133 {
00134 }
00135
00136 explicit tlm_generic_payload(tlm_mm_interface* mm)
00137 : m_address(0)
00138 , m_command(TLM_IGNORE_COMMAND)
00139 , m_data(0)
00140 , m_length(0)
00141 , m_response_status(TLM_INCOMPLETE_RESPONSE)
00142 , m_dmi(false)
00143 , m_byte_enable(0)
00144 , m_byte_enable_length(0)
00145 , m_streaming_width(0)
00146 , m_extensions(max_num_extensions())
00147 , m_mm(mm)
00148 , m_ref_count(0)
00149 {
00150 }
00151
00152 void acquire(){assert(m_mm != 0); m_ref_count++;}
00153 void release(){assert(m_mm != 0); if (--m_ref_count==0) m_mm->free(this);}
00154 int get_ref_count() const {return m_ref_count;}
00155 void set_mm(tlm_mm_interface* mm) { m_mm = mm; }
00156 bool has_mm() const { return m_mm != 0; }
00157
00158 void reset(){
00159
00160 m_extensions.free_entire_cache();
00161 };
00162
00163
00164 private:
00165
00166
00167 tlm_generic_payload(const tlm_generic_payload& x)
00168 : m_address(x.get_address())
00169 , m_command(x.get_command())
00170 , m_data(x.get_data_ptr())
00171 , m_length(x.get_data_length())
00172 , m_response_status(x.get_response_status())
00173 , m_dmi(x.is_dmi_allowed())
00174 , m_byte_enable(x.get_byte_enable_ptr())
00175 , m_byte_enable_length(x.get_byte_enable_length())
00176 , m_streaming_width(x.get_streaming_width())
00177 , m_extensions(max_num_extensions())
00178 {
00179
00180 for(unsigned int i=0; i<m_extensions.size(); i++)
00181 {
00182 m_extensions[i] = x.get_extension(i);
00183 }
00184 }
00185
00186
00187 tlm_generic_payload& operator= (const tlm_generic_payload& x)
00188 {
00189 m_command = x.get_command();
00190 m_address = x.get_address();
00191 m_data = x.get_data_ptr();
00192 m_length = x.get_data_length();
00193 m_response_status = x.get_response_status();
00194 m_byte_enable = x.get_byte_enable_ptr();
00195 m_byte_enable_length = x.get_byte_enable_length();
00196 m_streaming_width = x.get_streaming_width();
00197 m_dmi = x.is_dmi_allowed();
00198
00199
00200
00201
00202
00203 for(unsigned int i=0; i<m_extensions.size(); i++)
00204 {
00205 m_extensions[i] = x.get_extension(i);
00206 }
00207 return (*this);
00208 }
00209 public:
00210
00211 void deep_copy_from(const tlm_generic_payload & other)
00212 {
00213 m_command = other.get_command();
00214 m_address = other.get_address();
00215 m_length = other.get_data_length();
00216 m_response_status = other.get_response_status();
00217 m_byte_enable_length = other.get_byte_enable_length();
00218 m_streaming_width = other.get_streaming_width();
00219 m_dmi = other.is_dmi_allowed();
00220
00221
00222
00223 if(m_data && other.m_data)
00224 {
00225 memcpy(m_data, other.m_data, m_length);
00226 }
00227
00228
00229 if(m_byte_enable && other.m_byte_enable)
00230 {
00231 memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length);
00232 }
00233
00234 for(unsigned int i=0; i<other.m_extensions.size(); i++)
00235 {
00236 if(other.m_extensions[i])
00237 {
00238 if(!m_extensions[i])
00239 {
00240 tlm_extension_base *ext = other.m_extensions[i]->clone();
00241 if(ext)
00242 {
00243 if(has_mm())
00244 {
00245 set_auto_extension(i, ext);
00246 }
00247 else
00248 {
00249 set_extension(i, ext);
00250 }
00251 }
00252 }
00253 else
00254 {
00255 m_extensions[i]->copy_from(*other.m_extensions[i]);
00256 }
00257 }
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266 void update_original_from(const tlm_generic_payload & other,
00267 bool use_byte_enable_on_read = true)
00268 {
00269
00270 update_extensions_from(other);
00271
00272
00273 m_response_status = other.get_response_status();
00274 m_dmi = other.is_dmi_allowed();
00275
00276
00277
00278
00279
00280
00281 if(is_read() && m_data && other.m_data && m_data != other.m_data)
00282 {
00283 if (m_byte_enable && use_byte_enable_on_read)
00284 {
00285 if (m_byte_enable_length == 8 && m_length % 8 == 0 )
00286 {
00287
00288 for (unsigned int i = 0; i < m_length; i += 8)
00289 {
00290 typedef sc_dt::uint64* u;
00291 *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable);
00292 *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) &
00293 *reinterpret_cast<u>(m_byte_enable);
00294 }
00295 }
00296 else if (m_byte_enable_length == 4 && m_length % 4 == 0 )
00297 {
00298
00299 for (unsigned int i = 0; i < m_length; i += 4)
00300 {
00301 typedef unsigned int* u;
00302 *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable);
00303 *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) &
00304 *reinterpret_cast<u>(m_byte_enable);
00305 }
00306 }
00307 else
00308
00309 for (unsigned int i = 0; i < m_length; i++)
00310 if ( m_byte_enable[i % m_byte_enable_length] )
00311 m_data[i] = other.m_data[i];
00312 }
00313 else
00314 memcpy(m_data, other.m_data, m_length);
00315 }
00316 }
00317
00318 void update_extensions_from(const tlm_generic_payload & other)
00319 {
00320
00321 for(unsigned int i=0; i<other.m_extensions.size(); i++)
00322 {
00323 if(other.m_extensions[i])
00324 {
00325 if(m_extensions[i])
00326 {
00327 m_extensions[i]->copy_from(*other.m_extensions[i]);
00328 }
00329 }
00330 }
00331 }
00332
00333
00334
00335 void free_all_extensions()
00336 {
00337 m_extensions.free_entire_cache();
00338 for(unsigned int i=0; i<m_extensions.size(); i++)
00339 {
00340 if(m_extensions[i])
00341 {
00342 m_extensions[i]->free();
00343 m_extensions[i] = 0;
00344 }
00345 }
00346 }
00347
00348
00349
00350 virtual ~tlm_generic_payload() {
00351 for(unsigned int i=0; i<m_extensions.size(); i++)
00352 if(m_extensions[i]) m_extensions[i]->free();
00353 }
00354
00355
00356
00357
00358
00359
00360 bool is_read() const {return (m_command == TLM_READ_COMMAND);}
00361 void set_read() {m_command = TLM_READ_COMMAND;}
00362 bool is_write() const {return (m_command == TLM_WRITE_COMMAND);}
00363 void set_write() {m_command = TLM_WRITE_COMMAND;}
00364 tlm_command get_command() const {return m_command;}
00365 void set_command(const tlm_command command) {m_command = command;}
00366
00367
00368 sc_dt::uint64 get_address() const {return m_address;}
00369 void set_address(const sc_dt::uint64 address) {m_address = address;}
00370
00371
00372 unsigned char* get_data_ptr() const {return m_data;}
00373 void set_data_ptr(unsigned char* data) {m_data = data;}
00374
00375
00376 unsigned int get_data_length() const {return m_length;}
00377 void set_data_length(const unsigned int length) {m_length = length;}
00378
00379
00380 bool is_response_ok() const {return (m_response_status > 0);}
00381 bool is_response_error() const {return (m_response_status <= 0);}
00382 tlm_response_status get_response_status() const {return m_response_status;}
00383 void set_response_status(const tlm_response_status response_status)
00384 {m_response_status = response_status;}
00385 std::string get_response_string() const
00386 {
00387 switch(m_response_status)
00388 {
00389 case TLM_OK_RESPONSE: return "TLM_OK_RESPONSE";
00390 case TLM_INCOMPLETE_RESPONSE: return "TLM_INCOMPLETE_RESPONSE";
00391 case TLM_GENERIC_ERROR_RESPONSE: return "TLM_GENERIC_ERROR_RESPONSE";
00392 case TLM_ADDRESS_ERROR_RESPONSE: return "TLM_ADDRESS_ERROR_RESPONSE";
00393 case TLM_COMMAND_ERROR_RESPONSE: return "TLM_COMMAND_ERROR_RESPONSE";
00394 case TLM_BURST_ERROR_RESPONSE: return "TLM_BURST_ERROR_RESPONSE";
00395 case TLM_BYTE_ENABLE_ERROR_RESPONSE: return "TLM_BYTE_ENABLE_ERROR_RESPONSE";
00396 }
00397 return "TLM_UNKNOWN_RESPONSE";
00398 }
00399
00400
00401 unsigned int get_streaming_width() const {return m_streaming_width;}
00402 void set_streaming_width(const unsigned int streaming_width) {m_streaming_width = streaming_width; }
00403
00404
00405 unsigned char* get_byte_enable_ptr() const {return m_byte_enable;}
00406 void set_byte_enable_ptr(unsigned char* byte_enable){m_byte_enable = byte_enable;}
00407 unsigned int get_byte_enable_length() const {return m_byte_enable_length;}
00408 void set_byte_enable_length(const unsigned int byte_enable_length){m_byte_enable_length = byte_enable_length;}
00409
00410
00411
00412 void set_dmi_allowed(bool dmi_allowed) { m_dmi = dmi_allowed; }
00413 bool is_dmi_allowed() const { return m_dmi; }
00414
00415 private:
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 sc_dt::uint64 m_address;
00453 tlm_command m_command;
00454 unsigned char* m_data;
00455 unsigned int m_length;
00456 tlm_response_status m_response_status;
00457 bool m_dmi;
00458 unsigned char* m_byte_enable;
00459 unsigned int m_byte_enable_length;
00460 unsigned int m_streaming_width;
00461
00462 public:
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 template <typename T> T* set_extension(T* ext)
00502 {
00503 return static_cast<T*>(set_extension(T::ID, ext));
00504 }
00505
00506
00507 tlm_extension_base* set_extension(unsigned int index,
00508 tlm_extension_base* ext)
00509 {
00510 tlm_extension_base* tmp = m_extensions[index];
00511 m_extensions[index] = ext;
00512 return tmp;
00513 }
00514
00515
00516
00517 template <typename T> T* set_auto_extension(T* ext)
00518 {
00519 return static_cast<T*>(set_auto_extension(T::ID, ext));
00520 }
00521
00522
00523 tlm_extension_base* set_auto_extension(unsigned int index,
00524 tlm_extension_base* ext)
00525 {
00526 tlm_extension_base* tmp = m_extensions[index];
00527 m_extensions[index] = ext;
00528 if (!tmp) m_extensions.insert_in_cache(&m_extensions[index]);
00529 assert(m_mm != 0);
00530 return tmp;
00531 }
00532
00533
00534 template <typename T> void get_extension(T*& ext) const
00535 {
00536 ext = get_extension<T>();
00537 }
00538 template <typename T> T* get_extension() const
00539 {
00540 return static_cast<T*>(get_extension(T::ID));
00541 }
00542
00543 tlm_extension_base* get_extension(unsigned int index) const
00544 {
00545 return m_extensions[index];
00546 }
00547
00548
00549
00550
00551
00552 template <typename T> void clear_extension(const T* ext)
00553 {
00554 clear_extension<T>();
00555 }
00556
00557
00558
00559
00560
00561 template <typename T> void clear_extension()
00562 {
00563 clear_extension(T::ID);
00564 }
00565
00566
00567
00568
00569 template <typename T> void release_extension(T* ext)
00570 {
00571 release_extension<T>();
00572 }
00573
00574
00575
00576
00577 template <typename T> void release_extension()
00578 {
00579 release_extension(T::ID);
00580 }
00581
00582 private:
00583
00584 void clear_extension(unsigned int index)
00585 {
00586 m_extensions[index] = static_cast<tlm_extension_base*>(0);
00587 }
00588
00589 void release_extension(unsigned int index)
00590 {
00591 if (m_mm)
00592 {
00593 m_extensions.insert_in_cache(&m_extensions[index]);
00594 }
00595 else
00596 {
00597 m_extensions[index]->free();
00598 m_extensions[index] = static_cast<tlm_extension_base*>(0);
00599 }
00600 }
00601
00602 public:
00603
00604
00605
00606
00607
00608 void resize_extensions()
00609 {
00610 m_extensions.expand(max_num_extensions());
00611 }
00612
00613 private:
00614 tlm_array<tlm_extension_base*> m_extensions;
00615 tlm_mm_interface* m_mm;
00616 unsigned int m_ref_count;
00617 };
00618
00619 }
00620
00621 #endif