Exemple #1
0
def toFn(a, b):
    return SLICE.from_py(slice(a, b, 1))
Exemple #2
0
    def __getitem__(self, key):
        """
        [] operator

        :attention: Table below is for litle endian bit order (MSB:LSB)
            which is default.
            This is **reversed** as it is in pure python
            where it is [0, len(self)].

        :attention: slice on slice f signal is automatically reduced
            to single slice

        +-----------------------------+----------------------------------------------------------------------------------+
        | a[up:low]                   | items low through up; a[16:8] selects upper byte from 16b vector a               |
        +-----------------------------+----------------------------------------------------------------------------------+
        | a[up:]                      | low is automatically substituted with 0; a[8:] will select lower 8 bits          |
        +-----------------------------+----------------------------------------------------------------------------------+
        | a[:end]                     | up is automatically substituted; a[:8] will select upper byte from 16b vector a  |
        +-----------------------------+----------------------------------------------------------------------------------+
        | a[:], a[-1], a[-2:], a[:-2] | raises NotImplementedError   (not implemented due to complicated support in hdl) |
        +-----------+----------------------------------------------------------------------------------------------------+
        """
        st = self._dtype
        length = st.bit_length()
        if length == 1 and not st.force_vector:
            # assert not indexing on single bit
            raise TypeError("indexing on single bit")

        if isinstance(key, slice):
            key = slice_to_SLICE(key, length)
            isSLICE = True
        else:
            isSLICE = isinstance(key, Slice.getValueCls())

        if isSLICE:
            # :note: downto notation
            start = key.val.start
            stop = key.val.stop
            if key.val.step != -1:
                raise NotImplementedError()
            startIsVal = isinstance(start, HValue)
            stopIsVal = isinstance(stop, HValue)
            indexesareHValues = startIsVal and stopIsVal
        else:
            key = toHVal(key, INT)

        iamVal = isinstance(self, HValue)
        iAmResultOfIndexing = (not iamVal and len(self.drivers) == 1
                               and isinstance(self.origin, Operator)
                               and self.origin.operator == AllOps.INDEX)

        Bits = self._dtype.__class__
        if isSLICE:
            if indexesareHValues and start.val == length and stop.val == 0:
                # selecting all bits no conversion needed
                return self

            if iAmResultOfIndexing:
                # try reduce self and parent slice to one
                original, parentIndex = self.origin.operands
                if isinstance(parentIndex._dtype, Slice):
                    parentLower = parentIndex.val.stop
                    start = start + parentLower
                    stop = stop + parentLower
                    return original[start:stop]

            # check start boundaries
            if startIsVal:
                _start = int(start)
                if _start < 0 or _start > length:
                    raise IndexError(_start, length)

            # check end boundaries
            if stopIsVal:
                _stop = int(stop)
                if _stop < 0 or _stop > length:
                    raise IndexError(_stop, length)

            # check width of selected range
            if startIsVal and stopIsVal and _start - _stop <= 0:
                raise IndexError(_start, _stop)

            if iamVal:
                if isinstance(key, SLICE.getValueCls()):
                    key = key.val
                v = Bits3val.__getitem__(self, key)
                if v._dtype.bit_length() == 1 and not v._dtype.force_vector:
                    assert v._dtype is not self._dtype
                    v._dtype.force_vector = True
                return v
            else:
                key = SLICE.from_py(slice(start, stop, -1))
                _resWidth = start - stop
                resT = Bits(bit_length=_resWidth,
                            force_vector=True,
                            signed=st.signed,
                            negated=st.negated)

        elif isinstance(key, Bits.getValueCls()):
            if key._is_full_valid():
                # check index range
                _v = int(key)
                if _v < 0 or _v > length - 1:
                    raise IndexError(_v)
                if iAmResultOfIndexing:
                    original, parentIndex = self.origin.operands
                    if isinstance(parentIndex._dtype, Slice):
                        parentLower = parentIndex.val.stop
                        return original[parentLower + _v]

            if iamVal:
                return Bits3val.__getitem__(self, key)

            resT = BIT
        elif isinstance(key, RtlSignalBase):
            t = key._dtype
            if isinstance(t, Slice):
                resT = Bits(bit_length=key.staticEval()._size(),
                            force_vector=True,
                            signed=st.signed,
                            negated=st.negated)
            elif isinstance(t, Bits):
                resT = BIT
            else:
                raise TypeError("Index operation not implemented"
                                " for index of type %r" % (t))

        else:
            raise TypeError("Index operation not implemented for index %r" %
                            (key))
        if st.negated and resT is BIT:
            resT = BIT_N
        return Operator.withRes(AllOps.INDEX, [self, key], resT)
Exemple #3
0
def downtoFn(a, b):
    return SLICE.from_py(slice(a, b, -1))
Exemple #4
0
def resolve_final_parts_from_splitpoints_and_parts(signal_parts):
    # :type: Dict[RtlSignal, Dict[Tuple[Tuple[int, int], ...], Union[HValue, RtlSignal]]]
    final_signal_parts = {}
    # split part intervals to non-overlapping chunks
    for s, parts in sorted(signal_parts.items(),
                           key=lambda x: RtlSignal_sort_key(x[0])):
        split_point = resolve_splitpoints(s, parts)
        split_point = sorted(split_point)
        # prepare part signals
        new_parts = []
        new_parts_dict = {}
        split_i = 0
        end = 0
        # :attention: parts are likely to contain parts with same indexes
        for indexes, can_directly_replace_with_src_expr, src in sorted(
                parts, key=lambda x: x[0]):
            if len(indexes) != 1:
                raise NotImplementedError()
            i = indexes[0]
            split_p = split_point[split_i]
            if isinstance(i, BitsVal):
                low = int(i)
                high = low + 1
                index_key = ((high, low), )
            else:
                assert isinstance(i, SliceVal), (s, i)
                if i.val.step != -1:
                    raise NotImplementedError(s, i)
                high, low = int(i.val.start), int(i.val.stop)
                index_key = ((high, low), )

            while split_p < low:
                # some parts at the beginning are skiped
                # that means that that part is not driven by anything
                # and we need to check default and nop value
                part_indexes = (SLICE.from_py(slice(low, split_p, -1)), )
                _src = construct_tmp_dst_sig_for_slice(s, part_indexes, None,
                                                       False)
                new_parts.append(_src)
                _index_key = ((low, split_p), )
                new_parts_dict[_index_key] = _src, True
                split_i += 1
                split_p = split_point[split_i]

            this_start_split_p_i = split_i
            if split_p > low:
                # some parts at the beginning were already resolved
                # This can happen if there was some part which started on some <= index and overlaps with this part.
                try:
                    _, _can_directly_replace_with_src_expr = new_parts_dict[
                        index_key]
                    assert not _can_directly_replace_with_src_expr, (s,
                                                                     index_key)
                    # was already resolved and checked no need to check it again
                    continue
                except KeyError:
                    pass

                for i in range(split_i, -1, -1):
                    _sp = split_point[i]
                    if _sp == low:
                        this_start_split_p_i = i

            assert split_point[this_start_split_p_i] == low
            # just at the start of this slice
            next_split_p = split_point[this_start_split_p_i + 1]
            assert next_split_p <= high, "The next split point can be at most end of current part"
            if next_split_p == high:
                assert this_start_split_p_i == split_i, "We should see this part for the first time or the split_i should already be higher"
                # all bits on this slice are alwyas driven at once, we can instantiate whole part
                assert split_p == low
                _src = construct_tmp_dst_sig_for_slice(
                    s, indexes, src, not can_directly_replace_with_src_expr)
                new_parts.append(_src)
                assert index_key not in new_parts_dict, (s, index_key)
                new_parts_dict[
                    index_key] = _src, can_directly_replace_with_src_expr
                split_i += 1
            else:
                # list of part keys for later search
                _split_parts = []
                prev_sp = split_point[this_start_split_p_i]
                dst_offset = low
                assert not can_directly_replace_with_src_expr
                # continue instanciating parts until we reach the end of this part
                for sp_i, sp in zip(
                        range(this_start_split_p_i + 1, len(split_point)),
                        islice(split_point, this_start_split_p_i + 1, None)):
                    # need to generate sub slice
                    # because this slice has actually multiple individualy driven parts

                    # we need to generate all slice parts because there could be a case where only some sub parts are
                    # driven elsewhere and we would othervise resolve those segments as a constantly driven
                    # but they are in fact driven from this slice
                    if sp > high:
                        break

                    part_key = ((sp, prev_sp), )
                    if sp_i <= split_i:
                        # check if the slice is not driven from some top level constant assignment
                        # which would result is multiple drivers of this slice
                        assert src is None
                        existing_part, _can_directly_replace_with_src_expr = new_parts_dict[
                            part_key]
                        assert not _can_directly_replace_with_src_expr, (
                            s, low, high, existing_part)
                        assert not can_directly_replace_with_src_expr, (
                            s, low, high, existing_part)
                        assert isinstance(existing_part,
                                          RtlSignal), (s, low, high,
                                                       existing_part)
                    else:
                        assert sp_i == split_i + 1, (s, sp_i, split_i)
                        # get actual input signal
                        if src is None:
                            _src = None
                        else:
                            _src = src[sp - dst_offset:prev_sp - dst_offset]

                        part_indexes = (SLICE.from_py(slice(sp, prev_sp,
                                                            -1)), )
                        _src = construct_tmp_dst_sig_for_slice(
                            s, part_indexes, _src, True)

                        new_parts.append(_src)
                        new_parts_dict[
                            part_key] = _src, can_directly_replace_with_src_expr

                        split_i += 1
                    _split_parts.append(part_key)
                    prev_sp = sp

                new_parts_dict[index_key] = _split_parts, False

            end = max(end, high)

        if end < split_point[-1]:
            # something unconnected at the end
            high, low = split_point[-1], end
            part_indexes = (SLICE.from_py(slice(high, low, -1)), )
            _src = construct_tmp_dst_sig_for_slice(s, part_indexes, None,
                                                   False)
            new_parts.append(_src)
            index_key = ((high, low), )
            new_parts_dict[index_key] = _src, True

        # construct assignment of concatenation from all parts
        assert new_parts, (s, parts)
        s(Concat(*reversed(new_parts)))
        final_signal_parts[s] = new_parts_dict

    return final_signal_parts