| 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. | 
 |  | 
 | 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-high':      ('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 cop == '!': | 
 |                 if value != val: | 
 |                     result = True | 
 |                 else: | 
 |                     result = False | 
 |                 continue | 
 |  | 
 |             if cop == '=': | 
 |                 if value == val: | 
 |                     result = True | 
 |                 else: | 
 |                     result = False | 
 |                 continue | 
 |  | 
 |         if 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) |