113540Sandrea.mondelli@ucf.edu#! /usr/bin/env python2.7
28471SGiacomo.Gabrielli@arm.com
38471SGiacomo.Gabrielli@arm.com# Copyright (c) 2011 ARM Limited
48471SGiacomo.Gabrielli@arm.com# All rights reserved
58471SGiacomo.Gabrielli@arm.com#
68471SGiacomo.Gabrielli@arm.com# The license below extends only to copyright in the software and shall
78471SGiacomo.Gabrielli@arm.com# not be construed as granting a license to any other intellectual
88471SGiacomo.Gabrielli@arm.com# property including but not limited to intellectual property relating
98471SGiacomo.Gabrielli@arm.com# to a hardware implementation of the functionality of the software
108471SGiacomo.Gabrielli@arm.com# licensed hereunder.  You may use the software subject to the license
118471SGiacomo.Gabrielli@arm.com# terms below provided that you ensure that this notice is replicated
128471SGiacomo.Gabrielli@arm.com# unmodified and in its entirety in all distributions of the software,
138471SGiacomo.Gabrielli@arm.com# modified or unmodified, in source code or in binary form.
148471SGiacomo.Gabrielli@arm.com#
158471SGiacomo.Gabrielli@arm.com# Redistribution and use in source and binary forms, with or without
168471SGiacomo.Gabrielli@arm.com# modification, are permitted provided that the following conditions are
178471SGiacomo.Gabrielli@arm.com# met: redistributions of source code must retain the above copyright
188471SGiacomo.Gabrielli@arm.com# notice, this list of conditions and the following disclaimer;
198471SGiacomo.Gabrielli@arm.com# redistributions in binary form must reproduce the above copyright
208471SGiacomo.Gabrielli@arm.com# notice, this list of conditions and the following disclaimer in the
218471SGiacomo.Gabrielli@arm.com# documentation and/or other materials provided with the distribution;
228471SGiacomo.Gabrielli@arm.com# neither the name of the copyright holders nor the names of its
238471SGiacomo.Gabrielli@arm.com# contributors may be used to endorse or promote products derived from
248471SGiacomo.Gabrielli@arm.com# this software without specific prior written permission.
258471SGiacomo.Gabrielli@arm.com#
268471SGiacomo.Gabrielli@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
278471SGiacomo.Gabrielli@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
288471SGiacomo.Gabrielli@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
298471SGiacomo.Gabrielli@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
308471SGiacomo.Gabrielli@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
318471SGiacomo.Gabrielli@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
328471SGiacomo.Gabrielli@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
338471SGiacomo.Gabrielli@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
348471SGiacomo.Gabrielli@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
358471SGiacomo.Gabrielli@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
368471SGiacomo.Gabrielli@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
378471SGiacomo.Gabrielli@arm.com#
388471SGiacomo.Gabrielli@arm.com# Authors: Giacomo Gabrielli
398471SGiacomo.Gabrielli@arm.com
408471SGiacomo.Gabrielli@arm.com# Pipeline activity viewer for the O3 CPU model.
418471SGiacomo.Gabrielli@arm.com
428471SGiacomo.Gabrielli@arm.comimport optparse
438471SGiacomo.Gabrielli@arm.comimport os
448471SGiacomo.Gabrielli@arm.comimport sys
459252Sdjordje.kovacevic@arm.comimport copy
468471SGiacomo.Gabrielli@arm.com
479252Sdjordje.kovacevic@arm.com# Temporary storage for instructions. The queue is filled in out-of-order
489252Sdjordje.kovacevic@arm.com# until it reaches 'max_threshold' number of instructions. It is then
499252Sdjordje.kovacevic@arm.com# sorted out and instructions are printed out until their number drops to
509252Sdjordje.kovacevic@arm.com# 'min_threshold'.
519252Sdjordje.kovacevic@arm.com# It is assumed that the instructions are not out of order for more then
529252Sdjordje.kovacevic@arm.com# 'min_threshold' places - otherwise they will appear out of order.
539252Sdjordje.kovacevic@arm.cominsts = {
549252Sdjordje.kovacevic@arm.com    'queue': [] ,         # Instructions to print.
559252Sdjordje.kovacevic@arm.com    'max_threshold':2000, # Instructions are sorted out and printed when
569252Sdjordje.kovacevic@arm.com                          # their number reaches this threshold.
579252Sdjordje.kovacevic@arm.com    'min_threshold':1000, # Printing stops when this number is reached.
589252Sdjordje.kovacevic@arm.com    'sn_start':0,         # The first instruction seq. number to be printed.
599252Sdjordje.kovacevic@arm.com    'sn_stop':0,          # The last instruction seq. number to be printed.
609252Sdjordje.kovacevic@arm.com    'tick_start':0,       # The first tick to be printed
619252Sdjordje.kovacevic@arm.com    'tick_stop':0,        # The last tick to be printed
629252Sdjordje.kovacevic@arm.com    'tick_drift':2000,    # Used to calculate the start and the end of main
639252Sdjordje.kovacevic@arm.com                          # loop. We assume here that the instructions are not
649252Sdjordje.kovacevic@arm.com                          # out of order for more then 2000 CPU ticks,
659252Sdjordje.kovacevic@arm.com                          # otherwise the print may not start/stop
669252Sdjordje.kovacevic@arm.com                          # at the time specified by tick_start/stop.
679527SMatt.Horsnell@arm.com    'only_committed':0,   # Set if only committed instructions are printed.
689252Sdjordje.kovacevic@arm.com}
698471SGiacomo.Gabrielli@arm.com
708471SGiacomo.Gabrielli@arm.comdef process_trace(trace, outfile, cycle_time, width, color, timestamps,
719527SMatt.Horsnell@arm.com                  committed_only, store_completions, start_tick, stop_tick, start_sn, stop_sn):
729252Sdjordje.kovacevic@arm.com    global insts
739252Sdjordje.kovacevic@arm.com
749252Sdjordje.kovacevic@arm.com    insts['sn_start'] = start_sn
759252Sdjordje.kovacevic@arm.com    insts['sn_stop'] = stop_sn
769252Sdjordje.kovacevic@arm.com    insts['tick_start'] = start_tick
779252Sdjordje.kovacevic@arm.com    insts['tick_stop'] = stop_tick
789252Sdjordje.kovacevic@arm.com    insts['tick_drift'] = insts['tick_drift'] * cycle_time
799252Sdjordje.kovacevic@arm.com    insts['only_committed'] = committed_only
808471SGiacomo.Gabrielli@arm.com    line = None
818471SGiacomo.Gabrielli@arm.com    fields = None
829252Sdjordje.kovacevic@arm.com
839252Sdjordje.kovacevic@arm.com    # Skip lines up to the starting tick
848471SGiacomo.Gabrielli@arm.com    if start_tick != 0:
858471SGiacomo.Gabrielli@arm.com        while True:
868471SGiacomo.Gabrielli@arm.com            line = trace.readline()
878471SGiacomo.Gabrielli@arm.com            if not line: return
888471SGiacomo.Gabrielli@arm.com            fields = line.split(':')
899527SMatt.Horsnell@arm.com            if fields[0] != 'O3PipeView': continue
909527SMatt.Horsnell@arm.com            if int(fields[2]) >= start_tick: break
919527SMatt.Horsnell@arm.com    elif start_sn != 0:
929252Sdjordje.kovacevic@arm.com        while True:
938471SGiacomo.Gabrielli@arm.com            line = trace.readline()
948471SGiacomo.Gabrielli@arm.com            if not line: return
958471SGiacomo.Gabrielli@arm.com            fields = line.split(':')
969527SMatt.Horsnell@arm.com            if fields[0] != 'O3PipeView': continue
979527SMatt.Horsnell@arm.com            if fields[1] == 'fetch' and int(fields[5]) >= start_sn: break
989527SMatt.Horsnell@arm.com    else:
999527SMatt.Horsnell@arm.com        line = trace.readline()
1009527SMatt.Horsnell@arm.com        if not line: return
1019527SMatt.Horsnell@arm.com        fields = line.split(':')
1029252Sdjordje.kovacevic@arm.com
1038471SGiacomo.Gabrielli@arm.com    # Skip lines up to next instruction fetch
1048471SGiacomo.Gabrielli@arm.com    while fields[0] != 'O3PipeView' or fields[1] != 'fetch':
1058471SGiacomo.Gabrielli@arm.com        line = trace.readline()
1068471SGiacomo.Gabrielli@arm.com        if not line: return
1078471SGiacomo.Gabrielli@arm.com        fields = line.split(':')
1089252Sdjordje.kovacevic@arm.com
1098471SGiacomo.Gabrielli@arm.com    # Print header
1108471SGiacomo.Gabrielli@arm.com    outfile.write('// f = fetch, d = decode, n = rename, p = dispatch, '
1119527SMatt.Horsnell@arm.com                  'i = issue, c = complete, r = retire')
1129527SMatt.Horsnell@arm.com
1139527SMatt.Horsnell@arm.com    if store_completions:
1149527SMatt.Horsnell@arm.com        outfile.write(', s = store-complete')
1159527SMatt.Horsnell@arm.com    outfile.write('\n\n')
1169527SMatt.Horsnell@arm.com
1178471SGiacomo.Gabrielli@arm.com    outfile.write(' ' + 'timeline'.center(width) +
1188471SGiacomo.Gabrielli@arm.com                  '   ' + 'tick'.center(15) +
1198471SGiacomo.Gabrielli@arm.com                  '  ' + 'pc.upc'.center(12) +
1208471SGiacomo.Gabrielli@arm.com                  '  ' + 'disasm'.ljust(25) +
1219527SMatt.Horsnell@arm.com                  '  ' + 'seq_num'.center(10))
1228471SGiacomo.Gabrielli@arm.com    if timestamps:
1238471SGiacomo.Gabrielli@arm.com        outfile.write('timestamps'.center(25))
1248471SGiacomo.Gabrielli@arm.com    outfile.write('\n')
1259252Sdjordje.kovacevic@arm.com
1268471SGiacomo.Gabrielli@arm.com    # Region of interest
1278471SGiacomo.Gabrielli@arm.com    curr_inst = {}
1288471SGiacomo.Gabrielli@arm.com    while True:
1298471SGiacomo.Gabrielli@arm.com        if fields[0] == 'O3PipeView':
1308471SGiacomo.Gabrielli@arm.com            curr_inst[fields[1]] = int(fields[2])
1318471SGiacomo.Gabrielli@arm.com            if fields[1] == 'fetch':
1329252Sdjordje.kovacevic@arm.com                if ((stop_tick > 0 and int(fields[2]) > stop_tick+insts['tick_drift']) or
1339252Sdjordje.kovacevic@arm.com                    (stop_sn > 0 and int(fields[5]) > (stop_sn+insts['max_threshold']))):
1349252Sdjordje.kovacevic@arm.com                    print_insts(outfile, cycle_time, width, color, timestamps, 0)
1358471SGiacomo.Gabrielli@arm.com                    return
1368471SGiacomo.Gabrielli@arm.com                (curr_inst['pc'], curr_inst['upc']) = fields[3:5]
1378471SGiacomo.Gabrielli@arm.com                curr_inst['sn'] = int(fields[5])
1388471SGiacomo.Gabrielli@arm.com                curr_inst['disasm'] = ' '.join(fields[6][:-1].split())
1398471SGiacomo.Gabrielli@arm.com            elif fields[1] == 'retire':
1409527SMatt.Horsnell@arm.com                if curr_inst['retire'] == 0:
1419527SMatt.Horsnell@arm.com                    curr_inst['disasm'] = '-----' + curr_inst['disasm']
1429527SMatt.Horsnell@arm.com                if store_completions:
1439527SMatt.Horsnell@arm.com                    curr_inst[fields[3]] = int(fields[4])
1449527SMatt.Horsnell@arm.com                queue_inst(outfile, curr_inst, cycle_time, width, color, timestamps, store_completions)
1459527SMatt.Horsnell@arm.com
1468471SGiacomo.Gabrielli@arm.com        line = trace.readline()
1479527SMatt.Horsnell@arm.com        if not line:
1489527SMatt.Horsnell@arm.com            print_insts(outfile, cycle_time, width, color, timestamps, store_completions, 0)
1499527SMatt.Horsnell@arm.com            return
1508471SGiacomo.Gabrielli@arm.com        fields = line.split(':')
1518471SGiacomo.Gabrielli@arm.com
1528471SGiacomo.Gabrielli@arm.com
1539252Sdjordje.kovacevic@arm.com#Sorts out instructions according to sequence number
1549252Sdjordje.kovacevic@arm.comdef compare_by_sn(a, b):
1559252Sdjordje.kovacevic@arm.com    return cmp(a['sn'], b['sn'])
1569252Sdjordje.kovacevic@arm.com
1579252Sdjordje.kovacevic@arm.com# Puts new instruction into the print queue.
1589252Sdjordje.kovacevic@arm.com# Sorts out and prints instructions when their number reaches threshold value
1599527SMatt.Horsnell@arm.comdef queue_inst(outfile, inst, cycle_time, width, color, timestamps, store_completions):
1609252Sdjordje.kovacevic@arm.com    global insts
1619252Sdjordje.kovacevic@arm.com    l_copy = copy.deepcopy(inst)
1629252Sdjordje.kovacevic@arm.com    insts['queue'].append(l_copy)
1639252Sdjordje.kovacevic@arm.com    if len(insts['queue']) > insts['max_threshold']:
1649527SMatt.Horsnell@arm.com        print_insts(outfile, cycle_time, width, color, timestamps, store_completions, insts['min_threshold'])
1659252Sdjordje.kovacevic@arm.com
1669252Sdjordje.kovacevic@arm.com# Sorts out and prints instructions in print queue
1679527SMatt.Horsnell@arm.comdef print_insts(outfile, cycle_time, width, color, timestamps, store_completions, lower_threshold):
1689252Sdjordje.kovacevic@arm.com    global insts
1699252Sdjordje.kovacevic@arm.com    insts['queue'].sort(compare_by_sn)
1709252Sdjordje.kovacevic@arm.com    while len(insts['queue']) > lower_threshold:
1719252Sdjordje.kovacevic@arm.com        print_item=insts['queue'].pop(0)
1729252Sdjordje.kovacevic@arm.com        # As the instructions are processed out of order the main loop starts
1739252Sdjordje.kovacevic@arm.com        # earlier then specified by start_sn/tick and finishes later then what
1749252Sdjordje.kovacevic@arm.com        # is defined in stop_sn/tick.
1759252Sdjordje.kovacevic@arm.com        # Therefore, here we have to filter out instructions that reside out of
1769252Sdjordje.kovacevic@arm.com        # the specified boundaries.
1779252Sdjordje.kovacevic@arm.com        if (insts['sn_start'] > 0 and print_item['sn'] < insts['sn_start']):
1789252Sdjordje.kovacevic@arm.com            continue; # earlier then the starting sequence number
1799252Sdjordje.kovacevic@arm.com        if (insts['sn_stop'] > 0 and print_item['sn'] > insts['sn_stop']):
1809252Sdjordje.kovacevic@arm.com            continue; # later then the ending sequence number
1819252Sdjordje.kovacevic@arm.com        if (insts['tick_start'] > 0 and print_item['fetch'] < insts['tick_start']):
1829252Sdjordje.kovacevic@arm.com            continue; # earlier then the starting tick number
1839252Sdjordje.kovacevic@arm.com        if (insts['tick_stop'] > 0 and print_item['fetch'] > insts['tick_stop']):
1849252Sdjordje.kovacevic@arm.com            continue; # later then the ending tick number
1859252Sdjordje.kovacevic@arm.com
1869252Sdjordje.kovacevic@arm.com        if (insts['only_committed'] != 0 and print_item['retire'] == 0):
1879252Sdjordje.kovacevic@arm.com            continue; # retire is set to zero if it hasn't been completed
1889527SMatt.Horsnell@arm.com        print_inst(outfile,  print_item, cycle_time, width, color, timestamps, store_completions)
1899252Sdjordje.kovacevic@arm.com
1909252Sdjordje.kovacevic@arm.com# Prints a single instruction
1919527SMatt.Horsnell@arm.comdef print_inst(outfile, inst, cycle_time, width, color, timestamps, store_completions):
1928471SGiacomo.Gabrielli@arm.com    if color:
1938471SGiacomo.Gabrielli@arm.com        from m5.util.terminal import termcap
1948471SGiacomo.Gabrielli@arm.com    else:
1958471SGiacomo.Gabrielli@arm.com        from m5.util.terminal import no_termcap as termcap
1968471SGiacomo.Gabrielli@arm.com    # Pipeline stages
1978471SGiacomo.Gabrielli@arm.com    stages = [{'name': 'fetch',
1988471SGiacomo.Gabrielli@arm.com               'color': termcap.Blue + termcap.Reverse,
1998471SGiacomo.Gabrielli@arm.com               'shorthand': 'f'},
2008471SGiacomo.Gabrielli@arm.com              {'name': 'decode',
2018471SGiacomo.Gabrielli@arm.com               'color': termcap.Yellow + termcap.Reverse,
2028471SGiacomo.Gabrielli@arm.com               'shorthand': 'd'},
2038471SGiacomo.Gabrielli@arm.com              {'name': 'rename',
2048471SGiacomo.Gabrielli@arm.com               'color': termcap.Magenta + termcap.Reverse,
2058471SGiacomo.Gabrielli@arm.com               'shorthand': 'n'},
2068471SGiacomo.Gabrielli@arm.com              {'name': 'dispatch',
2078471SGiacomo.Gabrielli@arm.com               'color': termcap.Green + termcap.Reverse,
2088471SGiacomo.Gabrielli@arm.com               'shorthand': 'p'},
2098471SGiacomo.Gabrielli@arm.com              {'name': 'issue',
2108471SGiacomo.Gabrielli@arm.com               'color': termcap.Red + termcap.Reverse,
2118471SGiacomo.Gabrielli@arm.com               'shorthand': 'i'},
2128471SGiacomo.Gabrielli@arm.com              {'name': 'complete',
2138471SGiacomo.Gabrielli@arm.com               'color': termcap.Cyan + termcap.Reverse,
2148471SGiacomo.Gabrielli@arm.com               'shorthand': 'c'},
2158471SGiacomo.Gabrielli@arm.com              {'name': 'retire',
2168471SGiacomo.Gabrielli@arm.com               'color': termcap.Blue + termcap.Reverse,
2179527SMatt.Horsnell@arm.com               'shorthand': 'r'}
2189527SMatt.Horsnell@arm.com              ]
2199527SMatt.Horsnell@arm.com    if store_completions:
2209527SMatt.Horsnell@arm.com        stages.append(
2219527SMatt.Horsnell@arm.com            {'name': 'store',
2229527SMatt.Horsnell@arm.com             'color': termcap.Yellow + termcap.Reverse,
2239527SMatt.Horsnell@arm.com             'shorthand': 's'})
2249252Sdjordje.kovacevic@arm.com
2258471SGiacomo.Gabrielli@arm.com    # Print
2269252Sdjordje.kovacevic@arm.com
2278471SGiacomo.Gabrielli@arm.com    time_width = width * cycle_time
2288471SGiacomo.Gabrielli@arm.com    base_tick = (inst['fetch'] / time_width) * time_width
2299252Sdjordje.kovacevic@arm.com
2309252Sdjordje.kovacevic@arm.com    # Find out the time of the last event - it may not
2319252Sdjordje.kovacevic@arm.com    # be 'retire' if the instruction is not comlpeted.
2329252Sdjordje.kovacevic@arm.com    last_event_time = max(inst['fetch'], inst['decode'],inst['rename'],
2339527SMatt.Horsnell@arm.com                      inst['dispatch'],inst['issue'], inst['complete'], inst['retire'])
2349527SMatt.Horsnell@arm.com    if store_completions:
2359527SMatt.Horsnell@arm.com        last_event_time = max(last_event_time, inst['store'])
2369252Sdjordje.kovacevic@arm.com
2379188SDjordje.Kovacevic@arm.com    # Timeline shorter then time_width is printed in compact form where
2389188SDjordje.Kovacevic@arm.com    # the print continues at the start of the same line.
2399252Sdjordje.kovacevic@arm.com    if ((last_event_time - inst['fetch']) < time_width):
2409188SDjordje.Kovacevic@arm.com        num_lines = 1 # compact form
2419188SDjordje.Kovacevic@arm.com    else:
2429252Sdjordje.kovacevic@arm.com        num_lines = ((last_event_time - base_tick) / time_width) + 1
2439188SDjordje.Kovacevic@arm.com
2448471SGiacomo.Gabrielli@arm.com    curr_color = termcap.Normal
2459252Sdjordje.kovacevic@arm.com
2469252Sdjordje.kovacevic@arm.com    # This will visually distinguish completed and abandoned intructions.
2479252Sdjordje.kovacevic@arm.com    if inst['retire'] == 0: dot = '=' # abandoned instruction
2489252Sdjordje.kovacevic@arm.com    else:                   dot = '.' # completed instruction
2499252Sdjordje.kovacevic@arm.com
2508471SGiacomo.Gabrielli@arm.com    for i in range(num_lines):
2518471SGiacomo.Gabrielli@arm.com        start_tick = base_tick + i * time_width
2528471SGiacomo.Gabrielli@arm.com        end_tick = start_tick + time_width
2538471SGiacomo.Gabrielli@arm.com        if num_lines == 1:  # compact form
2548471SGiacomo.Gabrielli@arm.com            end_tick += (inst['fetch'] - base_tick)
2558471SGiacomo.Gabrielli@arm.com        events = []
2568471SGiacomo.Gabrielli@arm.com        for stage_idx in range(len(stages)):
2578471SGiacomo.Gabrielli@arm.com            tick = inst[stages[stage_idx]['name']]
2589252Sdjordje.kovacevic@arm.com            if tick != 0:
2599252Sdjordje.kovacevic@arm.com                if tick >= start_tick and tick < end_tick:
2609252Sdjordje.kovacevic@arm.com                    events.append((tick % time_width,
2619252Sdjordje.kovacevic@arm.com                                   stages[stage_idx]['name'],
2629252Sdjordje.kovacevic@arm.com                                   stage_idx, tick))
2638471SGiacomo.Gabrielli@arm.com        events.sort()
2648471SGiacomo.Gabrielli@arm.com        outfile.write('[')
2658471SGiacomo.Gabrielli@arm.com        pos = 0
2668471SGiacomo.Gabrielli@arm.com        if num_lines == 1 and events[0][2] != 0:  # event is not fetch
2678471SGiacomo.Gabrielli@arm.com            curr_color = stages[events[0][2] - 1]['color']
2688471SGiacomo.Gabrielli@arm.com        for event in events:
2698471SGiacomo.Gabrielli@arm.com            if (stages[event[2]]['name'] == 'dispatch' and
2708471SGiacomo.Gabrielli@arm.com                inst['dispatch'] == inst['issue']):
2718471SGiacomo.Gabrielli@arm.com                continue
2729252Sdjordje.kovacevic@arm.com            outfile.write(curr_color + dot * ((event[0] / cycle_time) - pos))
2738471SGiacomo.Gabrielli@arm.com            outfile.write(stages[event[2]]['color'] +
2748471SGiacomo.Gabrielli@arm.com                          stages[event[2]]['shorthand'])
2759252Sdjordje.kovacevic@arm.com
2769252Sdjordje.kovacevic@arm.com            if event[3] != last_event_time:  # event is not the last one
2778471SGiacomo.Gabrielli@arm.com                curr_color = stages[event[2]]['color']
2788471SGiacomo.Gabrielli@arm.com            else:
2798471SGiacomo.Gabrielli@arm.com                curr_color = termcap.Normal
2809252Sdjordje.kovacevic@arm.com
2818471SGiacomo.Gabrielli@arm.com            pos = (event[0] / cycle_time) + 1
2829252Sdjordje.kovacevic@arm.com        outfile.write(curr_color + dot * (width - pos) + termcap.Normal +
2838471SGiacomo.Gabrielli@arm.com                      ']-(' + str(base_tick + i * time_width).rjust(15) + ') ')
2848471SGiacomo.Gabrielli@arm.com        if i == 0:
2859527SMatt.Horsnell@arm.com            outfile.write('%s.%s %s [%s]' % (
2868471SGiacomo.Gabrielli@arm.com                    inst['pc'].rjust(10),
2878471SGiacomo.Gabrielli@arm.com                    inst['upc'],
2888471SGiacomo.Gabrielli@arm.com                    inst['disasm'].ljust(25),
2899527SMatt.Horsnell@arm.com                    str(inst['sn']).rjust(10)))
2908471SGiacomo.Gabrielli@arm.com            if timestamps:
2918471SGiacomo.Gabrielli@arm.com                outfile.write('  f=%s, r=%s' % (inst['fetch'], inst['retire']))
2928471SGiacomo.Gabrielli@arm.com            outfile.write('\n')
2938471SGiacomo.Gabrielli@arm.com        else:
2948471SGiacomo.Gabrielli@arm.com            outfile.write('...'.center(12) + '\n')
2958471SGiacomo.Gabrielli@arm.com
2968471SGiacomo.Gabrielli@arm.com
2978471SGiacomo.Gabrielli@arm.comdef validate_range(my_range):
2988471SGiacomo.Gabrielli@arm.com    my_range = [int(i) for i in my_range.split(':')]
2998471SGiacomo.Gabrielli@arm.com    if (len(my_range) != 2 or
3008471SGiacomo.Gabrielli@arm.com        my_range[0] < 0 or
3018471SGiacomo.Gabrielli@arm.com        my_range[1] > 0 and my_range[0] >= my_range[1]):
3028471SGiacomo.Gabrielli@arm.com        return None
3038471SGiacomo.Gabrielli@arm.com    return my_range
3048471SGiacomo.Gabrielli@arm.com
3058471SGiacomo.Gabrielli@arm.com
3068471SGiacomo.Gabrielli@arm.comdef main():
3078471SGiacomo.Gabrielli@arm.com    # Parse options
3088471SGiacomo.Gabrielli@arm.com    usage = ('%prog [OPTION]... TRACE_FILE')
3098471SGiacomo.Gabrielli@arm.com    parser = optparse.OptionParser(usage=usage)
3108471SGiacomo.Gabrielli@arm.com    parser.add_option(
3118471SGiacomo.Gabrielli@arm.com        '-o',
3128471SGiacomo.Gabrielli@arm.com        dest='outfile',
3138471SGiacomo.Gabrielli@arm.com        default=os.path.join(os.getcwd(), 'o3-pipeview.out'),
3148471SGiacomo.Gabrielli@arm.com        help="output file (default: '%default')")
3158471SGiacomo.Gabrielli@arm.com    parser.add_option(
3168471SGiacomo.Gabrielli@arm.com        '-t',
3178471SGiacomo.Gabrielli@arm.com        dest='tick_range',
3188471SGiacomo.Gabrielli@arm.com        default='0:-1',
3198471SGiacomo.Gabrielli@arm.com        help="tick range (default: '%default'; -1 == inf.)")
3208471SGiacomo.Gabrielli@arm.com    parser.add_option(
3218471SGiacomo.Gabrielli@arm.com        '-i',
3228471SGiacomo.Gabrielli@arm.com        dest='inst_range',
3238471SGiacomo.Gabrielli@arm.com        default='0:-1',
3248471SGiacomo.Gabrielli@arm.com        help="instruction range (default: '%default'; -1 == inf.)")
3258471SGiacomo.Gabrielli@arm.com    parser.add_option(
3268471SGiacomo.Gabrielli@arm.com        '-w',
3278471SGiacomo.Gabrielli@arm.com        dest='width',
3288471SGiacomo.Gabrielli@arm.com        type='int', default=80,
3298471SGiacomo.Gabrielli@arm.com        help="timeline width (default: '%default')")
3308471SGiacomo.Gabrielli@arm.com    parser.add_option(
3318471SGiacomo.Gabrielli@arm.com        '--color',
3328471SGiacomo.Gabrielli@arm.com        action='store_true', default=False,
3338471SGiacomo.Gabrielli@arm.com        help="enable colored output (default: '%default')")
3348471SGiacomo.Gabrielli@arm.com    parser.add_option(
3358471SGiacomo.Gabrielli@arm.com        '-c', '--cycle-time',
3368471SGiacomo.Gabrielli@arm.com        type='int', default=1000,
3378471SGiacomo.Gabrielli@arm.com        help="CPU cycle time in ticks (default: '%default')")
3388471SGiacomo.Gabrielli@arm.com    parser.add_option(
3398471SGiacomo.Gabrielli@arm.com        '--timestamps',
3408471SGiacomo.Gabrielli@arm.com        action='store_true', default=False,
3418471SGiacomo.Gabrielli@arm.com        help="print fetch and retire timestamps (default: '%default')")
3429252Sdjordje.kovacevic@arm.com    parser.add_option(
3439252Sdjordje.kovacevic@arm.com        '--only_committed',
3449252Sdjordje.kovacevic@arm.com        action='store_true', default=False,
3459252Sdjordje.kovacevic@arm.com        help="display only committed (completed) instructions (default: '%default')")
3469527SMatt.Horsnell@arm.com    parser.add_option(
3479527SMatt.Horsnell@arm.com        '--store_completions',
3489527SMatt.Horsnell@arm.com        action='store_true', default=False,
3499527SMatt.Horsnell@arm.com        help="additionally display store completion ticks (default: '%default')")
3508471SGiacomo.Gabrielli@arm.com    (options, args) = parser.parse_args()
3518471SGiacomo.Gabrielli@arm.com    if len(args) != 1:
3528471SGiacomo.Gabrielli@arm.com        parser.error('incorrect number of arguments')
3538471SGiacomo.Gabrielli@arm.com        sys.exit(1)
3548471SGiacomo.Gabrielli@arm.com    tick_range = validate_range(options.tick_range)
3558471SGiacomo.Gabrielli@arm.com    if not tick_range:
3568471SGiacomo.Gabrielli@arm.com        parser.error('invalid range')
3578471SGiacomo.Gabrielli@arm.com        sys.exit(1)
3588471SGiacomo.Gabrielli@arm.com    inst_range = validate_range(options.inst_range)
3598471SGiacomo.Gabrielli@arm.com    if not inst_range:
3608471SGiacomo.Gabrielli@arm.com        parser.error('invalid range')
3618471SGiacomo.Gabrielli@arm.com        sys.exit(1)
3628471SGiacomo.Gabrielli@arm.com    # Process trace
3638471SGiacomo.Gabrielli@arm.com    print 'Processing trace... ',
3648471SGiacomo.Gabrielli@arm.com    with open(args[0], 'r') as trace:
3658471SGiacomo.Gabrielli@arm.com        with open(options.outfile, 'w') as out:
3668471SGiacomo.Gabrielli@arm.com            process_trace(trace, out, options.cycle_time, options.width,
3678471SGiacomo.Gabrielli@arm.com                          options.color, options.timestamps,
3689527SMatt.Horsnell@arm.com                          options.only_committed, options.store_completions,
3699527SMatt.Horsnell@arm.com                          *(tick_range + inst_range))
3708471SGiacomo.Gabrielli@arm.com    print 'done!'
3718471SGiacomo.Gabrielli@arm.com
3728471SGiacomo.Gabrielli@arm.com
3738471SGiacomo.Gabrielli@arm.comif __name__ == '__main__':
3748471SGiacomo.Gabrielli@arm.com    sys.path.append(os.path.join(
3758471SGiacomo.Gabrielli@arm.com            os.path.dirname(os.path.abspath(__file__)),
3768471SGiacomo.Gabrielli@arm.com            '..', 'src', 'python'))
3778471SGiacomo.Gabrielli@arm.com    main()
378