freedreno: Split up freedreno_devices.py

Split up the data and code parts.

Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40283>
This commit is contained in:
Rob Clark 2026-03-07 08:26:18 -08:00 committed by Marge Bot
parent cd1770a077
commit fa90c2de03
2 changed files with 266 additions and 260 deletions

View file

@ -0,0 +1,263 @@
#
# Copyright © 2021 Google, Inc.
#
# SPDX-License-Identifier: MIT
from mako.template import Template
import sys
import argparse
from enum import Enum
def max_bitfield_val(high, low, shift):
return ((1 << (high - low)) - 1) << shift
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--import-path', required=True)
args = parser.parse_args()
sys.path.insert(0, args.import_path)
from a6xx import *
class CHIP(Enum):
A2XX = 2
A3XX = 3
A4XX = 4
A5XX = 5
A6XX = 6
A7XX = 7
A8XX = 8
class CCUColorCacheFraction(Enum):
FULL = 0
HALF = 1
QUARTER = 2
EIGHTH = 3
THREE_QUARTER = 3 # a8xx_gen2 and later
class State(object):
def __init__(self):
# List of unique device-info structs, multiple different GPU ids
# can map to a single info struct in cases where the differences
# are not sw visible, or the only differences are parameters
# queried from the kernel (like GMEM size)
self.gpu_infos = []
# Table mapping GPU id to device-info struct
self.gpus = {}
def info_index(self, gpu_info):
i = 0
for info in self.gpu_infos:
if gpu_info == info:
return i
i += 1
raise Error("invalid info")
s = State()
def add_gpus(ids, info):
for id in ids:
s.gpus[id] = info
class GPUId(object):
def __init__(self, gpu_id = None, chip_id = None, name=None):
if chip_id is None:
assert(gpu_id is not None)
val = gpu_id
core = int(val / 100)
val -= (core * 100)
major = int(val / 10)
val -= (major * 10)
minor = val
chip_id = (core << 24) | (major << 16) | (minor << 8) | 0xff
self.chip_id = chip_id
if gpu_id is None:
gpu_id = 0
self.gpu_id = gpu_id
if name is None:
assert(gpu_id != 0)
name = "FD%d" % gpu_id
self.name = name
class Struct(object):
"""A helper class that stringifies itself to a 'C' struct initializer
"""
def __str__(self):
s = "{"
for name, value in vars(self).items():
s += "." + name + "=" + str(value) + ","
return s + "}"
class GPUInfo(Struct):
"""Base class for any generation of adreno, consists of GMEM layout
related parameters
Note that tile_max_h is normally only constrained by corresponding
bitfield size/shift (ie. VSC_BIN_SIZE, or similar), but tile_max_h
tends to have lower limits, in which case a comment will describe
the bitfield size/shift
"""
def __init__(self, chip, gmem_align_w, gmem_align_h,
tile_align_w, tile_align_h,
tile_max_w, tile_max_h, num_vsc_pipes,
cs_shared_mem_size, num_sp_cores, wave_granularity, fibers_per_sp,
highest_bank_bit = 0, ubwc_swizzle = 0x7, macrotile_mode = 0,
threadsize_base = 64, max_waves = 16, compute_lb_size = 0):
self.chip = chip.value
self.gmem_align_w = gmem_align_w
self.gmem_align_h = gmem_align_h
self.tile_align_w = tile_align_w
self.tile_align_h = tile_align_h
self.tile_max_w = tile_max_w
self.tile_max_h = tile_max_h
self.num_vsc_pipes = num_vsc_pipes
self.cs_shared_mem_size = cs_shared_mem_size
self.num_sp_cores = num_sp_cores
self.wave_granularity = wave_granularity
self.fibers_per_sp = fibers_per_sp
self.threadsize_base = threadsize_base
self.max_waves = max_waves
self.highest_bank_bit = highest_bank_bit
self.ubwc_swizzle = ubwc_swizzle
self.macrotile_mode = macrotile_mode
s.gpu_infos.append(self)
class A6xxGPUInfo(GPUInfo):
"""The a6xx generation has a lot more parameters, and is broken down
into distinct sub-generations. The template parameter avoids
duplication of parameters that are unique to the sub-generation.
"""
def __init__(self, chip, template, num_ccu,
tile_align_w, tile_align_h, tile_max_w, tile_max_h, num_vsc_pipes,
cs_shared_mem_size, wave_granularity, fibers_per_sp,
magic_regs, raw_magic_regs = None, highest_bank_bit = 15,
ubwc_swizzle = 0x6, macrotile_mode = 1,
threadsize_base = 64, max_waves = 16, num_slices = 0):
if chip == CHIP.A6XX:
compute_lb_size = 0
else:
# on a7xx the compute_lb_size is 40KB for all known parts for now.
# We have a parameter for it in case some low-end parts cut it down.
compute_lb_size = 40 * 1024
super().__init__(chip, gmem_align_w = 16, gmem_align_h = 4,
tile_align_w = tile_align_w,
tile_align_h = tile_align_h,
tile_max_w = tile_max_w,
tile_max_h = tile_max_h,
num_vsc_pipes = num_vsc_pipes,
cs_shared_mem_size = cs_shared_mem_size,
num_sp_cores = num_ccu, # The # of SP cores seems to always match # of CCU
wave_granularity = wave_granularity,
fibers_per_sp = fibers_per_sp,
highest_bank_bit = highest_bank_bit,
ubwc_swizzle = ubwc_swizzle,
macrotile_mode = macrotile_mode,
threadsize_base = threadsize_base,
max_waves = max_waves,
compute_lb_size = compute_lb_size)
self.num_ccu = num_ccu
self.num_slices = num_slices
self.props = Struct()
self.magic = Struct()
for name, val in magic_regs.items():
setattr(self.magic, name, val)
if raw_magic_regs:
self.magic_raw = [[int(r[0]), r[1]] for r in raw_magic_regs]
templates = template if isinstance(template, list) else [template]
for template in templates:
template.apply_props(self)
def __str__(self):
return super(A6xxGPUInfo, self).__str__().replace('[', '{').replace("]", "}")
class GPUProps(dict):
unique_props = dict()
def apply_props(self, gpu_info):
for name, val in self.items():
setattr(getattr(gpu_info, "props"), name, val)
GPUProps.unique_props[(name, "props")] = val
template = """\
/* Copyright © 2021 Google, Inc.
*
* SPDX-License-Identifier: MIT
*/
#include "freedreno_dev_info.h"
#include "util/u_debug.h"
#include "util/log.h"
#include <stdlib.h>
/* Map python to C: */
#define True true
#define False false
%for info in s.gpu_infos:
static const struct fd_dev_info __info${s.info_index(info)} = ${str(info)};
%endfor
static const struct fd_dev_rec fd_dev_recs[] = {
%for id, info in s.gpus.items():
{ {${id.gpu_id}, ${hex(id.chip_id)}}, "${id.name}", &__info${s.info_index(info)} },
%endfor
};
void
fd_dev_info_apply_dbg_options(struct fd_dev_info *info)
{
const char *env = debug_get_option("FD_DEV_FEATURES", NULL);
if (!env || !*env)
return;
char *features = strdup(env);
char *feature, *feature_end;
feature = strtok_r(features, ":", &feature_end);
while (feature != NULL) {
char *name, *name_end;
name = strtok_r(feature, "=", &name_end);
if (!name) {
mesa_loge("Invalid feature \\"%s\\" in FD_DEV_FEATURES", feature);
exit(1);
}
char *value = strtok_r(NULL, "=", &name_end);
feature = strtok_r(NULL, ":", &feature_end);
%for (prop, gen), val in unique_props.items():
<%
if isinstance(val, bool):
parse_value = "debug_parse_bool_option"
else:
parse_value = "debug_parse_num_option"
%>
if (strcmp(name, "${prop}") == 0) {
info->${gen}.${prop} = ${parse_value}(value, info->${gen}.${prop});
continue;
}
%endfor
mesa_loge("Invalid feature \\"%s\\" in FD_DEV_FEATURES", name);
exit(1);
}
free(features);
}
"""
def main():
print(Template(template).render(s=s, unique_props=GPUProps.unique_props))

View file

@ -3,186 +3,7 @@
#
# SPDX-License-Identifier: MIT
from mako.template import Template
import sys
import argparse
from enum import Enum
def max_bitfield_val(high, low, shift):
return ((1 << (high - low)) - 1) << shift
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--import-path', required=True)
args = parser.parse_args()
sys.path.insert(0, args.import_path)
from a6xx import *
class CHIP(Enum):
A2XX = 2
A3XX = 3
A4XX = 4
A5XX = 5
A6XX = 6
A7XX = 7
A8XX = 8
class CCUColorCacheFraction(Enum):
FULL = 0
HALF = 1
QUARTER = 2
EIGHTH = 3
THREE_QUARTER = 3 # a8xx_gen2 and later
class State(object):
def __init__(self):
# List of unique device-info structs, multiple different GPU ids
# can map to a single info struct in cases where the differences
# are not sw visible, or the only differences are parameters
# queried from the kernel (like GMEM size)
self.gpu_infos = []
# Table mapping GPU id to device-info struct
self.gpus = {}
def info_index(self, gpu_info):
i = 0
for info in self.gpu_infos:
if gpu_info == info:
return i
i += 1
raise Error("invalid info")
s = State()
def add_gpus(ids, info):
for id in ids:
s.gpus[id] = info
class GPUId(object):
def __init__(self, gpu_id = None, chip_id = None, name=None):
if chip_id is None:
assert(gpu_id is not None)
val = gpu_id
core = int(val / 100)
val -= (core * 100)
major = int(val / 10)
val -= (major * 10)
minor = val
chip_id = (core << 24) | (major << 16) | (minor << 8) | 0xff
self.chip_id = chip_id
if gpu_id is None:
gpu_id = 0
self.gpu_id = gpu_id
if name is None:
assert(gpu_id != 0)
name = "FD%d" % gpu_id
self.name = name
class Struct(object):
"""A helper class that stringifies itself to a 'C' struct initializer
"""
def __str__(self):
s = "{"
for name, value in vars(self).items():
s += "." + name + "=" + str(value) + ","
return s + "}"
class GPUInfo(Struct):
"""Base class for any generation of adreno, consists of GMEM layout
related parameters
Note that tile_max_h is normally only constrained by corresponding
bitfield size/shift (ie. VSC_BIN_SIZE, or similar), but tile_max_h
tends to have lower limits, in which case a comment will describe
the bitfield size/shift
"""
def __init__(self, chip, gmem_align_w, gmem_align_h,
tile_align_w, tile_align_h,
tile_max_w, tile_max_h, num_vsc_pipes,
cs_shared_mem_size, num_sp_cores, wave_granularity, fibers_per_sp,
highest_bank_bit = 0, ubwc_swizzle = 0x7, macrotile_mode = 0,
threadsize_base = 64, max_waves = 16, compute_lb_size = 0):
self.chip = chip.value
self.gmem_align_w = gmem_align_w
self.gmem_align_h = gmem_align_h
self.tile_align_w = tile_align_w
self.tile_align_h = tile_align_h
self.tile_max_w = tile_max_w
self.tile_max_h = tile_max_h
self.num_vsc_pipes = num_vsc_pipes
self.cs_shared_mem_size = cs_shared_mem_size
self.num_sp_cores = num_sp_cores
self.wave_granularity = wave_granularity
self.fibers_per_sp = fibers_per_sp
self.threadsize_base = threadsize_base
self.max_waves = max_waves
self.highest_bank_bit = highest_bank_bit
self.ubwc_swizzle = ubwc_swizzle
self.macrotile_mode = macrotile_mode
s.gpu_infos.append(self)
class A6xxGPUInfo(GPUInfo):
"""The a6xx generation has a lot more parameters, and is broken down
into distinct sub-generations. The template parameter avoids
duplication of parameters that are unique to the sub-generation.
"""
def __init__(self, chip, template, num_ccu,
tile_align_w, tile_align_h, tile_max_w, tile_max_h, num_vsc_pipes,
cs_shared_mem_size, wave_granularity, fibers_per_sp,
magic_regs, raw_magic_regs = None, highest_bank_bit = 15,
ubwc_swizzle = 0x6, macrotile_mode = 1,
threadsize_base = 64, max_waves = 16, num_slices = 0):
if chip == CHIP.A6XX:
compute_lb_size = 0
else:
# on a7xx the compute_lb_size is 40KB for all known parts for now.
# We have a parameter for it in case some low-end parts cut it down.
compute_lb_size = 40 * 1024
super().__init__(chip, gmem_align_w = 16, gmem_align_h = 4,
tile_align_w = tile_align_w,
tile_align_h = tile_align_h,
tile_max_w = tile_max_w,
tile_max_h = tile_max_h,
num_vsc_pipes = num_vsc_pipes,
cs_shared_mem_size = cs_shared_mem_size,
num_sp_cores = num_ccu, # The # of SP cores seems to always match # of CCU
wave_granularity = wave_granularity,
fibers_per_sp = fibers_per_sp,
highest_bank_bit = highest_bank_bit,
ubwc_swizzle = ubwc_swizzle,
macrotile_mode = macrotile_mode,
threadsize_base = threadsize_base,
max_waves = max_waves,
compute_lb_size = compute_lb_size)
self.num_ccu = num_ccu
self.num_slices = num_slices
self.props = Struct()
self.magic = Struct()
for name, val in magic_regs.items():
setattr(self.magic, name, val)
if raw_magic_regs:
self.magic_raw = [[int(r[0]), r[1]] for r in raw_magic_regs]
templates = template if isinstance(template, list) else [template]
for template in templates:
template.apply_props(self)
def __str__(self):
return super(A6xxGPUInfo, self).__str__().replace('[', '{').replace("]", "}")
from freedreno_dev_info import *
# a2xx is really two sub-generations, a20x and a22x, but we don't currently
# capture that in the device-info tables
@ -300,14 +121,6 @@ add_gpus([
threadsize_base = 32,
))
class GPUProps(dict):
unique_props = dict()
def apply_props(self, gpu_info):
for name, val in self.items():
setattr(getattr(gpu_info, "props"), name, val)
GPUProps.unique_props[(name, "props")] = val
# Props could be modified with env var:
# FD_DEV_FEATURES=%feature_name%=%value%:%feature_name%=%value%:...
# e.g.
@ -1572,75 +1385,5 @@ add_gpus([
raw_magic_regs = a8xx_base_raw_magic_regs,
))
template = """\
/* Copyright © 2021 Google, Inc.
*
* SPDX-License-Identifier: MIT
*/
#include "freedreno_dev_info.h"
#include "util/u_debug.h"
#include "util/log.h"
#include <stdlib.h>
/* Map python to C: */
#define True true
#define False false
%for info in s.gpu_infos:
static const struct fd_dev_info __info${s.info_index(info)} = ${str(info)};
%endfor
static const struct fd_dev_rec fd_dev_recs[] = {
%for id, info in s.gpus.items():
{ {${id.gpu_id}, ${hex(id.chip_id)}}, "${id.name}", &__info${s.info_index(info)} },
%endfor
};
void
fd_dev_info_apply_dbg_options(struct fd_dev_info *info)
{
const char *env = debug_get_option("FD_DEV_FEATURES", NULL);
if (!env || !*env)
return;
char *features = strdup(env);
char *feature, *feature_end;
feature = strtok_r(features, ":", &feature_end);
while (feature != NULL) {
char *name, *name_end;
name = strtok_r(feature, "=", &name_end);
if (!name) {
mesa_loge("Invalid feature \\"%s\\" in FD_DEV_FEATURES", feature);
exit(1);
}
char *value = strtok_r(NULL, "=", &name_end);
feature = strtok_r(NULL, ":", &feature_end);
%for (prop, gen), val in unique_props.items():
<%
if isinstance(val, bool):
parse_value = "debug_parse_bool_option"
else:
parse_value = "debug_parse_num_option"
%>
if (strcmp(name, "${prop}") == 0) {
info->${gen}.${prop} = ${parse_value}(value, info->${gen}.${prop});
continue;
}
%endfor
mesa_loge("Invalid feature \\"%s\\" in FD_DEV_FEATURES", name);
exit(1);
}
free(features);
}
"""
print(Template(template).render(s=s, unique_props=GPUProps.unique_props))
if __name__ == "__main__":
main()