Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Instruction_Reduced_Reader.cc

Go to the documentation of this file.
00001 
00017 // ===================================================================
00018 // INCLUDES
00019 
00020 #include <math.h> // For pow()
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include "Instruction_Reduced_Reader.hh"
00024 #include "types-and-constants.hh"
00025 // ===================================================================
00026 
00027 
00028 
00029 // ===================================================================
00030 Instruction_Reduced_Reader::Instruction_Reduced_Reader
00031 (const char* const reference_trace_pathname) :
00032   Reference_Reader(reference_trace_pathname) {
00033 
00034   // Reset the clocks the zero.
00035   instruction_time = 0;
00036   reference_time = 0;
00037 
00038   // Reset the previous record values to zero, as the difference
00039   // encoder will have used that same starting point.
00040   previous_cycle_timestamp = 0;
00041   previous_context_ID = 0;
00042 
00043   // An array storing the previous virtual addresses of each type,
00044   // initialized.  Note that for efficiency and simplicity, we
00045   // allocate an array that is large enough so that there is an entry
00046   // for each possible tag value.
00047   const unsigned int bits_per_byte = 8;
00048   const unsigned int number_possible_tags =
00049     (unsigned int)pow(2.0, (double)(sizeof(tag_t) * bits_per_byte));
00050   previous_address_table = new virtual_address_t[number_possible_tags];
00051   if (previous_address_table == 0) {
00052     fprintf(stderr,
00053       "Instruction_Reduced_Reader(): Failed address table allocation\n");
00054     exit(1);
00055   }
00056   for (unsigned int i = 0; i < number_possible_tags; i++) {
00057     previous_address_table[i] = 0;
00058   }
00059 
00060 } // Instruction_Reduced_Reader
00061 // ===================================================================
00062 
00063 
00064 
00065 // ===================================================================
00066 Instruction_Reduced_Reader::~Instruction_Reduced_Reader () {
00067 
00068   // Delete the previous address table.
00069   delete previous_address_table;
00070   previous_address_table = 0;
00071 
00072 } // ~Instruction_Reduced_Reader
00073 // ===================================================================
00074 
00075 
00076 
00077 // ===================================================================
00078 void
00079 Instruction_Reduced_Reader::read
00080 (reference_record_s* const reference_record) {
00081 
00082   // Attempt to read the next record of the reference trace.
00083   char* read_result = fgets(buffer, BUFFER_SIZE, reference_stream);
00084 
00085   // Did the read fail?
00086   if (read_result == NULL) {
00087 
00088     // Distinguish between an EOF and other errors, but abort
00089     // processing in either case.
00090     if (feof(reference_stream)) {
00091       fprintf(stderr,
00092         "Instruction_Reduced_Reader::read(): Premature EOF\n");
00093     } else {
00094       fprintf(stderr,
00095         "Instruction_Reduced_Reader::read(): Read error\n");
00096     }
00097     exit(1);
00098   }
00099 
00100   // Parse the record type, which should be the first character of the
00101   // buffer.
00102   reference_record->tag = buffer[0];
00103 
00104   // Attempt to parse and process the rest of the record based on its
00105   // type.  Declare and assign some variables here to avoid compiler
00106   // complaints of skipping initialization in switch-case statement.
00107   unsigned int parse_result = 0;
00108   unsigned int items_to_parse = 0;
00109   timestamp_t timestamp_difference;
00110   context_ID_t context_ID;
00111   char address_difference_sign;
00112   virtual_address_t address_difference_magnitude;
00113   timestamp_t current_instruction_time = instruction_time;
00114   timestamp_t current_reference_time = reference_time;
00115   switch (reference_record->tag) {
00116 
00117   case TAG_USER_INSTRUCTION_FETCH:
00118   case TAG_KERNEL_INSTRUCTION_FETCH:
00119 
00120     // Tick the instruction clock to reflect that _after_ this event,
00121     // instruction time will have advanced.
00122     instruction_time++;
00123 
00124     // Fall through to read and parse the rest of the record...
00125 
00126   case TAG_USER_READ:
00127   case TAG_KERNEL_READ:
00128   case TAG_USER_WRITE:
00129   case TAG_KERNEL_WRITE:
00130 
00131     // Tick the reference clock to reflect that _after_ this event,
00132     // reference time will have advanced.
00133     reference_time++;
00134 
00135     // Read the remainder of the record.
00136     items_to_parse = 5;
00137     parse_result = sscanf(&buffer[2],
00138         "%qx %hx %lx %c %lx",
00139         &timestamp_difference,
00140         &reference_record->length,
00141         &context_ID,
00142         &address_difference_sign,
00143         &address_difference_magnitude);
00144 
00145     // Place the current instruction and reference times into the
00146     // structure.
00147     reference_record->instruction_timestamp = current_instruction_time;
00148     reference_record->reference_timestamp = current_reference_time;
00149 
00150     // Calculate the cycle time based on the previous timestamp and
00151     // the timestamp difference.
00152     previous_cycle_timestamp += timestamp_difference;
00153     reference_record->cycle_timestamp = previous_cycle_timestamp;
00154 
00155     // Calculate the context ID.  If the value read is zero, then it
00156     // is the same as the previous context ID; otherwise, the value
00157     // read is the new context ID.
00158     if (context_ID == 0) {
00159       reference_record->virtual_page.context_ID = previous_context_ID;
00160     } else {
00161       previous_context_ID = context_ID;
00162       reference_record->virtual_page.context_ID = context_ID;
00163     }
00164 
00165     // Calculate the virtual address based on the previous address and
00166     // the address difference.  Virtual addresses are calculated on a
00167     // per-reference-type basis.
00168     if (address_difference_sign == '+') {
00169 
00170       previous_address_table[reference_record->tag] +=
00171   address_difference_magnitude;
00172 
00173     } else if (address_difference_sign == '-') {
00174 
00175       previous_address_table[reference_record->tag] -=
00176   address_difference_magnitude;
00177 
00178     } else {
00179 
00180       fprintf(stderr, "Instruction_Reduced_Reader::read(): ");
00181       fprintf(stderr,
00182         "Unknown tag %c(%d) at reference time = %qx\n",
00183         address_difference_sign,
00184         (int)address_difference_sign,
00185         current_reference_time);
00186       exit(1);
00187 
00188     }
00189     reference_record->virtual_address =
00190       previous_address_table[reference_record->tag];
00191 
00192     // Compute the page ID by isolating the upper bits of the virtual
00193     // address and recording that value in the structure.
00194     reference_record->virtual_page.page_ID =
00195       reference_record->virtual_address >> PAGE_SIZE_ORDER;
00196 
00197     break;
00198 
00199   case TAG_KERNEL_EVENT:
00200 
00201     // Read the remainder of the record.  We care only about the
00202     // timestamp.
00203     items_to_parse = 1;
00204     parse_result = sscanf(&buffer[2],
00205         "%qx",
00206         &timestamp_difference);
00207 
00208     // Calculate the cycle time based on the previous timestamp and
00209     // the timestamp difference.
00210     previous_cycle_timestamp += timestamp_difference;
00211     reference_record->cycle_timestamp = previous_cycle_timestamp;
00212 
00213     // Assign the rest of the fields.
00214     reference_record->instruction_timestamp = current_instruction_time;
00215     reference_record->reference_timestamp = current_reference_time;
00216     reference_record->length = 0;
00217     reference_record->virtual_page.context_ID = 0;
00218     reference_record->virtual_page.page_ID = 0;
00219     reference_record->virtual_address = 0;
00220     break;
00221 
00222   case TAG_END_OF_TRACE:
00223 
00224     // Nothing to do.
00225     break;
00226 
00227   default:
00228     fprintf(stderr, "Instruction_Reduced_Reader::read(): ");
00229     fprintf(stderr,
00230       "Invalid reference tag %c(%d)\n",
00231       reference_record->tag,
00232       (int)reference_record->tag);
00233     exit(1);
00234 
00235   }
00236 
00237   // If the parse failed, emit the error and exit.
00238   if (parse_result != items_to_parse) {
00239     fprintf(stderr, "Instruction_Reduced_Reader::read(): ");
00240     fprintf(stderr, "Could not parse remainder\n");
00241     fprintf(stderr,
00242       "cycle_timestamp = %qx\n",
00243       reference_record->cycle_timestamp);
00244     fprintf(stderr,
00245       "instruction_timestamp = %qx\n",
00246       reference_record->instruction_timestamp);
00247     fprintf(stderr,
00248       "reference_timestamp = %qx\n",
00249       reference_record->reference_timestamp);
00250     exit(1);
00251   }
00252 
00253 } // read
00254 // ===================================================================

Generated on Fri Jan 31 10:33:34 2003 for Laplace-merge by doxygen1.3-rc2