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:
@@ -101,16 +101,32 @@ static void print_named_value(FILE *file, const char *name, uint32_t value,
|
|||||||
print_value(file, value, bits);
|
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,
|
void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
|
||||||
uint32_t value, uint32_t field_mask)
|
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++) {
|
if (chip_class >= GFX9)
|
||||||
const struct si_reg *reg = &sid_reg_table[r];
|
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;
|
const char *reg_name = sid_strings + reg->name_offset;
|
||||||
|
|
||||||
if (reg->offset == offset) {
|
|
||||||
bool first_field = true;
|
bool first_field = true;
|
||||||
|
|
||||||
print_spaces(file, INDENT_PKT);
|
print_spaces(file, INDENT_PKT);
|
||||||
@@ -122,7 +138,7 @@ void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
|
|||||||
return;
|
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 struct si_field *field = sid_fields_table + reg->fields_offset + f;
|
||||||
const int *values_offsets = sid_strings_offsets + field->values_offset;
|
const int *values_offsets = sid_strings_offsets + field->values_offset;
|
||||||
uint32_t val = (value & field->mask) >>
|
uint32_t val = (value & field->mask) >>
|
||||||
@@ -149,7 +165,6 @@ void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
print_spaces(file, INDENT_PKT);
|
print_spaces(file, INDENT_PKT);
|
||||||
fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value);
|
fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value);
|
||||||
|
@@ -27,8 +27,10 @@ CopyRight = '''
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import functools
|
import functools
|
||||||
import sys
|
import itertools
|
||||||
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class StringTable:
|
class StringTable:
|
||||||
@@ -217,15 +219,37 @@ class Reg:
|
|||||||
self.name = strip_prefix(r_name)
|
self.name = strip_prefix(r_name)
|
||||||
self.fields = []
|
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):
|
def strip_prefix(s):
|
||||||
'''Strip prefix in the form ._.*_, e.g. R_001234_'''
|
'''Strip prefix in the form ._.*_, e.g. R_001234_'''
|
||||||
return s[s[2:].find('_')+3:]
|
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 '):
|
if not line.startswith('#define '):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -234,21 +258,19 @@ def parse(filename, regs, packets):
|
|||||||
if line.startswith('R_'):
|
if line.startswith('R_'):
|
||||||
name = line.split()[0]
|
name = line.split()[0]
|
||||||
|
|
||||||
for it in regs:
|
for it in self.registers:
|
||||||
if it.r_name == name:
|
if it.r_name == name:
|
||||||
reg = it
|
sys.exit('Duplicate register define: %s' % (name))
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
reg = Reg(name)
|
reg = Reg(name)
|
||||||
regs.append(reg)
|
self.registers.append(reg)
|
||||||
|
|
||||||
elif line.startswith('S_'):
|
elif line.startswith('S_'):
|
||||||
name = line[:line.find('(')]
|
name = line[:line.find('(')]
|
||||||
|
|
||||||
for it in reg.fields:
|
for it in reg.fields:
|
||||||
if it.s_name == name:
|
if it.s_name == name:
|
||||||
field = it
|
sys.exit('Duplicate field define: %s' % (name))
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
field = Field(reg, name)
|
field = Field(reg, name)
|
||||||
reg.fields.append(field)
|
reg.fields.append(field)
|
||||||
@@ -260,14 +282,33 @@ def parse(filename, regs, packets):
|
|||||||
|
|
||||||
for (n,v) in field.values:
|
for (n,v) in field.values:
|
||||||
if n == name:
|
if n == name:
|
||||||
if v != value:
|
sys.exit('Duplicate value define: name = ' + name)
|
||||||
sys.exit('Value mismatch: name = ' + name)
|
|
||||||
|
|
||||||
field.values.append((name, value))
|
field.values.append((name, value))
|
||||||
|
|
||||||
elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
|
elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
|
||||||
packets.append(line.split()[0])
|
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
|
# Copy fields to indexed registers which have their fields only defined
|
||||||
# at register index 0.
|
# at register index 0.
|
||||||
# For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 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()
|
reg_dict = dict()
|
||||||
|
|
||||||
# Create a dict of registers with fields and '0' in their name
|
# 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:
|
if len(reg.fields) and reg.name.find('0') != -1:
|
||||||
reg_dict[reg.name] = reg
|
reg_dict[reg.name] = reg
|
||||||
|
|
||||||
# Assign fields
|
# Assign fields
|
||||||
for reg in regs:
|
for reg in self.registers:
|
||||||
if not len(reg.fields):
|
if not len(reg.fields):
|
||||||
reg0 = reg_dict.get(match_number.sub('0', reg.name))
|
reg0 = reg_dict.get(match_number.sub('0', reg.name))
|
||||||
if reg0 != None:
|
if reg0 != None:
|
||||||
reg.fields = reg0.fields
|
reg.fields = reg0.fields
|
||||||
|
|
||||||
|
|
||||||
def write_tables(regs, packets):
|
def write_tables(asics, packets):
|
||||||
|
|
||||||
strings = StringTable()
|
strings = StringTable()
|
||||||
strings_offsets = IntTable("int")
|
strings_offsets = IntTable("int")
|
||||||
fields = FieldTable()
|
fields = FieldTable()
|
||||||
@@ -326,13 +366,23 @@ struct si_packet3 {
|
|||||||
print '};'
|
print '};'
|
||||||
print
|
print
|
||||||
|
|
||||||
print 'static const struct si_reg sid_reg_table[] = {'
|
regs = {}
|
||||||
for reg in 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):
|
if len(reg.fields):
|
||||||
print '\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name,
|
print '\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name,
|
||||||
len(reg.fields), fields.add(reg.fields))
|
len(reg.fields), fields.add(reg.fields))
|
||||||
else:
|
else:
|
||||||
print '\t{%s, %s},' % (strings.add(reg.name), reg.r_name)
|
print '\t{%s, %s},' % (strings.add(reg.name), reg.r_name)
|
||||||
|
|
||||||
|
regs[reg.r_name] = reg
|
||||||
print '};'
|
print '};'
|
||||||
print
|
print
|
||||||
|
|
||||||
@@ -351,11 +401,16 @@ struct si_packet3 {
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
regs = []
|
asics = []
|
||||||
packets = []
|
packets = []
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
parse(arg, regs, packets)
|
basename = os.path.basename(arg)
|
||||||
write_tables(regs, packets)
|
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__':
|
if __name__ == '__main__':
|
||||||
|
Reference in New Issue
Block a user