verify_output.py (10235:0db28826e333) verify_output.py (11828:36b064696175)
1#!/usr/bin/env python
1#!/usr/bin/env python2
2
3# Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met: redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer;
10# redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution;
13# neither the name of the copyright holders nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29"""
30SYNOPSIS
31
32 ./regression/verify_output.py <McPAT output>
33
34DESCRIPTION
35
36 Verify the output from McPAT. In particular, ensure that the values in the
37 file sum up hierarchically.
38
39AUTHORS
40
41 Joel Hestness <hestness@cs.wisc.edu> (while interning at AMD)
42 Yasuko Eckert <yasuko.eckert@amd.com>
43
44"""
45
46import os
47import sys
48import optparse
49import re
50
51root = None
52curr_node = None
53
54optionsparser = optparse.OptionParser(
55 formatter = optparse.TitledHelpFormatter(),
56 usage = globals()['__doc__'])
57optionsparser.add_option(
58 "-v", "--verbose", action = "store_true", default = False,
59 help = "verbose output")
60(options, args) = optionsparser.parse_args()
61
62def warning(msg):
63 global options
64 if options.verbose:
65 print "WARNING: %s" %(msg)
66
67def toNumber(value):
68 try:
69 to_return = float(value)
70 except:
71 warning("Value, %s, is not a number" % value)
72 to_return = value
73
74 return to_return
75
76def withinTolerance(reference, calculated, tolerance = 0.001):
77 if tolerance > 1:
78 warning("Tolernance is too large: %s" % tolerance)
79 upper_bound = reference * (1 + tolerance)
80 lower_bound = reference * (1 - tolerance)
81 return calculated <= upper_bound and calculated >= lower_bound
82
83class Component:
84 def __init__(self):
85 self.parent = None
86 self.name = None
87 self.area = None
88 self.peak_dynamic_power = None
89 self.subthreshold_leakage = None
90 self.gate_leakage = None
91 self.runtime_dynamic_power = None
92 self.runtime_dynamic_energy = None
93 self.total_runtime_energy = None
94 self.children = []
95 self.hierarchy_level = None
96
97 def print_data(self):
98 print "%s:" % self.name
99 print " Area = %s" % self.area
100 print " Peak Dynamic Power = %s" % self.peak_dynamic_power
101 print " Subthreshold Leakage = %s" % self.subthreshold_leakage
102 print " Gate Leakage = %s" % self.gate_leakage
103 print " Runtime Dynamic Power = %s" % self.runtime_dynamic_power
104 print " Runtime Dynamic Energy = %s" % self.runtime_dynamic_energy
105 print " Total Runtime Energy = %s" % self.total_runtime_energy
106
107 def set_name_and_level(self, name_string):
108 self.name = name_string.lstrip().rstrip(":")
109 self.hierarchy_level = (len(re.match(r"\s*", name_string).group()) - 2) / 4
110
111 def verify_values(self):
112 if len(self.children) == 0:
113 return
114 temp_node = Component()
115 temp_node.area = 0
116 temp_node.peak_dynamic_power = 0
117 temp_node.subthreshold_leakage = 0
118 temp_node.gate_leakage = 0
119 temp_node.runtime_dynamic_power = 0
120 temp_node.runtime_dynamic_energy = 0
121 temp_node.total_runtime_energy = 0
122 for child in self.children:
123 if child != self:
124 temp_node.area += child.area
125 temp_node.peak_dynamic_power += child.peak_dynamic_power
126 temp_node.subthreshold_leakage += child.subthreshold_leakage
127 temp_node.gate_leakage += child.gate_leakage
128 temp_node.runtime_dynamic_power += child.runtime_dynamic_power
129 temp_node.runtime_dynamic_energy += child.runtime_dynamic_energy
130 temp_node.total_runtime_energy += child.total_runtime_energy
131 child.verify_values()
132
133 if not withinTolerance(self.area, temp_node.area):
134 print "WRONG: %s.area = %s != %s" % \
135 (self.name, self.area, temp_node.area)
136
137 if not withinTolerance(
138 self.peak_dynamic_power, temp_node.peak_dynamic_power):
139 print "WRONG: %s.peak_dynamic_power = %s != %s" % \
140 (self.name, self.peak_dynamic_power,
141 temp_node.peak_dynamic_power)
142
143 if not withinTolerance(
144 self.subthreshold_leakage, temp_node.subthreshold_leakage):
145 print "WRONG: %s.subthreshold_leakage = %s != %s" % \
146 (self.name, self.subthreshold_leakage,
147 temp_node.subthreshold_leakage)
148
149 if not withinTolerance(self.gate_leakage, temp_node.gate_leakage):
150 print "WRONG: %s.gate_leakage = %s != %s" % \
151 (self.name, self.gate_leakage, temp_node.gate_leakage)
152
153 if not withinTolerance(
154 self.runtime_dynamic_power, temp_node.runtime_dynamic_power):
155 print "WRONG: %s.runtime_dynamic_power = %s != %s" % \
156 (self.name, self.runtime_dynamic_power,
157 temp_node.runtime_dynamic_power)
158
159 if not withinTolerance(
160 self.runtime_dynamic_energy, temp_node.runtime_dynamic_energy):
161 print "WRONG: %s.runtime_dynamic_energy = %s != %s" % \
162 (self.name, self.runtime_dynamic_energy,
163 temp_node.runtime_dynamic_energy)
164
165 if not withinTolerance(
166 self.total_runtime_energy, temp_node.total_runtime_energy):
167 print "WRONG: %s.total_runtime_energy = %s != %s" % \
168 (self.name, self.total_runtime_energy,
169 temp_node.total_runtime_energy)
170
171if len(args) < 1:
172 print "ERROR: Must specify a McPAT output file to verify"
173 exit(0)
174
175# check params
176mcpat_output = args[0];
177if not os.path.exists(mcpat_output):
178 print "ERROR: Output file does not exist: %s" % mcpat_output
179 exit(0)
180
181output_file_handle = open(mcpat_output, 'r')
182for line in output_file_handle:
183 line = line.rstrip()
184 if ":" in line:
185 # Start a new component
186 new_node = Component()
187 if root is None:
188 root = new_node
189 curr_node = new_node
190 else:
191 if ((curr_node.area is None) or
192 (curr_node.peak_dynamic_power is None) or
193 (curr_node.subthreshold_leakage is None) or
194 (curr_node.gate_leakage is None) or
195 (curr_node.runtime_dynamic_power is None) or
196 (curr_node.runtime_dynamic_energy is None) or
197 (curr_node.total_runtime_energy is None)):
198 print "ERROR: Some value is not specified for %s" % curr_node.name
199 curr_node.print_data()
200 exit(0)
201
202 new_node.set_name_and_level(line)
203 while (
204 (new_node.hierarchy_level <= curr_node.hierarchy_level) and
205 not curr_node is root):
206 curr_node = curr_node.parent
207 new_node.parent = curr_node
208 curr_node.children.append(new_node)
209 curr_node = new_node
210
211 elif line is not "":
212 tokens = line.split()
213 if "Area" in line:
214 curr_node.area = toNumber(tokens[2])
215 elif "Peak Dynamic Power" in line:
216 curr_node.peak_dynamic_power = toNumber(tokens[4])
217 elif "Peak Dynamic" in line:
218 curr_node.peak_dynamic_power = toNumber(tokens[3])
219 elif "Subthreshold Leakage Power" in line:
220 curr_node.subthreshold_leakage = toNumber(tokens[4])
221 elif "Subthreshold Leakage" in line:
222 curr_node.subthreshold_leakage = toNumber(tokens[3])
223 elif "Gate Leakage Power" in line:
224 curr_node.gate_leakage = toNumber(tokens[4])
225 elif "Gate Leakage" in line:
226 curr_node.gate_leakage = toNumber(tokens[3])
227 elif "Runtime Dynamic Power" in line:
228 curr_node.runtime_dynamic_power = toNumber(tokens[4])
229 elif "Runtime Dynamic Energy" in line:
230 curr_node.runtime_dynamic_energy = toNumber(tokens[4])
231 elif "Total Runtime Energy" in line:
232 curr_node.total_runtime_energy = toNumber(tokens[4])
233 else:
234 warning("ERROR: Line not matched: %s" % line)
235
236curr_node = root
237
238curr_node.verify_values()
2
3# Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met: redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer;
10# redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution;
13# neither the name of the copyright holders nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29"""
30SYNOPSIS
31
32 ./regression/verify_output.py <McPAT output>
33
34DESCRIPTION
35
36 Verify the output from McPAT. In particular, ensure that the values in the
37 file sum up hierarchically.
38
39AUTHORS
40
41 Joel Hestness <hestness@cs.wisc.edu> (while interning at AMD)
42 Yasuko Eckert <yasuko.eckert@amd.com>
43
44"""
45
46import os
47import sys
48import optparse
49import re
50
51root = None
52curr_node = None
53
54optionsparser = optparse.OptionParser(
55 formatter = optparse.TitledHelpFormatter(),
56 usage = globals()['__doc__'])
57optionsparser.add_option(
58 "-v", "--verbose", action = "store_true", default = False,
59 help = "verbose output")
60(options, args) = optionsparser.parse_args()
61
62def warning(msg):
63 global options
64 if options.verbose:
65 print "WARNING: %s" %(msg)
66
67def toNumber(value):
68 try:
69 to_return = float(value)
70 except:
71 warning("Value, %s, is not a number" % value)
72 to_return = value
73
74 return to_return
75
76def withinTolerance(reference, calculated, tolerance = 0.001):
77 if tolerance > 1:
78 warning("Tolernance is too large: %s" % tolerance)
79 upper_bound = reference * (1 + tolerance)
80 lower_bound = reference * (1 - tolerance)
81 return calculated <= upper_bound and calculated >= lower_bound
82
83class Component:
84 def __init__(self):
85 self.parent = None
86 self.name = None
87 self.area = None
88 self.peak_dynamic_power = None
89 self.subthreshold_leakage = None
90 self.gate_leakage = None
91 self.runtime_dynamic_power = None
92 self.runtime_dynamic_energy = None
93 self.total_runtime_energy = None
94 self.children = []
95 self.hierarchy_level = None
96
97 def print_data(self):
98 print "%s:" % self.name
99 print " Area = %s" % self.area
100 print " Peak Dynamic Power = %s" % self.peak_dynamic_power
101 print " Subthreshold Leakage = %s" % self.subthreshold_leakage
102 print " Gate Leakage = %s" % self.gate_leakage
103 print " Runtime Dynamic Power = %s" % self.runtime_dynamic_power
104 print " Runtime Dynamic Energy = %s" % self.runtime_dynamic_energy
105 print " Total Runtime Energy = %s" % self.total_runtime_energy
106
107 def set_name_and_level(self, name_string):
108 self.name = name_string.lstrip().rstrip(":")
109 self.hierarchy_level = (len(re.match(r"\s*", name_string).group()) - 2) / 4
110
111 def verify_values(self):
112 if len(self.children) == 0:
113 return
114 temp_node = Component()
115 temp_node.area = 0
116 temp_node.peak_dynamic_power = 0
117 temp_node.subthreshold_leakage = 0
118 temp_node.gate_leakage = 0
119 temp_node.runtime_dynamic_power = 0
120 temp_node.runtime_dynamic_energy = 0
121 temp_node.total_runtime_energy = 0
122 for child in self.children:
123 if child != self:
124 temp_node.area += child.area
125 temp_node.peak_dynamic_power += child.peak_dynamic_power
126 temp_node.subthreshold_leakage += child.subthreshold_leakage
127 temp_node.gate_leakage += child.gate_leakage
128 temp_node.runtime_dynamic_power += child.runtime_dynamic_power
129 temp_node.runtime_dynamic_energy += child.runtime_dynamic_energy
130 temp_node.total_runtime_energy += child.total_runtime_energy
131 child.verify_values()
132
133 if not withinTolerance(self.area, temp_node.area):
134 print "WRONG: %s.area = %s != %s" % \
135 (self.name, self.area, temp_node.area)
136
137 if not withinTolerance(
138 self.peak_dynamic_power, temp_node.peak_dynamic_power):
139 print "WRONG: %s.peak_dynamic_power = %s != %s" % \
140 (self.name, self.peak_dynamic_power,
141 temp_node.peak_dynamic_power)
142
143 if not withinTolerance(
144 self.subthreshold_leakage, temp_node.subthreshold_leakage):
145 print "WRONG: %s.subthreshold_leakage = %s != %s" % \
146 (self.name, self.subthreshold_leakage,
147 temp_node.subthreshold_leakage)
148
149 if not withinTolerance(self.gate_leakage, temp_node.gate_leakage):
150 print "WRONG: %s.gate_leakage = %s != %s" % \
151 (self.name, self.gate_leakage, temp_node.gate_leakage)
152
153 if not withinTolerance(
154 self.runtime_dynamic_power, temp_node.runtime_dynamic_power):
155 print "WRONG: %s.runtime_dynamic_power = %s != %s" % \
156 (self.name, self.runtime_dynamic_power,
157 temp_node.runtime_dynamic_power)
158
159 if not withinTolerance(
160 self.runtime_dynamic_energy, temp_node.runtime_dynamic_energy):
161 print "WRONG: %s.runtime_dynamic_energy = %s != %s" % \
162 (self.name, self.runtime_dynamic_energy,
163 temp_node.runtime_dynamic_energy)
164
165 if not withinTolerance(
166 self.total_runtime_energy, temp_node.total_runtime_energy):
167 print "WRONG: %s.total_runtime_energy = %s != %s" % \
168 (self.name, self.total_runtime_energy,
169 temp_node.total_runtime_energy)
170
171if len(args) < 1:
172 print "ERROR: Must specify a McPAT output file to verify"
173 exit(0)
174
175# check params
176mcpat_output = args[0];
177if not os.path.exists(mcpat_output):
178 print "ERROR: Output file does not exist: %s" % mcpat_output
179 exit(0)
180
181output_file_handle = open(mcpat_output, 'r')
182for line in output_file_handle:
183 line = line.rstrip()
184 if ":" in line:
185 # Start a new component
186 new_node = Component()
187 if root is None:
188 root = new_node
189 curr_node = new_node
190 else:
191 if ((curr_node.area is None) or
192 (curr_node.peak_dynamic_power is None) or
193 (curr_node.subthreshold_leakage is None) or
194 (curr_node.gate_leakage is None) or
195 (curr_node.runtime_dynamic_power is None) or
196 (curr_node.runtime_dynamic_energy is None) or
197 (curr_node.total_runtime_energy is None)):
198 print "ERROR: Some value is not specified for %s" % curr_node.name
199 curr_node.print_data()
200 exit(0)
201
202 new_node.set_name_and_level(line)
203 while (
204 (new_node.hierarchy_level <= curr_node.hierarchy_level) and
205 not curr_node is root):
206 curr_node = curr_node.parent
207 new_node.parent = curr_node
208 curr_node.children.append(new_node)
209 curr_node = new_node
210
211 elif line is not "":
212 tokens = line.split()
213 if "Area" in line:
214 curr_node.area = toNumber(tokens[2])
215 elif "Peak Dynamic Power" in line:
216 curr_node.peak_dynamic_power = toNumber(tokens[4])
217 elif "Peak Dynamic" in line:
218 curr_node.peak_dynamic_power = toNumber(tokens[3])
219 elif "Subthreshold Leakage Power" in line:
220 curr_node.subthreshold_leakage = toNumber(tokens[4])
221 elif "Subthreshold Leakage" in line:
222 curr_node.subthreshold_leakage = toNumber(tokens[3])
223 elif "Gate Leakage Power" in line:
224 curr_node.gate_leakage = toNumber(tokens[4])
225 elif "Gate Leakage" in line:
226 curr_node.gate_leakage = toNumber(tokens[3])
227 elif "Runtime Dynamic Power" in line:
228 curr_node.runtime_dynamic_power = toNumber(tokens[4])
229 elif "Runtime Dynamic Energy" in line:
230 curr_node.runtime_dynamic_energy = toNumber(tokens[4])
231 elif "Total Runtime Energy" in line:
232 curr_node.total_runtime_energy = toNumber(tokens[4])
233 else:
234 warning("ERROR: Line not matched: %s" % line)
235
236curr_node = root
237
238curr_node.verify_values()