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