<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>