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