1# Copyright © 2023 Intel Corporation 2 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the "Software"), 5# to deal in the Software without restriction, including without limitation 6# the rights to use, copy, modify, merge, publish, distribute, sublicense, 7# and/or sell copies of the Software, and to permit persons to whom the 8# Software is furnished to do so, subject to the following conditions: 9 10# The above copyright notice and this permission notice (including the next 11# paragraph) shall be included in all copies or substantial portions of the 12# Software. 13 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21 22import argparse 23import collections 24import json 25import os 26import sys 27from mako.template import Template 28 29HEADER_TEMPLATE = Template("""\ 30/* 31 * Copyright © 2023 Intel Corporation 32 * 33 * Permission is hereby granted, free of charge, to any person obtaining a 34 * copy of this software and associated documentation files (the "Software"), 35 * to deal in the Software without restriction, including without limitation 36 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 37 * and/or sell copies of the Software, and to permit persons to whom the 38 * Software is furnished to do so, subject to the following conditions: 39 * 40 * The above copyright notice and this permission notice (including the next 41 * paragraph) shall be included in all copies or substantial portions of the 42 * Software. 43 * 44 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 47 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 49 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 50 * IN THE SOFTWARE. 51 * 52 */ 53 54#ifndef INTEL_WA_H 55#define INTEL_WA_H 56 57#include "util/macros.h" 58 59#ifdef __cplusplus 60extern "C" { 61#endif 62 63struct intel_device_info; 64void intel_device_info_init_was(struct intel_device_info *devinfo); 65 66enum intel_wa_steppings { 67% for a in stepping_enum: 68 INTEL_STEPPING_${a}, 69% endfor 70 INTEL_STEPPING_RELEASE 71}; 72 73enum intel_workaround_id { 74% for a in wa_def: 75 INTEL_WA_${a}, 76% endfor 77 INTEL_WA_NUM 78}; 79 80/* These defines apply workarounds to a subset of platforms within a graphics 81 * generation. They must be used in conjunction with intel_needs_workaround() 82 * to check platform details. Use these macros to compile out genxml code on 83 * generations where it can never execute. Whenever possible, prefer use of 84 * INTEL_NEEDS_WA_{num} instead of INTEL_WA_{num}_GFX_VER 85 */ 86% for a in wa_def: 87#define INTEL_WA_${a}_GFX_VER ${wa_macro[a]} 88% endfor 89 90/* These defines may be used to compile out genxml workaround implementations 91 * using #if guards. If a definition has been 'poisoned' below, then it applies to a 92 * subset of a graphics generation. In that case, use INTEL_WA_{NUM}_GFX_VER macros 93 * in conjunction with calls to intel_needs_workaround(). 94 */ 95% for a in partial_gens: 96 % if partial_gens[a]: 97PRAGMA_POISON(INTEL_NEEDS_WA_${a}) 98 % else: 99#define INTEL_NEEDS_WA_${a} INTEL_WA_${a}_GFX_VER 100 % endif 101% endfor 102 103#define INTEL_ALL_WA ${"\\\\"} 104% for wa_id in wa_def: 105 INTEL_WA(${wa_id}), ${"\\\\"} 106% endfor 107 108#ifdef __cplusplus 109} 110#endif 111 112#endif /* INTEL_WA_H */ 113""") 114 115IMPL_TEMPLATE = Template("""\ 116/* 117 * Copyright © 2023 Intel Corporation 118 * 119 * Permission is hereby granted, free of charge, to any person obtaining a 120 * copy of this software and associated documentation files (the "Software"), 121 * to deal in the Software without restriction, including without limitation 122 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 123 * and/or sell copies of the Software, and to permit persons to whom the 124 * Software is furnished to do so, subject to the following conditions: 125 * 126 * The above copyright notice and this permission notice (including the next 127 * paragraph) shall be included in all copies or substantial portions of the 128 * Software. 129 * 130 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 131 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 132 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 133 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 134 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 135 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 136 * IN THE SOFTWARE. 137 * 138 */ 139 140#include "dev/intel_wa.h" 141#include "dev/intel_device_info.h" 142#include "util/bitset.h" 143 144void intel_device_info_init_was(struct intel_device_info *devinfo) 145{ 146 switch(devinfo->platform) { 147% for platform in platform_bugs: 148 case ${platform}: 149% if platform in stepping_bugs: 150 switch(intel_device_info_wa_stepping(devinfo)) { 151% for stepping, ids in stepping_bugs[platform].items(): 152 case INTEL_STEPPING_${stepping}: 153% for id in ids: 154 BITSET_SET(devinfo->workarounds, INTEL_WA_${id}); 155% endfor 156 break; 157% endfor 158 default: 159 break; 160 } 161% endif 162% for id in platform_bugs[platform]: 163 BITSET_SET(devinfo->workarounds, INTEL_WA_${id}); 164% endfor 165 break; 166% endfor 167 default: 168 /* unsupported platform */ 169 break; 170 }; 171} 172""") 173 174def stepping_enums(wa_def): 175 """provide a sorted list of all known steppings""" 176 stepping_enum = [] 177 for bug in wa_def.values(): 178 for platform_info in bug["mesa_platforms"].values(): 179 steppings = platform_info["steppings"] 180 if steppings == "all": 181 continue 182 steppings = steppings.split("..") 183 for stepping in steppings: 184 stepping = stepping.upper() 185 if stepping and stepping != "None" and stepping not in stepping_enum: 186 stepping_enum.append(stepping) 187 return sorted(stepping_enum) 188 189_PLATFORM_GFXVERS = {"INTEL_PLATFORM_BDW" : 80, 190 "INTEL_PLATFORM_CHV" : 80, 191 "INTEL_PLATFORM_SKL" : 90, 192 "INTEL_PLATFORM_BXT" : 90, 193 "INTEL_PLATFORM_KBL" : 90, 194 "INTEL_PLATFORM_GLK" : 90, 195 "INTEL_PLATFORM_CFL" : 90, 196 "INTEL_PLATFORM_ICL" : 110, 197 "INTEL_PLATFORM_EHL" : 110, 198 "INTEL_PLATFORM_TGL" : 120, 199 "INTEL_PLATFORM_RKL" : 120, 200 "INTEL_PLATFORM_DG1" : 120, 201 "INTEL_PLATFORM_ADL" : 120, 202 "INTEL_PLATFORM_RPL" : 120, 203 "INTEL_PLATFORM_DG2_G10" : 125, 204 "INTEL_PLATFORM_DG2_G11" : 125, 205 "INTEL_PLATFORM_DG2_G12" : 125, 206 "INTEL_PLATFORM_MTL_U" : 125, 207 "INTEL_PLATFORM_MTL_H" : 125, 208 "INTEL_PLATFORM_ARL_U" : 125, 209 "INTEL_PLATFORM_ARL_H" : 125, 210 } 211 212def macro_versions(wa_def): 213 """provide a map of workaround id -> GFX_VERx10 macro test""" 214 wa_macro = {} 215 for bug_id, bug in wa_def.items(): 216 platforms = set() 217 for platform in bug["mesa_platforms"]: 218 gfxver = _PLATFORM_GFXVERS[platform] 219 if gfxver not in platforms: 220 platforms.add(gfxver) 221 if not platforms: 222 continue 223 ver_cmps = [f"(GFX_VERx10 == {platform})" for platform in sorted(platforms)] 224 wa_macro[bug_id] = ver_cmps[0] 225 if len(ver_cmps) > 1: 226 wa_macro[bug_id] = f"({' || '.join(ver_cmps)})" 227 return wa_macro 228 229def partial_gens(wa_def): 230 """provide a map of workaround id -> true/false, indicating whether the wa 231 applies to a subset of platforms in a generation""" 232 wa_partial_gen = {} 233 234 # map of gfxver -> set(all platforms for gfxver) 235 generations = collections.defaultdict(set) 236 for platform, gfxver in _PLATFORM_GFXVERS.items(): 237 generations[gfxver].add(platform) 238 239 # map of platform -> set(all required platforms for gen completeness) 240 required_platforms = collections.defaultdict(set) 241 for gen_set in generations.values(): 242 for platform in gen_set: 243 required_platforms[platform] = gen_set 244 245 for bug_id, bug in wa_def.items(): 246 # for the given wa, create a set which includes all platforms that 247 # match any of the affected gfxver. 248 wa_required_for_completeness = set() 249 for platform in bug["mesa_platforms"]: 250 wa_required_for_completeness.update(required_platforms[platform]) 251 252 # eliminate each platform specifically indicated by the WA, to see if 253 # are left over. 254 for platform, desc in bug["mesa_platforms"].items(): 255 if desc["steppings"] == "all": 256 wa_required_for_completeness.remove(platform) 257 258 # if any platform remains in the required set, then this wa *partially* 259 # applies to one of the gfxvers. 260 wa_partial_gen[bug_id] = bool(wa_required_for_completeness) 261 return wa_partial_gen 262 263def platform_was(wa_def): 264 """provide a map of platform -> list of workarounds""" 265 platform_bugs = collections.defaultdict(list) 266 for workaround, bug in wa_def.items(): 267 for platform, desc in bug["mesa_platforms"].items(): 268 if desc["steppings"] != "all": 269 # stepping-specific workaround, not platform-wide 270 continue 271 platform_bugs[platform].append(workaround) 272 return platform_bugs 273 274def stepping_was(wa_def, all_steppings): 275 """provide a map of wa[platform][stepping] -> [ids]""" 276 stepping_bugs = collections.defaultdict(lambda: collections.defaultdict(list)) 277 for workaround, bug in wa_def.items(): 278 for platform, desc in bug["mesa_platforms"].items(): 279 if desc["steppings"] == "all": 280 continue 281 first_stepping, fixed_stepping = desc["steppings"].split("..") 282 first_stepping = first_stepping.upper() 283 fixed_stepping = fixed_stepping.upper() 284 steppings = [] 285 for step in all_steppings: 286 if step <first_stepping: 287 continue 288 if step >= fixed_stepping: 289 break 290 steppings.append(step) 291 for step in steppings: 292 u_step = step.upper() 293 stepping_bugs[platform][u_step].append(workaround) 294 stepping_bugs[platform][u_step].sort() 295 return stepping_bugs 296 297def main(): 298 """writes c/h generated files to outdir""" 299 parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) 300 parser.add_argument("wa_file", type=str, 301 help="json data file with workaround definitions") 302 parser.add_argument("header_file", help="include file to generate") 303 parser.add_argument("impl_file", help="implementation file to generate") 304 args = parser.parse_args() 305 if not os.path.exists(args.wa_file): 306 print(f"Error: workaround definition not found: {args.wa_file}") 307 sys.exit(-1) 308 309 # json dictionary of workaround definitions 310 wa_def = {} 311 with open(args.wa_file, encoding='utf8') as wa_fh: 312 wa_def = json.load(wa_fh) 313 314 # detect unknown platforms 315 unknown_platforms = set() 316 for wa in wa_def.values(): 317 for p in wa['mesa_platforms']: 318 if p not in _PLATFORM_GFXVERS: 319 unknown_platforms.add(p) 320 if unknown_platforms: 321 abbrev = map(lambda s: s.replace('INTEL_PLATFORM_', ''), 322 unknown_platforms) 323 raise Exception(f'warning: unknown platforms in {args.wa_file}: ' 324 f'{", ".join(abbrev)}') 325 326 steppings = stepping_enums(wa_def) 327 with open(args.header_file, 'w', encoding='utf8') as header: 328 header.write(HEADER_TEMPLATE.render(wa_def=wa_def, 329 stepping_enum=steppings, 330 wa_macro=macro_versions(wa_def), 331 partial_gens=partial_gens(wa_def))) 332 with open(args.impl_file, 'w', encoding='utf8') as impl: 333 impl.write(IMPL_TEMPLATE.render(platform_bugs=platform_was(wa_def), 334 stepping_bugs=stepping_was(wa_def, steppings))) 335 336main() 337