5102fd5a27959d57807f39941577112d389220f3
3 # Copyright (c) 2012-2013,2015 ARM Limited
6 # The license below extends only to copyright in the software and shall
7 # not be construed as granting a license to any other intellectual
8 # property including but not limited to intellectual property relating
9 # to a hardware implementation of the functionality of the software
10 # licensed hereunder. You may use the software subject to the license
11 # terms below provided that you ensure that this notice is replicated
12 # unmodified and in its entirety in all distributions of the software,
13 # modified or unmodified, in source code or in binary form.
15 # Redistribution and use in source and binary forms, with or without
16 # modification, are permitted provided that the following conditions are
17 # met: redistributions of source code must retain the above copyright
18 # notice, this list of conditions and the following disclaimer;
19 # redistributions in binary form must reproduce the above copyright
20 # notice, this list of conditions and the following disclaimer in the
21 # documentation and/or other materials provided with the distribution;
22 # neither the name of the copyright holders nor the names of its
23 # contributors may be used to endorse or promote products derived from
24 # this software without specific prior written permission.
26 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 # This python code is used to migrate checkpoints that were created in one
43 # version of the simulator to newer version. As features are added or bugs are
44 # fixed some of the state that needs to be checkpointed can change. If you have
45 # many historic checkpoints that you use, manually editing them to fix them is
46 # both time consuming and error-prone.
48 # This script provides a way to migrate checkpoints to the newer repository in
49 # a programmatic way. It can be imported into another script or used on the
50 # command line. From the command line the script will either migrate every
51 # checkpoint it finds recursively (-r option) or a single checkpoint. When a
52 # change is made to the gem5 repository that breaks previous checkpoints an
53 # upgrade() method should be implemented in its own .py file and placed in
54 # src/util/cpt_upgraders/. For each upgrader whose tag is not present in
55 # the checkpoint tag list, the upgrade() method will be run, passing in a
56 # ConfigParser object which contains the open file. As these operations can
57 # be isa specific the method can verify the isa and use regexes to find the
58 # correct sections that need to be updated.
62 import glob
, types
, sys
, os
67 def verboseprint(*args
):
78 def __init__(self
, filename
):
79 self
.filename
= filename
80 execfile(filename
, {}, self
.__dict
__)
82 if not hasattr(self
, 'tag'):
83 self
.tag
= osp
.basename(filename
)[:-3]
84 if not hasattr(self
, 'depends'):
86 elif isinstance(self
.depends
, str):
87 self
.depends
= [self
.depends
]
89 if not hasattr(self
, 'upgrader'):
90 print "Error: no upgrader method for", self
.tag
92 elif not isinstance(self
.upgrader
, types
.FunctionType
):
93 print "Error: 'upgrader' for %s is %s, not function", \
97 if hasattr(self
, 'legacy_version'):
98 Upgrader
.legacy
[self
.legacy_version
] = self
100 Upgrader
.by_tag
[self
.tag
] = self
101 Upgrader
.tag_set
.add(self
.tag
)
103 def ready(self
, tags
):
104 for dep
in self
.depends
:
109 def upgrade(self
, cpt
):
111 verboseprint("applied upgrade for", self
.tag
)
115 return Upgrader
.by_tag
[tag
]
119 util_dir
= osp
.dirname(osp
.abspath(__file__
))
121 for py
in glob
.glob(util_dir
+ '/cpt_upgraders/*.py'):
124 # make linear dependences for legacy versions
126 while i
in Upgrader
.legacy
:
127 Upgrader
.legacy
[i
].depends
= [Upgrader
.legacy
[i
-1].tag
]
130 def process_file(path
, **kwargs
):
131 if not osp
.isfile(path
):
133 raise IOError(ennro
.ENOENT
, "No such file", path
)
135 verboseprint("Processing file %s...." % path
)
137 if kwargs
.get('backup', True):
139 shutil
.copyfile(path
, path
+ '.bak')
141 cpt
= ConfigParser
.SafeConfigParser()
143 # gem5 is case sensitive with paramaters
144 cpt
.optionxform
= str
146 # Read the current data
147 cpt_file
= file(path
, 'r')
153 # Make sure we know what we're starting from
154 if cpt
.has_option('root','cpt_ver'):
155 cpt_ver
= cpt
.getint('root','cpt_ver')
157 # Legacy linear checkpoint version
158 # convert to list of tags before proceeding
160 for i
in xrange(2, cpt_ver
+1):
161 tags
.add(Upgrader
.legacy
[i
].tag
)
162 verboseprint("performed legacy version -> tags conversion")
165 cpt
.remove_option('root', 'cpt_ver')
166 elif cpt
.has_option('Globals','version_tags'):
167 tags
= set((''.join(cpt
.get('Globals','version_tags'))).split())
169 print "fatal: no version information in checkpoint"
172 verboseprint("has tags", ' '.join(tags
))
173 # If the current checkpoint has a tag we don't know about, we have
174 # a divergence that (in general) must be addressed by (e.g.) merging
175 # simulator support for its changes.
176 unknown_tags
= tags
- Upgrader
.tag_set
178 print "warning: upgrade script does not recognize the following "\
179 "tags in this checkpoint:", ' '.join(unknown_tags
)
181 # Apply migrations for tags not in checkpoint, respecting dependences
182 to_apply
= Upgrader
.tag_set
- tags
184 ready
= set([ t
for t
in to_apply
if Upgrader
.get(t
).ready(tags
) ])
186 print "could not apply these upgrades:", ' '.join(to_apply
)
187 print "upgrade dependences impossible to resolve; aborting"
191 Upgrader
.get(tag
).upgrade(cpt
)
198 verboseprint("...nothing to do")
201 cpt
.set('Globals', 'version_tags', ' '.join(tags
))
203 # Write the old data back
204 verboseprint("...completed")
205 cpt
.write(file(path
, 'w'))
207 if __name__
== '__main__':
208 from optparse
import OptionParser
, SUPPRESS_HELP
209 parser
= OptionParser("usage: %prog [options] <filename or directory>")
210 parser
.add_option("-r", "--recurse", action
="store_true",
211 help="Recurse through all subdirectories modifying "\
212 "each checkpoint that is found")
213 parser
.add_option("-N", "--no-backup", action
="store_false",
214 dest
="backup", default
=True,
215 help="Do no backup each checkpoint before modifying it")
216 parser
.add_option("-v", "--verbose", action
="store_true",
217 help="Print out debugging information as")
218 parser
.add_option("--get-cc-file", action
="store_true",
219 # used during build; generate src/sim/tags.cc and exit
222 (options
, args
) = parser
.parse_args()
223 verbose_print
= options
.verbose
227 if options
.get_cc_file
:
228 print "// this file is auto-generated by util/cpt_upgrader.py"
229 print "#include <string>"
230 print "#include <set>"
232 print "std::set<std::string> version_tags = {"
233 for tag
in Upgrader
.tag_set
:
234 print " \"%s\"," % tag
238 parser
.error("You must specify a checkpoint file to modify or a "\
239 "directory of checkpoints to recursively update")
241 # Deal with shell variables and ~
242 path
= osp
.expandvars(osp
.expanduser(args
[0]))
244 # Process a single file if we have it
246 process_file(path
, **vars(options
))
247 # Process an entire directory
248 elif osp
.isdir(path
):
249 cpt_file
= osp
.join(path
, 'm5.cpt')
251 # Visit very file and see if it matches
252 for root
,dirs
,files
in os
.walk(path
):
255 process_file(osp
.join(root
,name
), **vars(options
))
258 # Maybe someone passed a cpt.XXXXXXX directory and not m5.cpt
259 elif osp
.isfile(cpt_file
):
260 process_file(cpt_file
, **vars(options
))
262 print "Error: checkpoint file not found at in %s " % path
,
263 print "and recurse not specified"