#include <Instruction_Reduced_Reader.hh>
Inheritance diagram for Instruction_Reduced_Reader:
Public Methods | |
Instruction_Reduced_Reader (const char *const reference_trace_pathname) | |
The constructor. | |
virtual | ~Instruction_Reduced_Reader () |
The destructor. | |
virtual void | read (reference_record_s *const reference_record) |
Read the next record from the reference trace. | |
Protected Attributes | |
timestamp_t | reference_time |
The current reference time. | |
timestamp_t | instruction_time |
The current instruction time. | |
timestamp_t | previous_cycle_timestamp |
The cycle timestamp of the previous record, used to calculate the absolute cycle time. | |
context_ID_t | previous_context_ID |
The context ID of the previous record, used to calculate the current context ID. | |
virtual_address_t * | previous_address_table |
An array that stores the virtual address of the previous record, indexed by tag (that is, reference type). |
It defines only the read() method that performs the actual reading, parsing, and processing of each reference record before it is provided to the caller in a reference_record_s structure.
Definition at line 44 of file Instruction_Reduced_Reader.hh.
|
The constructor.
Definition at line 31 of file Instruction_Reduced_Reader.cc. References virtual_address_t.
00031 : 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 // =================================================================== |
|
The destructor. Deallocate the table used to track tag-indexed previous virtual addresses for difference decoding. Definition at line 66 of file Instruction_Reduced_Reader.cc. References previous_address_table.
00066 { 00067 00068 // Delete the previous address table. 00069 delete previous_address_table; 00070 previous_address_table = 0; 00071 00072 } // ~Instruction_Reduced_Reader |
|
Read the next record from the reference trace.
Implements Reference_Reader. Definition at line 80 of file Instruction_Reduced_Reader.cc. References context_ID_t, PAGE_SIZE_ORDER, TAG_END_OF_TRACE, TAG_KERNEL_EVENT, TAG_KERNEL_INSTRUCTION_FETCH, TAG_KERNEL_READ, TAG_KERNEL_WRITE, TAG_USER_INSTRUCTION_FETCH, TAG_USER_READ, TAG_USER_WRITE, timestamp_t, and virtual_address_t.
00080 { 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 ×tamp_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 ×tamp_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 |
|
The current instruction time.
Definition at line 88 of file Instruction_Reduced_Reader.hh. |
|
An array that stores the virtual address of the previous record, indexed by tag (that is, reference type).
Definition at line 100 of file Instruction_Reduced_Reader.hh. Referenced by ~Instruction_Reduced_Reader(). |
|
The context ID of the previous record, used to calculate the current context ID.
Definition at line 96 of file Instruction_Reduced_Reader.hh. |
|
The cycle timestamp of the previous record, used to calculate the absolute cycle time.
Definition at line 92 of file Instruction_Reduced_Reader.hh. |
|
The current reference time.
Definition at line 85 of file Instruction_Reduced_Reader.hh. |