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 <nhaeh...@gmail.com> wrote:
From: Nicolai Hähnle <nicolai.haeh...@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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to