Andrew Geissler | 84ad7c5 | 2020-06-27 00:00:16 -0500 | [diff] [blame] | 1 | import argparse |
| 2 | import libfdt |
| 3 | import os |
| 4 | import sys |
| 5 | |
| 6 | # Format: FEATURE : (dtb property, condition_operator, condition_value) |
| 7 | # If dtb property is None, then the item is always on |
| 8 | # |
| 9 | # If the condition_operator is None, then enable if it exists for existance |
| 10 | # |
| 11 | # If the condition_operator is '!', and condition_value is None then enable if |
| 12 | # if is not defined |
| 13 | # |
| 14 | # Otherwise 'condition' and value are evaluated by type. |
| 15 | |
| 16 | microblaze_tune_features = { |
| 17 | 'microblaze' : (None, None, None), |
| 18 | 'bigendian': ('xlnx,endianness', '!', 1), |
| 19 | '64-bit' : ('xlnx,data-size', '=', 64), |
| 20 | 'barrel-shift': ('xlnx,use-barrel', '=', 1), |
| 21 | 'pattern-compare': ('xlnx,use-pcmp-instr', '=', 1), |
| 22 | 'reorder' : ('xlnx,use-reorder-instr', '!', 0), |
| 23 | 'frequency-optimized': ('xlnx,area-optimized', '=', 2), |
| 24 | 'multiply-low': ('xlnx,use-hw-mul', '=', 1), |
| 25 | 'multiply-high': ('xlnx,use-hw-mul', '=', 2), |
| 26 | 'divide-high': ('xlnx,use-div', '=', 1), |
| 27 | 'fpu-soft': ('xlnx,use-fpu', '!', [1,2]), |
| 28 | 'fpu-hard': ('xlnx,use-fpu', '=', 1), |
| 29 | 'fpu-hard-extended':('xlnx,use-fpu', '=', 2), |
| 30 | } |
| 31 | |
| 32 | def processProperties(fdt, node): |
| 33 | TUNE_FEATURES = [] |
| 34 | |
| 35 | for feature in microblaze_tune_features: |
| 36 | (property, cop, cvalue) = microblaze_tune_features[feature] |
| 37 | |
| 38 | if not property: |
| 39 | TUNE_FEATURES.append(feature) |
| 40 | |
| 41 | # Special processing to get the version |
| 42 | if feature == "microblaze": |
| 43 | ver = microblazeVersion(fdt, node) |
| 44 | if ver: |
| 45 | TUNE_FEATURES.append(ver) |
| 46 | continue |
| 47 | |
| 48 | prop_value = fdt.getprop( node, property, libfdt.QUIET_NOTFOUND) |
| 49 | |
| 50 | if not prop_value or prop_value == -1: |
| 51 | if cop == '!': |
| 52 | if not cvalue: |
| 53 | TUNE_FEATURES.append(ver) |
| 54 | continue |
| 55 | continue |
| 56 | |
| 57 | # If no operator |
| 58 | if not cop or (cop == '=' and not cvalue): |
| 59 | TUNE_FEATURES.append(feature) |
| 60 | continue |
| 61 | |
| 62 | ctype = type(cvalue) |
| 63 | if ctype == type(list()): |
| 64 | val_list = cvalue |
| 65 | else: |
| 66 | val_list = [ cvalue ] |
| 67 | |
| 68 | result = False |
| 69 | for value in val_list: |
| 70 | ctype = type(value) |
| 71 | if ctype == type(int()): |
| 72 | val = prop_value.as_uint32() |
| 73 | else: |
| 74 | raise TypeError('Unknown type %s' % ctype) |
| 75 | |
| 76 | if cop == '!': |
| 77 | if value != val: |
| 78 | result = True |
| 79 | else: |
| 80 | result = False |
| 81 | continue |
| 82 | |
| 83 | if cop == '=': |
| 84 | if value == val: |
| 85 | result = True |
| 86 | else: |
| 87 | result = False |
| 88 | continue |
| 89 | |
| 90 | if result == True: |
| 91 | TUNE_FEATURES.append(feature) |
| 92 | |
| 93 | return TUNE_FEATURES |
| 94 | |
| 95 | def microblazeVersion(fdt, node): |
| 96 | version = None |
| 97 | |
| 98 | val = fdt.getprop( node, 'model', libfdt.QUIET_NOTFOUND) |
| 99 | |
| 100 | if val and val != -1: |
| 101 | val = fdt.getprop( node, 'model' ).as_str() |
| 102 | version = val[val.find('microblaze,') + 11:] |
| 103 | |
| 104 | if version.startswith('8'): |
| 105 | # Strip 8.xx.y, to just 8.xx |
| 106 | v = version.split('.') |
| 107 | version = '.'.join(v[0:2]) |
| 108 | |
| 109 | version = 'v' + version |
| 110 | |
| 111 | return version |
| 112 | |
| 113 | def MicroblazeConfig(dtbfile, out): |
| 114 | fdt = libfdt.Fdt(open(dtbfile, mode='rb').read()) |
| 115 | |
| 116 | cpu = -1 |
| 117 | while (True): |
| 118 | cpu = cpu + 1 |
| 119 | try: |
| 120 | node = fdt.path_offset('/cpus/cpu@%d' % cpu) |
| 121 | |
| 122 | try: |
| 123 | prop = fdt.getprop( node, 'compatible' ) |
| 124 | |
| 125 | prop_val = prop[:-1].decode('utf-8').split('\x00') |
| 126 | |
| 127 | microblaze = False |
| 128 | for val in prop_val: |
| 129 | if "microblaze" in val: |
| 130 | microblaze = True |
| 131 | break |
| 132 | |
| 133 | if not microblaze: |
| 134 | continue |
| 135 | |
| 136 | # Construct TUNE_FEATURE here |
| 137 | TUNE_FEATURES = processProperties(fdt, node) |
| 138 | |
| 139 | out.write('AVAILTUNES += "microblaze-cpu%s"\n' % (cpu)) |
| 140 | out.write('TUNE_FEATURES_tune-microblaze-cpu%s = "%s"\n' % (cpu, ' '.join(TUNE_FEATURES))) |
| 141 | out.write('PACKAGE_EXTRA_ARCHS_tune-microblaze-cpu%s = "${TUNE_PKGARCH}"\n' % (cpu)) |
| 142 | |
| 143 | except Exception as e: |
| 144 | sys.stderr.write("Exception looking at properties: %s\n" % e) |
| 145 | |
| 146 | continue |
| 147 | |
| 148 | except Exception as e: |
| 149 | # CPUs SHOULD be consecutive w/o gaps, so no more to search |
| 150 | break |
| 151 | |
| 152 | if __name__ == "__main__": |
| 153 | parser = argparse.ArgumentParser(description='Generate MicroBlaze TUNE_FEATURES') |
| 154 | |
| 155 | parser.add_argument('-d', '--dtb-file', action='store', |
| 156 | help='DTB file to process') |
| 157 | |
| 158 | parser.add_argument('-o', '--output', action='store', |
| 159 | help='Output file to store TUNE_FEATURE settings') |
| 160 | |
| 161 | args = parser.parse_args() |
| 162 | |
| 163 | if not args.dtb_file: |
| 164 | sys.stderr.write('ERROR: You must specify a DTB_FILE to process.\n') |
| 165 | sys.exit(1) |
| 166 | |
| 167 | outputf = sys.stdout |
| 168 | if args.output: |
| 169 | if os.path.exists(args.output): |
| 170 | sys.stderr.write('ERROR: The output file "%s" exists!\n' % args.output) |
| 171 | sys.exit(1) |
| 172 | outputf = open(args.output, 'w') |
| 173 | |
| 174 | MicroblazeConfig(args.dtb_file, outputf) |