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)
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)
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)
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')
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)
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() 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)
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)
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')
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')
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')
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')
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('*/')
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')
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')
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')
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)
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')
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')
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)