brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 2c3c279 Raw
114 lines · plain
1#!/usr/bin/env python32 3import argparse4import csv5import sys6 7def parse_table(rows, table_title):8    """9    Parse a CSV table out of an iterator over rows.10 11    Return a tuple containing (extracted headers, extracted rows).12    """13    in_table = False14    rows_iter = iter(rows)15    extracted = []16    headers = None17    while True:18        try:19            row = next(rows_iter)20        except StopIteration:21            break22 23        if not in_table and row == [table_title]:24            in_table = True25            next_row = next(rows_iter)26            assert next_row == [], f'There should be an empty row after the title of the table, found {next_row}'27            headers = next(rows_iter) # Extract the headers28            continue29 30        elif in_table and row == []: # An empty row marks the end of the table31            in_table = False32            break33 34        elif in_table:35            extracted.append(row)36 37    assert len(extracted) != 0, f'Could not extract rows from the table, this is suspicious. Table title was {table_title}'38    assert headers is not None, f'Could not extract headers from the table, this is suspicious. Table title was {table_title}'39 40    return (headers, extracted)41 42def main(argv):43    parser = argparse.ArgumentParser(44        prog='parse-spec-results',45        description='Parse SPEC result files (in CSV format) and extract the selected result table, in the selected format.')46    parser.add_argument('filename', type=argparse.FileType('r'), nargs='+',47        help='One of more CSV files to extract the results from. The results parsed from each file are concatenated '48             'together.')49    parser.add_argument('--table', type=str, choices=['full', 'selected'], default='full',50        help='The name of the table to extract from SPEC results. `full` means extracting the Full Results Table '51             'and `selected` means extracting the Selected Results Table. Default is `full`.')52    parser.add_argument('--output-format', type=str, choices=['csv', 'lnt'], default='csv',53        help='The desired output format for the data. `csv` is CSV format and `lnt` is a format compatible with '54             '`lnt importreport` (see https://llvm.org/docs/lnt/importing_data.html#importing-data-in-a-text-file).')55    parser.add_argument('--extract', type=str,56        help='A comma-separated list of headers to extract from the table. If provided, only the data associated to '57             'those headers will be present in the resulting data. Invalid header names are diagnosed. Please make '58             'sure to use appropriate quoting for header names that contain spaces. This option only makes sense '59             'when the output format is CSV.')60    parser.add_argument('--keep-not-run', action='store_true',61        help='Keep entries whose "Base Status" is marked as "NR" (aka "Not Run"). By default, such entries are discarded.')62    parser.add_argument('--keep-failed', action='store_true',63        help='Keep entries whose "Base Status" is marked as "CE" (aka "Compilation Error") or "RE" (aka "Runtime Error"). '64             'By default, such entries are discarded.')65    args = parser.parse_args(argv)66 67    if args.table == 'full':68        table_title = 'Full Results Table'69    elif args.table == 'selected':70        table_title = 'Selected Results Table'71 72    # Parse the headers and the rows in each file, aggregating all the results73    headers = None74    rows = []75    for file in args.filename:76        reader = csv.reader(file)77        (parsed_headers, parsed_rows) = parse_table(reader, table_title)78        assert headers is None or headers == parsed_headers, f'Found files with different headers: {headers} and {parsed_headers}'79        headers = parsed_headers80        rows.extend(parsed_rows)81 82    # Remove rows that were not run (or failed) unless we were asked to keep them83    status = headers.index('Base Status')84    if not args.keep_not_run:85        rows = [row for row in rows if row[status] != 'NR']86    if not args.keep_failed:87        rows = [row for row in rows if row[status] not in ('CE', 'RE')]88 89    if args.extract is not None:90        if args.output_format != 'csv':91            raise RuntimeError('Passing --extract requires the output format to be csv')92        for h in args.extract.split(','):93            if h not in headers:94                raise RuntimeError(f'Header name {h} was not present in the parsed headers {headers}')95 96        extracted_fields = [headers.index(h) for h in args.extract.split(',')]97        headers = [headers[i] for i in extracted_fields]98        rows = [[row[i] for i in extracted_fields] for row in rows]99 100    # Print the results in the right format101    if args.output_format == 'csv':102        writer = csv.writer(sys.stdout)103        writer.writerow(headers)104        for row in rows:105            writer.writerow(row)106    elif args.output_format == 'lnt':107        benchmark = headers.index('Benchmark')108        time = headers.index('Est. Base Run Time')109        for row in rows:110            print(f'{row[benchmark].replace(".", "_")}.execution_time {row[time]}')111 112if __name__ == '__main__':113    main(sys.argv[1:])114