00001 /***************************************************************************** 00002 00003 The following code is derived, directly or indirectly, from the SystemC 00004 source code Copyright (c) 1996-2008 by all Contributors. 00005 All Rights reserved. 00006 00007 The contents of this file are subject to the restrictions and limitations 00008 set forth in the SystemC Open Source License Version 3.0 (the "License"); 00009 You may not use this file except in compliance with such restrictions and 00010 limitations. You may obtain instructions on how to receive a copy of the 00011 License at http://www.systemc.org/. Software distributed by Contributors 00012 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 00013 ANY KIND, either express or implied. See the License for the specific 00014 language governing rights and limitations under the License. 00015 00016 Author: Olaf Scheufen 00017 *****************************************************************************/ 00018 00019 #ifndef __TLM_ARRAY_H__ 00020 #define __TLM_ARRAY_H__ 00021 00022 #include <systemc> 00023 #include <exception> 00024 // unused for the time being: #include <assert.h> 00025 00026 namespace tlm { 00027 00028 // 00029 // To the LRM writer: the below class is an artifact of the tlm_generic_payload 00030 // implementation and not part of the core TLM standard 00031 // 00032 00033 00034 // This implements a lean and fast array class that supports array expansion on 00035 // request. The class is primarily used in the tlm_generic_payload class for 00036 // storing the pointers to the extensions. 00037 // 00038 // Individual array elements can be accessed through the [] operators, and the 00039 // array length is returned by the size() method. 00040 // 00041 // The size can be dynamically expanded using the expand(uint) method. There 00042 // is no shrinking mechanism implemented, because the extension mechanism 00043 // does not require this feature. Bear in mind that calling the expand method 00044 // may invalidate all direct pointers into the m_data array. 00045 00046 00047 //the tlm_array shall always be used with T=tlm_extension_base* 00048 template <typename T> 00049 class tlm_array 00050 { 00051 public: 00052 00053 // constructor: 00054 tlm_array(unsigned int size = 0, T default_value = 0) 00055 : m_data(0) 00056 , m_size(0) 00057 , m_entries(NULL) 00058 , m_last_entry(0) 00059 , m_default(default_value) 00060 { 00061 expand(size); 00062 } 00063 00064 // copy constructor: 00065 tlm_array(const tlm_array& orig) 00066 { 00067 m_size = orig.size(); 00068 m_last_entry=orig.m_last_entry; 00069 if (m_size>0) 00070 { 00071 try { 00072 m_data = new T[m_size]; 00073 } 00074 catch (std::exception &e) { 00075 report_error(e); return; 00076 } 00077 try { 00078 m_entries = new T*[m_size]; 00079 } 00080 catch (std::exception &e) { 00081 report_error(e); return; 00082 } 00083 for(unsigned int i=0; i<m_size; i++) 00084 { 00085 m_data[i] = orig.m_data[i]; 00086 m_entries[i] = orig.m_entries[i]; 00087 } 00088 } 00089 } 00090 00091 // destructor: 00092 ‾tlm_array() 00093 { 00094 if (m_size>0) {delete[] m_data; delete [] m_entries;} 00095 m_size = 0; 00096 } 00097 00098 // operators for dereferencing: 00099 T& operator[](const unsigned int index) 00100 { 00101 // assert(index < m_size); 00102 return m_data[index]; 00103 } 00104 const T& operator[](const unsigned int index) const 00105 { 00106 // assert(index < m_size); 00107 return m_data[index]; 00108 } 00109 00110 // array size: 00111 unsigned int size() const {return m_size;} 00112 00113 // expand the array if needed: 00114 void expand(unsigned int new_size) 00115 { 00116 if (new_size > m_size) 00117 { 00118 unsigned int i; 00119 if(m_size==0) 00120 { 00121 try { 00122 m_data = new T[new_size]; 00123 } 00124 catch (std::exception &e) { 00125 report_error(e); return; 00126 } 00127 00128 try { 00129 m_entries = new T*[new_size]; 00130 } 00131 catch (std::exception &e) { 00132 report_error(e); return; 00133 } 00134 00135 for(i=0; i<new_size; i++) 00136 { 00137 m_data[i] = m_default; 00138 m_entries[i] = NULL; 00139 } 00140 m_size = new_size; 00141 m_last_entry=0; 00142 } 00143 else 00144 { 00145 T* tmp = m_data; 00146 T** tmp2 = m_entries; 00147 try { 00148 m_data = new T[new_size]; 00149 } 00150 catch (std::exception &e) { 00151 report_error(e); return; 00152 } 00153 try { 00154 m_entries = new T*[new_size]; 00155 } 00156 catch (std::exception &e) { 00157 report_error(e); return; 00158 } 00159 00160 for(i=0; i<m_size; i++) 00161 { 00162 m_data[i] = tmp[i]; 00163 } 00164 00165 //since the array new the cache entries have to be update 00166 for (unsigned int j=0; j<m_size; j++) 00167 { 00168 if (tmp[j]) //if there was a valid extension in the old array ... 00169 { 00170 for (unsigned int i=0; i<m_last_entry; i++) //...we search its position in the old cache 00171 { 00172 if (tmp[j]==(*tmp2[i])) //...and if it was in the old cache 00173 { 00174 m_entries[i]=&m_data[j]; //...we put it into the same position in the new cache 00175 } 00176 } 00177 } 00178 } 00179 00180 for(i=m_size; i<new_size; i++) 00181 { 00182 m_data[i] = m_default; 00183 m_entries[i] = NULL; 00184 } 00185 m_size = new_size; 00186 delete[] tmp; 00187 delete[] tmp2; 00188 } 00189 } 00190 } 00191 00192 static const char* const kind_string; 00193 const char* kind() const { return kind_string; } 00194 00195 //this function shall get a pointer to a array slot 00196 // it stores this slot in a cache of active slots 00197 void insert_in_cache(T* p) 00198 { 00199 m_entries[m_last_entry++]=p; 00200 } 00201 00202 //this functions clears all active slots of the array 00203 void free_entire_cache() 00204 { 00205 while(m_last_entry) 00206 { 00207 m_last_entry--; 00208 if (*m_entries[m_last_entry]) //we make sure no one cleared the slot manually 00209 (*m_entries[m_last_entry])->free(); //...and then we call free on the content of the slot 00210 *m_entries[m_last_entry]=0; //afterwards we set the slot to NULL 00211 } 00212 } 00213 00214 protected: 00215 T* m_data; 00216 unsigned int m_size; 00217 00218 T** m_entries; 00219 unsigned int m_last_entry; 00220 00221 T m_default; 00222 00223 // disabled: 00224 tlm_array& operator=(const tlm_array<T>&); 00225 00226 // Report allocation error: 00227 void report_error(std::exception &e) 00228 { 00229 std::string msg("Allocation of array failed: "); 00230 msg += e.what(); 00231 SC_REPORT_FATAL(kind_string, msg.c_str()); 00232 } 00233 }; 00234 00235 00236 template <typename T> 00237 const char* const tlm_array<T>::kind_string = "tlm_array"; 00238 00239 } // namespace tlm 00240 00241 #endif /* __TLM_ARRAY_H__ */