113540Sandrea.mondelli@ucf.edu#!/usr/bin/env python2.7
29048SAli.Saidi@ARM.com
311834SCurtis.Dunham@arm.com# Copyright (c) 2012-2013,2015-2016 ARM Limited
49048SAli.Saidi@ARM.com# All rights reserved
59048SAli.Saidi@ARM.com#
69048SAli.Saidi@ARM.com# The license below extends only to copyright in the software and shall
79048SAli.Saidi@ARM.com# not be construed as granting a license to any other intellectual
89048SAli.Saidi@ARM.com# property including but not limited to intellectual property relating
99048SAli.Saidi@ARM.com# to a hardware implementation of the functionality of the software
109048SAli.Saidi@ARM.com# licensed hereunder.  You may use the software subject to the license
119048SAli.Saidi@ARM.com# terms below provided that you ensure that this notice is replicated
129048SAli.Saidi@ARM.com# unmodified and in its entirety in all distributions of the software,
139048SAli.Saidi@ARM.com# modified or unmodified, in source code or in binary form.
149048SAli.Saidi@ARM.com#
159048SAli.Saidi@ARM.com# Redistribution and use in source and binary forms, with or without
169048SAli.Saidi@ARM.com# modification, are permitted provided that the following conditions are
179048SAli.Saidi@ARM.com# met: redistributions of source code must retain the above copyright
189048SAli.Saidi@ARM.com# notice, this list of conditions and the following disclaimer;
199048SAli.Saidi@ARM.com# redistributions in binary form must reproduce the above copyright
209048SAli.Saidi@ARM.com# notice, this list of conditions and the following disclaimer in the
219048SAli.Saidi@ARM.com# documentation and/or other materials provided with the distribution;
229048SAli.Saidi@ARM.com# neither the name of the copyright holders nor the names of its
239048SAli.Saidi@ARM.com# contributors may be used to endorse or promote products derived from
249048SAli.Saidi@ARM.com# this software without specific prior written permission.
259048SAli.Saidi@ARM.com#
269048SAli.Saidi@ARM.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
279048SAli.Saidi@ARM.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
289048SAli.Saidi@ARM.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
299048SAli.Saidi@ARM.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
309048SAli.Saidi@ARM.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
319048SAli.Saidi@ARM.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
329048SAli.Saidi@ARM.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
339048SAli.Saidi@ARM.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
349048SAli.Saidi@ARM.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
359048SAli.Saidi@ARM.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
369048SAli.Saidi@ARM.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
379048SAli.Saidi@ARM.com#
389048SAli.Saidi@ARM.com# Authors: Ali Saidi
3911077SCurtis.Dunham@arm.com#          Curtis Dunham
409048SAli.Saidi@ARM.com#
419048SAli.Saidi@ARM.com
429056SAli.Saidi@ARM.com# This python code is used to migrate checkpoints that were created in one
439056SAli.Saidi@ARM.com# version of the simulator to newer version. As features are added or bugs are
449056SAli.Saidi@ARM.com# fixed some of the state that needs to be checkpointed can change. If you have
459056SAli.Saidi@ARM.com# many historic checkpoints that you use, manually editing them to fix them is
469056SAli.Saidi@ARM.com# both time consuming and error-prone.
479056SAli.Saidi@ARM.com
489056SAli.Saidi@ARM.com# This script provides a way to migrate checkpoints to the newer repository in
4911077SCurtis.Dunham@arm.com# a programmatic way. It can be imported into another script or used on the
509056SAli.Saidi@ARM.com# command line. From the command line the script will either migrate every
519056SAli.Saidi@ARM.com# checkpoint it finds recursively (-r option) or a single checkpoint. When a
5211077SCurtis.Dunham@arm.com# change is made to the gem5 repository that breaks previous checkpoints an
5311077SCurtis.Dunham@arm.com# upgrade() method should be implemented in its own .py file and placed in
5411077SCurtis.Dunham@arm.com# src/util/cpt_upgraders/.  For each upgrader whose tag is not present in
5511077SCurtis.Dunham@arm.com# the checkpoint tag list, the upgrade() method will be run, passing in a
5611077SCurtis.Dunham@arm.com# ConfigParser object which contains the open file. As these operations can
5711077SCurtis.Dunham@arm.com# be isa specific the method can verify the isa and use regexes to find the
5811077SCurtis.Dunham@arm.com# correct sections that need to be updated.
599056SAli.Saidi@ARM.com
6011834SCurtis.Dunham@arm.com# It is also possible to use this mechanism to revert prior tags.  In this
6111834SCurtis.Dunham@arm.com# case, implement a downgrade() method instead.  Dependencies should still
6211834SCurtis.Dunham@arm.com# work naturally - a tag depending on a tag with a downgrader means that it
6311834SCurtis.Dunham@arm.com# insists on the other tag being removed and its downgrader executed before
6411834SCurtis.Dunham@arm.com# its upgrader (or downgrader) can run.  It is still the case that a tag
6511834SCurtis.Dunham@arm.com# can only be used once.
6611834SCurtis.Dunham@arm.com
6711835SCurtis.Dunham@arm.com# Dependencies between tags are expressed by two variables at the top-level
6811835SCurtis.Dunham@arm.com# of the upgrader script: "depends" can be either a string naming another
6911835SCurtis.Dunham@arm.com# tag that it depends upon or a list of such strings; and "fwd_depends"
7011835SCurtis.Dunham@arm.com# accepts the same datatypes but it reverses the sense of the dependency
7111835SCurtis.Dunham@arm.com# arrow(s) -- it expresses that that tag depends upon the tag of the current
7211835SCurtis.Dunham@arm.com# upgrader. This can be especially valuable when maintaining private
7311835SCurtis.Dunham@arm.com# upgraders in private branches.
7411835SCurtis.Dunham@arm.com
759056SAli.Saidi@ARM.com
769048SAli.Saidi@ARM.comimport ConfigParser
7711077SCurtis.Dunham@arm.comimport glob, types, sys, os
789048SAli.Saidi@ARM.comimport os.path as osp
799048SAli.Saidi@ARM.com
809048SAli.Saidi@ARM.comverbose_print = False
819048SAli.Saidi@ARM.com
829048SAli.Saidi@ARM.comdef verboseprint(*args):
839048SAli.Saidi@ARM.com    if not verbose_print:
849048SAli.Saidi@ARM.com        return
859048SAli.Saidi@ARM.com    for arg in args:
869048SAli.Saidi@ARM.com        print arg,
879048SAli.Saidi@ARM.com    print
889048SAli.Saidi@ARM.com
8911077SCurtis.Dunham@arm.comclass Upgrader:
9011077SCurtis.Dunham@arm.com    tag_set = set()
9111834SCurtis.Dunham@arm.com    untag_set = set() # tags to remove by downgrading
9211077SCurtis.Dunham@arm.com    by_tag = {}
9311077SCurtis.Dunham@arm.com    legacy = {}
9411077SCurtis.Dunham@arm.com    def __init__(self, filename):
9511077SCurtis.Dunham@arm.com        self.filename = filename
9611077SCurtis.Dunham@arm.com        execfile(filename, {}, self.__dict__)
9711077SCurtis.Dunham@arm.com
9811077SCurtis.Dunham@arm.com        if not hasattr(self, 'tag'):
9911077SCurtis.Dunham@arm.com            self.tag = osp.basename(filename)[:-3]
10011077SCurtis.Dunham@arm.com        if not hasattr(self, 'depends'):
10111077SCurtis.Dunham@arm.com            self.depends = []
10211077SCurtis.Dunham@arm.com        elif isinstance(self.depends, str):
10311077SCurtis.Dunham@arm.com            self.depends = [self.depends]
10411077SCurtis.Dunham@arm.com
10511835SCurtis.Dunham@arm.com        if not isinstance(self.depends, list):
10611835SCurtis.Dunham@arm.com            print "Error: 'depends' for %s is the wrong type" % self.tag
10711835SCurtis.Dunham@arm.com            sys.exit(1)
10811835SCurtis.Dunham@arm.com
10911835SCurtis.Dunham@arm.com        if hasattr(self, 'fwd_depends'):
11011835SCurtis.Dunham@arm.com            if isinstance(self.fwd_depends, str):
11111835SCurtis.Dunham@arm.com                self.fwd_depends = [self.fwd_depends]
11211835SCurtis.Dunham@arm.com        else:
11311835SCurtis.Dunham@arm.com            self.fwd_depends = []
11411835SCurtis.Dunham@arm.com
11511835SCurtis.Dunham@arm.com        if not isinstance(self.fwd_depends, list):
11611835SCurtis.Dunham@arm.com            print "Error: 'fwd_depends' for %s is the wrong type" % self.tag
11711835SCurtis.Dunham@arm.com            sys.exit(1)
11811835SCurtis.Dunham@arm.com
11911834SCurtis.Dunham@arm.com        if hasattr(self, 'upgrader'):
12011834SCurtis.Dunham@arm.com            if not isinstance(self.upgrader, types.FunctionType):
12111834SCurtis.Dunham@arm.com                print "Error: 'upgrader' for %s is %s, not function" \
12211834SCurtis.Dunham@arm.com                    % (self.tag, type(self))
12311834SCurtis.Dunham@arm.com                sys.exit(1)
12411834SCurtis.Dunham@arm.com            Upgrader.tag_set.add(self.tag)
12511834SCurtis.Dunham@arm.com        elif hasattr(self, 'downgrader'):
12611834SCurtis.Dunham@arm.com            if not isinstance(self.downgrader, types.FunctionType):
12711834SCurtis.Dunham@arm.com                print "Error: 'downgrader' for %s is %s, not function" \
12811834SCurtis.Dunham@arm.com                    % (self.tag, type(self))
12911834SCurtis.Dunham@arm.com                sys.exit(1)
13011834SCurtis.Dunham@arm.com            Upgrader.untag_set.add(self.tag)
13111834SCurtis.Dunham@arm.com        else:
13211834SCurtis.Dunham@arm.com            print "Error: no upgrader or downgrader method for", self.tag
13311077SCurtis.Dunham@arm.com            sys.exit(1)
13411077SCurtis.Dunham@arm.com
13511077SCurtis.Dunham@arm.com        if hasattr(self, 'legacy_version'):
13611077SCurtis.Dunham@arm.com            Upgrader.legacy[self.legacy_version] = self
13711077SCurtis.Dunham@arm.com
13811077SCurtis.Dunham@arm.com        Upgrader.by_tag[self.tag] = self
13911077SCurtis.Dunham@arm.com
14011077SCurtis.Dunham@arm.com    def ready(self, tags):
14111077SCurtis.Dunham@arm.com        for dep in self.depends:
14211077SCurtis.Dunham@arm.com            if dep not in tags:
14311077SCurtis.Dunham@arm.com                return False
14411077SCurtis.Dunham@arm.com        return True
14511077SCurtis.Dunham@arm.com
14611834SCurtis.Dunham@arm.com    def update(self, cpt, tags):
14711834SCurtis.Dunham@arm.com        if hasattr(self, 'upgrader'):
14811834SCurtis.Dunham@arm.com            self.upgrader(cpt)
14911834SCurtis.Dunham@arm.com            tags.add(self.tag)
15011834SCurtis.Dunham@arm.com            verboseprint("applied upgrade for", self.tag)
15111834SCurtis.Dunham@arm.com        else:
15211834SCurtis.Dunham@arm.com            self.downgrader(cpt)
15311834SCurtis.Dunham@arm.com            tags.remove(self.tag)
15411834SCurtis.Dunham@arm.com            verboseprint("applied downgrade for", self.tag)
15511077SCurtis.Dunham@arm.com
15611077SCurtis.Dunham@arm.com    @staticmethod
15711077SCurtis.Dunham@arm.com    def get(tag):
15811077SCurtis.Dunham@arm.com        return Upgrader.by_tag[tag]
15911077SCurtis.Dunham@arm.com
16011077SCurtis.Dunham@arm.com    @staticmethod
16111077SCurtis.Dunham@arm.com    def load_all():
16211077SCurtis.Dunham@arm.com        util_dir = osp.dirname(osp.abspath(__file__))
16311077SCurtis.Dunham@arm.com
16411077SCurtis.Dunham@arm.com        for py in glob.glob(util_dir + '/cpt_upgraders/*.py'):
16511077SCurtis.Dunham@arm.com            Upgrader(py)
16611077SCurtis.Dunham@arm.com
16711077SCurtis.Dunham@arm.com        # make linear dependences for legacy versions
16811077SCurtis.Dunham@arm.com        i = 3
16911077SCurtis.Dunham@arm.com        while i in Upgrader.legacy:
17011077SCurtis.Dunham@arm.com            Upgrader.legacy[i].depends = [Upgrader.legacy[i-1].tag]
17111077SCurtis.Dunham@arm.com            i = i + 1
17211077SCurtis.Dunham@arm.com
17311835SCurtis.Dunham@arm.com        # resolve forward dependencies and audit normal dependencies
17411835SCurtis.Dunham@arm.com        for tag, upg in Upgrader.by_tag.items():
17511835SCurtis.Dunham@arm.com            for fd in upg.fwd_depends:
17611835SCurtis.Dunham@arm.com                if fd not in Upgrader.by_tag:
17711835SCurtis.Dunham@arm.com                    print "Error: '%s' cannot (forward) depend on "\
17811835SCurtis.Dunham@arm.com                          "nonexistent tag '%s'" % (fd, tag)
17911835SCurtis.Dunham@arm.com                    sys.exit(1)
18011835SCurtis.Dunham@arm.com                Upgrader.by_tag[fd].depends.append(tag)
18111835SCurtis.Dunham@arm.com            for dep in upg.depends:
18211835SCurtis.Dunham@arm.com                if dep not in Upgrader.by_tag:
18311835SCurtis.Dunham@arm.com                    print "Error: '%s' cannot depend on "\
18411835SCurtis.Dunham@arm.com                          "nonexistent tag '%s'" % (tag, dep)
18511835SCurtis.Dunham@arm.com                    sys.exit(1)
18611835SCurtis.Dunham@arm.com
1879048SAli.Saidi@ARM.comdef process_file(path, **kwargs):
1889048SAli.Saidi@ARM.com    if not osp.isfile(path):
1899048SAli.Saidi@ARM.com        import errno
1909048SAli.Saidi@ARM.com        raise IOError(ennro.ENOENT, "No such file", path)
1919048SAli.Saidi@ARM.com
1929048SAli.Saidi@ARM.com    verboseprint("Processing file %s...." % path)
1939048SAli.Saidi@ARM.com
1949048SAli.Saidi@ARM.com    if kwargs.get('backup', True):
1959048SAli.Saidi@ARM.com        import shutil
1969048SAli.Saidi@ARM.com        shutil.copyfile(path, path + '.bak')
1979048SAli.Saidi@ARM.com
1989048SAli.Saidi@ARM.com    cpt = ConfigParser.SafeConfigParser()
1999048SAli.Saidi@ARM.com
2009048SAli.Saidi@ARM.com    # gem5 is case sensitive with paramaters
2019048SAli.Saidi@ARM.com    cpt.optionxform = str
2029048SAli.Saidi@ARM.com
2039048SAli.Saidi@ARM.com    # Read the current data
2049048SAli.Saidi@ARM.com    cpt_file = file(path, 'r')
2059048SAli.Saidi@ARM.com    cpt.readfp(cpt_file)
2069048SAli.Saidi@ARM.com    cpt_file.close()
2079048SAli.Saidi@ARM.com
20811077SCurtis.Dunham@arm.com    change = False
20911077SCurtis.Dunham@arm.com
2109048SAli.Saidi@ARM.com    # Make sure we know what we're starting from
21111077SCurtis.Dunham@arm.com    if cpt.has_option('root','cpt_ver'):
21211077SCurtis.Dunham@arm.com        cpt_ver = cpt.getint('root','cpt_ver')
2139048SAli.Saidi@ARM.com
21411077SCurtis.Dunham@arm.com        # Legacy linear checkpoint version
21511077SCurtis.Dunham@arm.com        # convert to list of tags before proceeding
21611077SCurtis.Dunham@arm.com        tags = set([])
21711077SCurtis.Dunham@arm.com        for i in xrange(2, cpt_ver+1):
21811077SCurtis.Dunham@arm.com            tags.add(Upgrader.legacy[i].tag)
21911077SCurtis.Dunham@arm.com        verboseprint("performed legacy version -> tags conversion")
22011077SCurtis.Dunham@arm.com        change = True
2219048SAli.Saidi@ARM.com
22211077SCurtis.Dunham@arm.com        cpt.remove_option('root', 'cpt_ver')
22311077SCurtis.Dunham@arm.com    elif cpt.has_option('Globals','version_tags'):
22411077SCurtis.Dunham@arm.com        tags = set((''.join(cpt.get('Globals','version_tags'))).split())
22511077SCurtis.Dunham@arm.com    else:
22611077SCurtis.Dunham@arm.com        print "fatal: no version information in checkpoint"
22711077SCurtis.Dunham@arm.com        exit(1)
2289048SAli.Saidi@ARM.com
22911077SCurtis.Dunham@arm.com    verboseprint("has tags", ' '.join(tags))
23011077SCurtis.Dunham@arm.com    # If the current checkpoint has a tag we don't know about, we have
23111077SCurtis.Dunham@arm.com    # a divergence that (in general) must be addressed by (e.g.) merging
23211077SCurtis.Dunham@arm.com    # simulator support for its changes.
23311834SCurtis.Dunham@arm.com    unknown_tags = tags - (Upgrader.tag_set | Upgrader.untag_set)
23411077SCurtis.Dunham@arm.com    if unknown_tags:
23511077SCurtis.Dunham@arm.com        print "warning: upgrade script does not recognize the following "\
23611077SCurtis.Dunham@arm.com              "tags in this checkpoint:", ' '.join(unknown_tags)
2379048SAli.Saidi@ARM.com
23811834SCurtis.Dunham@arm.com    # Apply migrations for tags not in checkpoint and tags present for which
23911834SCurtis.Dunham@arm.com    # downgraders are present, respecting dependences
24011834SCurtis.Dunham@arm.com    to_apply = (Upgrader.tag_set - tags) | (Upgrader.untag_set & tags)
24111077SCurtis.Dunham@arm.com    while to_apply:
24211077SCurtis.Dunham@arm.com        ready = set([ t for t in to_apply if Upgrader.get(t).ready(tags) ])
24311077SCurtis.Dunham@arm.com        if not ready:
24411077SCurtis.Dunham@arm.com            print "could not apply these upgrades:", ' '.join(to_apply)
24511834SCurtis.Dunham@arm.com            print "update dependences impossible to resolve; aborting"
24611077SCurtis.Dunham@arm.com            exit(1)
24711077SCurtis.Dunham@arm.com
24811077SCurtis.Dunham@arm.com        for tag in ready:
24911834SCurtis.Dunham@arm.com            Upgrader.get(tag).update(cpt, tags)
25011077SCurtis.Dunham@arm.com            change = True
25111077SCurtis.Dunham@arm.com
25211077SCurtis.Dunham@arm.com        to_apply -= ready
25311077SCurtis.Dunham@arm.com
25411077SCurtis.Dunham@arm.com    if not change:
25511077SCurtis.Dunham@arm.com        verboseprint("...nothing to do")
2569048SAli.Saidi@ARM.com        return
2579048SAli.Saidi@ARM.com
25811077SCurtis.Dunham@arm.com    cpt.set('Globals', 'version_tags', ' '.join(tags))
2599048SAli.Saidi@ARM.com
2609048SAli.Saidi@ARM.com    # Write the old data back
26111077SCurtis.Dunham@arm.com    verboseprint("...completed")
2629048SAli.Saidi@ARM.com    cpt.write(file(path, 'w'))
2639048SAli.Saidi@ARM.com
2649048SAli.Saidi@ARM.comif __name__ == '__main__':
26511077SCurtis.Dunham@arm.com    from optparse import OptionParser, SUPPRESS_HELP
2669048SAli.Saidi@ARM.com    parser = OptionParser("usage: %prog [options] <filename or directory>")
2679048SAli.Saidi@ARM.com    parser.add_option("-r", "--recurse", action="store_true",
2689048SAli.Saidi@ARM.com                      help="Recurse through all subdirectories modifying "\
2699048SAli.Saidi@ARM.com                           "each checkpoint that is found")
2709048SAli.Saidi@ARM.com    parser.add_option("-N", "--no-backup", action="store_false",
2719048SAli.Saidi@ARM.com                      dest="backup", default=True,
2729048SAli.Saidi@ARM.com                      help="Do no backup each checkpoint before modifying it")
2739048SAli.Saidi@ARM.com    parser.add_option("-v", "--verbose", action="store_true",
2749048SAli.Saidi@ARM.com                      help="Print out debugging information as")
27511077SCurtis.Dunham@arm.com    parser.add_option("--get-cc-file", action="store_true",
27611077SCurtis.Dunham@arm.com                      # used during build; generate src/sim/tags.cc and exit
27711077SCurtis.Dunham@arm.com                      help=SUPPRESS_HELP)
2789048SAli.Saidi@ARM.com
2799048SAli.Saidi@ARM.com    (options, args) = parser.parse_args()
28011077SCurtis.Dunham@arm.com    verbose_print = options.verbose
28111077SCurtis.Dunham@arm.com
28211077SCurtis.Dunham@arm.com    Upgrader.load_all()
28311077SCurtis.Dunham@arm.com
28411077SCurtis.Dunham@arm.com    if options.get_cc_file:
28511077SCurtis.Dunham@arm.com        print "// this file is auto-generated by util/cpt_upgrader.py"
28611077SCurtis.Dunham@arm.com        print "#include <string>"
28711077SCurtis.Dunham@arm.com        print "#include <set>"
28811077SCurtis.Dunham@arm.com        print
28911077SCurtis.Dunham@arm.com        print "std::set<std::string> version_tags = {"
29011077SCurtis.Dunham@arm.com        for tag in Upgrader.tag_set:
29111077SCurtis.Dunham@arm.com            print "  \"%s\"," % tag
29211077SCurtis.Dunham@arm.com        print "};"
29311077SCurtis.Dunham@arm.com        exit(0)
29411077SCurtis.Dunham@arm.com    elif len(args) != 1:
2959048SAli.Saidi@ARM.com        parser.error("You must specify a checkpoint file to modify or a "\
2969048SAli.Saidi@ARM.com                     "directory of checkpoints to recursively update")
2979048SAli.Saidi@ARM.com
2989048SAli.Saidi@ARM.com    # Deal with shell variables and ~
2999048SAli.Saidi@ARM.com    path = osp.expandvars(osp.expanduser(args[0]))
3009048SAli.Saidi@ARM.com
3019048SAli.Saidi@ARM.com    # Process a single file if we have it
3029048SAli.Saidi@ARM.com    if osp.isfile(path):
3039048SAli.Saidi@ARM.com        process_file(path, **vars(options))
3049048SAli.Saidi@ARM.com    # Process an entire directory
3059048SAli.Saidi@ARM.com    elif osp.isdir(path):
3069048SAli.Saidi@ARM.com        cpt_file = osp.join(path, 'm5.cpt')
3079048SAli.Saidi@ARM.com        if options.recurse:
3089048SAli.Saidi@ARM.com            # Visit very file and see if it matches
3099048SAli.Saidi@ARM.com            for root,dirs,files in os.walk(path):
3109048SAli.Saidi@ARM.com                for name in files:
3119048SAli.Saidi@ARM.com                    if name == 'm5.cpt':
3129048SAli.Saidi@ARM.com                        process_file(osp.join(root,name), **vars(options))
3139048SAli.Saidi@ARM.com                for dir in dirs:
3149048SAli.Saidi@ARM.com                    pass
3159048SAli.Saidi@ARM.com        # Maybe someone passed a cpt.XXXXXXX directory and not m5.cpt
3169048SAli.Saidi@ARM.com        elif osp.isfile(cpt_file):
3179048SAli.Saidi@ARM.com            process_file(cpt_file, **vars(options))
3189048SAli.Saidi@ARM.com        else:
3199048SAli.Saidi@ARM.com            print "Error: checkpoint file not found at in %s " % path,
3209048SAli.Saidi@ARM.com            print "and recurse not specified"
3219048SAli.Saidi@ARM.com            sys.exit(1)
3229048SAli.Saidi@ARM.com    sys.exit(0)
3239048SAli.Saidi@ARM.com
324