diff options
Diffstat (limited to 'ext/mcpat/regression/verify_output.py')
-rw-r--r-- | ext/mcpat/regression/verify_output.py | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/ext/mcpat/regression/verify_output.py b/ext/mcpat/regression/verify_output.py new file mode 100644 index 000000000..c37663c8f --- /dev/null +++ b/ext/mcpat/regression/verify_output.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python + +# Copyright (c) 2010-2013 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +SYNOPSIS + + ./regression/verify_output.py <McPAT output> + +DESCRIPTION + + Verify the output from McPAT. In particular, ensure that the values in the + file sum up hierarchically. + +AUTHORS + + Joel Hestness <hestness@cs.wisc.edu> (while interning at AMD) + Yasuko Eckert <yasuko.eckert@amd.com> + +""" + +import os +import sys +import optparse +import re + +root = None +curr_node = None + +optionsparser = optparse.OptionParser( + formatter = optparse.TitledHelpFormatter(), + usage = globals()['__doc__']) +optionsparser.add_option( + "-v", "--verbose", action = "store_true", default = False, + help = "verbose output") +(options, args) = optionsparser.parse_args() + +def warning(msg): + global options + if options.verbose: + print "WARNING: %s" %(msg) + +def toNumber(value): + try: + to_return = float(value) + except: + warning("Value, %s, is not a number" % value) + to_return = value + + return to_return + +def withinTolerance(reference, calculated, tolerance = 0.001): + if tolerance > 1: + warning("Tolernance is too large: %s" % tolerance) + upper_bound = reference * (1 + tolerance) + lower_bound = reference * (1 - tolerance) + return calculated <= upper_bound and calculated >= lower_bound + +class Component: + def __init__(self): + self.parent = None + self.name = None + self.area = None + self.peak_dynamic_power = None + self.subthreshold_leakage = None + self.gate_leakage = None + self.runtime_dynamic_power = None + self.runtime_dynamic_energy = None + self.total_runtime_energy = None + self.children = [] + self.hierarchy_level = None + + def print_data(self): + print "%s:" % self.name + print " Area = %s" % self.area + print " Peak Dynamic Power = %s" % self.peak_dynamic_power + print " Subthreshold Leakage = %s" % self.subthreshold_leakage + print " Gate Leakage = %s" % self.gate_leakage + print " Runtime Dynamic Power = %s" % self.runtime_dynamic_power + print " Runtime Dynamic Energy = %s" % self.runtime_dynamic_energy + print " Total Runtime Energy = %s" % self.total_runtime_energy + + def set_name_and_level(self, name_string): + self.name = name_string.lstrip().rstrip(":") + self.hierarchy_level = (len(re.match(r"\s*", name_string).group()) - 2) / 4 + + def verify_values(self): + if len(self.children) == 0: + return + temp_node = Component() + temp_node.area = 0 + temp_node.peak_dynamic_power = 0 + temp_node.subthreshold_leakage = 0 + temp_node.gate_leakage = 0 + temp_node.runtime_dynamic_power = 0 + temp_node.runtime_dynamic_energy = 0 + temp_node.total_runtime_energy = 0 + for child in self.children: + if child != self: + temp_node.area += child.area + temp_node.peak_dynamic_power += child.peak_dynamic_power + temp_node.subthreshold_leakage += child.subthreshold_leakage + temp_node.gate_leakage += child.gate_leakage + temp_node.runtime_dynamic_power += child.runtime_dynamic_power + temp_node.runtime_dynamic_energy += child.runtime_dynamic_energy + temp_node.total_runtime_energy += child.total_runtime_energy + child.verify_values() + + if not withinTolerance(self.area, temp_node.area): + print "WRONG: %s.area = %s != %s" % \ + (self.name, self.area, temp_node.area) + + if not withinTolerance( + self.peak_dynamic_power, temp_node.peak_dynamic_power): + print "WRONG: %s.peak_dynamic_power = %s != %s" % \ + (self.name, self.peak_dynamic_power, + temp_node.peak_dynamic_power) + + if not withinTolerance( + self.subthreshold_leakage, temp_node.subthreshold_leakage): + print "WRONG: %s.subthreshold_leakage = %s != %s" % \ + (self.name, self.subthreshold_leakage, + temp_node.subthreshold_leakage) + + if not withinTolerance(self.gate_leakage, temp_node.gate_leakage): + print "WRONG: %s.gate_leakage = %s != %s" % \ + (self.name, self.gate_leakage, temp_node.gate_leakage) + + if not withinTolerance( + self.runtime_dynamic_power, temp_node.runtime_dynamic_power): + print "WRONG: %s.runtime_dynamic_power = %s != %s" % \ + (self.name, self.runtime_dynamic_power, + temp_node.runtime_dynamic_power) + + if not withinTolerance( + self.runtime_dynamic_energy, temp_node.runtime_dynamic_energy): + print "WRONG: %s.runtime_dynamic_energy = %s != %s" % \ + (self.name, self.runtime_dynamic_energy, + temp_node.runtime_dynamic_energy) + + if not withinTolerance( + self.total_runtime_energy, temp_node.total_runtime_energy): + print "WRONG: %s.total_runtime_energy = %s != %s" % \ + (self.name, self.total_runtime_energy, + temp_node.total_runtime_energy) + +if len(args) < 1: + print "ERROR: Must specify a McPAT output file to verify" + exit(0) + +# check params +mcpat_output = args[0]; +if not os.path.exists(mcpat_output): + print "ERROR: Output file does not exist: %s" % mcpat_output + exit(0) + +output_file_handle = open(mcpat_output, 'r') +for line in output_file_handle: + line = line.rstrip() + if ":" in line: + # Start a new component + new_node = Component() + if root is None: + root = new_node + curr_node = new_node + else: + if ((curr_node.area is None) or + (curr_node.peak_dynamic_power is None) or + (curr_node.subthreshold_leakage is None) or + (curr_node.gate_leakage is None) or + (curr_node.runtime_dynamic_power is None) or + (curr_node.runtime_dynamic_energy is None) or + (curr_node.total_runtime_energy is None)): + print "ERROR: Some value is not specified for %s" % curr_node.name + curr_node.print_data() + exit(0) + + new_node.set_name_and_level(line) + while ( + (new_node.hierarchy_level <= curr_node.hierarchy_level) and + not curr_node is root): + curr_node = curr_node.parent + new_node.parent = curr_node + curr_node.children.append(new_node) + curr_node = new_node + + elif line is not "": + tokens = line.split() + if "Area" in line: + curr_node.area = toNumber(tokens[2]) + elif "Peak Dynamic Power" in line: + curr_node.peak_dynamic_power = toNumber(tokens[4]) + elif "Peak Dynamic" in line: + curr_node.peak_dynamic_power = toNumber(tokens[3]) + elif "Subthreshold Leakage Power" in line: + curr_node.subthreshold_leakage = toNumber(tokens[4]) + elif "Subthreshold Leakage" in line: + curr_node.subthreshold_leakage = toNumber(tokens[3]) + elif "Gate Leakage Power" in line: + curr_node.gate_leakage = toNumber(tokens[4]) + elif "Gate Leakage" in line: + curr_node.gate_leakage = toNumber(tokens[3]) + elif "Runtime Dynamic Power" in line: + curr_node.runtime_dynamic_power = toNumber(tokens[4]) + elif "Runtime Dynamic Energy" in line: + curr_node.runtime_dynamic_energy = toNumber(tokens[4]) + elif "Total Runtime Energy" in line: + curr_node.total_runtime_energy = toNumber(tokens[4]) + else: + warning("ERROR: Line not matched: %s" % line) + +curr_node = root + +curr_node.verify_values() |