[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