diff --git a/main.py b/main.py index 57ec0683727c9934b09a55ecf2862b0268a42d17..1f4e82843dc9cbc9622481ced0685260c78221a0 100644 --- a/main.py +++ b/main.py @@ -107,11 +107,11 @@ class CacheSimulator(): print('hits:{0} misses:{1} evictions:{2}'.format(self.hits, self.misses, self.evictions)) - def handle_line(self, line, main_cache_line=True): + def handle_line(self, line, main_bool=True): """ Handles cache simulation for given line instruction. :param line: Line to handle for. - :param main_cache_line: Bool to indicate if this is an initial cache line read in or a subquery from one. + :param main_bool: Bool to indicate if this is an initial cache line read in or a subquery from one. Note that only initial cache line read ins will print or update missed/skipped/evicted variables. """ split_line = re.split(r'[ ,\n]', line) @@ -123,9 +123,11 @@ class CacheSimulator(): else: line = line.strip() - # Not an instruction load. Keep processing. Start by getting address. - address = int(split_line[2]) % self.M - value_size = int(split_line[3]) + # Not an instruction load. Keep processing. Start by parsing line info. + parsed_data = {} + address = int(split_line[2]) + parsed_data['address'] = address + parsed_data['value_size'] = int(split_line[3]) # Get mask values. block_mask = self.B - 1 @@ -135,94 +137,26 @@ class CacheSimulator(): tag_mask = (self.M - 1) ^ set_mask ^ block_mask # Use masks to get address chunks. - block = address & block_mask + parsed_data['block'] = address & block_mask set = (address & set_mask) >> block_offset + parsed_data['set'] = set tag = (address & tag_mask) >> (block_offset + set_offset) + parsed_data['tag'] = tag # We have our values. Now compare against the all entries in the cache. for index in range(len(self.cache[set])): # Check if match. if self.cache[set][index]['valid'] == True and self.cache[set][index]['tag'] == tag: # Match found. - if main_cache_line: - # Is main cache file line. Update hits/misses/evictions. - self.hits += 1 - - # Print if verbose flag set. - if self.verbose: - print('{0} hit'.format(line)) - - return + return self.process_hit(line, set, main_bool) else: # Not a match. Examine why. if self.cache[set][index]['valid'] == False: # Cache location was not set. Cold miss. We can just set and return. - if main_cache_line: - # Is main cache file line. Update hits/misses/evictions. - self.misses += 1 - - # Print if verbose flag set. - if self.verbose: - print('{0} miss'.format(line)) - - self.cache[set][index]['valid'] = True - self.cache[set][index]['tag'] = tag - - # Set block values that are "loaded" into memory. - lower_offset = int(address / self.B) * self.B - upper_offset = (int(address / self.B) + 1) * self.B - value_offset = address + value_size - self.cache[set][index]['block'] = [] - for i in range(self.B): - self.cache[set][index]['block'].append(lower_offset + i) - - # Check if size sets address outside of current cache block. - if value_offset >= upper_offset: - # Size sets address outside of current cache block. Update additional blocks as needed. - # Start by getting our new size. - new_size = value_offset - upper_offset - if new_size < 0: - new_size = 0 - - # Pass our new line data. - new_line = ' L {0},{1}'.format(upper_offset, new_size) - self.handle_line(new_line, main_cache_line=False) - - return + return self.process_miss(line, parsed_data, index, main_bool) # If we made it this far, cache locations were set, but tags did not match. Conflict miss. - if main_cache_line: - # Is main cache file line. Update hits/misses/evictions. - self.misses += 1 - self.evictions += 1 - - # Print if verbose flag set. - if self.verbose: - print('{0} miss eviction'.format(line)) - - self.cache[set][0]['tag'] = tag - - # Set block values that are "loaded" into memory. - lower_offset = int(address / self.B) * self.B - upper_offset = (int(address / self.B) + 1) * self.B - value_offset = address + value_size - self.cache[set][0]['block'] = [] - for i in range(self.B): - self.cache[set][0]['block'].append(lower_offset + i) - - # Check if size sets address outside of current cache block. - if value_offset >= upper_offset: - # Size sets address outside of current cache block. Update additional blocks as needed. - # Start by getting our new size. - new_size = value_offset - upper_offset - if new_size < 0: - new_size = 0 - - # Pass our new line data. - new_line = ' L {0},{1}'.format(upper_offset, new_size) - self.handle_line(new_line, main_cache_line=False) - - return + return self.process_eviction(line, parsed_data, main_bool) def print_cache(self): """ @@ -235,6 +169,91 @@ class CacheSimulator(): print(' Line {0}: {1}'.format(line_index, self.cache[set_index][line_index])) print('') + def process_hit(self, line, parsed_data, main_bool): + if main_bool: + # Is main cache file line. Update hits/misses/evictions. + self.hits += 1 + + # Print if verbose flag set. + if self.verbose: + print('{0} hit'.format(line)) + + def process_miss(self, line, parsed_data, index, main_bool): + if main_bool: + # Is main cache file line. Update hits/misses/evictions. + self.misses += 1 + + # Print if verbose flag set. + if self.verbose: + print('{0} miss'.format(line)) + + # Pull out relevant data from passed dict. + address = parsed_data['address'] + value_size = parsed_data['value_size'] + set = parsed_data['set'] + tag = parsed_data['tag'] + + self.cache[set][index]['valid'] = True + self.cache[set][index]['tag'] = tag + + # Set block values that are "loaded" into memory. + lower_offset = int(address / self.B) * self.B + upper_offset = (int(address / self.B) + 1) * self.B + value_offset = address + value_size + self.cache[set][index]['block'] = [] + for i in range(self.B): + self.cache[set][index]['block'].append(lower_offset + i) + + # Check if size sets address outside of current cache block. + if value_offset >= upper_offset: + # Size sets address outside of current cache block. Update additional blocks as needed. + # Start by getting our new size. + new_size = value_offset - upper_offset + if new_size < 0: + new_size = 0 + + # Pass our new line data. + new_line = ' L {0},{1}'.format(upper_offset, new_size) + self.handle_line(new_line, main_bool=False) + + def process_eviction(self, line, parsed_data, main_bool): + if main_bool: + # Is main cache file line. Update hits/misses/evictions. + self.misses += 1 + self.evictions += 1 + + # Print if verbose flag set. + if self.verbose: + print('{0} miss eviction'.format(line)) + + # Pull out relevant data from passed dict. + address = parsed_data['address'] + value_size = parsed_data['value_size'] + set = parsed_data['set'] + tag = parsed_data['tag'] + + self.cache[set][0]['tag'] = tag + + # Set block values that are "loaded" into memory. + lower_offset = int(address / self.B) * self.B + upper_offset = (int(address / self.B) + 1) * self.B + value_offset = address + value_size + self.cache[set][0]['block'] = [] + for i in range(self.B): + self.cache[set][0]['block'].append(lower_offset + i) + + # Check if size sets address outside of current cache block. + if value_offset >= upper_offset: + # Size sets address outside of current cache block. Update additional blocks as needed. + # Start by getting our new size. + new_size = value_offset - upper_offset + if new_size < 0: + new_size = 0 + + # Pass our new line data. + new_line = ' L {0},{1}'.format(upper_offset, new_size) + self.handle_line(new_line, main_bool=False) + if __name__ == '__main__': print('Starting program.')