mesa/src/intel/dev/gen_wa_helpers.py

320 lines
12 KiB
Python

# Copyright © 2023 Intel Corporation
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
import argparse
import collections
import json
import os
import sys
from mako.template import Template
HEADER_TEMPLATE = Template("""\
/*
* Copyright © 2023 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
*/
#ifndef INTEL_WA_H
#define INTEL_WA_H
#include "util/macros.h"
#ifdef __cplusplus
extern "C" {
#endif
struct intel_device_info;
void intel_device_info_init_was(struct intel_device_info *devinfo);
enum intel_wa_steppings {
% for a in stepping_enum:
INTEL_STEPPING_${a},
% endfor
INTEL_STEPPING_RELEASE
};
enum intel_workaround_id {
% for a in wa_def:
INTEL_WA_${a},
% endfor
INTEL_WA_NUM
};
/* These defines are used to identify when a workaround potentially applies
* in genxml code. They should not be used directly. intel_needs_workaround()
* checks these definitions to eliminate bitset tests at compile time.
*/
% for a in wa_def:
#define INTEL_WA_${a}_GFX_VER ${wa_macro[a]}
% endfor
/* These defines are suitable for use to compile out genxml code using #if
* guards. Workarounds that apply to part of a generation must use a
* combination of run time checks and INTEL_WA_{NUM}_GFX_VER macros. Those
* workarounds are 'poisoned' below.
*/
% for a in partial_gens:
% if partial_gens[a]:
PRAGMA_POISON(INTEL_NEEDS_WA_${a})
% else:
#define INTEL_NEEDS_WA_${a} INTEL_WA_${a}_GFX_VER
% endif
% endfor
#define INTEL_ALL_WA ${"\\\\"}
% for wa_id in wa_def:
INTEL_WA(${wa_id}), ${"\\\\"}
% endfor
#ifdef __cplusplus
}
#endif
#endif /* INTEL_WA_H */
""")
IMPL_TEMPLATE = Template("""\
/*
* Copyright © 2023 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
*/
#include "dev/intel_wa.h"
#include "dev/intel_device_info.h"
#include "util/bitset.h"
void intel_device_info_init_was(struct intel_device_info *devinfo)
{
switch(devinfo->platform) {
% for platform in platform_bugs:
case ${platform}:
% if platform in stepping_bugs:
switch(intel_device_info_wa_stepping(devinfo)) {
% for stepping, ids in stepping_bugs[platform].items():
case INTEL_STEPPING_${stepping}:
% for id in ids:
BITSET_SET(devinfo->workarounds, INTEL_WA_${id});
% endfor
break;
% endfor
default:
break;
}
% endif
% for id in platform_bugs[platform]:
BITSET_SET(devinfo->workarounds, INTEL_WA_${id});
% endfor
break;
% endfor
default:
/* unsupported platform */
break;
};
}
""")
def stepping_enums(wa_def):
"""provide a sorted list of all known steppings"""
stepping_enum = []
for bug in wa_def.values():
for platform_info in bug["mesa_platforms"].values():
steppings = platform_info["steppings"]
if steppings == "all":
continue
steppings = steppings.split("..")
for stepping in steppings:
stepping = stepping.upper()
if stepping and stepping != "None" and stepping not in stepping_enum:
stepping_enum.append(stepping)
return sorted(stepping_enum)
_PLATFORM_GFXVERS = {"INTEL_PLATFORM_BDW" : 80,
"INTEL_PLATFORM_CHV" : 80,
"INTEL_PLATFORM_SKL" : 90,
"INTEL_PLATFORM_BXT" : 90,
"INTEL_PLATFORM_KBL" : 90,
"INTEL_PLATFORM_GLK" : 90,
"INTEL_PLATFORM_CFL" : 90,
"INTEL_PLATFORM_ICL" : 110,
"INTEL_PLATFORM_EHL" : 110,
"INTEL_PLATFORM_TGL" : 120,
"INTEL_PLATFORM_RKL" : 120,
"INTEL_PLATFORM_DG1" : 120,
"INTEL_PLATFORM_ADL" : 120,
"INTEL_PLATFORM_RPL" : 120,
"INTEL_PLATFORM_DG2_G10" : 125,
"INTEL_PLATFORM_DG2_G11" : 125,
"INTEL_PLATFORM_DG2_G12" : 125,
"INTEL_PLATFORM_MTL_M" : 125,
"INTEL_PLATFORM_MTL_P" : 125,
}
def macro_versions(wa_def):
"""provide a map of workaround id -> GFX_VERx10 macro test"""
wa_macro = {}
for bug_id, bug in wa_def.items():
platforms = set()
for platform in bug["mesa_platforms"]:
gfxver = _PLATFORM_GFXVERS[platform]
if gfxver not in platforms:
platforms.add(gfxver)
if not platforms:
continue
ver_cmps = [f"(GFX_VERx10 == {platform})" for platform in sorted(platforms)]
wa_macro[bug_id] = ver_cmps[0]
if len(ver_cmps) > 1:
wa_macro[bug_id] = f"({' || '.join(ver_cmps)})"
return wa_macro
def partial_gens(wa_def):
"""provide a map of workaround id -> true/false, indicating whether the wa
applies to a subset of platforms in a generation"""
wa_partial_gen = {}
# map of gfxver -> set(all platforms for gfxver)
generations = collections.defaultdict(set)
for platform, gfxver in _PLATFORM_GFXVERS.items():
generations[gfxver].add(platform)
# map of platform -> set(all required platforms for gen completeness)
required_platforms = collections.defaultdict(set)
for gen_set in generations.values():
for platform in gen_set:
required_platforms[platform] = gen_set
for bug_id, bug in wa_def.items():
# for the given wa, create a set which includes all platforms that
# match any of the affected gfxver.
wa_required_for_completeness = set()
for platform in bug["mesa_platforms"]:
wa_required_for_completeness.update(required_platforms[platform])
# eliminate each platform specifically indicated by the WA, to see if
# are left over.
for platform in bug["mesa_platforms"]:
wa_required_for_completeness.remove(platform)
# if any platform remains in the required set, then this wa *partially*
# applies to one of the gfxvers.
wa_partial_gen[bug_id] = bool(wa_required_for_completeness)
return wa_partial_gen
def platform_was(wa_def):
"""provide a map of platform -> list of workarounds"""
platform_bugs = collections.defaultdict(list)
for workaround, bug in wa_def.items():
for platform, desc in bug["mesa_platforms"].items():
if desc["steppings"] != "all":
# stepping-specific workaround, not platform-wide
continue
platform_bugs[platform].append(workaround)
return platform_bugs
def stepping_was(wa_def, all_steppings):
"""provide a map of wa[platform][stepping] -> [ids]"""
stepping_bugs = collections.defaultdict(lambda: collections.defaultdict(list))
for workaround, bug in wa_def.items():
for platform, desc in bug["mesa_platforms"].items():
if desc["steppings"] == "all":
continue
first_stepping, fixed_stepping = desc["steppings"].split("..")
first_stepping = first_stepping.upper()
fixed_stepping = fixed_stepping.upper()
steppings = []
for step in all_steppings:
if step <first_stepping:
continue
if step >= fixed_stepping:
break
steppings.append(step)
for step in steppings:
u_step = step.upper()
stepping_bugs[platform][u_step].append(workaround)
stepping_bugs[platform][u_step].sort()
return stepping_bugs
def main():
"""writes c/h generated files to outdir"""
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("wa_file", type=str,
help="json data file with workaround definitions")
parser.add_argument("header_file", help="include file to generate")
parser.add_argument("impl_file", help="implementation file to generate")
args = parser.parse_args()
if not os.path.exists(args.wa_file):
print(f"Error: workaround definition not found: {args.wa_file}")
sys.exit(-1)
# json dictionary of workaround definitions
wa_def = {}
with open(args.wa_file, encoding='utf8') as wa_fh:
wa_def = json.load(wa_fh)
steppings = stepping_enums(wa_def)
with open(args.header_file, 'w', encoding='utf8') as header:
header.write(HEADER_TEMPLATE.render(wa_def=wa_def,
stepping_enum=steppings,
wa_macro=macro_versions(wa_def),
partial_gens=partial_gens(wa_def)))
with open(args.impl_file, 'w', encoding='utf8') as impl:
impl.write(IMPL_TEMPLATE.render(platform_bugs=platform_was(wa_def),
stepping_bugs=stepping_was(wa_def, steppings)))
main()