Example #1
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        asm = Assembler(isa)
        errors = []
        for linenr, line in enumerate(f):
            line = line.rstrip('\n')
            asm.parse(line)

        if not asm.errors:
            code = asm.generate_code()
        else:
            code = None

        for line, error in asm.errors:
            print('Line %i: %s' % (line, error))

        if code is not None:
            data = b''.join(struct.pack(b'<IIII', *inst) for inst in code)
            if args.bin_out is not None:
                with open(args.bin_out, 'wb') as f:
                    f.write(data)
            else:  # no binary output, print as C-ish ASCII through disassembler
                disasm_format(out,
                              isa,
                              data,
                              opt_addr=False,
                              opt_raw=False,
                              opt_cfmt=True)
        else:
            exit(1)
Example #2
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        asm = Assembler(isa)
        errors = []
        for linenr, line in enumerate(f):
            line = line.rstrip('\n')
            asm.parse(line)
       
        if not asm.errors:
            code = asm.generate_code()
        else: 
            code = None

        for line, error in asm.errors:
            print('Line %i: %s' % (line, error))

        if code is not None:
            if args.bin_out is not None:
                with open(args.bin_out, 'wb') as f:
                    for inst in code:
                        f.write(struct.pack(b'<IIII', *inst))
            else: # no binary output, print as ascii
                for inst in code:
                    print('0x%08x,0x%08x,0x%08x,0x%08x,' % tuple(inst))
        else:
            exit(1)
Example #3
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        asm = Assembler(isa)
        errors = []
        for linenr, line in enumerate(f):
            line = line.rstrip('\n')
            asm.parse(line)

        if not asm.errors:
            code = asm.generate_code()
        else:
            code = None

        for line, error in asm.errors:
            print('Line %i: %s' % (line, error))

        if code is not None:
            if args.bin_out is not None:
                with open(args.bin_out, 'wb') as f:
                    for inst in code:
                        f.write(struct.pack(b'<IIII', *inst))
            else:  # no binary output, print as ascii
                for inst in code:
                    print('0x%08x,0x%08x,0x%08x,0x%08x,' % tuple(inst))
        else:
            exit(1)
Example #4
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        data = f.read()
        if len(data) % 16:
            print('Size of code must be multiple of 16.', file=sys.stderr)
            exit(1)
        disasm_format(out, isa, data, args.addr, args.raw, args.cfmt)
Example #5
0
def main():
    args = parse_arguments()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')

    cmdstream_xml = parse_rng_file(args.cmdstream_file)
    fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE')
    cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE')
    cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map)

    global options
    options = args
    import re

    if args.binary:
        with open(args.input_file,'rb') as f:
            data = f.read()
        assert((len(data) % 8)==0)
        values = bytes_to_words(data)
    else:
        with open(args.input_file,'r') as f:
            # parse ascii
            values = []
            for line in f:
                value = line.strip()
                if value.startswith(':'):
                    value = int(value[1:9], 16)
                    values.append(value)
    recs = parse_command_buffer(values, cmdstream_info, initial_padding=0)
    if args.output_c_raw:
        dump_command_buffer_c_raw(sys.stdout, recs, state_map)
    elif args.output_c:
        dump_command_buffer_c(sys.stdout, recs, state_map)
    else:
        dump_command_buffer(sys.stdout, recs, [], state_map)
    sys.stdout.write('\n')
Example #6
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)
    try:
        args.model = Model.by_name[args.model.upper()]
    except KeyError:
        print('Unknown model identifier %s' % args.model, file=sys.stderr)
        exit(1)

    if args.input == '-':
        do_disasm(out, isa, args, sys.stdin)
    else:
        with open(args.input, 'rb') as f:
            do_disasm(out, isa, args, f)
Example #7
0
def main():
    args = parse_arguments()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    global options
    options = args
    import re

    with open(args.input_file,'r') as f:
        # parse ascii
        values = []
        for line in f:
            value = line.strip()
            if value.startswith(':'):
                value = int(value[1:9], 16)
                values.append(value)

        dump_command_buffer(sys.stdout, values, [], state_map)
        sys.stdout.write('\n')
def main():
    args = parse_arguments()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    global options
    options = args
    import re

    with open(args.input_file,'r') as f:
        # parse ascii
        values = []
        for line in f:
            value = line.strip()
            if value.startswith(':'):
                value = int(value[1:9], 16)
                values.append(value)

        dump_command_buffer(sys.stdout, values, [], state_map)
        sys.stdout.write('\n')
Example #9
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)
    try:
        model = Model.by_name[args.model.upper()]
    except KeyError:
        print('Unknown model identifier %s' % args.model, file=sys.stderr)
        exit(1)
    try:
        flags = Flags.from_str(args.isa_flags)
    except KeyError:
        print('Unknown ISA flag identifier %s' % args.isa_flags, file=sys.stderr)
        exit(1)
    dialect = Dialect(model, flags)

    if args.input == '-':
        do_disasm(out, isa, dialect, args, sys.stdin)
    else:
        with open(args.input, 'rb') as f:
            do_disasm(out, isa, dialect, args, f)
Example #10
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)
    try:
        model = Model.by_name[args.model.upper()]
    except KeyError:
        print('Unknown model identifier %s' % args.model, file=sys.stderr)
        exit(1)
    try:
        flags = Flags.from_str(args.isa_flags)
    except KeyError:
        print('Unknown ISA flag identifier %s' % args.isa_flags,
              file=sys.stderr)
        exit(1)
    dialect = Dialect(model, flags)

    if args.input == '-':
        do_asm(out, isa, dialect, args, sys.stdin)
    else:
        with open(args.input, 'rb') as f:
            do_asm(out, isa, dialect, args, f)
Example #11
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        data = f.read()
        if len(data)%16:
            print >>sys.stderr,'Size of code must be multiple of 16.'
            exit(1)
        for idx in xrange(len(data)//16):
            inst = struct.unpack(b'<IIII', data[idx*16:idx*16+16])
            if args.addr:
                out.write('%3x: ' % idx)
            if args.raw:
                out.write('%08x %08x %08x %08x  ' % inst)
            warnings = []
            parsed = disassemble(isa, inst, warnings)
            text = format_instruction(isa, parsed)
            out.write(text)
            if warnings:
                out.write(' ; ')
                out.write(' '.join(warnings))
            out.write('\n')
Example #12
0
def main():
    args = parse_arguments()
    out = sys.stdout
    isa = parse_rng_file(args.isa_file)

    with open(args.input, 'rb') as f:
        data = f.read()
        if len(data) % 16:
            print >> sys.stderr, 'Size of code must be multiple of 16.'
            exit(1)
        for idx in xrange(len(data) // 16):
            inst = struct.unpack(b'<IIII', data[idx * 16:idx * 16 + 16])
            if args.addr:
                out.write('%3x: ' % idx)
            if args.raw:
                out.write('%08x %08x %08x %08x  ' % inst)
            warnings = []
            parsed = disassemble(isa, inst, warnings)
            text = format_instruction(isa, parsed)
            out.write(text)
            if warnings:
                out.write(' ; ')
                out.write(' '.join(warnings))
            out.write('\n')
Example #13
0
def main():
    args = parse_arguments()
    defs = load_data_definitions(args.struct_file)
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    fdr = FDRLoader(args.input)
    global options
    options = args

    def handle_comment(f, val, depth):
        '''Annotate value with a comment'''
        if not depth:
            return None
        parent = depth[-1][0]
        field = depth[-1][1]
        parent_type = parent.type['name']
        # Show names for features and minor feature bits
        if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY':
            if field == 'chipMinorFeatures':
                field = 'chipMinorFeatures0'
            if field in state_xml.types and isinstance(state_xml.types[field],
                                                       BitSet):
                feat = state_xml.types[field]
                active_feat = [
                    bit.name for bit in feat.bitfields
                    if bit.extract(val.value)
                ]
                return ' '.join(active_feat)
        elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY':
            if field == 'address':  # annotate addresses with unique identifier
                return format_addr(val.value)

    def handle_pointer(f, ptr, depth):
        parent = depth[-1][0]
        field = depth[-1][1]
        if ptr.type in ['_gcoCMDBUF', '_gcoCONTEXT', '_gcsQUEUE']:
            s = extract_structure(fdr,
                                  ptr.addr,
                                  defs,
                                  ptr.type,
                                  resolver=resolver)
            f.write('&(%s)0x%x' % (ptr.type, ptr.addr))
            dump_structure(f, s, handle_pointer, handle_comment, depth)
            return
        elif field == 'logical' and ptr.addr != 0:
            # Command stream
            if parent.type['name'] == '_gcoCMDBUF':
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(
                    f, fdr, ptr.addr + parent.members['startOffset'].value,
                    ptr.addr + parent.members['offset'].value, depth,
                    state_map)
                return
            if parent.type[
                    'name'] == '_gcoCONTEXT' and options.show_context_commands:
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(
                    f, fdr, ptr.addr,
                    ptr.addr + parent.members['bufferSize'].value, depth,
                    state_map)
                return
        elif parent.type[
                'name'] == '_gcoCONTEXT' and field == 'map' and ptr.addr != 0 and options.show_state_map:
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_context_map(f, fdr, ptr.addr,
                             ptr.addr + parent.members['stateCount'].value * 4,
                             depth, state_map)
            return
        elif parent.type[
                'name'] == '_gcoCONTEXT' and field == 'buffer' and ptr.addr != 0 and options.show_context_buffer:
            # Equivalent to gcoCONTEXT.map
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_command_buffer(f, fdr, ptr.addr,
                                ptr.addr + parent.members['bufferSize'].value,
                                depth, state_map)
            return

        print_address(f, ptr, depth)

    if options.ioctl_64bit:
        vivante_ioctl_data_t = IOCTL_SIZE_SPEC_64B
    else:
        vivante_ioctl_data_t = IOCTL_SIZE_SPEC

    f = sys.stdout
    thread_id = Counter()

    def thread_name(rec):
        return '[thread %i]' % thread_id[rec.parameters['thread'].value]

    for seq, rec in enumerate(fdr):
        if isinstance(rec, Event):  # Print events as they appear in the fdr
            f.write(('[seq %i] ' % seq) + thread_name(rec) + ' ')
            params = rec.parameters
            if rec.event_type == 'MMAP_AFTER':
                f.write(
                    'mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n'
                    % (params['addr'].value, params['length'].value,
                       params['prot'].value, params['flags'].value,
                       params['offset'].value, params['ret'].value))
            elif rec.event_type == 'MUNMAP_AFTER':
                f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' %
                        (params['addr'].value, params['length'].value,
                         params['ret'].value))
            elif rec.event_type == 'IOCTL_BEFORE':  # addr, length, prot, flags, offset
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(
                        fdr[ptr:ptr + vivante_ioctl_data_t.size])
                    f.write('in=')
                    resolver = HalResolver('in')
                    s = extract_structure(fdr,
                                          inout[0],
                                          defs,
                                          '_gcsHAL_INTERFACE',
                                          resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' %
                            rec.parameters['request'].value)
            elif rec.event_type == 'IOCTL_AFTER':
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(
                        fdr[ptr:ptr + vivante_ioctl_data_t.size])
                    f.write('out=')
                    resolver = HalResolver('out')
                    s = extract_structure(fdr,
                                          inout[2],
                                          defs,
                                          '_gcsHAL_INTERFACE',
                                          resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                    f.write(
                        '/* ================================================ */\n'
                    )
                else:
                    f.write('Unknown Vivante ioctl %i\n' %
                            rec.parameters['request'].value)
            else:
                f.write('unhandled event ' + rec.event_type + '\n')
Example #14
0
def main():
    parser = argparse.ArgumentParser(description='Compare GCxxx chips.')
    parser.add_argument('-i', dest='gpus_file', metavar='GPUSFILE', type=str, 
            help='gpus.json file', default=GPUS_FILE)
    parser.add_argument('-s', dest='state_xml_file', metavar='STATEXML', type=str, 
            help='State map definition file (rules-ng-ng)', default=STATE_MAP)
    args = parser.parse_args()

    with open(args.gpus_file, 'r') as f:
        gpus = json.load(f)
    state_xml = parse_rng_file(args.state_xml_file)
    state_map = state_xml.lookup_domain('VIVS')

    feature_fields = ["chipFeatures", "chipMinorFeatures", "chipMinorFeatures1", "chipMinorFeatures2", "chipMinorFeatures3", "chipMinorFeatures4", "chipMinorFeatures5", "chipMinorFeatures6", "chipMinorFeatures7", "chipMinorFeatures8", "chipMinorFeatures9", "chipMinorFeatures10", "chipMinorFeatures11"]
    all_features = []
    for field in feature_fields:
        if field == 'chipMinorFeatures':
            set_desc = state_xml.types['chipMinorFeatures0']
        else:
            set_desc = state_xml.types[field]
        all_features.extend([(field,bit) for bit in set_desc.bitfields])

    table = []
    
    cur_row = 0
    table.append(Cell(cur_row, 0, 'Platform', cls='header firstrow'))
    cur_col = 1
    for platform in gpus:
        table.append(Cell(cur_row, cur_col, platform['platform'], colspan=len(platform['chips']), cls='firstrow'))
        cur_col += len(platform['chips'])
    full_width = cur_col

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Type', cls='header'))
    cur_col = 1
    for platform in gpus:
        for idx,chip in enumerate(platform['chips']):
            table.append(Cell(cur_row, cur_col, chip['type']))
            cur_col += 1
    
    cur_row += 1
    table.append(Cell(cur_row, 0, 'Revision', cls='header'))
    cur_col = 1
    for platform in gpus:
        for idx,chip in enumerate(platform['chips']):
            if 'chipRevision' in chip:
                revision_str = '0x%04x' % int(chip['chipRevision'],0)
            else:
                revision_str = '?'
            table.append(Cell(cur_row, cur_col, revision_str))
            cur_col += 1

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Specs', colspan=full_width, cls='category'))
    spec_fields = ["streamCount", "registerMax", "threadCount", "shaderCoreCount",  "vertexCacheSize", "vertexOutputBufferSize",
              "pixelPipes", "instructionCount", "numConstants", "bufferSize", "numVaryings", "superTileLayout"]
    for (field) in spec_fields:
        cur_row += 1
        table.append(Cell(cur_row, 0, field, cls='subheader'))
        cur_col = 1
        for platform in gpus:
            for chip in platform['chips']:
                if field in chip:
                    value = int(chip[field], 0)
                else:
                    value = '?'
                table.append(Cell(cur_row, cur_col, value))
                cur_col += 1

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Features', colspan=full_width, cls='category'))
    for (field, bit) in all_features:
        cur_row += 1
        table.append(Cell(cur_row, 0, bit.name, cls='subheader featurename'))
        cur_col = 1
        for platform in gpus:
            for chip in platform['chips']:
                value = int(chip.get(field,'0'), 0)
                active_feat = bit.extract(value)
                if active_feat:
                    active_feat = '+'
                    cls = 'plus'
                else:
                    active_feat = '-'
                    cls = 'minus'
                table.append(Cell(cur_row, cur_col, active_feat, cls=cls))
                cur_col += 1
    
    layout = {}
    rows = 0
    columns = 0
    for cell in table:
        layout[cell.row,cell.column] = cell
        rows = max(cell.row+1, rows)
        columns = max(cell.column+1, columns)

    out = sys.stdout 
    out.write('<html>\n')
    out.write('<head><!-- Auto-generated by make_feature_comparison.py from gpus.json -->\n')
    out.write('<title>Vivante GPU feature bits comparison</title>\n')
    out.write("""<style>
body { background-color: white; }
table.gpu-comparison { table-layout: fixed; word-wrap:break-all; }
table.gpu-comparison td { width: 80px; text-align: center; fixed; word-wrap:break-word; word-break:break-all; }
table.gpu-comparison tr:nth-child(odd) td {
    background-color: #e0e0ff;
}
table.gpu-comparison tr:nth-child(even) td {
    background-color: #d0d0ff;
}
table.gpu-comparison tr td.firstrow { text-align: left; background-color: #F0F0F0; }
table.gpu-comparison tr td.header { text-align: left; width: 15em; }
table.gpu-comparison tr td.subheader { text-align: left; }
table.gpu-comparison tr td.category { text-align: left; font-style: italic; background-color: #F0F0F0; }
table.gpu-comparison td.minus { color: #808080; }
table.gpu-comparison td.plus { }
table.gpu-comparison .featurename { font-family:monospace; font-size: 10px; }
</style>
""")
    out.write('</head>\n')
    out.write('<body>\n')
    out.write('<table class="gpu-comparison">\n')
    for row in xrange(rows):
        out.write('<tr>')
        for column in xrange(columns):
            try:
                cell = layout[row, column]
            except KeyError:
                pass #out.write('<td></td>')
            else:
                args = ''
                if cell.colspan != 1:
                    args += ' colspan="%i"' % cell.colspan
                if cell.cls is not None:
                    args += ' class="%s"' % cell.cls
                out.write('<td%s>%s</td>' %(args,cgi.escape(str(cell.value))))
        out.write('</tr>\n')
    out.write('</table>\n')
    out.write('</body>\n')
    out.write('</html>\n')
Example #15
0
def main():
    args = parse_args()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    out = sys.stdout

    # Read input file
    with open(args.input, 'r') as f:
        fields = None
        recordname = None
        data = []
        for line in f:
            (line, _, _) = line.partition('#')
            line = line.rstrip()
            if not line:
                continue
            if line.startswith('    '):
                # If line starts with four spaces this is a field
                # specification.
                line = line.strip().split()
                field_attr = parse_field_attributes(line[1:])
                fields.append((line[0], field_attr))
            else:
                if recordname is not None:
                    data.append([recordname, fields])
                fields = []
                recordname = line.strip()
        if recordname is not None:
            data.append([recordname, fields])

    # Preprocess input file, look up field names and sort by register offset
    recs_by_offset = defaultdict(list)
    field_by_offset = {}
    field_attrs_by_offset = {}
    for rec in data:
        rec_info = rec[0].split()
        for field,field_attr in rec[1]:
            path = rnn_lookup(state_map, field)
            offset, strides = rnn_strides(path)
            field_by_offset[offset] = (field, path, strides)
            recs_by_offset[offset].append(rec_info)
            if not offset in field_attrs_by_offset:
                field_attrs_by_offset[offset] = field_attr
            else:
                # if this field is specified in multiple state atoms,
                # the attributes must be equal for each
                if field_attrs_by_offset[offset] != field_attr:
                    print('Field attribute conflict for %s' % field)
                    exit(1)

    # Emit weave state code
    print('/* Weave state */')
    offsets = sorted(field_by_offset.keys())
    last_dirty_bits = None
    indent = 1
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        # strides is a list of (stride,length) tuples
        name = name.replace('.', '_')
        recs = recs_by_offset[offset]

        # build target state
        target_state = name
        target_state_sub = ', '.join(('{%i}' % (src_idx)) for src_idx,_ in enumerate(strides))
        if target_state_sub:
            target_state += '('+target_state_sub+')'

        # build target field reference
        target_field = name
        #   to sort destination state addresses in order, sort array indices by decreasing stride
        dest_strides = sorted([(idx,stride,length) for idx,(stride,length) in enumerate(strides)], 
                key=lambda x:-x[1]) 
        for src_idx,stride,length in dest_strides:
            target_field += '[{%i}]' % (src_idx)

        fieldrefs = [] 
        dirty_bits = set()
        for rec in recs:
            source_field = name
            for idx,(stride,length) in enumerate(strides):
                iname = '{%i}' % idx
                if not iname in rec[1]: # if quantifier not already used in record name itself
                    source_field += '[' + iname + ']'
            fieldrefs.append('%s%s%s' % (SRC_SPEC,rec[1],source_field))
            dirty_bits.add(rec[2])
       
        if last_dirty_bits != dirty_bits:
            if last_dirty_bits is not None:
                indent -= 1
                out.write('    ' * indent)
                out.write('}\n')
            out.write('    ' * indent)
            out.write('if(dirty & (%s))\n' % (' | '.join(dirty_bits)))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1
        for src_idx,stride,length in dest_strides:
            out.write('    ' * indent)
            out.write('for(int {0}=0; {0}<{1}; ++{0})\n'.format(VARNAMES[src_idx], length))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1

        macro = 'EMIT_STATE'
        if isinstance(path[-1].type, BaseType) and path[-1].type.kind == 'fixedp':
            macro += '_FIXP'

        out.write('    ' * indent)
        out.write('/*%05X*/ %s(%s, %s, %s);\n' % (
            offset,
            macro,
            target_state.format(*VARNAMES), 
            target_field.format(*VARNAMES), 
            (' | '.join(fieldrefs)).format(*VARNAMES)))
        
        for src_idx,stride,length in dest_strides:
            indent -= 1
            out.write('    ' * indent)
            out.write('}\n')

        last_dirty_bits = dirty_bits
    if last_dirty_bits is not None:
        indent -= 1
        out.write('    ' * indent)
        out.write('}\n')

    # Emit reset state function code
    # This function pushes the current context structure to the gpu
    print()
    print('/* Reset state */')
    indent = 1
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        # strides is a list of (stride,length) tuples
        name = name.replace('.', '_')
        recs = recs_by_offset[offset]

        # build target state
        target_state = name
        target_state_sub = ', '.join(('{%i}' % (src_idx)) for src_idx,_ in enumerate(strides))
        if target_state_sub:
            target_state += '('+target_state_sub+')'

        # build target field reference
        target_field = name
        #   to sort destination state addresses in order, sort array indices by decreasing stride
        dest_strides = sorted([(idx,stride,length) for idx,(stride,length) in enumerate(strides)], key=lambda x:-x[1])
        for src_idx,stride,length in dest_strides:
            target_field += '[{%i}]' % (src_idx)

        fieldrefs = []
        dirty_bits = set()
        for rec in recs:
            source_field = name
            for idx,(stride,length) in enumerate(strides):
                iname = '{%i}' % idx
                if not iname in rec[1]: # if quantifier not already used in record name itself
                    source_field += '[' + iname + ']'
            fieldrefs.append('%s%s%s' % (SRC_SPEC,rec[1],source_field))
            dirty_bits.add(rec[2])

        for src_idx,stride,length in dest_strides:
            out.write('    ' * indent)
            out.write('for(int {0}=0; {0}<{1}; ++{0})\n'.format(VARNAMES[src_idx], length))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1

        macro = 'EMIT_STATE'
        if isinstance(path[-1].type, BaseType) and path[-1].type.kind == 'fixedp':
            macro += '_FIXP'

        out.write('    ' * indent)
        out.write('/*%05X*/ %s(%s, %s);\n' % (
            offset,
            macro,
            target_state.format(*VARNAMES),
            target_field.format(*VARNAMES)))

        for src_idx,stride,length in dest_strides:
            indent -= 1
            out.write('    ' * indent)
            out.write('}\n')

    # Generate statistics
    total_updates_fixed = 0
    total_updates_dynamic = 0
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        state_count = reduce(operator.mul, (length for (stride,length) in strides), 1)
        attrs = field_attrs_by_offset[offset]

        if not attrs.dynamic:
            total_updates_fixed += state_count
        else:
            total_updates_dynamic += state_count
    print()
    print('/* Statistics')
    print('   Total state updates (fixed): %i' % total_updates_fixed)
    print('   Maximum state updates (dynamic): %i' % total_updates_dynamic)
    print('*/')
Example #16
0
    Usage:
      gpu-inspect <resource>
    """

    def __init__ (self):
        super(GPUInspect, self).__init__ ("gpu-inspect", gdb.COMMAND_USER)

    def invoke(self, arg, from_tty):
        self.dont_repeat()
        arg = gdb.string_to_argv(arg)
        arg[0] = gdb.parse_and_eval(arg[0])
        etna_resource_type = gdb.lookup_type('struct etna_resource').pointer()
        res = arg[0].cast(etna_resource_type)
        # this is very, very primitive now
        # dump first 128 bytes of level 0 by default, as floats
        # XXX make this more flexible
        logical = res['levels'][0]['logical']
        size = 128
        buffer = indirect_memcpy(logical, logical+size)
        data = struct.unpack_from(b'%df' % (len(buffer)/4), buffer)
        print(data)

state_xml = parse_rng_file(rnndb_path('state.xml'))
isa_xml = parse_rng_file(rnndb_path('isa.xml'))

GPUState(state_xml)
GPUDisassemble(isa_xml) 
GPUTrace(state_xml)
GPUInspect()

def main():
    args = parse_arguments()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')

    cmdstream_xml = parse_rng_file(args.cmdstream_file)
    fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE')
    cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE')
    cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map)

    global options
    options = args
    import re

    if args.binary:
        # Binary format
        with open(args.input_file, 'rb') as f:
            data = f.read()
        assert ((len(data) % 8) == 0)
        values = bytes_to_words(data)
        addrs = None
        tgtaddrs = None
    elif args.galcore:
        # Vivante kernel format
        values = []
        addrs = []
        tgtaddrs = set()
        with open(args.input_file, 'r') as f:
            for line in f:
                #value = line.strip()
                #if value.startswith(':'):
                #    value = int(value[1:9], 16)
                #    values.append(value)
                m = re.search('DMA Address 0x([0-9A-F]{8})', line)
                if m:
                    tgtaddrs.add(int(m.group(1), 16))
                m = re.search('([0-9A-F]{8}) : (([0-9A-F]{8} )*[0-9A-F]{8})$',
                              line)
                # [  309.029521] 3FD84000 : 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
                if m:
                    addr = int(m.group(1), 16)
                    for i, d in enumerate(m.group(2).split(' ')):
                        addrs.append(addr + i * 4)
                        values.append(int(d, 16))
    else:
        # old etnaviv ASCII format
        values = []
        addrs = None
        tgtaddrs = None
        with open(args.input_file, 'r') as f:
            for line in f:
                value = line.strip()
                if value.startswith(':'):
                    value = int(value[1:9], 16)
                    values.append(value)

    recs = parse_command_buffer(values, cmdstream_info, initial_padding=0)
    if args.output_c_raw:
        dump_command_buffer_c_raw(sys.stdout, recs, state_map)
    elif args.output_c:
        dump_command_buffer_c(sys.stdout, recs, state_map)
    else:
        dump_command_buffer(sys.stdout, recs, [], state_map, addrs, tgtaddrs)
    sys.stdout.write('\n')
Example #18
0
def main():
    args = parse_arguments()
    defs = load_data_definitions(args.struct_file)
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    fdr = FDRLoader(args.input)
    global options
    options = args
    global isa
    isa = parse_rng_file(args.isa_file)

    def handle_comment(f, val, depth):
        '''Annotate value with a comment'''
        if not depth:
            return None
        parent = depth[-1][0]
        field = depth[-1][1]
        parent_type = parent.type['name']
        # Show names for features and minor feature bits
        if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY':
            if field == 'chipMinorFeatures':
                field = 'chipMinorFeatures0'
            if field in state_xml.types and isinstance(state_xml.types[field], BitSet):
                feat = state_xml.types[field]
                active_feat = [bit.name for bit in feat.bitfields if bit.extract(val.value)]
                return ' '.join(active_feat)
        elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY':
            if field == 'address': # annotate addresses with unique identifier
                return format_addr(val.value)

    def handle_pointer(f, ptr, depth):
        parent = depth[-1][0]
        field = depth[-1][1]
        if ptr.type in ['_gcoCMDBUF','_gcoCONTEXT','_gcsQUEUE']:
            s = extract_structure(fdr, ptr.addr, defs, ptr.type, resolver=resolver)
            f.write('&(%s)0x%x' % (ptr.type,ptr.addr))
            dump_structure(f, s, handle_pointer, handle_comment, depth)
            return
        elif field == 'logical' and ptr.addr != 0:
            # Command stream
            if parent.type['name'] == '_gcoCMDBUF':
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(f, fdr, ptr.addr + parent.members['startOffset'].value, 
                         ptr.addr + parent.members['offset'].value,
                         depth, state_map)
                return
            if parent.type['name'] == '_gcoCONTEXT' and options.show_context_commands:
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(f, fdr, ptr.addr, 
                         ptr.addr + parent.members['bufferSize'].value,
                         depth, state_map)
                return
        elif parent.type['name'] == '_gcoCONTEXT' and field == 'map' and ptr.addr != 0 and options.show_state_map:
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_context_map(f, fdr, ptr.addr, 
                     ptr.addr + parent.members['stateCount'].value*4,
                     depth, state_map)
            return
        elif parent.type['name'] == '_gcoCONTEXT' and field == 'buffer' and ptr.addr != 0 and options.show_context_buffer:
            # Equivalent to gcoCONTEXT.map
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_command_buffer(f, fdr, ptr.addr, 
                     ptr.addr + parent.members['bufferSize'].value,
                     depth, state_map)
            return

        print_address(f, ptr, depth)

    vivante_ioctl_data_t = struct.Struct(ENDIAN + ADDR_CHAR + WORD_CHAR + ADDR_CHAR + WORD_CHAR)
    f = sys.stdout
    thread_id = Counter()

    def thread_name(rec):
        return '[thread %i]' % thread_id[rec.parameters['thread'].value]

    for seq,rec in enumerate(fdr):
        if isinstance(rec, Event): # Print events as they appear in the fdr
            f.write(('[seq %i] ' % seq) + thread_name(rec) + ' ')
            params = rec.parameters
            if rec.event_type == 'MMAP_AFTER':
                f.write('mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n' % (
                    params['addr'].value, params['length'].value, params['prot'].value, params['flags'].value, params['offset'].value, 
                    params['ret'].value))
            elif rec.event_type == 'MUNMAP_AFTER':
                f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' % (
                    params['addr'].value, params['length'].value, params['ret'].value))
            elif rec.event_type == 'IOCTL_BEFORE': # addr, length, prot, flags, offset
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size])
                    f.write('in=')
                    resolver = HalResolver('in')
                    s = extract_structure(fdr, inout[0], defs, '_gcsHAL_INTERFACE', resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value)
            elif rec.event_type == 'IOCTL_AFTER':
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size])
                    f.write('out=')
                    resolver = HalResolver('out')
                    s = extract_structure(fdr, inout[2], defs, '_gcsHAL_INTERFACE', resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                    f.write('/* ================================================ */\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value)
            else:
                f.write('unhandled event ' + rec.event_type + '\n')
Example #19
0
def main():
    args = parse_args()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    out = sys.stdout
    # Read input file
    with open(args.input, 'r') as f:
        fields = None
        recordname = None
        data = []
        for line in f:
            line = line.rstrip()
            if not line or line.startswith('#'):
                continue
            if line.startswith('    '):
                line = line.strip().split()
                fields.append(line[0])
            else:
                if recordname is not None:
                    data.append([recordname, fields])
                fields = []
                recordname = line.strip()
        if recordname is not None:
            data.append([recordname, fields])
    # Preprocess input file, look up field names and sort by offset
    recs_by_offset = defaultdict(list)
    field_by_offset = {}
    for rec in data:
        rec_info = rec[0].split()
        for field in rec[1]:
            path = rnn_lookup(state_map, field)
            offset, strides = rnn_strides(path)
            #print(field, '%05x' % offset, strides)
            field_by_offset[offset] = (field, path, strides)
            recs_by_offset[offset].append(rec_info)
    # Emit output
    offsets = sorted(field_by_offset.keys())
    last_dirty_bits = None
    indent = 1
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        # strides is a list of (stride,length) tuples
        name = name.replace('.', '_')
        recs = recs_by_offset[offset]

        # build target state
        target_state = name
        target_state_sub = ', '.join(('{%i}' % (src_idx)) for src_idx,_ in enumerate(strides))
        if target_state_sub:
            target_state += '('+target_state_sub+')'

        # build target field reference
        target_field = name
        #   to sort destination state addresses in order, sort array indices by decreasing stride
        dest_strides = sorted([(idx,stride,length) for idx,(stride,length) in enumerate(strides)], key=lambda x:-x[1]) 
        for src_idx,stride,length in dest_strides:
            target_field += '[{%i}]' % (src_idx)

        fieldrefs = [] 
        dirty_bits = set()
        for rec in recs:
            source_field = name
            for idx,(stride,length) in enumerate(strides):
                iname = '{%i}' % idx
                if not iname in rec[1]: # if quantifier not already used in record name itself
                    source_field += '[' + iname + ']'
            fieldrefs.append('%s%s%s' % (SRC_SPEC,rec[1],source_field))
            dirty_bits.add(rec[2])
       
        if last_dirty_bits != dirty_bits:
            if last_dirty_bits is not None:
                indent -= 1
                out.write('    ' * indent)
                out.write('}\n')
            out.write('    ' * indent)
            out.write('if(dirty & (%s))\n' % (' | '.join(dirty_bits)))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1
        for src_idx,stride,length in dest_strides:
            out.write('    ' * indent)
            out.write('for(int {0}=0; {0}<{1}; ++{0})\n'.format(VARNAMES[src_idx], length))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1

        macro = 'EMIT_STATE'
        if isinstance(path[-1].type, BaseType) and path[-1].type.kind == 'fixedp':
            macro += '_FIXP'

        out.write('    ' * indent)
        out.write('/*%05X*/ %s(%s, %s, %s);\n' % (
            offset,
            macro,
            target_state.format(*VARNAMES), 
            target_field.format(*VARNAMES), 
            (' | '.join(fieldrefs)).format(*VARNAMES)))
        
        for src_idx,stride,length in dest_strides:
            indent -= 1
            out.write('    ' * indent)
            out.write('}\n')

        last_dirty_bits = dirty_bits
    if last_dirty_bits is not None:
        indent -= 1
        out.write('    ' * indent)
        out.write('}\n')
Example #20
0
    Usage:
      gpu-inspect <resource>
    """

    def __init__ (self):
        super(GPUInspect, self).__init__ ("gpu-inspect", gdb.COMMAND_USER)

    def invoke(self, arg, from_tty):
        self.dont_repeat()
        arg = gdb.string_to_argv(arg)
        arg[0] = gdb.parse_and_eval(arg[0])
        etna_resource_type = gdb.lookup_type('struct etna_resource').pointer()
        res = arg[0].cast(etna_resource_type)
        # this is very, very primitive now
        # dump first 128 bytes of level 0 by default, as floats
        # XXX make this more flexible
        logical = res['levels'][0]['logical']
        size = 128
        buffer = indirect_memcpy(logical, logical+size)
        data = struct.unpack_from(b'%df' % (len(buffer)/4), buffer)
        print(data)

state_xml = parse_rng_file(rnndb_path('state.xml'))
isa_xml = parse_rng_file(rnndb_path('isa.xml'))

GPUState(state_xml)
GPUDisassemble(isa_xml) 
GPUTrace(state_xml)
GPUInspect()

Example #21
0
def main():
    args = parse_arguments()
    
    if args.struct_file is None:
        args.struct_file = guess_from_fdr(args.input)
        print('[Using struct file %s]' % args.struct_file)
    if args.struct_file is None:
        print('Could not determine struct file from GCABI in FDR, provide --struct-file= argument')

    defs = load_data_definitions(args.struct_file)
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')

    cmdstream_xml = parse_rng_file(args.cmdstream_file)
    fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE')
    cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE')
    cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map)

    txdesc_xml = parse_rng_file(args.txdesc_file)
    txdesc_map = txdesc_xml.lookup_domain('TEXDESC')

    fdr = FDRLoader(args.input)
    global options
    options = args

    def handle_comment(f, val, depth):
        '''Annotate value with a comment'''
        if not depth:
            return None
        parent = depth[-1][0]
        field = depth[-1][1]
        parent_type = parent.type['name']
        # Show names for features and minor feature bits
        if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY':
            if field == 'chipMinorFeatures':
                field = 'chipMinorFeatures0'
            if field in state_xml.types and isinstance(state_xml.types[field], BitSet):
                feat = state_xml.types[field]
                active_feat = [bit.name for bit in feat.bitfields if bit.extract(val.value)]
                return ' '.join(active_feat)
        elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY':
            if field == 'address': # annotate addresses with unique identifier
                return tracking.format_addr(val.value)
        elif parent_type == '_gcsUSER_MEMORY_DESC':
            if field == 'physical': # annotate addresses with unique identifier
                return tracking.format_addr(val.value)
        elif parent_type == '_gcsHAL_SIGNAL':
            if field == 'signal':
                return 'id = %d' % val.value
        if field == 'node':
            if val.value in tracking.nodes:
                return tracking.nodes[val.value].name

    def handle_pointer(f, ptr, depth):
        parent = depth[-1][0]
        field = depth[-1][1]
        if ptr.type in ['_gcoCMDBUF','_gcsQUEUE']:
            s = extract_structure(fdr, ptr.addr, defs, ptr.type, resolver=resolver)
            f.write('&(%s)0x%x' % (ptr.type,ptr.addr))
            dump_structure(f, s, handle_pointer, handle_comment, depth)
            return
        elif field == 'logical' and ptr.addr != 0:
            # Command stream
            if parent.type['name'] == '_gcoCMDBUF':
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(f, fdr, ptr.addr + parent.members['startOffset'].value, 
                         ptr.addr + parent.members['offset'].value,
                         depth, state_map, cmdstream_info, tracking, txdesc_map)
                return

        print_address(f, ptr, depth)

    f = sys.stdout
    tracking = DriverState(defs)

    for seq,rec in enumerate(fdr):
        if isinstance(rec, Event): # Print events as they appear in the fdr
            if not args.summary:
                f.write(('[seq %i] ' % seq) + tracking.thread_name(rec) + ' ')
            params = rec.parameters
            if rec.event_type == 'MMAP_BEFORE': # ignore
                pass
            elif rec.event_type == 'MMAP_AFTER':
                f.write('mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n' % (
                    params['addr'].value, params['length'].value, params['prot'].value, params['flags'].value, params['offset'].value, 
                    params['ret'].value))
            elif rec.event_type == 'MUNMAP_AFTER':
                f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' % (
                    params['addr'].value, params['length'].value, params['ret'].value))
            elif rec.event_type == 'IOCTL_BEFORE': # addr, length, prot, flags, offset
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size])
                    if not args.summary:
                        f.write('in=')
                    resolver = HalResolver('in')
                    s = extract_structure(fdr, inout[0], defs, '_gcsHAL_INTERFACE', resolver=resolver)
                    tracking.handle_gcin(rec.parameters['thread'].value, s, extract_meta(fdr, defs, resolver, s))
                    if not args.summary or s.members['command'].name == 'gcvHAL_COMMIT':
                        dump_structure(f, s, handle_pointer, handle_comment)
                        f.write('\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value)
            elif rec.event_type == 'IOCTL_AFTER':
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size])
                    if not args.summary:
                        f.write('out=')
                    resolver = HalResolver('out')
                    s = extract_structure(fdr, inout[2], defs, '_gcsHAL_INTERFACE', resolver=resolver)
                    tracking.handle_gcout(rec.parameters['thread'].value, s)
                    if not args.summary:
                        dump_structure(f, s, handle_pointer, handle_comment)
                        f.write('\n')
                        f.write('/* ================================================ */\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value)
            else:
                f.write('unhandled event ' + rec.event_type + '\n')
        elif isinstance(rec, Comment):
            t = WORD_SPEC.unpack(rec.data[0:4])[0]
            if t == 0x594e4f50:
                v = struct.unpack(ENDIAN + WORD_CHAR * 3, rec.data[4:])
                print('[end of frame %d: %d.%09d]' % v)
            elif t == 0x424f4c42:
                v = struct.unpack(ENDIAN + WORD_CHAR * 4, rec.data[4:])
                print('[driver version %d.%d.%d.%d]' % v)
Example #22
0
def main():
    args = parse_args()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')
    out = sys.stdout

    # Read input file
    with open(args.input, 'r') as f:
        fields = None
        recordname = None
        data = []
        for line in f:
            (line, _, _) = line.partition('#')
            line = line.rstrip()
            if not line:
                continue
            if line.startswith('    '):
                # If line starts with four spaces this is a field
                # specification.
                line = line.strip().split()
                field_attr = parse_field_attributes(line[1:])
                fields.append((line[0], field_attr))
            else:
                if recordname is not None:
                    data.append([recordname, fields])
                fields = []
                recordname = line.strip()
        if recordname is not None:
            data.append([recordname, fields])

    # Preprocess input file, look up field names and sort by register offset
    recs_by_offset = defaultdict(list)
    field_by_offset = {}
    field_attrs_by_offset = {}
    for rec in data:
        rec_info = rec[0].split()
        for field, field_attr in rec[1]:
            path = rnn_lookup(state_map, field)
            offset, strides = rnn_strides(path)
            field_by_offset[offset] = (field, path, strides)
            recs_by_offset[offset].append(rec_info)
            if not offset in field_attrs_by_offset:
                field_attrs_by_offset[offset] = field_attr
            else:
                # if this field is specified in multiple state atoms,
                # the attributes must be equal for each
                if field_attrs_by_offset[offset] != field_attr:
                    print('Field attribute conflict for %s' % field)
                    exit(1)

    # Emit weave state code
    print('/* Weave state */')
    offsets = sorted(field_by_offset.keys())
    last_dirty_bits = None
    indent = 1
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        # strides is a list of (stride,length) tuples
        name = name.replace('.', '_')
        recs = recs_by_offset[offset]

        # build target state
        target_state = name
        target_state_sub = ', '.join(
            ('{%i}' % (src_idx)) for src_idx, _ in enumerate(strides))
        if target_state_sub:
            target_state += '(' + target_state_sub + ')'

        # build target field reference
        target_field = name
        #   to sort destination state addresses in order, sort array indices by decreasing stride
        dest_strides = sorted(
            [(idx, stride, length)
             for idx, (stride, length) in enumerate(strides)],
            key=lambda x: -x[1])
        for src_idx, stride, length in dest_strides:
            target_field += '[{%i}]' % (src_idx)

        fieldrefs = []
        dirty_bits = set()
        for rec in recs:
            source_field = name
            for idx, (stride, length) in enumerate(strides):
                iname = '{%i}' % idx
                if not iname in rec[
                        1]:  # if quantifier not already used in record name itself
                    source_field += '[' + iname + ']'
            fieldrefs.append('%s%s%s' % (SRC_SPEC, rec[1], source_field))
            dirty_bits.add(rec[2])

        if last_dirty_bits != dirty_bits:
            if last_dirty_bits is not None:
                indent -= 1
                out.write('    ' * indent)
                out.write('}\n')
            out.write('    ' * indent)
            out.write('if(dirty & (%s))\n' % (' | '.join(dirty_bits)))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1
        for src_idx, stride, length in dest_strides:
            out.write('    ' * indent)
            out.write('for(int {0}=0; {0}<{1}; ++{0})\n'.format(
                VARNAMES[src_idx], length))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1

        macro = 'EMIT_STATE'
        if isinstance(path[-1].type,
                      BaseType) and path[-1].type.kind == 'fixedp':
            macro += '_FIXP'

        out.write('    ' * indent)
        out.write('/*%05X*/ %s(%s, %s, %s);\n' %
                  (offset, macro, target_state.format(*VARNAMES),
                   target_field.format(*VARNAMES),
                   (' | '.join(fieldrefs)).format(*VARNAMES)))

        for src_idx, stride, length in dest_strides:
            indent -= 1
            out.write('    ' * indent)
            out.write('}\n')

        last_dirty_bits = dirty_bits
    if last_dirty_bits is not None:
        indent -= 1
        out.write('    ' * indent)
        out.write('}\n')

    # Emit reset state function code
    # This function pushes the current context structure to the gpu
    print()
    print('/* Reset state */')
    indent = 1
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        # strides is a list of (stride,length) tuples
        name = name.replace('.', '_')
        recs = recs_by_offset[offset]

        # build target state
        target_state = name
        target_state_sub = ', '.join(
            ('{%i}' % (src_idx)) for src_idx, _ in enumerate(strides))
        if target_state_sub:
            target_state += '(' + target_state_sub + ')'

        # build target field reference
        target_field = name
        #   to sort destination state addresses in order, sort array indices by decreasing stride
        dest_strides = sorted(
            [(idx, stride, length)
             for idx, (stride, length) in enumerate(strides)],
            key=lambda x: -x[1])
        for src_idx, stride, length in dest_strides:
            target_field += '[{%i}]' % (src_idx)

        fieldrefs = []
        dirty_bits = set()
        for rec in recs:
            source_field = name
            for idx, (stride, length) in enumerate(strides):
                iname = '{%i}' % idx
                if not iname in rec[
                        1]:  # if quantifier not already used in record name itself
                    source_field += '[' + iname + ']'
            fieldrefs.append('%s%s%s' % (SRC_SPEC, rec[1], source_field))
            dirty_bits.add(rec[2])

        for src_idx, stride, length in dest_strides:
            out.write('    ' * indent)
            out.write('for(int {0}=0; {0}<{1}; ++{0})\n'.format(
                VARNAMES[src_idx], length))
            out.write('    ' * indent)
            out.write('{\n')
            indent += 1

        macro = 'EMIT_STATE'
        if isinstance(path[-1].type,
                      BaseType) and path[-1].type.kind == 'fixedp':
            macro += '_FIXP'

        out.write('    ' * indent)
        out.write('/*%05X*/ %s(%s, %s);\n' %
                  (offset, macro, target_state.format(*VARNAMES),
                   target_field.format(*VARNAMES)))

        for src_idx, stride, length in dest_strides:
            indent -= 1
            out.write('    ' * indent)
            out.write('}\n')

    # Generate statistics
    total_updates_fixed = 0
    total_updates_dynamic = 0
    for offset in offsets:
        (name, path, strides) = field_by_offset[offset]
        state_count = reduce(operator.mul,
                             (length for (stride, length) in strides), 1)
        attrs = field_attrs_by_offset[offset]

        if not attrs.dynamic:
            total_updates_fixed += state_count
        else:
            total_updates_dynamic += state_count
    print()
    print('/* Statistics')
    print('   Total state updates (fixed): %i' % total_updates_fixed)
    print('   Maximum state updates (dynamic): %i' % total_updates_dynamic)
    print('*/')
def main():
    parser = argparse.ArgumentParser(description='Compare GCxxx chips.')
    parser.add_argument('-i', dest='gpus_file', metavar='GPUSFILE', type=str, 
            help='gpus.json file', default=GPUS_FILE)
    parser.add_argument('-s', dest='state_xml_file', metavar='STATEXML', type=str, 
            help='State map definition file (rules-ng-ng)', default=STATE_MAP)
    args = parser.parse_args()

    with open(args.gpus_file, 'r') as f:
        gpus = json.load(f)
    state_xml = parse_rng_file(args.state_xml_file)
    state_map = state_xml.lookup_domain('VIVS')

    feature_fields = ["chipFeatures", "chipMinorFeatures", "chipMinorFeatures1", "chipMinorFeatures2", "chipMinorFeatures3"]
    all_features = []
    for field in feature_fields:
        if field == 'chipMinorFeatures':
            set_desc = state_xml.types['chipMinorFeatures0']
        else:
            set_desc = state_xml.types[field]
        all_features.extend([(field,bit) for bit in set_desc.bitfields])

    table = []
    
    cur_row = 0
    table.append(Cell(cur_row, 0, 'Platform', cls='header firstrow'))
    cur_col = 1
    for platform in gpus:
        table.append(Cell(cur_row, cur_col, platform['platform'], colspan=len(platform['chips']), cls='firstrow'))
        cur_col += len(platform['chips'])
    full_width = cur_col

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Type', cls='header'))
    cur_col = 1
    for platform in gpus:
        for idx,chip in enumerate(platform['chips']):
            table.append(Cell(cur_row, cur_col, chip['type']))
            cur_col += 1
    
    cur_row += 1
    table.append(Cell(cur_row, 0, 'Revision', cls='header'))
    cur_col = 1
    for platform in gpus:
        for idx,chip in enumerate(platform['chips']):
            if 'chipRevision' in chip:
                revision_str = '0x%04x' % int(chip['chipRevision'],0)
            else:
                revision_str = '?'
            table.append(Cell(cur_row, cur_col, revision_str))
            cur_col += 1

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Specs', colspan=full_width, cls='category'))
    spec_fields = ["streamCount", "registerMax", "threadCount", "shaderCoreCount",  "vertexCacheSize", "vertexOutputBufferSize"]
    for (field) in spec_fields:
        cur_row += 1
        table.append(Cell(cur_row, 0, field, cls='subheader'))
        cur_col = 1
        for platform in gpus:
            for chip in platform['chips']:
                if field in chip:
                    value = int(chip[field], 0)
                else:
                    value = '?'
                table.append(Cell(cur_row, cur_col, value))
                cur_col += 1

    cur_row += 1
    table.append(Cell(cur_row, 0, 'Features', colspan=full_width, cls='category'))
    for (field, bit) in all_features:
        cur_row += 1
        table.append(Cell(cur_row, 0, bit.name, cls='subheader featurename'))
        cur_col = 1
        for platform in gpus:
            for chip in platform['chips']:
                value = int(chip.get(field,'0'), 0)
                active_feat = bit.extract(value)
                if active_feat:
                    active_feat = '+'
                    cls = 'plus'
                else:
                    active_feat = '-'
                    cls = 'minus'
                table.append(Cell(cur_row, cur_col, active_feat, cls=cls))
                cur_col += 1
    
    layout = {}
    rows = 0
    columns = 0
    for cell in table:
        layout[cell.row,cell.column] = cell
        rows = max(cell.row+1, rows)
        columns = max(cell.column+1, columns)

    out = sys.stdout 
    out.write('<html>\n')
    out.write('<head><!-- Auto-generated by make_feature_comparison.py from gpus.json -->\n')
    out.write('<title>Vivante GPU feature bits comparison</title>\n')
    out.write("""<style>
body { background-color: white; }
table.gpu-comparison { table-layout: fixed; word-wrap:break-all; }
table.gpu-comparison td { width: 80px; text-align: center; fixed; word-wrap:break-word; word-break:break-all; }
table.gpu-comparison tr:nth-child(odd) td {
    background-color: #e0e0ff;
}
table.gpu-comparison tr:nth-child(even) td {
    background-color: #d0d0ff;
}
table.gpu-comparison tr td.firstrow { text-align: left; background-color: #F0F0F0; }
table.gpu-comparison tr td.header { text-align: left; width: 15em; }
table.gpu-comparison tr td.subheader { text-align: left; }
table.gpu-comparison tr td.category { text-align: left; font-style: italic; background-color: #F0F0F0; }
table.gpu-comparison td.minus { color: #808080; }
table.gpu-comparison td.plus { }
table.gpu-comparison .featurename { font-family:monospace; font-size: 10px; }
</style>
""")
    out.write('</head>\n')
    out.write('<body>\n')
    out.write('<table class="gpu-comparison">\n')
    for row in xrange(rows):
        out.write('<tr>')
        for column in xrange(columns):
            try:
                cell = layout[row, column]
            except KeyError:
                pass #out.write('<td></td>')
            else:
                args = ''
                if cell.colspan != 1:
                    args += ' colspan="%i"' % cell.colspan
                if cell.cls is not None:
                    args += ' class="%s"' % cell.cls
                out.write('<td%s>%s</td>' %(args,cgi.escape(str(cell.value))))
        out.write('</tr>\n')
    out.write('</table>\n')
    out.write('</body>\n')
    out.write('</html>\n')
Example #24
0
def main():
    args = parse_arguments()
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')

    cmdstream_xml = parse_rng_file(args.cmdstream_file)
    fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE')
    cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE')
    cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map)

    global options
    options = args
    import re

    if args.binary:
        # Binary format
        with open(args.input_file,'rb') as f:
            data = f.read()
        assert((len(data) % 8)==0)
        values = bytes_to_words(data)
        addrs = None
        tgtaddrs = None
    elif args.galcore:
        # Vivante kernel format
        values = []
        addrs = []
        tgtaddrs = set()
        with open(args.input_file,'r') as f:
            for line in f:
                #value = line.strip()
                #if value.startswith(':'):
                #    value = int(value[1:9], 16)
                #    values.append(value)
                m = re.search('DMA Address 0x([0-9A-F]{8})', line)
                if m:
                    tgtaddrs.add(int(m.group(1), 16))
                m = re.search('([0-9A-F]{8}) ?: (([0-9A-F]{8} )*[0-9A-F]{8})$', line, flags=re.IGNORECASE)
                # Vendor kernel with vivante HAL
                # [  309.029521] 3FD84000 : 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
                # Mainline kernel with etnaviv DRM
                # [ 2121.178339] cmd 00000000: 380000c8 00000000 40000002 00000000
                if m:
                    addr = int(m.group(1), 16)
                    for i,d in enumerate(m.group(2).split(' ')):
                        addrs.append(addr + i*4)
                        values.append(int(d, 16))
    else:
        # old etnaviv ASCII format
        values = []
        addrs = None
        tgtaddrs = None
        with open(args.input_file,'r') as f:
            for line in f:
                value = line.strip()
                if value.startswith(':'):
                    value = int(value[1:9], 16)
                    values.append(value)

    recs = parse_command_buffer(values, cmdstream_info, initial_padding=0)
    if args.output_c_raw:
        dump_command_buffer_c_raw(sys.stdout, recs, state_map)
    elif args.output_c:
        dump_command_buffer_c(sys.stdout, recs, state_map)
    else:
        dump_command_buffer(sys.stdout, recs, [], state_map, addrs, tgtaddrs)
    sys.stdout.write('\n')
Example #25
0
def main():
    args = parse_arguments()

    if args.struct_file is None:
        args.struct_file = guess_from_fdr(args.input)
        print('[Using struct file %s]' % args.struct_file)
    if args.struct_file is None:
        print(
            'Could not determine struct file from GCABI in FDR, provide --struct-file= argument'
        )

    defs = load_data_definitions(args.struct_file)
    state_xml = parse_rng_file(args.rules_file)
    state_map = state_xml.lookup_domain('VIVS')

    cmdstream_xml = parse_rng_file(args.cmdstream_file)
    fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE')
    cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE')
    cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map)
    #print(fe_opcode.values_by_value[1].name)
    #print(format_path(cmdstream_map.lookup_address(0,('LOAD_STATE','FE_OPCODE'))))

    fdr = FDRLoader(args.input)
    global options
    options = args

    def handle_comment(f, val, depth):
        '''Annotate value with a comment'''
        if not depth:
            return None
        parent = depth[-1][0]
        field = depth[-1][1]
        parent_type = parent.type['name']
        # Show names for features and minor feature bits
        if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY':
            if field == 'chipMinorFeatures':
                field = 'chipMinorFeatures0'
            if field in state_xml.types and isinstance(state_xml.types[field],
                                                       BitSet):
                feat = state_xml.types[field]
                active_feat = [
                    bit.name for bit in feat.bitfields
                    if bit.extract(val.value)
                ]
                return ' '.join(active_feat)
        elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY':
            if field == 'address':  # annotate addresses with unique identifier
                return format_addr(val.value)

    def handle_pointer(f, ptr, depth):
        parent = depth[-1][0]
        field = depth[-1][1]
        if ptr.type in ['_gcoCMDBUF', '_gcoCONTEXT', '_gcsQUEUE']:
            s = extract_structure(fdr,
                                  ptr.addr,
                                  defs,
                                  ptr.type,
                                  resolver=resolver)
            f.write('&(%s)0x%x' % (ptr.type, ptr.addr))
            dump_structure(f, s, handle_pointer, handle_comment, depth)
            return
        elif field == 'logical' and ptr.addr != 0:
            # Command stream
            if parent.type['name'] == '_gcoCMDBUF':
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(
                    f, fdr, ptr.addr + parent.members['startOffset'].value,
                    ptr.addr + parent.members['offset'].value, depth,
                    state_map, cmdstream_info)
                return
            if parent.type[
                    'name'] == '_gcoCONTEXT' and options.show_context_commands:
                f.write('&(uint32[])0x%x' % (ptr.addr))
                dump_command_buffer(
                    f, fdr, ptr.addr,
                    ptr.addr + parent.members['bufferSize'].value, depth,
                    state_map, cmdstream_info)
                return
        elif parent.type[
                'name'] == '_gcoCONTEXT' and field == 'map' and ptr.addr != 0 and options.show_state_map:
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_context_map(f, fdr, ptr.addr,
                             ptr.addr + parent.members['stateCount'].value * 4,
                             depth, state_map)
            return
        elif parent.type[
                'name'] == '_gcoCONTEXT' and field == 'buffer' and ptr.addr != 0 and options.show_context_buffer:
            # Equivalent to gcoCONTEXT.map
            f.write('&(uint32[])0x%x' % (ptr.addr))
            dump_command_buffer(f, fdr, ptr.addr,
                                ptr.addr + parent.members['bufferSize'].value,
                                depth, state_map, cmdstream_info)
            return

        print_address(f, ptr, depth)

    f = sys.stdout
    thread_id = Counter()

    def thread_name(rec):
        return '[thread %i]' % thread_id[rec.parameters['thread'].value]

    for seq, rec in enumerate(fdr):
        if isinstance(rec, Event):  # Print events as they appear in the fdr
            f.write(('[seq %i] ' % seq) + thread_name(rec) + ' ')
            params = rec.parameters
            if rec.event_type == 'MMAP_AFTER':
                f.write(
                    'mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n'
                    % (params['addr'].value, params['length'].value,
                       params['prot'].value, params['flags'].value,
                       params['offset'].value, params['ret'].value))
            elif rec.event_type == 'MUNMAP_AFTER':
                f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' %
                        (params['addr'].value, params['length'].value,
                         params['ret'].value))
            elif rec.event_type == 'IOCTL_BEFORE':  # addr, length, prot, flags, offset
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(
                        fdr[ptr:ptr + vivante_ioctl_data_t.size])
                    f.write('in=')
                    resolver = HalResolver('in')
                    s = extract_structure(fdr,
                                          inout[0],
                                          defs,
                                          '_gcsHAL_INTERFACE',
                                          resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                else:
                    f.write('Unknown Vivante ioctl %i\n' %
                            rec.parameters['request'].value)
            elif rec.event_type == 'IOCTL_AFTER':
                if params['request'].value == IOCTL_GCHAL_INTERFACE:
                    ptr = params['ptr'].value
                    inout = vivante_ioctl_data_t.unpack(
                        fdr[ptr:ptr + vivante_ioctl_data_t.size])
                    f.write('out=')
                    resolver = HalResolver('out')
                    s = extract_structure(fdr,
                                          inout[2],
                                          defs,
                                          '_gcsHAL_INTERFACE',
                                          resolver=resolver)
                    dump_structure(f, s, handle_pointer, handle_comment)
                    f.write('\n')
                    f.write(
                        '/* ================================================ */\n'
                    )
                else:
                    f.write('Unknown Vivante ioctl %i\n' %
                            rec.parameters['request'].value)
            else:
                f.write('unhandled event ' + rec.event_type + '\n')
        elif isinstance(rec, Comment):
            t = WORD_SPEC.unpack(rec.data[0:4])[0]
            if t == 0x594e4f50:
                v = struct.unpack(ENDIAN + WORD_CHAR * 3, rec.data[4:])
                print('[end of frame %d: %d.%09d]' % v)
            elif t == 0x424f4c42:
                v = struct.unpack(ENDIAN + WORD_CHAR * 4, rec.data[4:])
                print('[driver version %d.%d.%d.%d]' % v)