decode_packet_trace.py revision 10065:58bf21ca88de
1#!/usr/bin/env python 2 3# Copyright (c) 2013-2014 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# Copyright 2008 Google Inc. All rights reserved. 39# http://code.google.com/p/protobuf/ 40# 41# Redistribution and use in source and binary forms, with or without 42# modification, are permitted provided that the following conditions are 43# met: 44# 45# * Redistributions of source code must retain the above copyright 46# notice, this list of conditions and the following disclaimer. 47# * Redistributions in binary form must reproduce the above 48# copyright notice, this list of conditions and the following disclaimer 49# in the documentation and/or other materials provided with the 50# distribution. 51# * Neither the name of Google Inc. nor the names of its 52# contributors may be used to endorse or promote products derived from 53# this software without specific prior written permission. 54# 55# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 56# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 58# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 59# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 60# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 61# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 62# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 63# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 64# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 65# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 66# 67# Authors: Andreas Hansson 68# 69 70# This script is used to dump protobuf packet traces to ASCII 71# format. It assumes that protoc has been executed and already 72# generated the Python package for the packet messages. This can 73# be done manually using: 74# protoc --python_out=. --proto_path=src/proto src/proto/packet.proto 75# 76# The ASCII trace format uses one line per request on the format cmd, 77# addr, size, tick,flags. For example: 78# r,128,64,4000,0 79# w,232123,64,500000,0 80 81import struct 82import sys 83 84# Import the packet proto definitions. If they are not found, attempt 85# to generate them automatically. This assumes that the script is 86# executed from the gem5 root. 87try: 88 import packet_pb2 89except: 90 print "Did not find packet proto definitions, attempting to generate" 91 from subprocess import call 92 error = call(['protoc', '--python_out=util', '--proto_path=src/proto', 93 'src/proto/packet.proto']) 94 if not error: 95 print "Generated packet proto definitions" 96 97 try: 98 import google.protobuf 99 except: 100 print "Please install Python protobuf module" 101 exit(-1) 102 103 import packet_pb2 104 else: 105 print "Failed to import packet proto definitions" 106 exit(-1) 107 108def DecodeVarint(in_file): 109 """ 110 The decoding of the Varint32 is copied from 111 google.protobuf.internal.decoder and is only repeated here to 112 avoid depending on the internal functions in the library. If the 113 end of file is reached, return (0, 0). 114 """ 115 result = 0 116 shift = 0 117 pos = 0 118 # Use a 32-bit mask 119 mask = 0xffffffff 120 while 1: 121 c = in_file.read(1) 122 if len(c) == 0: 123 return (0, 0) 124 b = struct.unpack('<B', c)[0] 125 result |= ((b & 0x7f) << shift) 126 pos += 1 127 if not (b & 0x80): 128 if result > 0x7fffffffffffffff: 129 result -= (1 << 64) 130 result |= ~mask 131 else: 132 result &= mask 133 return (result, pos) 134 shift += 7 135 if shift >= 64: 136 raise IOError('Too many bytes when decoding varint.') 137 138def decodeMessage(in_file, message): 139 """ 140 Attempt to read a message from the file and decode it. Return 141 False if no message could be read. 142 """ 143 try: 144 size, pos = DecodeVarint(in_file) 145 if size == 0: 146 return False 147 buf = in_file.read(size) 148 message.ParseFromString(buf) 149 return True 150 except IOError: 151 return False 152 153def main(): 154 if len(sys.argv) != 3: 155 print "Usage: ", sys.argv[0], " <protobuf input> <ASCII output>" 156 exit(-1) 157 158 try: 159 proto_in = open(sys.argv[1], 'rb') 160 except IOError: 161 print "Failed to open ", sys.argv[1], " for reading" 162 exit(-1) 163 164 try: 165 ascii_out = open(sys.argv[2], 'w') 166 except IOError: 167 print "Failed to open ", sys.argv[2], " for writing" 168 exit(-1) 169 170 # Read the magic number in 4-byte Little Endian 171 magic_number = proto_in.read(4) 172 173 if magic_number != "gem5": 174 print "Unrecognized file" 175 exit(-1) 176 177 print "Parsing packet header" 178 179 # Add the packet header 180 header = packet_pb2.PacketHeader() 181 decodeMessage(proto_in, header) 182 183 print "Object id:", header.obj_id 184 print "Tick frequency:", header.tick_freq 185 186 print "Parsing packets" 187 188 num_packets = 0 189 ignored_flags = False 190 packet = packet_pb2.Packet() 191 192 # Decode the packet messages until we hit the end of the file 193 while decodeMessage(proto_in, packet): 194 num_packets += 1 195 # ReadReq is 1 and WriteReq is 4 in src/mem/packet.hh Command enum 196 cmd = 'r' if packet.cmd == 1 else ('w' if packet.cmd == 4 else 'u') 197 if packet.HasField('flags'): 198 # Currently not printing flags 199 ignored_flags = True 200 ascii_out.write('%s,%s,%s,%s\n' % (cmd, packet.addr, packet.size, 201 packet.tick)) 202 203 print "Parsed packets:", num_packets 204 if ignored_flags: 205 print "Encountered packet flags that were ignored" 206 207 # We're done 208 ascii_out.close() 209 proto_in.close() 210 211if __name__ == "__main__": 212 main() 213