예제 #1
0
    def __fini_register(self):
        if self.__regmap is None:
            return

        if self.__fields:
            self.regdb.add_register_type(self.__regmap.name,
                                         Object(fields=self.__fields))
            self.__regmap.type_ref = self.__regmap.name
        self.regdb.add_register_mapping(self.__regmap)

        self.__regmap = None
        self.__fields = None
예제 #2
0
    def __fini_field(self):
        if self.__field is None:
            return

        if self.__enumentries:
            self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name
            self.regdb.add_enum(self.__field.enum_ref,
                                Object(entries=self.__enumentries))
        self.__fields.append(self.__field)

        self.__enumentries = None
        self.__field = None
예제 #3
0
def hardcoded_format(hw_enum):
    return Object(img_format=hw_enum, flags=[])
예제 #4
0
    def map(self, fmt):
        if fmt.layout == PLAIN:
            chan_type = set(
                [chan.type for chan in fmt.le_channels if chan.type != VOID])
            chan_norm = set(
                [chan.norm for chan in fmt.le_channels if chan.type != VOID])
            chan_pure = set(
                [chan.pure for chan in fmt.le_channels if chan.type != VOID])
            if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1:
                print(
                    ('Format {fmt.name} has inconsistent channel types: ' +
                     '{chan_type} {chan_norm} {chan_pure}').format(**locals()),
                    file=sys.stderr)
                return None

            chan_type = chan_type.pop()
            chan_norm = chan_norm.pop()
            chan_pure = chan_pure.pop()
            chan_sizes = [
                chan.size for chan in fmt.le_channels if chan.size != 0
            ]

            extra_flags = []

            if fmt.colorspace == SRGB:
                assert chan_type == UNSIGNED and chan_norm
                num_format = 'SRGB'
            else:
                if chan_type == UNSIGNED:
                    if chan_pure:
                        num_format = 'UINT'
                    elif chan_sizes[0] == 32:
                        # Shader-based work-around for 32-bit non-pure-integer
                        num_format = 'UINT'
                        extra_flags.append('buffers_only')
                    elif chan_norm:
                        num_format = 'UNORM'
                    else:
                        num_format = 'USCALED'
                elif chan_type == SIGNED:
                    if chan_pure:
                        num_format = 'SINT'
                    elif chan_sizes[0] == 32:
                        # Shader-based work-around for 32-bit non-pure-integer
                        num_format = 'SINT'
                        extra_flags.append('buffers_only')
                    elif chan_norm:
                        num_format = 'SNORM'
                    else:
                        num_format = 'SSCALED'
                elif chan_type == FLOAT:
                    num_format = 'FLOAT'

                    if chan_sizes[0] == 64:
                        # Shader-based work-around for doubles
                        if len(chan_sizes) % 2 == 1:
                            # 1 or 3 loads for 1 or 3 double channels
                            chan_sizes = [32, 32]
                        else:
                            # 1 or 2 loads for 2 or 4 double channels
                            chan_sizes = [32, 32, 32, 32]
                        extra_flags.append('buffers_only')
                else:
                    # Shader-based work-around
                    assert chan_type == FIXED
                    assert chan_sizes[0] == 32
                    num_format = 'SINT'
                    extra_flags.append('buffers_only')

            # These are not supported as render targets, so we don't support
            # them as images either.
            if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32)
                    and chan_sizes[0] == chan_sizes[1]):
                extra_flags.append('buffers_only')
                if chan_sizes[0] in (8, 16):
                    # Shader-based work-around: one load per channel
                    chan_sizes = [chan_sizes[0]]

            # Don't expose SRGB buffer formats
            if 'buffers_only' in extra_flags and fmt.colorspace == SRGB:
                return None

            # Don't support 4_4 because it's not supported as render targets
            # and it's useless in other cases.
            if len(chan_sizes) == 2 and chan_sizes[0] == 4:
                return None

            key = tuple([num_format] + chan_sizes)
            if key not in self.plain_gfx10_formats:
                return None

            gfx10_fmt = self.plain_gfx10_formats[key]
            return Object(
                img_format=gfx10_fmt.img_format,
                flags=gfx10_fmt.flags + extra_flags,
            )

        return None
예제 #5
0
    def __init__(self, regdb, guard=None):
        self.guard = guard

        # The following contain: Object(address, chips, name, regmap/field/enumentry)
        self.register_lines = []
        self.field_lines = []
        self.value_lines = []

        regtype_emit = defaultdict(set)
        enum_emit = defaultdict(set)

        for regmap in regdb.register_mappings():
            type_ref = getattr(regmap, 'type_ref', None)
            self.register_lines.append(
                Object(
                    address=regmap.map.at,
                    chips=set(regmap.chips),
                    name=regmap.name,
                    regmap=regmap,
                    type_refs=set([type_ref]) if type_ref else set(),
                ))

            basename = re.sub(r'[0-9]+', '', regmap.name)
            key = '{type_ref}::{basename}'.format(**locals())
            if type_ref is not None and regtype_emit[key].isdisjoint(
                    regmap.chips):
                regtype_emit[key].update(regmap.chips)

                regtype = regdb.register_type(type_ref)
                for field in regtype.fields:
                    if field.name == 'RESERVED':
                        continue

                    enum_ref = getattr(field, 'enum_ref', None)
                    self.field_lines.append(
                        Object(
                            address=regmap.map.at,
                            chips=set(regmap.chips),
                            name=field.name,
                            field=field,
                            bits=field.bits[:],
                            type_refs=set([type_ref]) if type_ref else set(),
                            enum_refs=set([enum_ref]) if enum_ref else set(),
                        ))

                    key = '{type_ref}::{basename}::{enum_ref}'.format(
                        **locals())
                    if enum_ref is not None and enum_emit[key].isdisjoint(
                            regmap.chips):
                        enum_emit[key].update(regmap.chips)

                        enum = regdb.enum(enum_ref)
                        for entry in enum.entries:
                            self.value_lines.append(
                                Object(
                                    address=regmap.map.at,
                                    chips=set(regmap.chips),
                                    name=entry.name,
                                    enumentry=entry,
                                    enum_refs=set([enum_ref])
                                    if enum_ref else set(),
                                ))

        # Merge register lines
        lines = self.register_lines
        lines.sort(key=lambda line: (line.address, line.name))

        self.register_lines = []
        for line in lines:
            prev = self.register_lines[-1] if self.register_lines else None
            if prev and prev.address == line.address and prev.name == line.name:
                prev.chips.update(line.chips)
                prev.type_refs.update(line.type_refs)
                continue
            self.register_lines.append(line)

        # Merge field lines
        lines = self.field_lines
        lines.sort(key=lambda line: (line.address, line.name))

        self.field_lines = []
        for line in lines:
            merged = False
            for prev in reversed(self.field_lines):
                if prev.address != line.address or prev.name != line.name:
                    break

                # Can merge fields if they have the same starting bit and the
                # range of the field as intended by the current line does not
                # conflict with any of the regtypes covered by prev.
                if prev.bits[0] != line.bits[0]:
                    continue

                if prev.bits[1] != line.bits[1]:
                    # Current line's field extends beyond the range of prev.
                    # Need to check for conflicts
                    if detect_conflict(regdb, prev, line):
                        continue

                prev.bits[1] = max(prev.bits[1], line.bits[1])
                prev.chips.update(line.chips)
                prev.type_refs.update(line.type_refs)
                prev.enum_refs.update(line.enum_refs)
                merged = True
                break
            if not merged:
                self.field_lines.append(line)

        # Merge value lines
        lines = self.value_lines
        lines.sort(key=lambda line: (line.address, line.name))

        self.value_lines = []
        for line in lines:
            for prev in reversed(self.value_lines):
                if prev.address == line.address and prev.name == line.name and\
                   prev.enumentry.value == line.enumentry.value:
                    prev.chips.update(line.chips)
                    prev.enum_refs.update(line.enum_refs)
                    break
            else:
                self.value_lines.append(line)

        # Disambiguate field and value lines
        for idx, line in enumerate(self.field_lines):
            prev = self.field_lines[idx - 1] if idx > 0 else None
            next = self.field_lines[idx + 1] if idx + 1 < len(
                self.field_lines) else None
            if (prev and prev.address == line.address and prev.field.name == line.field.name) or\
               (next and next.address == line.address and next.field.name == line.field.name):
                line.name += '_' + get_disambiguation_suffix(line.chips)

        for idx, line in enumerate(self.value_lines):
            prev = self.value_lines[idx - 1] if idx > 0 else None
            next = self.value_lines[idx + 1] if idx + 1 < len(
                self.value_lines) else None
            if (prev and prev.address == line.address and prev.enumentry.name == line.enumentry.name) or\
               (next and next.address == line.address and next.enumentry.name == line.enumentry.name):
                line.name += '_' + get_disambiguation_suffix(line.chips)
예제 #6
0
"""

import argparse
from collections import defaultdict
import itertools
import json
import re
import sys

from regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types

######### BEGIN HARDCODED CONFIGURATION

# Chips are sorted chronologically
CHIPS = [
    Object(name='gfx6', disambiguation='GFX6'),
    Object(name='gfx7', disambiguation='GFX7'),
    Object(name='gfx8', disambiguation='GFX8'),
    Object(name='gfx81', disambiguation='GFX81'),
    Object(name='gfx9', disambiguation='GFX9'),
    Object(name='gfx10', disambiguation='GFX10'),
    Object(name='gfx103', disambiguation='GFX103'),
]

######### END HARDCODED CONFIGURATION


def get_chip_index(chip):
    """
    Given a chip name, return its index in the global CHIPS list.
    """
예제 #7
0
"""

import argparse
from collections import defaultdict
import itertools
import json
import re
import sys

from regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types

######### BEGIN HARDCODED CONFIGURATION

# Chips are sorted chronologically
CHIPS = [
    Object(name='gfx6', disambiguation='GFX6'),
    Object(name='gfx7', disambiguation='GFX7'),
    Object(name='gfx8', disambiguation='GFX8'),
    Object(name='fiji', disambiguation='GFX8'),
    Object(name='stoney', disambiguation='GFX8'),
    Object(name='gfx9', disambiguation='GFX9'),
]

######### END HARDCODED CONFIGURATION


def get_chip_index(chip):
    """
    Given a chip name, return its index in the global CHIPS list.
    """
    return next(idx for idx, obj in enumerate(CHIPS) if obj.name == chip)
예제 #8
0
    def parse_header(self, filp):
        regdb = RegisterDatabase()
        chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']

        self.__regmap = None
        self.__fields = None
        self.__field = None
        self.__enumentries = None

        for line in filp:
            if not line.startswith('#define '):
                continue

            line = line[8:].strip()

            comment = None
            m = RE_comment.search(line)
            if m is not None:
                comment = m.group(2) or m.group(4)
                comment = comment.strip()
                line = line[:m.span()[0]].strip()

            split = line.split(None, 1)
            name = split[0]

            m = RE_prefix.match(name)
            if m is None:
                continue

            prefix = m.group(1)
            prefix_address = int(m.group(2), 16)
            name = name[m.span()[1]:]

            if prefix == 'V':
                value = int(split[1], 0)

                for entry in self.__enumentries:
                    if name == entry.name:
                        sys.exit(
                            'Duplicate value define: name = {0}'.format(name))

                entry = Object(name=name, value=value)
                if comment is not None:
                    entry.comment = comment
                self.__enumentries.append(entry)
                continue

            if prefix == 'S':
                self.__fini_field()

                if not name.endswith('(x)'):
                    sys.exit('Missing (x) in S line: {0}'.line)
                name = name[:-3]

                for field in self.__fields:
                    if name == field.name:
                        sys.exit('Duplicate field define: {0}'.format(name))

                m = RE_set_value.match(split[1])
                if m is not None:
                    unshifted_mask = int(m.group(1), 0)
                    shift = int(m.group(2), 0)
                else:
                    m = RE_set_value_no_shift.match(split[1])
                    if m is not None:
                        unshifted_mask = int(m.group(2), 0)
                        shift = 0
                    else:
                        sys.exit('Bad S_xxx_xxx define: {0}'.format(line))

                num_bits = int(math.log2(unshifted_mask + 1))
                if unshifted_mask != (1 << num_bits) - 1:
                    sys.exit('Bad unshifted mask in {0}'.format(line))

                self.__field = Object(
                    name=name,
                    bits=[shift, shift + num_bits - 1],
                )
                if comment is not None:
                    self.__field.comment = comment
                self.__enumentries = []

            if prefix == 'R':
                self.__fini_field()
                self.__fini_register()

                if regdb.register_mappings_by_name(name):
                    sys.exit('Duplicate register define: {0}'.format(name))

                address = int(split[1], 0)
                if address != prefix_address:
                    sys.exit('Inconsistent register address: {0}'.format(line))

                self.__regmap = Object(
                    name=name,
                    chips=self.chips,
                    map=Object(to=self.address_space, at=address),
                )
                self.__fields = []

        self.__fini_field()
        self.__fini_register()