113540Sandrea.mondelli@ucf.edu#!/usr/bin/env python2.7 210235Syasuko.eckert@amd.com 310235Syasuko.eckert@amd.com# Copyright (c) 2010-2013 Advanced Micro Devices, Inc. 410235Syasuko.eckert@amd.com# All rights reserved. 510235Syasuko.eckert@amd.com# 610235Syasuko.eckert@amd.com# Redistribution and use in source and binary forms, with or without 710235Syasuko.eckert@amd.com# modification, are permitted provided that the following conditions are 810235Syasuko.eckert@amd.com# met: redistributions of source code must retain the above copyright 910235Syasuko.eckert@amd.com# notice, this list of conditions and the following disclaimer; 1010235Syasuko.eckert@amd.com# redistributions in binary form must reproduce the above copyright 1110235Syasuko.eckert@amd.com# notice, this list of conditions and the following disclaimer in the 1210235Syasuko.eckert@amd.com# documentation and/or other materials provided with the distribution; 1310235Syasuko.eckert@amd.com# neither the name of the copyright holders nor the names of its 1410235Syasuko.eckert@amd.com# contributors may be used to endorse or promote products derived from 1510235Syasuko.eckert@amd.com# this software without specific prior written permission. 1610235Syasuko.eckert@amd.com# 1710235Syasuko.eckert@amd.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1810235Syasuko.eckert@amd.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1910235Syasuko.eckert@amd.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2010235Syasuko.eckert@amd.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2110235Syasuko.eckert@amd.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2210235Syasuko.eckert@amd.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2310235Syasuko.eckert@amd.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2410235Syasuko.eckert@amd.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2510235Syasuko.eckert@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2610235Syasuko.eckert@amd.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2710235Syasuko.eckert@amd.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2810235Syasuko.eckert@amd.com 2910235Syasuko.eckert@amd.com""" 3010235Syasuko.eckert@amd.comSYNOPSIS 3110235Syasuko.eckert@amd.com 3210235Syasuko.eckert@amd.com ./regression/verify_output.py <McPAT output> 3310235Syasuko.eckert@amd.com 3410235Syasuko.eckert@amd.comDESCRIPTION 3510235Syasuko.eckert@amd.com 3610235Syasuko.eckert@amd.com Verify the output from McPAT. In particular, ensure that the values in the 3710235Syasuko.eckert@amd.com file sum up hierarchically. 3810235Syasuko.eckert@amd.com 3910235Syasuko.eckert@amd.comAUTHORS 4010235Syasuko.eckert@amd.com 4110235Syasuko.eckert@amd.com Joel Hestness <hestness@cs.wisc.edu> (while interning at AMD) 4210235Syasuko.eckert@amd.com Yasuko Eckert <yasuko.eckert@amd.com> 4310235Syasuko.eckert@amd.com 4410235Syasuko.eckert@amd.com""" 4510235Syasuko.eckert@amd.com 4610235Syasuko.eckert@amd.comimport os 4710235Syasuko.eckert@amd.comimport sys 4810235Syasuko.eckert@amd.comimport optparse 4910235Syasuko.eckert@amd.comimport re 5010235Syasuko.eckert@amd.com 5110235Syasuko.eckert@amd.comroot = None 5210235Syasuko.eckert@amd.comcurr_node = None 5310235Syasuko.eckert@amd.com 5410235Syasuko.eckert@amd.comoptionsparser = optparse.OptionParser( 5510235Syasuko.eckert@amd.com formatter = optparse.TitledHelpFormatter(), 5610235Syasuko.eckert@amd.com usage = globals()['__doc__']) 5710235Syasuko.eckert@amd.comoptionsparser.add_option( 5810235Syasuko.eckert@amd.com "-v", "--verbose", action = "store_true", default = False, 5910235Syasuko.eckert@amd.com help = "verbose output") 6010235Syasuko.eckert@amd.com(options, args) = optionsparser.parse_args() 6110235Syasuko.eckert@amd.com 6210235Syasuko.eckert@amd.comdef warning(msg): 6310235Syasuko.eckert@amd.com global options 6410235Syasuko.eckert@amd.com if options.verbose: 6510235Syasuko.eckert@amd.com print "WARNING: %s" %(msg) 6610235Syasuko.eckert@amd.com 6710235Syasuko.eckert@amd.comdef toNumber(value): 6810235Syasuko.eckert@amd.com try: 6910235Syasuko.eckert@amd.com to_return = float(value) 7010235Syasuko.eckert@amd.com except: 7110235Syasuko.eckert@amd.com warning("Value, %s, is not a number" % value) 7210235Syasuko.eckert@amd.com to_return = value 7310235Syasuko.eckert@amd.com 7410235Syasuko.eckert@amd.com return to_return 7510235Syasuko.eckert@amd.com 7610235Syasuko.eckert@amd.comdef withinTolerance(reference, calculated, tolerance = 0.001): 7710235Syasuko.eckert@amd.com if tolerance > 1: 7810235Syasuko.eckert@amd.com warning("Tolernance is too large: %s" % tolerance) 7910235Syasuko.eckert@amd.com upper_bound = reference * (1 + tolerance) 8010235Syasuko.eckert@amd.com lower_bound = reference * (1 - tolerance) 8110235Syasuko.eckert@amd.com return calculated <= upper_bound and calculated >= lower_bound 8210235Syasuko.eckert@amd.com 8310235Syasuko.eckert@amd.comclass Component: 8410235Syasuko.eckert@amd.com def __init__(self): 8510235Syasuko.eckert@amd.com self.parent = None 8610235Syasuko.eckert@amd.com self.name = None 8710235Syasuko.eckert@amd.com self.area = None 8810235Syasuko.eckert@amd.com self.peak_dynamic_power = None 8910235Syasuko.eckert@amd.com self.subthreshold_leakage = None 9010235Syasuko.eckert@amd.com self.gate_leakage = None 9110235Syasuko.eckert@amd.com self.runtime_dynamic_power = None 9210235Syasuko.eckert@amd.com self.runtime_dynamic_energy = None 9310235Syasuko.eckert@amd.com self.total_runtime_energy = None 9410235Syasuko.eckert@amd.com self.children = [] 9510235Syasuko.eckert@amd.com self.hierarchy_level = None 9610235Syasuko.eckert@amd.com 9710235Syasuko.eckert@amd.com def print_data(self): 9810235Syasuko.eckert@amd.com print "%s:" % self.name 9910235Syasuko.eckert@amd.com print " Area = %s" % self.area 10010235Syasuko.eckert@amd.com print " Peak Dynamic Power = %s" % self.peak_dynamic_power 10110235Syasuko.eckert@amd.com print " Subthreshold Leakage = %s" % self.subthreshold_leakage 10210235Syasuko.eckert@amd.com print " Gate Leakage = %s" % self.gate_leakage 10310235Syasuko.eckert@amd.com print " Runtime Dynamic Power = %s" % self.runtime_dynamic_power 10410235Syasuko.eckert@amd.com print " Runtime Dynamic Energy = %s" % self.runtime_dynamic_energy 10510235Syasuko.eckert@amd.com print " Total Runtime Energy = %s" % self.total_runtime_energy 10610235Syasuko.eckert@amd.com 10710235Syasuko.eckert@amd.com def set_name_and_level(self, name_string): 10810235Syasuko.eckert@amd.com self.name = name_string.lstrip().rstrip(":") 10910235Syasuko.eckert@amd.com self.hierarchy_level = (len(re.match(r"\s*", name_string).group()) - 2) / 4 11010235Syasuko.eckert@amd.com 11110235Syasuko.eckert@amd.com def verify_values(self): 11210235Syasuko.eckert@amd.com if len(self.children) == 0: 11310235Syasuko.eckert@amd.com return 11410235Syasuko.eckert@amd.com temp_node = Component() 11510235Syasuko.eckert@amd.com temp_node.area = 0 11610235Syasuko.eckert@amd.com temp_node.peak_dynamic_power = 0 11710235Syasuko.eckert@amd.com temp_node.subthreshold_leakage = 0 11810235Syasuko.eckert@amd.com temp_node.gate_leakage = 0 11910235Syasuko.eckert@amd.com temp_node.runtime_dynamic_power = 0 12010235Syasuko.eckert@amd.com temp_node.runtime_dynamic_energy = 0 12110235Syasuko.eckert@amd.com temp_node.total_runtime_energy = 0 12210235Syasuko.eckert@amd.com for child in self.children: 12310235Syasuko.eckert@amd.com if child != self: 12410235Syasuko.eckert@amd.com temp_node.area += child.area 12510235Syasuko.eckert@amd.com temp_node.peak_dynamic_power += child.peak_dynamic_power 12610235Syasuko.eckert@amd.com temp_node.subthreshold_leakage += child.subthreshold_leakage 12710235Syasuko.eckert@amd.com temp_node.gate_leakage += child.gate_leakage 12810235Syasuko.eckert@amd.com temp_node.runtime_dynamic_power += child.runtime_dynamic_power 12910235Syasuko.eckert@amd.com temp_node.runtime_dynamic_energy += child.runtime_dynamic_energy 13010235Syasuko.eckert@amd.com temp_node.total_runtime_energy += child.total_runtime_energy 13110235Syasuko.eckert@amd.com child.verify_values() 13210235Syasuko.eckert@amd.com 13310235Syasuko.eckert@amd.com if not withinTolerance(self.area, temp_node.area): 13410235Syasuko.eckert@amd.com print "WRONG: %s.area = %s != %s" % \ 13510235Syasuko.eckert@amd.com (self.name, self.area, temp_node.area) 13610235Syasuko.eckert@amd.com 13710235Syasuko.eckert@amd.com if not withinTolerance( 13810235Syasuko.eckert@amd.com self.peak_dynamic_power, temp_node.peak_dynamic_power): 13910235Syasuko.eckert@amd.com print "WRONG: %s.peak_dynamic_power = %s != %s" % \ 14010235Syasuko.eckert@amd.com (self.name, self.peak_dynamic_power, 14110235Syasuko.eckert@amd.com temp_node.peak_dynamic_power) 14210235Syasuko.eckert@amd.com 14310235Syasuko.eckert@amd.com if not withinTolerance( 14410235Syasuko.eckert@amd.com self.subthreshold_leakage, temp_node.subthreshold_leakage): 14510235Syasuko.eckert@amd.com print "WRONG: %s.subthreshold_leakage = %s != %s" % \ 14610235Syasuko.eckert@amd.com (self.name, self.subthreshold_leakage, 14710235Syasuko.eckert@amd.com temp_node.subthreshold_leakage) 14810235Syasuko.eckert@amd.com 14910235Syasuko.eckert@amd.com if not withinTolerance(self.gate_leakage, temp_node.gate_leakage): 15010235Syasuko.eckert@amd.com print "WRONG: %s.gate_leakage = %s != %s" % \ 15110235Syasuko.eckert@amd.com (self.name, self.gate_leakage, temp_node.gate_leakage) 15210235Syasuko.eckert@amd.com 15310235Syasuko.eckert@amd.com if not withinTolerance( 15410235Syasuko.eckert@amd.com self.runtime_dynamic_power, temp_node.runtime_dynamic_power): 15510235Syasuko.eckert@amd.com print "WRONG: %s.runtime_dynamic_power = %s != %s" % \ 15610235Syasuko.eckert@amd.com (self.name, self.runtime_dynamic_power, 15710235Syasuko.eckert@amd.com temp_node.runtime_dynamic_power) 15810235Syasuko.eckert@amd.com 15910235Syasuko.eckert@amd.com if not withinTolerance( 16010235Syasuko.eckert@amd.com self.runtime_dynamic_energy, temp_node.runtime_dynamic_energy): 16110235Syasuko.eckert@amd.com print "WRONG: %s.runtime_dynamic_energy = %s != %s" % \ 16210235Syasuko.eckert@amd.com (self.name, self.runtime_dynamic_energy, 16310235Syasuko.eckert@amd.com temp_node.runtime_dynamic_energy) 16410235Syasuko.eckert@amd.com 16510235Syasuko.eckert@amd.com if not withinTolerance( 16610235Syasuko.eckert@amd.com self.total_runtime_energy, temp_node.total_runtime_energy): 16710235Syasuko.eckert@amd.com print "WRONG: %s.total_runtime_energy = %s != %s" % \ 16810235Syasuko.eckert@amd.com (self.name, self.total_runtime_energy, 16910235Syasuko.eckert@amd.com temp_node.total_runtime_energy) 17010235Syasuko.eckert@amd.com 17110235Syasuko.eckert@amd.comif len(args) < 1: 17210235Syasuko.eckert@amd.com print "ERROR: Must specify a McPAT output file to verify" 17310235Syasuko.eckert@amd.com exit(0) 17410235Syasuko.eckert@amd.com 17510235Syasuko.eckert@amd.com# check params 17610235Syasuko.eckert@amd.commcpat_output = args[0]; 17710235Syasuko.eckert@amd.comif not os.path.exists(mcpat_output): 17810235Syasuko.eckert@amd.com print "ERROR: Output file does not exist: %s" % mcpat_output 17910235Syasuko.eckert@amd.com exit(0) 18010235Syasuko.eckert@amd.com 18110235Syasuko.eckert@amd.comoutput_file_handle = open(mcpat_output, 'r') 18210235Syasuko.eckert@amd.comfor line in output_file_handle: 18310235Syasuko.eckert@amd.com line = line.rstrip() 18410235Syasuko.eckert@amd.com if ":" in line: 18510235Syasuko.eckert@amd.com # Start a new component 18610235Syasuko.eckert@amd.com new_node = Component() 18710235Syasuko.eckert@amd.com if root is None: 18810235Syasuko.eckert@amd.com root = new_node 18910235Syasuko.eckert@amd.com curr_node = new_node 19010235Syasuko.eckert@amd.com else: 19110235Syasuko.eckert@amd.com if ((curr_node.area is None) or 19210235Syasuko.eckert@amd.com (curr_node.peak_dynamic_power is None) or 19310235Syasuko.eckert@amd.com (curr_node.subthreshold_leakage is None) or 19410235Syasuko.eckert@amd.com (curr_node.gate_leakage is None) or 19510235Syasuko.eckert@amd.com (curr_node.runtime_dynamic_power is None) or 19610235Syasuko.eckert@amd.com (curr_node.runtime_dynamic_energy is None) or 19710235Syasuko.eckert@amd.com (curr_node.total_runtime_energy is None)): 19810235Syasuko.eckert@amd.com print "ERROR: Some value is not specified for %s" % curr_node.name 19910235Syasuko.eckert@amd.com curr_node.print_data() 20010235Syasuko.eckert@amd.com exit(0) 20110235Syasuko.eckert@amd.com 20210235Syasuko.eckert@amd.com new_node.set_name_and_level(line) 20310235Syasuko.eckert@amd.com while ( 20410235Syasuko.eckert@amd.com (new_node.hierarchy_level <= curr_node.hierarchy_level) and 20510235Syasuko.eckert@amd.com not curr_node is root): 20610235Syasuko.eckert@amd.com curr_node = curr_node.parent 20710235Syasuko.eckert@amd.com new_node.parent = curr_node 20810235Syasuko.eckert@amd.com curr_node.children.append(new_node) 20910235Syasuko.eckert@amd.com curr_node = new_node 21010235Syasuko.eckert@amd.com 21110235Syasuko.eckert@amd.com elif line is not "": 21210235Syasuko.eckert@amd.com tokens = line.split() 21310235Syasuko.eckert@amd.com if "Area" in line: 21410235Syasuko.eckert@amd.com curr_node.area = toNumber(tokens[2]) 21510235Syasuko.eckert@amd.com elif "Peak Dynamic Power" in line: 21610235Syasuko.eckert@amd.com curr_node.peak_dynamic_power = toNumber(tokens[4]) 21710235Syasuko.eckert@amd.com elif "Peak Dynamic" in line: 21810235Syasuko.eckert@amd.com curr_node.peak_dynamic_power = toNumber(tokens[3]) 21910235Syasuko.eckert@amd.com elif "Subthreshold Leakage Power" in line: 22010235Syasuko.eckert@amd.com curr_node.subthreshold_leakage = toNumber(tokens[4]) 22110235Syasuko.eckert@amd.com elif "Subthreshold Leakage" in line: 22210235Syasuko.eckert@amd.com curr_node.subthreshold_leakage = toNumber(tokens[3]) 22310235Syasuko.eckert@amd.com elif "Gate Leakage Power" in line: 22410235Syasuko.eckert@amd.com curr_node.gate_leakage = toNumber(tokens[4]) 22510235Syasuko.eckert@amd.com elif "Gate Leakage" in line: 22610235Syasuko.eckert@amd.com curr_node.gate_leakage = toNumber(tokens[3]) 22710235Syasuko.eckert@amd.com elif "Runtime Dynamic Power" in line: 22810235Syasuko.eckert@amd.com curr_node.runtime_dynamic_power = toNumber(tokens[4]) 22910235Syasuko.eckert@amd.com elif "Runtime Dynamic Energy" in line: 23010235Syasuko.eckert@amd.com curr_node.runtime_dynamic_energy = toNumber(tokens[4]) 23110235Syasuko.eckert@amd.com elif "Total Runtime Energy" in line: 23210235Syasuko.eckert@amd.com curr_node.total_runtime_energy = toNumber(tokens[4]) 23310235Syasuko.eckert@amd.com else: 23410235Syasuko.eckert@amd.com warning("ERROR: Line not matched: %s" % line) 23510235Syasuko.eckert@amd.com 23610235Syasuko.eckert@amd.comcurr_node = root 23710235Syasuko.eckert@amd.com 23810235Syasuko.eckert@amd.comcurr_node.verify_values() 239