Beispiel #1
0
def toFn(a, b):
    return SLICE.from_py(slice(a, b, 1))
Beispiel #2
0
def downtoFn(a, b):
    return SLICE.from_py(slice(a, b, -1))
Beispiel #3
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)
Beispiel #4
0
from hwt.hdl.value import Value, areValues
from hwt.hdl.types.defs import BOOL, INT, SLICE
from hwt.hdl.operator import Operator
from hwt.hdl.operatorDefs import AllOps
from hwt.hdl.types.typeCast import toHVal
from hwt.hdl.types.integer import Integer
from operator import pow, eq

BoolVal = BOOL.getValueCls()
SliceVal = SLICE.getValueCls()


def intOp__val(self, other, resT, evalFn):
    v = evalFn(self.val, other.val)
    vldMask = int(self.vldMask and other.vldMask)
    updateTime = max(self.updateTime, other.updateTime)
    return resT.getValueCls()(v, resT, vldMask, updateTime)


def intOp(self, other, op, resT, evalFn=None):
    if evalFn is None:
        evalFn = op._evalFn

    other = toHVal(other)._auto_cast(INT)
    if areValues(self, other):
        return intOp__val(self, other, resT, evalFn)
    else:
        return Operator.withRes(op, [self, other], resT)


def intAritmeticOp(self, other, op):
Beispiel #5
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