Exemplo n.º 1
0
class ListType(Type):
    '''
    Derived class which represents a list of some other datatype.  Fixed- or variable-sized.

    Public fields added:
    member is the datatype of the list elements.
    parent is the structure type containing the list.
    expr is an Expression object containing the length information, for variable-sized lists.
    '''
    def __init__(self, elt, member, *parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parents = list(parent)
        lenfield_name = False

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
            is_list_in_parent = self.parents[0].elt.tag in ('request', 'event', 'reply', 'error')
            if not len(elts) and is_list_in_parent:
                self.expr = Expression(elt,self)
                self.expr.op = 'calculate_len'
            else:
                self.expr = Expression(elts[0] if len(elts) else elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None

        self.required_start_align = self.member.required_start_align

    def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
        if not self.fixed_size():
            # We need a length field.
            # Ask our Expression object for it's name, type, and whether it's on the wire.
            lenfid = self.expr.lenfield_type
            lenfield_name = self.expr.lenfield_name
            lenwire = self.expr.lenwire
            needlen = True

            # See if the length field is already in the structure.
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == lenfield_name:
                        needlen = False

            # It isn't, so we need to add it to the structure ourself.
            if needlen:
                type = module.get_type(lenfid)
                lenfield_type = module.get_type_name(lenfid)
                type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)

        # Add ourself to the structure by calling our original method.
        Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)

    def resolve(self, module):
        if self.resolved:
            return
        self.member.resolve(module)
        self.expr.resolve(module, self.parents)

        self.required_start_align = self.member.required_start_align

        # Find my length field again.  We need the actual Field object in the expr.
        # This is needed because we might have added it ourself above.
        if not self.fixed_size():
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == self.expr.lenfield_name and field.wire:
                        self.expr.lenfield = field
                        break

        self.resolved = True

    def fixed_size(self):
        return self.member.fixed_size() and self.expr.fixed_size()

    def unchecked_get_alignment_after(self, start_align, callstack, log):
        my_callstack = callstack[:]
        my_callstack.append(self)
        if start_align is None:
            log.fail(start_align, "", self, my_callstack, "start_align is None")
            return None
        if self.expr.fixed_size():
            # fixed number of elements
            num_elements = self.nmemb
            prev_alignment = None
            alignment = start_align
            while num_elements > 0:
                if alignment is None:
                    if log is not None:
                        log.fail(start_align, "", self, my_callstack,
                            ("fixed size list with size %d after %d iterations"
                            + ", at transition from alignment \"%s\"")
                            % (self.nmemb,
                               (self.nmemb - num_elements),
                               str(prev_alignment)))
                    return None
                prev_alignment = alignment
                alignment = self.member.get_alignment_after(prev_alignment, my_callstack, log)
                num_elements -= 1
            if log is not None:
                log.ok(start_align, "", self, my_callstack, alignment)
            return alignment
        else:
            # variable number of elements
            # check whether the number of elements is a multiple
            multiple = self.expr.get_multiple()
            assert multiple > 0

            # iterate until the combined alignment does not change anymore
            alignment = start_align
            while True:
                prev_multiple_alignment = alignment
                # apply "multiple" amount of changes sequentially
                prev_alignment = alignment
                for multiple_count in range(0, multiple):

                    after_alignment = self.member.get_alignment_after(prev_alignment, my_callstack, log)
                    if after_alignment is None:
                        if log is not None:
                            log.fail(start_align, "", self, my_callstack,
                                ("variable size list "
                                + "at transition from alignment \"%s\"")
                                % (str(prev_alignment)))
                        return None

                    prev_alignment = after_alignment

                # combine with the cumulatively combined alignment
                # (to model the variable number of entries)
                alignment = prev_multiple_alignment.combine_with(after_alignment)

                if alignment == prev_multiple_alignment:
                    # does not change anymore by adding more potential elements
                    # -> finished
                    if log is not None:
                        log.ok(start_align, "", self, my_callstack, alignment)
                    return alignment
Exemplo n.º 2
0
class ListType(Type):
    '''
    Derived class which represents a list of some other datatype.  Fixed- or variable-sized.

    Public fields added:
    member is the datatype of the list elements.
    parent is the structure type containing the list.
    expr is an Expression object containing the length information, for variable-sized lists.
    '''
    def __init__(self, elt, member, *parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parents = list(parent)

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None

    def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
        if not self.fixed_size():
            # We need a length field.
            # Ask our Expression object for it's name, type, and whether it's on the wire.
            lenfid = self.expr.lenfield_type
            lenfield_name = self.expr.lenfield_name
            lenwire = self.expr.lenwire
            needlen = True

            # See if the length field is already in the structure.
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == lenfield_name:
                        needlen = False

            # It isn't, so we need to add it to the structure ourself.
            if needlen:
                type = module.get_type(lenfid)
                lenfield_type = module.get_type_name(lenfid)
                type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)

        # Add ourself to the structure by calling our original method.
        Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)

    def resolve(self, module):
        if self.resolved:
            return
        self.member.resolve(module)
        self.expr.resolve(module, self.parents)

        # Find my length field again.  We need the actual Field object in the expr.
        # This is needed because we might have added it ourself above.
        if not self.fixed_size():
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == self.expr.lenfield_name and field.wire:
                        self.expr.lenfield = field
                        break

        self.resolved = True

    def fixed_size(self):
        return self.member.fixed_size() and self.expr.fixed_size()
Exemplo n.º 3
0
class ListType(Type):
    '''
    Derived class which represents a list of some other datatype.  Fixed- or variable-sized.

    Public fields added:
    member is the datatype of the list elements.
    parent is the structure type containing the list.
    expr is an Expression object containing the length information, for variable-sized lists.
    '''
    def __init__(self, elt, member, *parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parents = list(parent)
        lenfield_name = False

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
            is_list_in_parent = self.parents[0].elt.tag in ('request', 'event',
                                                            'reply', 'error')
            if not len(elts) and is_list_in_parent:
                self.expr = Expression(elt, self)
                self.expr.op = 'calculate_len'
            else:
                self.expr = Expression(elts[0] if len(elts) else elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None

        self.required_start_align = self.member.required_start_align

    def make_member_of(self,
                       module,
                       complex_type,
                       field_type,
                       field_name,
                       visible,
                       wire,
                       auto,
                       enum=None):
        if not self.fixed_size():
            # We need a length field.
            # Ask our Expression object for it's name, type, and whether it's on the wire.
            lenfid = self.expr.lenfield_type
            lenfield_name = self.expr.lenfield_name
            lenwire = self.expr.lenwire
            needlen = True

            # See if the length field is already in the structure.
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == lenfield_name:
                        needlen = False

            # It isn't, so we need to add it to the structure ourself.
            if needlen:
                type = module.get_type(lenfid)
                lenfield_type = module.get_type_name(lenfid)
                type.make_member_of(module, complex_type, lenfield_type,
                                    lenfield_name, True, lenwire, False, enum)

        # Add ourself to the structure by calling our original method.
        Type.make_member_of(self, module, complex_type, field_type, field_name,
                            visible, wire, auto, enum)

    def resolve(self, module):
        if self.resolved:
            return
        self.member.resolve(module)
        self.expr.resolve(module, self.parents)

        self.required_start_align = self.member.required_start_align

        # Find my length field again.  We need the actual Field object in the expr.
        # This is needed because we might have added it ourself above.
        if not self.fixed_size():
            for parent in self.parents:
                for field in parent.fields:
                    if field.field_name == self.expr.lenfield_name and field.wire:
                        self.expr.lenfield = field
                        break

        self.resolved = True

    def fixed_size(self):
        return self.member.fixed_size() and self.expr.fixed_size()

    def unchecked_get_alignment_after(self, start_align, callstack, log):
        my_callstack = callstack[:]
        my_callstack.append(self)
        if start_align is None:
            log.fail(start_align, "", self, my_callstack,
                     "start_align is None")
            return None
        if self.expr.fixed_size():
            # fixed number of elements
            num_elements = self.nmemb
            prev_alignment = None
            alignment = start_align
            while num_elements > 0:
                if alignment is None:
                    if log is not None:
                        log.fail(
                            start_align, "", self, my_callstack,
                            ("fixed size list with size %d after %d iterations"
                             + ", at transition from alignment \"%s\"") %
                            (self.nmemb,
                             (self.nmemb - num_elements), str(prev_alignment)))
                    return None
                prev_alignment = alignment
                alignment = self.member.get_alignment_after(
                    prev_alignment, my_callstack, log)
                num_elements -= 1
            if log is not None:
                log.ok(start_align, "", self, my_callstack, alignment)
            return alignment
        else:
            # variable number of elements
            # check whether the number of elements is a multiple
            multiple = self.expr.get_multiple()
            assert multiple > 0

            # iterate until the combined alignment does not change anymore
            alignment = start_align
            while True:
                prev_multiple_alignment = alignment
                # apply "multiple" amount of changes sequentially
                prev_alignment = alignment
                for multiple_count in range(0, multiple):

                    after_alignment = self.member.get_alignment_after(
                        prev_alignment, my_callstack, log)
                    if after_alignment is None:
                        if log is not None:
                            log.fail(start_align, "", self, my_callstack,
                                     ("variable size list " +
                                      "at transition from alignment \"%s\"") %
                                     (str(prev_alignment)))
                        return None

                    prev_alignment = after_alignment

                # combine with the cumulatively combined alignment
                # (to model the variable number of entries)
                alignment = prev_multiple_alignment.combine_with(
                    after_alignment)

                if alignment == prev_multiple_alignment:
                    # does not change anymore by adding more potential elements
                    # -> finished
                    if log is not None:
                        log.ok(start_align, "", self, my_callstack, alignment)
                    return alignment