Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

ac_storage.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 
00003 /*  ArchC Storage Library for the ArchC architecture simulators
00004     Copyright (C) 2002-2004  The ArchC Team
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 */
00016 
00017 /********************************************************/
00018 /* The ArchC storage device base class.                 */
00019 /* Author:  Sandro Rigo                                 */
00020 /*                                                      */
00021 /*                                                      */
00022 /* The ArchC Team                                       */
00023 /* Computer Systems Laboratory (LSC)                    */
00024 /* IC-UNICAMP                                           */
00025 /* http://www.lsc.ic.unicamp.br                         */
00026 /********************************************************/
00027 
00029 
00035 /************************************************
00036  * Author: Sandro Rigo
00037  ************************************************/
00039 
00040 #include <sstream>
00041 #include <string>
00042 #include <fstream>
00043 #include <iterator>
00044 #include  "ac_storage.H"
00045 #include "ac_resources.H"
00046 //#include "ac_types.H"
00047 
00048 //#define DEBUG_STORAGE
00049 
00051 // ac_storage methods      
00053 
00055 ac_word ac_storage::read( unsigned address ) { 
00056 
00057 #ifdef AC_STATS
00058   ac_resources::ac_sim_stats.add_access(name);
00059 #endif
00060 #ifdef DEBUG_STORAGE
00061   if( !Data )
00062     cout << "Data is uninitialized" <<endl;
00063 
00064   if( address > size)
00065     cout << "Access out of bounds" <<endl;
00066 #endif
00067 
00068   return *((ac_word *)(Data+(address)));
00069 }
00070 
00072 unsigned char ac_storage::read_byte( unsigned address ) { 
00073 
00074   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00075   int byte_idx;
00076 
00077   ac_word word;
00078 
00079   //Getting the word containing the requested byte. 
00080   //This is necessary because the address may not be the beginning of a memory word.
00081   word = *((ac_word *)(Data+(address & ~align)));
00082   //Checking target endianess to discover which byte must be returned
00083   byte_idx = (ac_resources::ac_tgt_endian) ? (align - (address & align)) : (address & align); 
00084 
00085 #ifdef AC_STATS
00086   ac_resources::ac_sim_stats.add_access(name);
00087 #endif
00088 
00089   return  (unsigned char) ((word & (0xFF << (byte_idx *8))) >> (byte_idx*8));
00090 }
00091 
00093 ac_Hword ac_storage::read_half( unsigned address ) { 
00094 
00095   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00096   int byte_idx;
00097 
00098   ac_word word;
00099 
00100   //Getting the word containing the requested byte. 
00101   //This is necessary because the address may not be the beginning of a memory word.
00102   word = *((ac_word *)(Data+(address & ~align)));
00103   //Checking target endianess to discover which byte must be returned
00104   byte_idx = (ac_resources::ac_tgt_endian) ? (2 - (address & align)) : (address & align); 
00105 
00106 #ifdef AC_STATS
00107   ac_resources::ac_sim_stats.add_access(name);
00108 #endif
00109 
00110   return  (ac_Hword) ((word & (0xFFFF << (byte_idx *8))) >> (byte_idx*8));
00111 }
00112 
00114 void ac_storage::write( unsigned address, ac_word datum ) { 
00115 
00116 #ifdef AC_UPDATE_LOG
00117   changes.push_back( change_log(address, datum , sc_simulation_time()));
00118 #endif
00119   
00120 #ifdef DEBUG_STORAGE
00121   cout << "Address: " << address << " PC: " << ac_resources::ac_pc << endl;
00122   if( !Data )
00123     cout << "Data is uninitialized" <<endl;
00124 
00125   if( address > size)
00126     cout << "Access out of bounds" <<endl;
00127 #endif
00128 
00129   *((ac_word *)(Data+(address))) = (ac_word)datum;
00130 
00131 #ifdef AC_STATS
00132   ac_resources::ac_sim_stats.add_access(name);
00133 #endif
00134 
00135 }
00136 
00138 void ac_storage::write_byte( unsigned address, unsigned char datum ) { 
00139 
00140   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00141   int byte_idx;
00142 
00143   ac_word word;
00144 
00145   //Getting the word containing the requested byte. 
00146   //This is necessary because the address may not be at the beginning of a memory word.
00147   word = *((ac_word *)(Data+(address & ~align)));
00148 
00149   //Checking target endianess to discover which byte must be written
00150   byte_idx = (ac_resources::ac_tgt_endian) ? (align - (address & align)) : (address & align); 
00151   
00152   //Writing
00153   *((ac_word *)(Data+(address & ~align))) = (ac_word)((word & ~(0xFF << (byte_idx *8))) | (datum << (byte_idx*8)));
00154 
00155 #ifdef AC_UPDATE_LOG
00156   changes.push_back( change_log(address, (ac_word)datum , sc_simulation_time()));
00157 #endif
00158 
00159 #ifdef AC_STATS
00160   ac_resources::ac_sim_stats.add_access(name);
00161 #endif
00162 
00163 }
00164 
00166 void ac_storage::write_half( unsigned address, ac_Hword datum ) { 
00167 
00168   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00169   int byte_idx;
00170 
00171   ac_word word;
00172 
00173   //Getting the word containing the requested byte. 
00174   //This is necessary because the address may not be at the beginning of a memory word.
00175   word = *((ac_word *)(Data+(address & ~align)));
00176 
00177   //Checking target endianess to discover which byte must be written
00178   byte_idx = (ac_resources::ac_tgt_endian) ? (2 - (address & align)) : (address & align); 
00179   
00180   //Writing
00181   *((ac_word *)(Data+(address & ~align))) = (ac_word)((word & ~(0xFFFF << (byte_idx *8))) | (datum << (byte_idx*8)));
00182 
00183 #ifdef AC_UPDATE_LOG
00184   changes.push_back( change_log(address, (ac_word)datum , sc_simulation_time()));
00185 #endif
00186 
00187 #ifdef AC_STATS
00188   ac_resources::ac_sim_stats.add_access(name);
00189 #endif
00190 
00191 }
00192 
00193 #ifdef AC_DELAY
00194 /*******************************
00195  * This methods are used for delayed assignment through write methods.
00196  * Normally used for memories and caches.
00197  */
00199 void ac_storage::write( unsigned address, ac_word datum, unsigned time ) { 
00200 
00201   delays.push_back( change_log( address, datum , time+ac_resources::ac_cycle_counter ));
00202 
00203 }
00204 
00206 void ac_storage::write_byte( unsigned address, unsigned char datum, unsigned time ) { 
00207 
00208   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00209   int byte_idx;
00210 
00211   ac_word word;
00212 
00213   //Getting the word containing the requested byte. 
00214   //This is necessary because the address may not be at the beginning of a memory word.
00215   word = *((ac_word *)(Data+(address & ~align)));
00216 
00217   //Checking target endianess to discover which byte must be written
00218   byte_idx = (ac_resources::ac_tgt_endian) ? (align - (address & align)) : (address & align); 
00219   
00220   //Delaying writing
00221   *((ac_word *)(Data+(address & ~align))) = (ac_word)((word & ~(0xFF << (byte_idx *8))) | (datum << (byte_idx*8)));
00222 
00223   delays.push_back( change_log( (address & ~align),
00224                                 (ac_word)((word & ~(0xFF << (byte_idx *8))) | (datum << (byte_idx*8))),
00225                                 time+ac_resources::ac_cycle_counter));
00226 }
00227 
00229 void ac_storage::write_half( unsigned address, ac_Hword datum, unsigned time ) { 
00230 
00231   int align = sizeof(ac_word) -1;  //Indicates the memory alignment
00232   int byte_idx;
00233 
00234   ac_word word;
00235 
00236   //Getting the word containing the requested byte. 
00237   //This is necessary because the address may not be at the beginning of a memory word.
00238   word = *((ac_word *)(Data+(address & ~align)));
00239 
00240   //Checking target endianess to discover which byte must be written
00241   byte_idx = (ac_resources::ac_tgt_endian) ? (2 - (address & align)) : (address & align); 
00242   
00243   //Delaying writing
00244   delays.push_back( change_log( (address & ~align),
00245                                 (ac_word)((word & ~(0xFFFF << (byte_idx *8))) | (datum << (byte_idx*8))),
00246                                 time+ac_resources::ac_cycle_counter));
00247 }
00248 
00249 #endif   // AC_DELAY
00250 
00251 #ifdef AC_UPDATE_LOG
00252 
00254 void ac_storage::reset_log(){ changes.clear();}
00255   
00257 int ac_storage::change_dump( ostream& output) {
00258 
00259   log_list::iterator itor;
00260     
00261   if( changes.size() ){
00262     output <<endl << endl;
00263     output << "**************** ArchC Change log *****************\n";
00264     output << "* Device: "<< name << "\t\t" << "PC: " << hex << ac_resources::ac_pc << dec << endl;
00265     output << "***************************************************\n";
00266     output << "*        Address         Value          Time      *\n";
00267     output << "***************************************************\n";
00268       
00269     for( itor = changes.begin(); itor != changes.end(); itor++)  
00270       output << "*  " << *itor << "     *" << endl;
00271       
00272     output << "***************************************************\n";
00273   }
00274   return 0;
00275 }
00276     
00278 void ac_storage::change_save( ) {
00279 
00280   log_list::iterator itor;
00281     
00282   if( changes.size() ){
00283 
00284     for( itor = changes.begin(); itor != changes.end(); itor++)  
00285       itor->save(this->update_file);
00286       
00287   }
00288 }
00289     
00290 #endif
00291 
00292 
00293 
00295 void ac_storage::load( char* file ){
00296 
00297   ifstream input;
00298   string read;
00299   string word;
00300   istringstream line;
00301   unsigned text_size=0;
00302   extern unsigned dec_cache_size;
00303   bool is_addr, is_text=0, first_addr=1;
00304   long long data;
00305   unsigned int  addr=0;
00306 
00307   //Try to read as ELF first
00308   extern int  ac_load_elf(char*, char*, unsigned int);
00309   if (ac_load_elf(file, Data, size) == EXIT_SUCCESS) {
00310     //init decode cache and return
00311     if(!dec_cache_size)
00312       dec_cache_size = ac_heap_ptr;
00313     return;
00314   }
00315 
00316   // Looking for initialization file.
00317   input.open(file);
00318   if(!input){
00319     AC_ERROR("Could not open input file:" << file);
00320     AC_ERROR("Simulation aborted.");
00321     exit(1);
00322   }
00323   else{
00324       
00325     while( !input.eof() ){
00326 
00327       line.clear();
00328       getline(input, read);
00329       line.str(read);
00330                         
00331       is_addr = 1;
00332 
00333       //Processing line
00334       while(line >> word){
00335 
00336         if( word == ".text:" ){
00337           is_text = 1;
00338           continue;
00339         }
00340                                                 
00341         if( word[0] == '.' ){
00342           is_text = 0;
00343           continue;
00344         }
00345 
00346         //Processing word
00347         if( is_addr ){
00348           addr = strtol(word.c_str(), NULL, 16);
00349           is_addr = 0;
00350           if( is_text && first_addr ){
00351             first_addr = 0;
00352             ac_resources::ac_start_addr = addr;
00353           }
00354         }
00355         else{
00356                                         
00357           if(is_text)text_size++;
00358           data = strtoll( word.c_str(), NULL, 16);
00359           write(addr,(ac_word)data);
00360           addr+= AC_WORDSIZE/8;
00361         }
00362       }
00363     }
00364   }
00365   if(!dec_cache_size)
00366       dec_cache_size = addr;
00367 
00368   input.close();
00369 
00370 }
00371 
00372 
00374 void ac_storage::load_array( const unsigned char* d, const unsigned s )
00375 {
00376   if (size < s) {
00377     fprintf(stderr, "Storage %s: trying to load an array bigger then storage size.\n", name);
00378     exit(EXIT_FAILURE);
00379   }
00380   memcpy(Data, d, s);
00381 }
00382 
00383 
00384 
00385 #ifdef AC_DELAY
00386 
00388 void ac_storage::commit_delays( double time ){
00389   log_list::iterator itor;
00390     
00391   itor = delays.begin();
00392 
00393   //Sometimes, when a memory hierarchy is present and the processor spends some
00394   //cycles in a wait status, we may have to commit changes for every cycle <= 
00395   //current time.
00396   while( delays.size() && (itor->time <= time) ){
00397     write( itor->addr, itor->value );
00398     itor = delays.erase( itor);
00399   }
00400 }
00401 #endif
00402 
00403                 

Generated on Thu Jun 24 08:30:05 2004 for ArchC by doxygen 1.3.4