cpt_upgrader.py revision 9056:0e38b529c387
1360SN/A#!/usr/bin/env python
210850SGiacomo.Gabrielli@arm.com
310796Sbrandon.potter@amd.com# Copyright (c) 2012 ARM Limited
410027SChris.Adeniyi-Jones@arm.com# All rights reserved
510027SChris.Adeniyi-Jones@arm.com#
610027SChris.Adeniyi-Jones@arm.com# The license below extends only to copyright in the software and shall
710027SChris.Adeniyi-Jones@arm.com# not be construed as granting a license to any other intellectual
810027SChris.Adeniyi-Jones@arm.com# property including but not limited to intellectual property relating
910027SChris.Adeniyi-Jones@arm.com# to a hardware implementation of the functionality of the software
1010027SChris.Adeniyi-Jones@arm.com# licensed hereunder.  You may use the software subject to the license
1110027SChris.Adeniyi-Jones@arm.com# terms below provided that you ensure that this notice is replicated
1210027SChris.Adeniyi-Jones@arm.com# unmodified and in its entirety in all distributions of the software,
1310027SChris.Adeniyi-Jones@arm.com# modified or unmodified, in source code or in binary form.
1410027SChris.Adeniyi-Jones@arm.com#
151458SN/A# Redistribution and use in source and binary forms, with or without
16360SN/A# modification, are permitted provided that the following conditions are
17360SN/A# met: redistributions of source code must retain the above copyright
18360SN/A# notice, this list of conditions and the following disclaimer;
19360SN/A# redistributions in binary form must reproduce the above copyright
20360SN/A# notice, this list of conditions and the following disclaimer in the
21360SN/A# documentation and/or other materials provided with the distribution;
22360SN/A# neither the name of the copyright holders nor the names of its
23360SN/A# contributors may be used to endorse or promote products derived from
24360SN/A# this software without specific prior written permission.
25360SN/A#
26360SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27360SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28360SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29360SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30360SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31360SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32360SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33360SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34360SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35360SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36360SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37360SN/A#
38360SN/A# Authors: Ali Saidi
39360SN/A#
402665Ssaidi@eecs.umich.edu
412665Ssaidi@eecs.umich.edu# This python code is used to migrate checkpoints that were created in one
422665Ssaidi@eecs.umich.edu# version of the simulator to newer version. As features are added or bugs are
43360SN/A# fixed some of the state that needs to be checkpointed can change. If you have
44360SN/A# many historic checkpoints that you use, manually editing them to fix them is
451354SN/A# both time consuming and error-prone.
461354SN/A
47360SN/A# This script provides a way to migrate checkpoints to the newer repository in
4812018Sandreas.sandberg@arm.com# a programatic way. It can be imported into another script or used on the
4912018Sandreas.sandberg@arm.com# command line. From the command line the script will either migrate every
5012018Sandreas.sandberg@arm.com# checkpoint it finds recursively (-r option) or a single checkpoint. When a
5112018Sandreas.sandberg@arm.com# change is made to the gem5 repository that breaks previous checkpoints a
5212018Sandreas.sandberg@arm.com# from_N() method should be implemented here and the gem5CheckpointVersion
5312018Sandreas.sandberg@arm.com# variable in src/sim/serialize.hh should be incremented. For each version
5412018Sandreas.sandberg@arm.com# between the checkpoints current version and the new version the from_N()
552064SN/A# method will be run, passing in a ConfigParser object which contains the open
5612018Sandreas.sandberg@arm.com# file. As these operations can be isa specific the method can verify the isa
5712018Sandreas.sandberg@arm.com# and use regexes to find the correct sections that need to be updated.
5812018Sandreas.sandberg@arm.com
5912018Sandreas.sandberg@arm.com
6012018Sandreas.sandberg@arm.comimport ConfigParser
6112018Sandreas.sandberg@arm.comimport sys, os
6211799Sbrandon.potter@amd.comimport os.path as osp
6312018Sandreas.sandberg@arm.com
6412018Sandreas.sandberg@arm.comdef from_0(cpt):
6512018Sandreas.sandberg@arm.com    pass
6612018Sandreas.sandberg@arm.com
6712018Sandreas.sandberg@arm.com# An example of a translator
6812018Sandreas.sandberg@arm.comdef from_1(cpt):
6911799Sbrandon.potter@amd.com    if cpt.get('root','isa') == 'arm':
70360SN/A        for sec in cpt.sections():
71360SN/A            import re
72360SN/A            # Search for all the execution contexts
73360SN/A            if re.search('.*sys.*\.cpu.*\.x.\..*', sec):
74360SN/A                # Update each one
75360SN/A                mr = cpt.get(sec, 'miscRegs').split()
761809SN/A                #mr.insert(21,0)
7711800Sbrandon.potter@amd.com                #mr.insert(26,0)
7811392Sbrandon.potter@amd.com                cpt.set(sec, 'miscRegs', ' '.join(str(x) for x in mr))
791809SN/A
8011392Sbrandon.potter@amd.commigrations = []
8113902Sbrandon.potter@amd.commigrations.append(from_0)
8213570Sbrandon.potter@amd.commigrations.append(from_1)
8313902Sbrandon.potter@amd.com
8411383Sbrandon.potter@amd.comverbose_print = False
8513568Sbrandon.potter@amd.com
863113Sgblack@eecs.umich.edudef verboseprint(*args):
8713902Sbrandon.potter@amd.com    if not verbose_print:
8811799Sbrandon.potter@amd.com        return
8911759Sbrandon.potter@amd.com    for arg in args:
9013902Sbrandon.potter@amd.com        print arg,
9111812Sbaz21@cam.ac.uk    print
9211812Sbaz21@cam.ac.uk
9313902Sbrandon.potter@amd.comdef process_file(path, **kwargs):
9411799Sbrandon.potter@amd.com    if not osp.isfile(path):
958229Snate@binkert.org        import errno
9613570Sbrandon.potter@amd.com        raise IOError(ennro.ENOENT, "No such file", path)
978229Snate@binkert.org
9811594Santhony.gutierrez@amd.com    verboseprint("Processing file %s...." % path)
997075Snate@binkert.org
1008229Snate@binkert.org    if kwargs.get('backup', True):
10111856Sbrandon.potter@amd.com        import shutil
1027075Snate@binkert.org        shutil.copyfile(path, path + '.bak')
103360SN/A
10412461Sgabeblack@google.com    cpt = ConfigParser.SafeConfigParser()
10511886Sbrandon.potter@amd.com
10611800Sbrandon.potter@amd.com    # gem5 is case sensitive with paramaters
10711392Sbrandon.potter@amd.com    cpt.optionxform = str
10812334Sgabeblack@google.com
1091354SN/A    # Read the current data
1106216Snate@binkert.org    cpt_file = file(path, 'r')
1116658Snate@binkert.org    cpt.readfp(cpt_file)
1122474SN/A    cpt_file.close()
1132680Sktlim@umich.edu
1148229Snate@binkert.org    # Make sure we know what we're starting from
11511886Sbrandon.potter@amd.com    if not cpt.has_option('root','cpt_ver'):
11610496Ssteve.reinhardt@amd.com        raise LookupError("cannot determine version of checkpoint")
11711911SBrandon.Potter@amd.com
1188229Snate@binkert.org    cpt_ver = cpt.getint('root','cpt_ver')
11911794Sbrandon.potter@amd.com
12011886Sbrandon.potter@amd.com    # If the current checkpoint is longer than the migrations list, we have a problem
12110497Ssteve.reinhardt@amd.com    # and someone didn't update this file
12211794Sbrandon.potter@amd.com    if cpt_ver > len(migrations):
123360SN/A        raise ValueError("upgrade script is too old and needs updating")
12413629SAndrea.Mondelli@ucf.edu
12513629SAndrea.Mondelli@ucf.edu    verboseprint("\t...file is at version %#x" % cpt_ver)
12613629SAndrea.Mondelli@ucf.edu
12713629SAndrea.Mondelli@ucf.edu    if cpt_ver == len(migrations):
128360SN/A        verboseprint("\t...nothing to do")
129360SN/A        return
130360SN/A
131360SN/A    # Walk through every function from now until the end fixing the checkpoint
132360SN/A    for v in xrange(cpt_ver,len(migrations)):
133360SN/A        verboseprint("\t...migrating to version %#x" %  (v + 1))
134360SN/A        migrations[v](cpt)
135360SN/A        cpt.set('root','cpt_ver', str(v + 1))
136360SN/A
137378SN/A    # Write the old data back
1381706SN/A    verboseprint("\t...completed")
13911851Sbrandon.potter@amd.com    cpt.write(file(path, 'w'))
140378SN/A
141378SN/A
142378SN/Aif __name__ == '__main__':
143378SN/A    from optparse import OptionParser
144378SN/A    parser = OptionParser("usage: %prog [options] <filename or directory>")
1451706SN/A    parser.add_option("-r", "--recurse", action="store_true",
14611851Sbrandon.potter@amd.com                      help="Recurse through all subdirectories modifying "\
147360SN/A                           "each checkpoint that is found")
14811760Sbrandon.potter@amd.com    parser.add_option("-N", "--no-backup", action="store_false",
14911760Sbrandon.potter@amd.com                      dest="backup", default=True,
15011851Sbrandon.potter@amd.com                      help="Do no backup each checkpoint before modifying it")
15111760Sbrandon.potter@amd.com    parser.add_option("-v", "--verbose", action="store_true",
1526109Ssanchezd@stanford.edu                      help="Print out debugging information as")
1531706SN/A
15411851Sbrandon.potter@amd.com    (options, args) = parser.parse_args()
155378SN/A    if len(args) != 1:
1566109Ssanchezd@stanford.edu        parser.error("You must specify a checkpoint file to modify or a "\
1576109Ssanchezd@stanford.edu                     "directory of checkpoints to recursively update")
15811851Sbrandon.potter@amd.com
1596109Ssanchezd@stanford.edu    verbose_print = options.verbose
16011886Sbrandon.potter@amd.com
16111886Sbrandon.potter@amd.com    # Deal with shell variables and ~
16211886Sbrandon.potter@amd.com    path = osp.expandvars(osp.expanduser(args[0]))
16311886Sbrandon.potter@amd.com
164378SN/A    # Process a single file if we have it
1651706SN/A    if osp.isfile(path):
16611851Sbrandon.potter@amd.com        process_file(path, **vars(options))
167378SN/A    # Process an entire directory
1685748SSteve.Reinhardt@amd.com    elif osp.isdir(path):
1695748SSteve.Reinhardt@amd.com        cpt_file = osp.join(path, 'm5.cpt')
17011851Sbrandon.potter@amd.com        if options.recurse:
171378SN/A            # Visit very file and see if it matches
172378SN/A            for root,dirs,files in os.walk(path):
1731706SN/A                for name in files:
17411851Sbrandon.potter@amd.com                    if name == 'm5.cpt':
175378SN/A                        process_file(osp.join(root,name), **vars(options))
176378SN/A                for dir in dirs:
1771706SN/A                    pass
17811851Sbrandon.potter@amd.com        # Maybe someone passed a cpt.XXXXXXX directory and not m5.cpt
179378SN/A        elif osp.isfile(cpt_file):
1804118Sgblack@eecs.umich.edu            process_file(cpt_file, **vars(options))
1814118Sgblack@eecs.umich.edu        else:
18211851Sbrandon.potter@amd.com            print "Error: checkpoint file not found at in %s " % path,
1834118Sgblack@eecs.umich.edu            print "and recurse not specified"
184378SN/A            sys.exit(1)
1851706SN/A    sys.exit(0)
18611851Sbrandon.potter@amd.com
187378SN/A