diff options
author | Mark Hatle <mark.hatle@xilinx.com> | 2020-03-09 18:39:50 +0000 |
---|---|---|
committer | Mark Hatle <mark.hatle@xilinx.com> | 2020-03-09 20:13:10 +0000 |
commit | e72a682cfb7d353ebb10b4afa365809b5bd2dd05 (patch) | |
tree | 5583aa37551072f3330d7823f4a9bafd0b63fd7f | |
parent | dcd6396033568f3d733a8d02d417e6cf83a934c0 (diff) | |
download | meta-xilinx-e72a682cfb7d353ebb10b4afa365809b5bd2dd05.tar.gz |
microblaze_dtb.py: Convert a dtb to one or more microblaze TUNE_FEATURES
Because the microblaze is adjustable on the FPGA, we need a way for
the system to adjust the TUNE_FEATURES for a given build. The
device tree can specify the capabilities of the microblaze
implementations defined in a specific design. If present, these can
then be processed to provide a set of TUNE_FEATURES for each declared
microblaze CPU.
The output of the tool is formated in a way that it can be directly
included in the user's local.conf, or placed in a file that is included
by a machine or other file. The user will only have to declare the
DEFAULTTUNE value that matches one of the generated tunes.
General rules that are implemented:
TUNE_FEATURE CONDITION
------------ -------------------------------
microblaze (all microblaze cpus)
bigendian xlnx,endianness is not 1
64-bit xlnx,data-size is 64
barrel-shift xlnx,use-barrel is 1
pattern-compare xlnx,use-pcmp-instr is 1
reorder xlnx,use-reorder-instr is not 0
frequency-optimized xlnx,area-optimized is 2
multiply-low xlnx,use-hw-mul is 1
multiple-high xlnx,use-hw-mul is 2
divide-hard xlnx,use-div is 1
fpu-soft xlnx,use-fpu is not 1 or 2
fpu-hard xlnx,use-fpu is 1
fpu-hard-extended xlnx,use-fpu is 2
vX.YY model value of X.YY[.Z]
Signed-off-by: Mark Hatle <mark.hatle@xilinx.com>
-rw-r--r-- | meta-xilinx-standalone/microblaze_dtb.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/meta-xilinx-standalone/microblaze_dtb.py b/meta-xilinx-standalone/microblaze_dtb.py new file mode 100644 index 00000000..aba72497 --- /dev/null +++ b/meta-xilinx-standalone/microblaze_dtb.py | |||
@@ -0,0 +1,174 @@ | |||
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) | ||