[Mesa-dev] [PATCH 4/4] ac/debug: take ASIC generation into account when printing registers

Marek Olšák maraeo at gmail.com
Mon Sep 4 23:05:16 UTC 2017


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?

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


More information about the mesa-dev mailing list