[Mesa-dev] [PATCH 4/4] ac/debug: take ASIC generation into account when printing registers
Marek Olšák
maraeo at gmail.com
Tue Sep 5 09:40:07 UTC 2017
For the series:
Acked-by: Marek Olšák <marek.olsak at amd.com>
M.
On Sep 5, 2017 8:53 AM, "Nicolai Hähnle" <nhaehnle at gmail.com> wrote:
> On 05.09.2017 01:05, Marek Olšák wrote:
>
>> gfx9d.h contains almost no named values. Does it obtain named values
>> from sid.h when the same field is also present in gfx9d.h?
>>
>
> One possible difference from the old code is that the new code assumes
> that if *any* values are defined for a field in gfx9d.h, then *all* values
> are defined.
>
> In the old code, values in gfx9d.h would have just overwritten values from
> sid.h. I don't know if there are any fields like that with partial value
> definitions in gfx9d.h.
>
> Cheers,
> Nicolai
>
>
>
>> Marek
>>
>>
>> On Mon, Sep 4, 2017 at 2:11 PM, Nicolai Hähnle <nhaehnle at gmail.com>
>> wrote:
>>
>>> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>>>
>>> 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.
>>> ---
>>> src/amd/common/ac_debug.c | 83 ++++++++++--------
>>> src/amd/common/sid_tables.py | 201 +++++++++++++++++++++++++++---
>>> -------------
>>> 2 files changed, 177 insertions(+), 107 deletions(-)
>>>
>>> diff --git a/src/amd/common/ac_debug.c b/src/amd/common/ac_debug.c
>>> index 570ba850851..54685356f1d 100644
>>> --- a/src/amd/common/ac_debug.c
>>> +++ b/src/amd/common/ac_debug.c
>>> @@ -94,68 +94,83 @@ static void print_value(FILE *file, uint32_t value,
>>> int bits)
>>> }
>>>
>>> static void print_named_value(FILE *file, const char *name, uint32_t
>>> value,
>>> int bits)
>>> {
>>> print_spaces(file, INDENT_PKT);
>>> fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", name);
>>> 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];
>>> - const char *reg_name = sid_strings + reg->name_offset;
>>> + 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->offset == offset) {
>>> - bool first_field = true;
>>> + if (reg) {
>>> + const char *reg_name = sid_strings + reg->name_offset;
>>> + bool first_field = true;
>>>
>>> - print_spaces(file, INDENT_PKT);
>>> - fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <-
>>> ",
>>> - reg_name);
>>> + print_spaces(file, INDENT_PKT);
>>> + fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ",
>>> + reg_name);
>>>
>>> - if (!reg->num_fields) {
>>> - print_value(file, value, 32);
>>> - return;
>>> - }
>>> + if (!reg->num_fields) {
>>> + print_value(file, value, 32);
>>> + return;
>>> + }
>>>
>>> - for (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) >>
>>> - (ffs(field->mask) - 1);
>>> + 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) >>
>>> + (ffs(field->mask) - 1);
>>>
>>> - if (!(field->mask & field_mask))
>>> - continue;
>>> + if (!(field->mask & field_mask))
>>> + continue;
>>>
>>> - /* Indent the field. */
>>> - if (!first_field)
>>> - print_spaces(file,
>>> - INDENT_PKT +
>>> strlen(reg_name) + 4);
>>> + /* Indent the field. */
>>> + if (!first_field)
>>> + print_spaces(file,
>>> + INDENT_PKT +
>>> strlen(reg_name) + 4);
>>>
>>> - /* Print the field. */
>>> - fprintf(file, "%s = ", sid_strings +
>>> field->name_offset);
>>> + /* Print the field. */
>>> + fprintf(file, "%s = ", sid_strings +
>>> field->name_offset);
>>>
>>> - if (val < field->num_values &&
>>> values_offsets[val] >= 0)
>>> - fprintf(file, "%s\n",
>>> sid_strings + values_offsets[val]);
>>> - else
>>> - print_value(file, val,
>>> -
>>> util_bitcount(field->mask));
>>> + if (val < field->num_values &&
>>> values_offsets[val] >= 0)
>>> + fprintf(file, "%s\n", sid_strings +
>>> values_offsets[val]);
>>> + else
>>> + print_value(file, val,
>>> + util_bitcount(field->mask));
>>>
>>> - first_field = false;
>>> - }
>>> - return;
>>> + first_field = false;
>>> }
>>> + return;
>>> }
>>>
>>> print_spaces(file, INDENT_PKT);
>>> fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n",
>>> offset, value);
>>> }
>>>
>>> static uint32_t ac_ib_get(struct ac_ib_parser *ib)
>>> {
>>> uint32_t v = 0;
>>>
>>> diff --git a/src/amd/common/sid_tables.py b/src/amd/common/sid_tables.py
>>> index 808a96f834f..4e53acefa44 100644
>>> --- a/src/amd/common/sid_tables.py
>>> +++ b/src/amd/common/sid_tables.py
>>> @@ -20,22 +20,24 @@ CopyRight = '''
>>> * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 collections
>>> import functools
>>> -import sys
>>> +import itertools
>>> +import os.path
>>> import re
>>> +import sys
>>>
>>>
>>> class StringTable:
>>> """
>>> A class for collecting multiple strings in a single larger string
>>> that is
>>> used by indexing (to avoid relocations in the resulting binary)
>>> """
>>> def __init__(self):
>>> self.table = []
>>> self.length = 0
>>> @@ -210,92 +212,130 @@ class FieldTable:
>>>
>>> filp.write('};\n')
>>>
>>>
>>> class Reg:
>>> def __init__(self, r_name):
>>> self.r_name = r_name
>>> 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:
>>> - if not line.startswith('#define '):
>>> - continue
>>> -
>>> - line = line[8:].strip()
>>> -
>>> - if line.startswith('R_'):
>>> - name = line.split()[0]
>>> -
>>> - for it in regs:
>>> - if it.r_name == name:
>>> - reg = it
>>> - break
>>> - else:
>>> - reg = Reg(name)
>>> - regs.append(reg)
>>> -
>>> - elif line.startswith('S_'):
>>> - name = line[:line.find('(')]
>>> -
>>> - for it in reg.fields:
>>> - if it.s_name == name:
>>> - field = it
>>> - break
>>> - else:
>>> - field = Field(reg, name)
>>> - reg.fields.append(field)
>>>
>>> - elif line.startswith('V_'):
>>> - split = line.split()
>>> - name = split[0]
>>> - value = int(split[1], 0)
>>> -
>>> - for (n,v) in field.values:
>>> - if n == name:
>>> - if v != value:
>>> - sys.exit('Value mismatch: 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])
>>> +class Asic:
>>> + """
>>> + Store the registers of one ASIC class / group of classes.
>>> + """
>>> + def __init__(self, name):
>>> + self.name = name
>>> + self.registers = []
>>>
>>> - # 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.
>>> - match_number = re.compile('[0-9]+')
>>> - reg_dict = dict()
>>> + 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
>>>
>>> - # Create a dict of registers with fields and '0' in their name
>>> - for reg in regs:
>>> - if len(reg.fields) and reg.name.find('0') != -1:
>>> - reg_dict[reg.name] = reg
>>> + line = line[8:].strip()
>>>
>>> - # Assign fields
>>> - for reg in regs:
>>> - if not len(reg.fields):
>>> - reg0 = reg_dict.get(match_number.sub('0', reg.name))
>>> - if reg0 != None:
>>> - reg.fields = reg0.fields
>>> + if line.startswith('R_'):
>>> + name = line.split()[0]
>>>
>>> + for it in self.registers:
>>> + if it.r_name == name:
>>> + sys.exit('Duplicate register define: %s' %
>>> (name))
>>> + else:
>>> + reg = Reg(name)
>>> + self.registers.append(reg)
>>>
>>> -def write_tables(regs, packets):
>>> + elif line.startswith('S_'):
>>> + name = line[:line.find('(')]
>>>
>>> + for it in reg.fields:
>>> + if it.s_name == name:
>>> + sys.exit('Duplicate field define: %s' % (name))
>>> + else:
>>> + field = Field(reg, name)
>>> + reg.fields.append(field)
>>> +
>>> + elif line.startswith('V_'):
>>> + split = line.split()
>>> + name = split[0]
>>> + value = int(split[1], 0)
>>> +
>>> + for (n,v) in field.values:
>>> + if n == 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.
>>> + match_number = re.compile('[0-9]+')
>>> + reg_dict = dict()
>>> +
>>> + # Create a dict of registers with fields and '0' in their name
>>> + 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 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(asics, packets):
>>> strings = StringTable()
>>> strings_offsets = IntTable("int")
>>> fields = FieldTable()
>>>
>>> print '/* This file is autogenerated by sid_tables.py from sid.h.
>>> Do not edit directly. */'
>>> print
>>> print CopyRight.strip()
>>> print '''
>>> #ifndef SID_TABLES_H
>>> #define SID_TABLES_H
>>> @@ -319,46 +359,61 @@ struct si_packet3 {
>>> unsigned op;
>>> };
>>> '''
>>>
>>> print 'static const struct si_packet3 packet3_table[] = {'
>>> for pkt in packets:
>>> print '\t{%s, %s},' % (strings.add(pkt[5:]), pkt)
>>> print '};'
>>> print
>>>
>>> - print 'static const struct si_reg sid_reg_table[] = {'
>>> - for reg in regs:
>>> - 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)
>>> - print '};'
>>> - print
>>> + 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
>>>
>>> fields.emit(sys.stdout, strings, strings_offsets)
>>>
>>> print
>>>
>>> strings.emit(sys.stdout, "sid_strings")
>>>
>>> print
>>>
>>> strings_offsets.emit(sys.stdout, "sid_strings_offsets")
>>>
>>> print
>>> print '#endif'
>>>
>>>
>>> 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__':
>>> main()
>>>
>>> # kate: space-indent on; indent-width 4; replace-tabs on;
>>> --
>>> 2.11.0
>>>
>>> _______________________________________________
>>> mesa-dev mailing list
>>> mesa-dev at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>>
>>
>
> --
> Lerne, wie die Welt wirklich ist,
> Aber vergiss niemals, wie sie sein sollte.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170905/33bccec3/attachment-0001.html>
More information about the mesa-dev
mailing list