ac/debug: take ASIC generation into account when printing registers

There were some overlapping changes in gfx9 especially in the CB/DB
blocks which made register dumps rather misleading.

The split is along the lines of the header files, so we'll print VI-only
fields on SI and CI, for example, but we won't print GFX9 fields on
SI/CI/VI, and we won't print SI/CI/VI fields on GFX9.

Acked-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
Nicolai Hähnle
2017-09-04 11:05:13 +02:00
parent 274f1dace7
commit 552aaa11ed
2 changed files with 174 additions and 104 deletions

View File

@@ -101,16 +101,32 @@ static void print_named_value(FILE *file, const char *name, uint32_t value,
print_value(file, value, bits);
}
static const struct si_reg *find_register(const struct si_reg *table,
unsigned table_size,
unsigned offset)
{
for (unsigned i = 0; i < table_size; i++) {
const struct si_reg *reg = &table[i];
if (reg->offset == offset)
return reg;
}
return NULL;
}
void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
uint32_t value, uint32_t field_mask)
{
int r, f;
const struct si_reg *reg = NULL;
for (r = 0; r < ARRAY_SIZE(sid_reg_table); r++) {
const struct si_reg *reg = &sid_reg_table[r];
if (chip_class >= GFX9)
reg = find_register(gfx9d_reg_table, ARRAY_SIZE(gfx9d_reg_table), offset);
if (!reg)
reg = find_register(sid_reg_table, ARRAY_SIZE(sid_reg_table), offset);
if (reg) {
const char *reg_name = sid_strings + reg->name_offset;
if (reg->offset == offset) {
bool first_field = true;
print_spaces(file, INDENT_PKT);
@@ -122,7 +138,7 @@ void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
return;
}
for (f = 0; f < reg->num_fields; f++) {
for (unsigned f = 0; f < reg->num_fields; f++) {
const struct si_field *field = sid_fields_table + reg->fields_offset + f;
const int *values_offsets = sid_strings_offsets + field->values_offset;
uint32_t val = (value & field->mask) >>
@@ -149,7 +165,6 @@ void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
}
return;
}
}
print_spaces(file, INDENT_PKT);
fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value);

View File

@@ -27,8 +27,10 @@ CopyRight = '''
import collections
import functools
import sys
import itertools
import os.path
import re
import sys
class StringTable:
@@ -217,15 +219,37 @@ class Reg:
self.name = strip_prefix(r_name)
self.fields = []
def __eq__(self, other):
if not isinstance(other, Reg):
return False
return (self.r_name == other.r_name and
self.name == other.name and
len(self.fields) == len(other.fields) and
all(a == b for a, b in zip(self.fields, other.fields)))
def __ne__(self, other):
return not (self == other)
def strip_prefix(s):
'''Strip prefix in the form ._.*_, e.g. R_001234_'''
return s[s[2:].find('_')+3:]
def parse(filename, regs, packets):
stream = open(filename)
for line in stream:
class Asic:
"""
Store the registers of one ASIC class / group of classes.
"""
def __init__(self, name):
self.name = name
self.registers = []
def parse(self, filp, packets, older_asics):
"""
Parse registers from the given header file. Packets are separately
stored in the packets array.
"""
for line in filp:
if not line.startswith('#define '):
continue
@@ -234,21 +258,19 @@ def parse(filename, regs, packets):
if line.startswith('R_'):
name = line.split()[0]
for it in regs:
for it in self.registers:
if it.r_name == name:
reg = it
break
sys.exit('Duplicate register define: %s' % (name))
else:
reg = Reg(name)
regs.append(reg)
self.registers.append(reg)
elif line.startswith('S_'):
name = line[:line.find('(')]
for it in reg.fields:
if it.s_name == name:
field = it
break
sys.exit('Duplicate field define: %s' % (name))
else:
field = Field(reg, name)
reg.fields.append(field)
@@ -260,14 +282,33 @@ def parse(filename, regs, packets):
for (n,v) in field.values:
if n == name:
if v != value:
sys.exit('Value mismatch: name = ' + name)
sys.exit('Duplicate value define: name = ' + name)
field.values.append((name, value))
elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
packets.append(line.split()[0])
# Copy values for corresponding fields from older ASICs if they were
# not redefined
for reg in self.registers:
old_reg = False
for field in reg.fields:
if len(field.values) > 0:
continue
if old_reg is False:
for old_reg in itertools.chain(
*(asic.registers for asic in reversed(older_asics))):
if old_reg.name == reg.name:
break
else:
old_reg = None
if old_reg is not None:
for old_field in old_reg.fields:
if old_field.name == field.name:
field.values = old_field.values
break
# Copy fields to indexed registers which have their fields only defined
# at register index 0.
# For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.
@@ -275,20 +316,19 @@ def parse(filename, regs, packets):
reg_dict = dict()
# Create a dict of registers with fields and '0' in their name
for reg in regs:
for reg in self.registers:
if len(reg.fields) and reg.name.find('0') != -1:
reg_dict[reg.name] = reg
# Assign fields
for reg in regs:
for reg in self.registers:
if not len(reg.fields):
reg0 = reg_dict.get(match_number.sub('0', reg.name))
if reg0 != None:
reg.fields = reg0.fields
def write_tables(regs, packets):
def write_tables(asics, packets):
strings = StringTable()
strings_offsets = IntTable("int")
fields = FieldTable()
@@ -326,13 +366,23 @@ struct si_packet3 {
print '};'
print
print 'static const struct si_reg sid_reg_table[] = {'
for reg in regs:
regs = {}
for asic in asics:
print 'static const struct si_reg %s_reg_table[] = {' % (asic.name)
for reg in asic.registers:
# Only output a register that was changed or added relative to
# the previous generation
previous = regs.get(reg.r_name, None)
if previous == reg:
continue
if len(reg.fields):
print '\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name,
len(reg.fields), fields.add(reg.fields))
else:
print '\t{%s, %s},' % (strings.add(reg.name), reg.r_name)
regs[reg.r_name] = reg
print '};'
print
@@ -351,11 +401,16 @@ struct si_packet3 {
def main():
regs = []
asics = []
packets = []
for arg in sys.argv[1:]:
parse(arg, regs, packets)
write_tables(regs, packets)
basename = os.path.basename(arg)
m = re.match(r'(.*)\.h', basename)
asic = Asic(m.group(1))
with open(arg) as filp:
asic.parse(filp, packets, asics)
asics.append(asic)
write_tables(asics, packets)
if __name__ == '__main__':