| import argparse |
| import libfdt |
| import os |
| import sys |
| |
| # Format: FEATURE : (dtb property, condition_operator, condition_value) |
| # If dtb property is None, then the item is always on |
| # |
| # If the condition_operator is None, then enable if it exists for existance |
| # |
| # If the condition_operator is '!', and condition_value is None then enable if |
| # if is not defined |
| # |
| # Otherwise 'condition' and value are evaluated by type. |
| # |
| # If the condition is = then any value of condition_values will set it |
| # If the condition is ! then no value of condition_values will set it |
| |
| microblaze_tune_features = { |
| 'microblaze' : (None, None, None), |
| 'bigendian': ('xlnx,endianness', '!', 1), |
| '64-bit' : ('xlnx,data-size', '=', 64), |
| 'barrel-shift': ('xlnx,use-barrel', '=', 1), |
| 'pattern-compare': ('xlnx,use-pcmp-instr', '=', 1), |
| 'reorder' : ('xlnx,use-reorder-instr', '!', 0), |
| 'frequency-optimized': ('xlnx,area-optimized', '=', 2), |
| 'multiply-low': ('xlnx,use-hw-mul', '=', 1), |
| 'multiply-high': ('xlnx,use-hw-mul', '=', 2), |
| 'divide-hard': ('xlnx,use-div', '=', 1), |
| 'fpu-soft': ('xlnx,use-fpu', '!', [1,2]), |
| 'fpu-hard': ('xlnx,use-fpu', '=', 1), |
| 'fpu-hard-extended':('xlnx,use-fpu', '=', 2), |
| } |
| |
| def processProperties(fdt, node): |
| TUNE_FEATURES = [] |
| |
| for feature in microblaze_tune_features: |
| (property, cop, cvalue) = microblaze_tune_features[feature] |
| |
| if not property: |
| TUNE_FEATURES.append(feature) |
| |
| # Special processing to get the version |
| if feature == "microblaze": |
| ver = microblazeVersion(fdt, node) |
| if ver: |
| TUNE_FEATURES.append(ver) |
| continue |
| |
| prop_value = fdt.getprop( node, property, libfdt.QUIET_NOTFOUND) |
| |
| if not prop_value or prop_value == -1: |
| if cop == '!': |
| if not cvalue: |
| TUNE_FEATURES.append(ver) |
| continue |
| continue |
| |
| # If no operator |
| if not cop or (cop == '=' and not cvalue): |
| TUNE_FEATURES.append(feature) |
| continue |
| |
| ctype = type(cvalue) |
| if ctype == type(list()): |
| val_list = cvalue |
| else: |
| val_list = [ cvalue ] |
| |
| result = False |
| for value in val_list: |
| ctype = type(value) |
| if ctype == type(int()): |
| val = prop_value.as_uint32() |
| else: |
| raise TypeError('Unknown type %s' % ctype) |
| |
| if value == val: |
| result = True |
| break |
| else: |
| result = False |
| |
| if (cop == '!' and result == False) or \ |
| (cop == '=' and result == True): |
| TUNE_FEATURES.append(feature) |
| |
| return TUNE_FEATURES |
| |
| def microblazeVersion(fdt, node): |
| version = None |
| |
| val = fdt.getprop( node, 'model', libfdt.QUIET_NOTFOUND) |
| |
| if val and val != -1: |
| val = fdt.getprop( node, 'model' ).as_str() |
| version = val[val.find('microblaze,') + 11:] |
| |
| if version.startswith('8'): |
| # Strip 8.xx.y, to just 8.xx |
| v = version.split('.') |
| version = '.'.join(v[0:2]) |
| |
| version = 'v' + version |
| |
| return version |
| |
| def MicroblazeConfig(dtbfile, out): |
| fdt = libfdt.Fdt(open(dtbfile, mode='rb').read()) |
| |
| cpu = -1 |
| while (True): |
| cpu = cpu + 1 |
| try: |
| node = fdt.path_offset('/cpus/cpu@%d' % cpu) |
| |
| try: |
| prop = fdt.getprop( node, 'compatible' ) |
| |
| prop_val = prop[:-1].decode('utf-8').split('\x00') |
| |
| microblaze = False |
| for val in prop_val: |
| if "microblaze" in val: |
| microblaze = True |
| break |
| |
| if not microblaze: |
| continue |
| |
| # Construct TUNE_FEATURE here |
| TUNE_FEATURES = processProperties(fdt, node) |
| |
| out.write('AVAILTUNES += "microblaze-cpu%s"\n' % (cpu)) |
| out.write('TUNE_FEATURES_tune-microblaze-cpu%s = "%s"\n' % (cpu, ' '.join(TUNE_FEATURES))) |
| out.write('PACKAGE_EXTRA_ARCHS_tune-microblaze-cpu%s = "${TUNE_PKGARCH}"\n' % (cpu)) |
| |
| except Exception as e: |
| sys.stderr.write("Exception looking at properties: %s\n" % e) |
| |
| continue |
| |
| except Exception as e: |
| # CPUs SHOULD be consecutive w/o gaps, so no more to search |
| break |
| |
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser(description='Generate MicroBlaze TUNE_FEATURES') |
| |
| parser.add_argument('-d', '--dtb-file', action='store', |
| help='DTB file to process') |
| |
| parser.add_argument('-o', '--output', action='store', |
| help='Output file to store TUNE_FEATURE settings') |
| |
| args = parser.parse_args() |
| |
| if not args.dtb_file: |
| sys.stderr.write('ERROR: You must specify a DTB_FILE to process.\n') |
| sys.exit(1) |
| |
| outputf = sys.stdout |
| if args.output: |
| if os.path.exists(args.output): |
| sys.stderr.write('ERROR: The output file "%s" exists!\n' % args.output) |
| sys.exit(1) |
| outputf = open(args.output, 'w') |
| |
| MicroblazeConfig(args.dtb_file, outputf) |