<div dir="auto">For the series:<div dir="auto"><br></div><div dir="auto">Acked-by: Marek Olšák <<a href="mailto:marek.olsak@amd.com">marek.olsak@amd.com</a>></div><div dir="auto"><br></div><div dir="auto">M.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sep 5, 2017 8:53 AM, "Nicolai Hähnle" <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 05.09.2017 01:05, Marek Olšák wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
gfx9d.h contains almost no named values. Does it obtain named values<br>
from sid.h when the same field is also present in gfx9d.h?<br>
</blockquote>
<br>
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.<br>
<br>
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.<br>
<br>
Cheers,<br>
Nicolai<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Marek<br>
<br>
<br>
On Mon, Sep 4, 2017 at 2:11 PM, Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com" target="_blank">nicolai.haehnle@amd.com</a>><br>
<br>
There were some overlapping changes in gfx9 especially in the CB/DB<br>
blocks which made register dumps rather misleading.<br>
<br>
The split is along the lines of the header files, so we'll print VI-only<br>
fields on SI and CI, for example, but we won't print GFX9 fields on<br>
SI/CI/VI, and we won't print SI/CI/VI fields on GFX9.<br>
---<br>
  src/amd/common/ac_debug.c    |  83 ++++++++++--------<br>
  src/amd/common/sid_tables.py | 201 +++++++++++++++++++++++++++---<wbr>-------------<br>
  2 files changed, 177 insertions(+), 107 deletions(-)<br>
<br>
diff --git a/src/amd/common/ac_debug.c b/src/amd/common/ac_debug.c<br>
index 570ba850851..54685356f1d 100644<br>
--- a/src/amd/common/ac_debug.c<br>
+++ b/src/amd/common/ac_debug.c<br>
@@ -94,68 +94,83 @@ static void print_value(FILE *file, uint32_t value, int bits)<br>
  }<br>
<br>
  static void print_named_value(FILE *file, const char *name, uint32_t value,<br>
                               int bits)<br>
  {<br>
         print_spaces(file, INDENT_PKT);<br>
         fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", name);<br>
         print_value(file, value, bits);<br>
  }<br>
<br>
+static const struct si_reg *find_register(const struct si_reg *table,<br>
+                                         unsigned table_size,<br>
+                                         unsigned offset)<br>
+{<br>
+       for (unsigned i = 0; i < table_size; i++) {<br>
+               const struct si_reg *reg = &table[i];<br>
+<br>
+               if (reg->offset == offset)<br>
+                       return reg;<br>
+       }<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
  void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset,<br>
                  uint32_t value, uint32_t field_mask)<br>
  {<br>
-       int r, f;<br>
+       const struct si_reg *reg = NULL;<br>
<br>
-       for (r = 0; r < ARRAY_SIZE(sid_reg_table); r++) {<br>
-               const struct si_reg *reg = &sid_reg_table[r];<br>
-               const char *reg_name = sid_strings + reg->name_offset;<br>
+       if (chip_class >= GFX9)<br>
+               reg = find_register(gfx9d_reg_table, ARRAY_SIZE(gfx9d_reg_table), offset);<br>
+       if (!reg)<br>
+               reg = find_register(sid_reg_table, ARRAY_SIZE(sid_reg_table), offset);<br>
<br>
-               if (reg->offset == offset) {<br>
-                       bool first_field = true;<br>
+       if (reg) {<br>
+               const char *reg_name = sid_strings + reg->name_offset;<br>
+               bool first_field = true;<br>
<br>
-                       print_spaces(file, INDENT_PKT);<br>
-                       fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ",<br>
-                               reg_name);<br>
+               print_spaces(file, INDENT_PKT);<br>
+               fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ",<br>
+                       reg_name);<br>
<br>
-                       if (!reg->num_fields) {<br>
-                               print_value(file, value, 32);<br>
-                               return;<br>
-                       }<br>
+               if (!reg->num_fields) {<br>
+                       print_value(file, value, 32);<br>
+                       return;<br>
+               }<br>
<br>
-                       for (f = 0; f < reg->num_fields; f++) {<br>
-                               const struct si_field *field = sid_fields_table + reg->fields_offset + f;<br>
-                               const int *values_offsets = sid_strings_offsets + field->values_offset;<br>
-                               uint32_t val = (value & field->mask) >><br>
-                                              (ffs(field->mask) - 1);<br>
+               for (unsigned f = 0; f < reg->num_fields; f++) {<br>
+                       const struct si_field *field = sid_fields_table + reg->fields_offset + f;<br>
+                       const int *values_offsets = sid_strings_offsets + field->values_offset;<br>
+                       uint32_t val = (value & field->mask) >><br>
+                                      (ffs(field->mask) - 1);<br>
<br>
-                               if (!(field->mask & field_mask))<br>
-                                       continue;<br>
+                       if (!(field->mask & field_mask))<br>
+                               continue;<br>
<br>
-                               /* Indent the field. */<br>
-                               if (!first_field)<br>
-                                       print_spaces(file,<br>
-                                                    INDENT_PKT + strlen(reg_name) + 4);<br>
+                       /* Indent the field. */<br>
+                       if (!first_field)<br>
+                               print_spaces(file,<br>
+                                            INDENT_PKT + strlen(reg_name) + 4);<br>
<br>
-                               /* Print the field. */<br>
-                               fprintf(file, "%s = ", sid_strings + field->name_offset);<br>
+                       /* Print the field. */<br>
+                       fprintf(file, "%s = ", sid_strings + field->name_offset);<br>
<br>
-                               if (val < field->num_values && values_offsets[val] >= 0)<br>
-                                       fprintf(file, "%s\n", sid_strings + values_offsets[val]);<br>
-                               else<br>
-                                       print_value(file, val,<br>
-                                                   util_bitcount(field->mask));<br>
+                       if (val < field->num_values && values_offsets[val] >= 0)<br>
+                               fprintf(file, "%s\n", sid_strings + values_offsets[val]);<br>
+                       else<br>
+                               print_value(file, val,<br>
+                                           util_bitcount(field->mask));<br>
<br>
-                               first_field = false;<br>
-                       }<br>
-                       return;<br>
+                       first_field = false;<br>
                 }<br>
+               return;<br>
         }<br>
<br>
         print_spaces(file, INDENT_PKT);<br>
         fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value);<br>
  }<br>
<br>
  static uint32_t ac_ib_get(struct ac_ib_parser *ib)<br>
  {<br>
         uint32_t v = 0;<br>
<br>
diff --git a/src/amd/common/sid_tables.py b/src/amd/common/sid_tables.py<br>
index 808a96f834f..4e53acefa44 100644<br>
--- a/src/amd/common/sid_tables.py<br>
+++ b/src/amd/common/sid_tables.py<br>
@@ -20,22 +20,24 @@ CopyRight = '''<br>
   * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,<br>
   * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR<br>
   * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE<br>
   * USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
   *<br>
   */<br>
  '''<br>
<br>
  import collections<br>
  import functools<br>
-import sys<br>
+import itertools<br>
+import os.path<br>
  import re<br>
+import sys<br>
<br>
<br>
  class StringTable:<br>
      """<br>
      A class for collecting multiple strings in a single larger string that is<br>
      used by indexing (to avoid relocations in the resulting binary)<br>
      """<br>
      def __init__(self):<br>
          self.table = []<br>
          self.length = 0<br>
@@ -210,92 +212,130 @@ class FieldTable:<br>
<br>
          filp.write('};\n')<br>
<br>
<br>
  class Reg:<br>
      def __init__(self, r_name):<br>
          self.r_name = r_name<br>
          <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> = strip_prefix(r_name)<br>
          self.fields = []<br>
<br>
+    def __eq__(self, other):<br>
+        if not isinstance(other, Reg):<br>
+            return False<br>
+        return (self.r_name == other.r_name and<br>
+                <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> == <a href="http://other.name" rel="noreferrer" target="_blank">other.name</a> and<br>
+                len(self.fields) == len(other.fields) and<br>
+                all(a == b for a, b in zip(self.fields, other.fields)))<br>
+<br>
+    def __ne__(self, other):<br>
+        return not (self == other)<br>
+<br>
<br>
  def strip_prefix(s):<br>
      '''Strip prefix in the form ._.*_, e.g. R_001234_'''<br>
      return s[s[2:].find('_')+3:]<br>
<br>
-def parse(filename, regs, packets):<br>
-    stream = open(filename)<br>
-<br>
-    for line in stream:<br>
-        if not line.startswith('#define '):<br>
-            continue<br>
-<br>
-        line = line[8:].strip()<br>
-<br>
-        if line.startswith('R_'):<br>
-            name = line.split()[0]<br>
-<br>
-            for it in regs:<br>
-                if it.r_name == name:<br>
-                    reg = it<br>
-                    break<br>
-            else:<br>
-                reg = Reg(name)<br>
-                regs.append(reg)<br>
-<br>
-        elif line.startswith('S_'):<br>
-            name = line[:line.find('(')]<br>
-<br>
-            for it in reg.fields:<br>
-                if it.s_name == name:<br>
-                    field = it<br>
-                    break<br>
-            else:<br>
-                field = Field(reg, name)<br>
-                reg.fields.append(field)<br>
<br>
-        elif line.startswith('V_'):<br>
-            split = line.split()<br>
-            name = split[0]<br>
-            value = int(split[1], 0)<br>
-<br>
-            for (n,v) in field.values:<br>
-                if n == name:<br>
-                    if v != value:<br>
-                        sys.exit('Value mismatch: name = ' + name)<br>
-<br>
-            field.values.append((name, value))<br>
-<br>
-        elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:<br>
-            packets.append(line.split()[0]<wbr>)<br>
+class Asic:<br>
+    """<br>
+    Store the registers of one ASIC class / group of classes.<br>
+    """<br>
+    def __init__(self, name):<br>
+        <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> = name<br>
+        self.registers = []<br>
<br>
-    # Copy fields to indexed registers which have their fields only defined<br>
-    # at register index 0.<br>
-    # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.<br>
-    match_number = re.compile('[0-9]+')<br>
-    reg_dict = dict()<br>
+    def parse(self, filp, packets, older_asics):<br>
+        """<br>
+        Parse registers from the given header file. Packets are separately<br>
+        stored in the packets array.<br>
+        """<br>
+        for line in filp:<br>
+            if not line.startswith('#define '):<br>
+                continue<br>
<br>
-    # Create a dict of registers with fields and '0' in their name<br>
-    for reg in regs:<br>
-        if len(reg.fields) and reg.name.find('0') != -1:<br>
-            reg_dict[<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>] = reg<br>
+            line = line[8:].strip()<br>
<br>
-    # Assign fields<br>
-    for reg in regs:<br>
-        if not len(reg.fields):<br>
-            reg0 = reg_dict.get(match_number.sub(<wbr>'0', <a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>))<br>
-            if reg0 != None:<br>
-                reg.fields = reg0.fields<br>
+            if line.startswith('R_'):<br>
+                name = line.split()[0]<br>
<br>
+                for it in self.registers:<br>
+                    if it.r_name == name:<br>
+                        sys.exit('Duplicate register define: %s' % (name))<br>
+                else:<br>
+                    reg = Reg(name)<br>
+                    self.registers.append(reg)<br>
<br>
-def write_tables(regs, packets):<br>
+            elif line.startswith('S_'):<br>
+                name = line[:line.find('(')]<br>
<br>
+                for it in reg.fields:<br>
+                    if it.s_name == name:<br>
+                        sys.exit('Duplicate field define: %s' % (name))<br>
+                else:<br>
+                    field = Field(reg, name)<br>
+                    reg.fields.append(field)<br>
+<br>
+            elif line.startswith('V_'):<br>
+                split = line.split()<br>
+                name = split[0]<br>
+                value = int(split[1], 0)<br>
+<br>
+                for (n,v) in field.values:<br>
+                    if n == name:<br>
+                        sys.exit('Duplicate value define: name = ' + name)<br>
+<br>
+                field.values.append((name, value))<br>
+<br>
+            elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:<br>
+                packets.append(line.split()[0]<wbr>)<br>
+<br>
+        # Copy values for corresponding fields from older ASICs if they were<br>
+        # not redefined<br>
+        for reg in self.registers:<br>
+            old_reg = False<br>
+            for field in reg.fields:<br>
+                if len(field.values) > 0:<br>
+                    continue<br>
+                if old_reg is False:<br>
+                    for old_reg in itertools.chain(<br>
+                            *(asic.registers for asic in reversed(older_asics))):<br>
+                        if <a href="http://old_reg.name" rel="noreferrer" target="_blank">old_reg.name</a> == <a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>:<br>
+                            break<br>
+                    else:<br>
+                        old_reg = None<br>
+                if old_reg is not None:<br>
+                    for old_field in old_reg.fields:<br>
+                        if <a href="http://old_field.name" rel="noreferrer" target="_blank">old_field.name</a> == <a href="http://field.name" rel="noreferrer" target="_blank">field.name</a>:<br>
+                            field.values = old_field.values<br>
+                            break<br>
+<br>
+        # Copy fields to indexed registers which have their fields only defined<br>
+        # at register index 0.<br>
+        # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.<br>
+        match_number = re.compile('[0-9]+')<br>
+        reg_dict = dict()<br>
+<br>
+        # Create a dict of registers with fields and '0' in their name<br>
+        for reg in self.registers:<br>
+            if len(reg.fields) and reg.name.find('0') != -1:<br>
+                reg_dict[<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>] = reg<br>
+<br>
+        # Assign fields<br>
+        for reg in self.registers:<br>
+            if not len(reg.fields):<br>
+                reg0 = reg_dict.get(match_number.sub(<wbr>'0', <a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>))<br>
+                if reg0 != None:<br>
+                    reg.fields = reg0.fields<br>
+<br>
+<br>
+def write_tables(asics, packets):<br>
      strings = StringTable()<br>
      strings_offsets = IntTable("int")<br>
      fields = FieldTable()<br>
<br>
      print '/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */'<br>
      print<br>
      print CopyRight.strip()<br>
      print '''<br>
  #ifndef SID_TABLES_H<br>
  #define SID_TABLES_H<br>
@@ -319,46 +359,61 @@ struct si_packet3 {<br>
          unsigned op;<br>
  };<br>
  '''<br>
<br>
      print 'static const struct si_packet3 packet3_table[] = {'<br>
      for pkt in packets:<br>
          print '\t{%s, %s},' % (strings.add(pkt[5:]), pkt)<br>
      print '};'<br>
      print<br>
<br>
-    print 'static const struct si_reg sid_reg_table[] = {'<br>
-    for reg in regs:<br>
-        if len(reg.fields):<br>
-            print '\t{%s, %s, %s, %s},' % (strings.add(<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>), reg.r_name,<br>
-                len(reg.fields), fields.add(reg.fields))<br>
-        else:<br>
-            print '\t{%s, %s},' % (strings.add(<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>), reg.r_name)<br>
-    print '};'<br>
-    print<br>
+    regs = {}<br>
+    for asic in asics:<br>
+        print 'static const struct si_reg %s_reg_table[] = {' % (<a href="http://asic.name" rel="noreferrer" target="_blank">asic.name</a>)<br>
+        for reg in asic.registers:<br>
+            # Only output a register that was changed or added relative to<br>
+            # the previous generation<br>
+            previous = regs.get(reg.r_name, None)<br>
+            if previous == reg:<br>
+                continue<br>
+<br>
+            if len(reg.fields):<br>
+                print '\t{%s, %s, %s, %s},' % (strings.add(<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>), reg.r_name,<br>
+                    len(reg.fields), fields.add(reg.fields))<br>
+            else:<br>
+                print '\t{%s, %s},' % (strings.add(<a href="http://reg.name" rel="noreferrer" target="_blank">reg.name</a>), reg.r_name)<br>
+<br>
+            regs[reg.r_name] = reg<br>
+        print '};'<br>
+        print<br>
<br>
      fields.emit(sys.stdout, strings, strings_offsets)<br>
<br>
      print<br>
<br>
      strings.emit(sys.stdout, "sid_strings")<br>
<br>
      print<br>
<br>
      strings_offsets.emit(sys.stdou<wbr>t, "sid_strings_offsets")<br>
<br>
      print<br>
      print '#endif'<br>
<br>
<br>
  def main():<br>
-    regs = []<br>
+    asics = []<br>
      packets = []<br>
      for arg in sys.argv[1:]:<br>
-        parse(arg, regs, packets)<br>
-    write_tables(regs, packets)<br>
+        basename = os.path.basename(arg)<br>
+        m = re.match(r'(.*)\.h', basename)<br>
+        asic = Asic(m.group(1))<br>
+        with open(arg) as filp:<br>
+            asic.parse(filp, packets, asics)<br>
+        asics.append(asic)<br>
+    write_tables(asics, packets)<br>
<br>
<br>
  if __name__ == '__main__':<br>
      main()<br>
<br>
  # kate: space-indent on; indent-width 4; replace-tabs on;<br>
--<br>
2.11.0<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></blockquote>
<br>
<br>
-- <br>
Lerne, wie die Welt wirklich ist,<br>
Aber vergiss niemals, wie sie sein sollte.<br>
</blockquote></div></div>