ARM: fix value of MISCREG_CTR returned by readMiscReg()
[gem5.git] / util / cpt_upgrader.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2012 ARM Limited
4 # All rights reserved
5 #
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.
14 #
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.
25 #
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.
37 #
38 # Authors: Ali Saidi
39 #
40
41 # This python code is used to migrate checkpoints that were created in one
42 # version of the simulator to newer version. As features are added or bugs are
43 # fixed some of the state that needs to be checkpointed can change. If you have
44 # many historic checkpoints that you use, manually editing them to fix them is
45 # both time consuming and error-prone.
46
47 # This script provides a way to migrate checkpoints to the newer repository in
48 # a programatic way. It can be imported into another script or used on the
49 # command line. From the command line the script will either migrate every
50 # checkpoint it finds recursively (-r option) or a single checkpoint. When a
51 # change is made to the gem5 repository that breaks previous checkpoints a
52 # from_N() method should be implemented here and the gem5CheckpointVersion
53 # variable in src/sim/serialize.hh should be incremented. For each version
54 # between the checkpoints current version and the new version the from_N()
55 # method will be run, passing in a ConfigParser object which contains the open
56 # file. As these operations can be isa specific the method can verify the isa
57 # and use regexes to find the correct sections that need to be updated.
58
59
60 import ConfigParser
61 import sys, os
62 import os.path as osp
63
64 def from_0(cpt):
65 pass
66
67 # An example of a translator
68 def from_1(cpt):
69 if cpt.get('root','isa') == 'arm':
70 for sec in cpt.sections():
71 import re
72 # Search for all the execution contexts
73 if re.search('.*sys.*\.cpu.*\.x.\..*', sec):
74 # Update each one
75 mr = cpt.get(sec, 'miscRegs').split()
76 #mr.insert(21,0)
77 #mr.insert(26,0)
78 cpt.set(sec, 'miscRegs', ' '.join(str(x) for x in mr))
79
80 migrations = []
81 migrations.append(from_0)
82 migrations.append(from_1)
83
84 verbose_print = False
85
86 def verboseprint(*args):
87 if not verbose_print:
88 return
89 for arg in args:
90 print arg,
91 print
92
93 def process_file(path, **kwargs):
94 if not osp.isfile(path):
95 import errno
96 raise IOError(ennro.ENOENT, "No such file", path)
97
98 verboseprint("Processing file %s...." % path)
99
100 if kwargs.get('backup', True):
101 import shutil
102 shutil.copyfile(path, path + '.bak')
103
104 cpt = ConfigParser.SafeConfigParser()
105
106 # gem5 is case sensitive with paramaters
107 cpt.optionxform = str
108
109 # Read the current data
110 cpt_file = file(path, 'r')
111 cpt.readfp(cpt_file)
112 cpt_file.close()
113
114 # Make sure we know what we're starting from
115 if not cpt.has_option('root','cpt_ver'):
116 raise LookupError("cannot determine version of checkpoint")
117
118 cpt_ver = cpt.getint('root','cpt_ver')
119
120 # If the current checkpoint is longer than the migrations list, we have a problem
121 # and someone didn't update this file
122 if cpt_ver > len(migrations):
123 raise ValueError("upgrade script is too old and needs updating")
124
125 verboseprint("\t...file is at version %#x" % cpt_ver)
126
127 if cpt_ver == len(migrations):
128 verboseprint("\t...nothing to do")
129 return
130
131 # Walk through every function from now until the end fixing the checkpoint
132 for v in xrange(cpt_ver,len(migrations)):
133 verboseprint("\t...migrating to version %#x" % (v + 1))
134 migrations[v](cpt)
135 cpt.set('root','cpt_ver', str(v + 1))
136
137 # Write the old data back
138 verboseprint("\t...completed")
139 cpt.write(file(path, 'w'))
140
141
142 if __name__ == '__main__':
143 from optparse import OptionParser
144 parser = OptionParser("usage: %prog [options] <filename or directory>")
145 parser.add_option("-r", "--recurse", action="store_true",
146 help="Recurse through all subdirectories modifying "\
147 "each checkpoint that is found")
148 parser.add_option("-N", "--no-backup", action="store_false",
149 dest="backup", default=True,
150 help="Do no backup each checkpoint before modifying it")
151 parser.add_option("-v", "--verbose", action="store_true",
152 help="Print out debugging information as")
153
154 (options, args) = parser.parse_args()
155 if len(args) != 1:
156 parser.error("You must specify a checkpoint file to modify or a "\
157 "directory of checkpoints to recursively update")
158
159 verbose_print = options.verbose
160
161 # Deal with shell variables and ~
162 path = osp.expandvars(osp.expanduser(args[0]))
163
164 # Process a single file if we have it
165 if osp.isfile(path):
166 process_file(path, **vars(options))
167 # Process an entire directory
168 elif osp.isdir(path):
169 cpt_file = osp.join(path, 'm5.cpt')
170 if options.recurse:
171 # Visit very file and see if it matches
172 for root,dirs,files in os.walk(path):
173 for name in files:
174 if name == 'm5.cpt':
175 process_file(osp.join(root,name), **vars(options))
176 for dir in dirs:
177 pass
178 # Maybe someone passed a cpt.XXXXXXX directory and not m5.cpt
179 elif osp.isfile(cpt_file):
180 process_file(cpt_file, **vars(options))
181 else:
182 print "Error: checkpoint file not found at in %s " % path,
183 print "and recurse not specified"
184 sys.exit(1)
185 sys.exit(0)
186