예제 #1
0
    def test_non_mergable_no_ack(self, N=10, randomized=False):
        u = self.u
        u.w._ag.data.extend(
            (i, 10 + i, mask(u.CACHE_LINE_SIZE)) for i in range(N))
        if randomized:
            self.randomize_all()

        self.runSim((N + 10) * 2 * CLK_PERIOD * u.BUS_WORDS_IN_CACHE_LINE)

        SIZE = 2**u.ID_WIDTH
        aw = u.m.aw._ag
        self.assertValSequenceEqual(aw.data, [
            aw.create_addr_req(addr=u.CACHE_LINE_SIZE * i,
                               _len=u.BUS_WORDS_IN_CACHE_LINE - 1,
                               _id=i) for i in range(min(SIZE, N))
        ])

        w_ref = []
        for i in range(min(SIZE, N)):
            for last, w_i in iter_with_last(range(u.BUS_WORDS_IN_CACHE_LINE)):
                d = (10 + i if w_i == 0 else 0, mask(u.DATA_WIDTH // 8),
                     int(last))
                w_ref.append(d)
        # for i, (x0, x1) in enumerate(zip(u.m.w._ag.data, w_ref)):
        #    print(i, allValuesToInts(x0), x1)

        self.assertValSequenceEqual(u.m.w._ag.data, w_ref)

        # 1 item is currently handled by agent, 1 item in tmp reg
        self.assertEqual(len(u.w._ag.data), N - SIZE - 1 - 1)
예제 #2
0
def bitsArithOp__val(self: Bits3val, other: Union[Bits3val, int],
                     evalFn) -> "Bits3val":
    """
    Apply arithmetic operator
    """
    if isinstance(other, int):
        other = self._dtype.from_py(other)
    v = self.__copy__()
    self_vld = self._is_full_valid()
    other_vld = other._is_full_valid()

    v.val = evalFn(self.val, other.val)

    w = v._dtype.bit_length()
    if self._dtype.signed:
        _v = v.val
        _max = mask(w - 1)
        _min = -_max - 1
        if _v > _max:
            _v = _min + (_v - _max - 1)
        elif _v < _min:
            _v = _max - (_v - _min + 1)

        v.val = _v
    else:
        v.val &= mask(w)

    if self_vld and other_vld:
        v.vld_mask = mask(w)
    else:
        v.vld_mask = 0

    return v
예제 #3
0
def bitsCmp_detect_useless_cmp(op0, op1, op):
    v = int(op1)
    width = op1._dtype.bit_length()
    if op0._dtype.signed:
        min_val = -1 if width == 1 else mask(width - 1) - 1
        max_val = 0 if width == 1 else mask(width - 1)
    else:
        min_val = 0
        max_val = mask(width)

    if v == min_val:
        # value can not be lower than min_val
        if op == AllOps.GE:
            # -> always True
            return BOOL.from_py(1, 1)
        elif op == AllOps.LT:
            # -> always False
            return BOOL.from_py(0, 1)
        elif op == AllOps.LE:
            # convert <= to == to highlight the real function
            return AllOps.EQ
    elif v == max_val:
        # value can not be greater than max_val
        if op == AllOps.GT:
            # always False
            return BOOL.from_py(0, 1)
        elif op == AllOps.LE:
            # always True
            return BOOL.from_py(1, 1)
        elif op == AllOps.GE:
            # because value can not be greater than max
            return AllOps.EQ
예제 #4
0
    def test_write(self, N=20, randomize=False):
        u = self.u
        s_w = u.s_w
        axi = u.m

        m = AxiSimRam(axi=axi)
        M_DW = axi.DATA_WIDTH
        FRAME_WORD_CNT = ceil((u.S_ADDR_STEP) / M_DW)
        w_data = [
            i  # self._rand.getrandbits(M_DW)
            for i in range(N * FRAME_WORD_CNT)
        ]
        # create data words for P4AppPort
        wr_data = self.pack_words(w_data, M_DW, s_w.DATA_WIDTH)

        for addr, frame in enumerate(wr_data):
            s_w._ag.data.append((addr, frame))

        if randomize:
            axi_randomize_per_channel(self, axi)

        self.runSim(N * FRAME_WORD_CNT * 10 * CLK_PERIOD)

        w_m = mask(
            s_w.DATA_WIDTH) if s_w.DATA_WIDTH < axi.DATA_WIDTH else mask(
                axi.DATA_WIDTH)
        addr = u.M_ADDR_OFFSET
        inMem = m.getArray(addr, M_DW // 8, FRAME_WORD_CNT * N)
        inMem = [None if v is None else v & w_m for v in inMem]
        self.assertValSequenceEqual(inMem, w_data)
예제 #5
0
    def generateRequests(self, baseAddress, spaceValues):
        """
        Generate reference requests and data
        data words are containing it's indexes,
        baseAddresses are multiplies baseAddress

        :param spaceValues: is iterable of space values
        """
        requests = []
        responses = []
        wordCntr = 0
        inBlockRem = self.ITEMS_IN_BLOCK
        _baseAddress = baseAddress
        for space in spaceValues:
            while space != 0:
                constraingSpace = min(inBlockRem, space)
                reqId = self.ID
                if constraingSpace > self.MAX_LEN + 1:
                    reqLen = self.MAX_LEN
                elif inBlockRem == 0:
                    reqLen = 0
                    reqId = self.ID_LAST
                else:
                    if (constraingSpace <= self.MAX_LEN + 1
                            and inBlockRem < self.MAX_LEN + 1):
                        # we will download next* as well
                        reqLen = constraingSpace
                        reqId = self.ID_LAST
                    else:
                        # if constraingSpace == inBlockRem:
                        #    reqId = self.ID_LAST
                        #    reqLen = constraingSpace
                        # else:
                        reqLen = constraingSpace - 1

                inBlockIndex = self.ITEMS_IN_BLOCK - inBlockRem
                req = (reqId, _baseAddress + inBlockIndex * 8, reqLen, 0)
                requests.append(req)

                for i in range(reqLen + 1):
                    if i == reqLen and reqId == self.ID_LAST:
                        r = (reqId, baseAddress, mask(8), True)
                        _baseAddress += baseAddress
                    else:
                        r = (reqId, wordCntr + i, mask(8), i == reqLen)

                    responses.append(r)

                if reqId == self.ID_LAST:
                    inBlockRem = self.ITEMS_IN_BLOCK
                    wordCntr += reqLen
                    space -= reqLen
                else:
                    inBlockRem -= reqLen + 1
                    wordCntr += reqLen + 1
                    space -= reqLen + 1

        return requests, responses
예제 #6
0
    def test_noLast(self):
        u = self.u

        u.dataIn._ag.data.append((it(16, 1, 2, 3, 4),
                                  it(2, mask(2), mask(2), mask(2), mask(2)),
                                  0))
        self.runSim(200 * Time.ns)

        self.assertValSequenceEqual(u.dataOut._ag.data,
                                    [(i + 1, mask(2), 0) for i in range(4)])
예제 #7
0
    def test_singleWordPacket(self):
        u = self.u

        u.dataIn._ag.data.extend([
            (2, mask(8), 1),
        ])

        self.runSim(20 * CLK_PERIOD)
        self.assertValSequenceEqual(u.sizes._ag.data, [8, ])
        self.assertValSequenceEqual(u.dataOut._ag.data, [(2, mask(8), 1), ])
예제 #8
0
    def test_simple(self):
        u = self.u

        # (data, strb, user, last)
        d = [(13, mask(8), 0b01, 0), (14, mask(1), 0b10, 1)]

        u.dataIn._ag.data.extend(d)
        self.runSim(200 * Time.ns)

        self.assertValSequenceEqual(u.dataOut._ag.data, d)
예제 #9
0
    def test_pass(self):
        u = self.u

        u.a._ag.data.extend([(11, mask(u.a.strb._dtype.bit_length()), 1),
                             NOP,
                             (12, mask(u.a.strb._dtype.bit_length()), 1)
                             ])

        self.runSim(200 * Time.ns)
        self.assertEqual(len(u.b._ag.data), 2)
예제 #10
0
    def _impl(self):
        propagateClkRstn(self)
        dIn = AxiSBuilder(self, self.dataIn).buff().end

        sb = self.sizesBuff
        db = self.dataBuff

        wordCntr = self._reg("wordCntr",
                             Bits(log2ceil(self.MAX_LEN) + 1),
                             def_val=0)

        overflow = wordCntr._eq(self.MAX_LEN)
        last = dIn.last | overflow
        If(
            StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn]).ack(),
            If(last, wordCntr(0)).Else(wordCntr(wordCntr + 1)))

        length = self._sig("length", wordCntr._dtype)
        BYTE_CNT = dIn.data._dtype.bit_length() // 8
        if dIn.USE_STRB:
            # compress strb mask as binary number
            rem = self._sig("rem", Bits(log2ceil(BYTE_CNT)))

            SwitchLogic(cases=[(dIn.strb[i],
                                rem(0 if i == BYTE_CNT - 1 else i + 1))
                               for i in reversed(range(BYTE_CNT))],
                        default=[
                            rem(0),
                        ])
            if self.EXPORT_ALIGNMENT_ERROR:
                errorAlignment = self._reg("errorAlignment_reg", def_val=0)
                self.errorAlignment(errorAlignment)
                If(dIn.valid & (dIn.strb != mask(BYTE_CNT)) & ~dIn.last,
                   errorAlignment(1))

            If(last & (dIn.strb != mask(BYTE_CNT)),
               length(wordCntr)).Else(length(wordCntr + 1))
        else:
            length(wordCntr + 1)
            rem = Bits(log2ceil(BYTE_CNT)).from_py(0)

        sb.dataIn.data(Concat(length, rem))

        db.dataIn(dIn, exclude=[dIn.valid, dIn.ready, dIn.last])
        db.dataIn.last(last)

        StreamNode(masters=[dIn],
                   slaves=[sb.dataIn, db.dataIn],
                   extraConds={
                       sb.dataIn: last
                   }).sync()

        self.sizes(sb.dataOut)
        self.dataOut(db.dataOut)
예제 #11
0
    def test_simple_mask_7_outof_8(self):
        u = self.setUpCrc(CRC_32, use_mask=True)
        inp = b"abcdefg"

        u.dataIn._ag.data.extend([(stoi(inp[0:4]), mask(32 // 8), 0),
                                  (stoi(inp[4:]), mask(24 // 8), 1)])
        # u.dataIn._ag.data.extend([ord("a") for _ in range(4)])
        self.runSim(40 * Time.ns)
        out = int(u.dataOut._ag.data[-1])
        ref = crc32(inp)
        self.assertEqual(out, ref, "0x{:08X} 0x{:08X}".format(out, ref))
예제 #12
0
    def test_onlyPartOfMask(self):
        u = self.u
        u.dataIn._ag.data.append(
            (it(16, 1, 2, 3, 4),
             it(2, mask(2), 0, 0, 0),
             1)
        )
        self.runSim(200 * Time.ns)

        self.assertValSequenceEqual(u.dataOut._ag.data,
                                    [(1, mask(2), 1),
                                     ])
예제 #13
0
    def test_u8b_proper_val(self):
        self.test_8b_proper_val(uint8_t)
        t = uint8_t
        with self.assertRaises(ValueError):
            t.from_py("0b0000000e")

        v = t.from_py("0b0000000x")
        self.assertEqual(v.val, 0)
        self.assertEqual(v.vld_mask, mask(7) << 1)

        v = t.from_py("0bxx000000")
        self.assertEqual(v.val, 0)
        self.assertEqual(v.vld_mask, mask(6))
예제 #14
0
    def test_doubleWordPacket(self):
        u = self.u
        sizes = u.sizes._ag.data
        data = u.dataOut._ag.data

        goldenData = [(1, mask(8), 0),
                      (2, mask(8), 1)
                      ]
        u.dataIn._ag.data.extend(goldenData)

        self.runSim(20 * CLK_PERIOD)
        self.assertValSequenceEqual(data, goldenData)
        self.assertValSequenceEqual(sizes, (16,))
예제 #15
0
def axis_mask_propagate_best_effort(src: AxiStream, dst: AxiStream):
    res = []
    if src.USE_STRB:
        if not src.USE_KEEP and not dst.USE_STRB and dst.USE_KEEP:
            res.append(dst.keep(src.strb))
    if src.USE_KEEP:
        if not src.USE_STRB and not dst.USE_KEEP and dst.USE_STRB:
            res.append(dst.strb(src.keep))
    if not src.USE_KEEP and not src.USE_STRB:
        if dst.USE_KEEP:
            res.append(dst.keep(mask(dst.keep._dtype.bit_length())))
        if dst.USE_STRB:
            res.append(dst.strb(mask(dst.strb._dtype.bit_length())))
    return res
예제 #16
0
 def test_8b_cast(self, t=int8_t):
     w = t.bit_length()
     if t.signed:
         ut = Bits3t(w)
     else:
         ut = t
         t = Bits3t(w, True)
     self.assertEqual(int(t.from_py(-1).cast(ut)), mask(w))
     self.assertEqual(int(t.from_py(-1).cast_sign(False)), mask(w))
     self.assertEqual(int(t.from_py(-1).cast_sign(None)), mask(w))
     self.assertEqual(int(t.from_py(1).cast(ut)), 1)
     self.assertEqual(int(t.from_py(0).cast(ut)), 0)
     self.assertEqual(int(ut.from_py(1).cast(t)), 1)
     self.assertEqual(int(ut.from_py(mask(w)).cast(t)), -1)
     self.assertEqual(int(ut.from_py(mask(w)).cast_sign(True)), -1)
예제 #17
0
    def test_multiplePackets(self):
        u = self.u
        sizes = u.sizes._ag.data
        data = u.dataOut._ag.data

        goldenData = [(1, mask(8), 1),
                      (2, mask(8), 1),
                      (3, mask(8), 1)
                      ]

        u.dataIn._ag.data.extend(goldenData)

        self.runSim(20 * CLK_PERIOD)
        self.assertValSequenceEqual(data, goldenData)
        self.assertValSequenceEqual(sizes, [8, 8, 8])
예제 #18
0
    def test_noPass(self):
        u = self.u
        u.dataIn._ag.data.extend([(1, mask(2), 0) for _ in range(2)])

        self.runSim(200 * Time.ns)

        self.assertEmpty(u.dataOut._ag.data)
예제 #19
0
    def test_passData(self):
        u = self.u
        expectedW = []

        for i, driver in enumerate(u.drivers):
            _id = i + 1
            _len = i + 1
            driver.req._ag.data.append((_id, i + 1, _len, 0))
            strb = mask(u.DATA_WIDTH // 8)
            for i2 in range(_len + 1):
                _data = i + i2 + 1
                last = int(i2 == _len)
                d = (_data, strb, last)
                driver.w._ag.data.append(d)
                expectedW.append(d)

        self.runSim(80 * Time.ns)

        req = u.wDatapump.req._ag.data
        wData = u.wDatapump.w._ag.data

        for i, _req in enumerate(req):
            self.assertValSequenceEqual(_req, (i + 1, i + 1, i + 1, 0))

        self.assertEqual(len(req), self.DRIVER_CNT)

        for w, expW in zip(wData, expectedW):
            self.assertValSequenceEqual(w, expW)
예제 #20
0
    def test_write(self, n=4 * (512 // 32), n2=2, magic=99, randomize=False):
        u = self.u
        in_addr_step = u.DATA_WIDTH // 8
        out_addr_step = u.OUT_DATA_WIDTH // 8
        in_words_in_out_word = out_addr_step // in_addr_step
        w_data = []
        for _ in range(n2):
            for in_i in range(n):
                u.s.aw._ag.data.append((in_i * in_addr_step, PROT_DEFAULT))
                in_w = magic + in_i
                w_data.append(in_w)
        u.s.w._ag.data.extend([(d, mask(in_addr_step)) for d in w_data])

        m = Axi4LiteSimRam(u.m)

        in_t = Bits(u.DATA_WIDTH)[n]
        out_t = Bits(u.OUT_DATA_WIDTH)[n // in_words_in_out_word]

        t = n2 * n
        if randomize:
            self.randomize_all()
            t *= 5

        self.runSim((t + 10) * CLK_PERIOD)
        v = m.getArray(0x0, out_addr_step, n // in_words_in_out_word)
        v = out_t.from_py(v)._reinterpret_cast(in_t)

        self.assertValSequenceEqual(v, w_data[n * (n2 - 1):])
예제 #21
0
파일: test.py 프로젝트: mfkiwl/hwtLib
    def test_s2Pading_normal(self):
        u = self.u = AxiS_frameDeparser(s2Pading)
        self.DATA_WIDTH = 64
        u.USE_STRB = u.USE_KEEP = True
        u.DATA_WIDTH = self.DATA_WIDTH
        m = mask(self.DATA_WIDTH // 8)
        self.compileSimAndStart(self.u)

        def enDataOut():
            u.dataOut._ag.enable = False
            yield Timer(50 * Time.ns)
            u.dataOut._ag.enable = True

        self.procs.append(enDataOut())

        MAGIC = 468
        u.dataIn.item0_0._ag.data.append(MAGIC)
        u.dataIn.item0_1._ag.data.append(MAGIC + 1)
        u.dataIn.item1_0._ag.data.append(MAGIC + 2)
        u.dataIn.item1_1._ag.data.append(MAGIC + 3)

        t = 200
        self.runSim(t * Time.ns)

        self.assertValSequenceEqual(u.dataOut._ag.data, [
            (MAGIC, m, m, 0),
            (MAGIC + 1, m, m, 0),
            (None, 0, m, 0),
            (MAGIC + 2, m, m, 0),
            (MAGIC + 3, m, m, 0),
            (None, 0, m, 1),
        ])
예제 #22
0
파일: test.py 프로젝트: mfkiwl/hwtLib
    def test_3Fields_outOccupiedAtStart(self):
        u = self.u = AxiS_frameDeparser(s3field)
        u.USE_STRB = u.USE_KEEP = True
        u.DATA_WIDTH = self.DATA_WIDTH = 64
        m = mask(self.DATA_WIDTH // 8)

        self.compileSimAndStart(self.u)

        def enDataOut():
            u.dataOut._ag.enable = False
            yield Timer(50 * Time.ns)
            u.dataOut._ag.enable = True

        self.procs.append(enDataOut())

        MAGIC = 468
        u.dataIn.item0._ag.data.append(MAGIC)
        u.dataIn.item1._ag.data.append(MAGIC + 1)
        u.dataIn.item2._ag.data.append(MAGIC + 2)

        t = 200
        self.runSim(t * Time.ns)

        self.assertValSequenceEqual(u.dataOut._ag.data, [
            (MAGIC, m, m, 0),
            (MAGIC + 1, m, m, 0),
            (MAGIC + 2, m, m, 1),
        ])
예제 #23
0
    def test_3to1(self):
        def set_dw_in(intf):
            intf.DATA_WIDTH = 3 * 32

        def set_dw_out(intf):
            intf.DATA_WIDTH = 32

        u = HsResizer(Handshaked, [3, 1], set_dw_in, set_dw_out)
        self.compileSimAndStart(u)
        # self.randomize(u.dataIn)
        # self.randomize(u.dataOut)
        N = 9

        d = [self._rand.getrandbits(3 * 32) for _ in range(N)]

        u.dataIn._ag.data.extend(d)

        self.runSim(3 * N * 40 * Time.ns)

        expected = []
        m = mask(32)
        for a in d:
            expected.extend([a & m, (a >> 32) & m, (a >> 64) & m])

        self.assertValSequenceEqual(u.dataOut._ag.data, expected)
예제 #24
0
파일: intf.py 프로젝트: mfkiwl/hwtLib
    def set_data(self, data):
        intf = self.intf
        if data is None:
            intf.addr.write(None)
            intf.be.write(None)
            intf.rd.write(0)
            intf.wr.write(0)
        else:
            rw = data[0]
            if rw is READ:
                _, address = data
                rd, wr = 1, 0
                be = mask(intf.DATA_WIDTH // 8)
                wdata = None
            elif rw is WRITE:
                rd, wr = 0, 1
                _, address, wdata, be = data
            elif rw is READ_WRITE:
                rd, wr = 1, 1
                _, address, wdata, be = data
            else:
                raise TypeError(f"rw is in invalid format {rw}")

            intf.addr.write(address)
            intf.rd.write(rd)
            intf.wr.write(wr)
            intf.be.write(be)
            intf.dwr.write(wdata)
예제 #25
0
    def __lshift__(self, other: Union[int, "Bits3val"]) -> "Bits3val":
        "Operator <<."
        try:
            o = int(other)
        except ValidityError:
            o = None

        v = self.__copy__()
        if o is None:
            v.vld_mask = 0
            v.val = 0
        elif o == 0:
            return v
        else:
            if o < 0:
                raise ValueError("negative shift count")
            t = self._dtype
            m = t.all_mask()
            v.vld_mask <<= o
            v.vld_mask |= mask(o)
            v.vld_mask &= m
            v.val <<= o
            v.val &= m
            if t.signed:
                v.val = to_signed(v.val, t.bit_length())
        return v
예제 #26
0
 def data_transaction(self, id_, data):
     transactions = []
     DW = self.u.s[0].w.DATA_WIDTH
     m = mask(DW // 8)
     for is_last, d in iter_with_last(data):
         transactions.append((d, m, int(is_last)))
     return transactions
예제 #27
0
    def set_data(self, data):
        intf = self.intf
        if data is None:
            intf.address.write(None)
            intf.byteEnable.write(None)
            if intf.MAX_BURST != 0:
                intf.burstCount.write(None)
            intf.read.write(0)
            intf.write.write(0)

        else:
            rw, address, burstCount = data
            if rw is READ:
                rd, wr = 1, 0
                be = mask(intf.readData._dtype.bit_length() // 8)
            elif rw is WRITE:
                rd, wr = 0, 1
                rw, address, burstCount = data
                d, be = self.wData.popleft()
                intf.writeData.write(d)
            else:
                raise TypeError(f"rw is in invalid format {rw}")

            intf.address.write(address)
            intf.byteEnable.write(be)
            assert int(burstCount) >= 1, burstCount
            if intf.MAX_BURST:
                intf.burstCount.write(burstCount)
            intf.read.write(rd)
            intf.write.write(wr)
예제 #28
0
    def test_pass_data(self, N=8):
        assert N % 2 == 0, N
        u = self.u
        m = mask(u.s.DATA_WIDTH // 8)
        STEP = u.s.DATA_WIDTH // 8

        # rw, address, burstCount
        inAddr = [(READ if (i % 2) == 0 else WRITE, i * STEP, 1)
                  for i in range(N)]
        u.s._ag.req.extend(inAddr)
        # d, be
        inW = [(i + 1, m) for i in range(N // 2)]
        u.s._ag.wData.extend(inW)

        # readData, response
        inR = [(i + 1, RESP_OKAY) for i in range(N // 2)]
        u.m._ag.rData.extend(inR)
        inWResp = [RESP_OKAY for _ in range(N // 2)]
        u.m._ag.wResp.extend(inWResp)

        t = N + 5
        self.runSim(t * CLK_PERIOD)

        ae = self.assertValSequenceEqual
        ae(u.m._ag.req, inAddr)
        ae(u.m._ag.wData, inW)
        ae(u.s._ag.rData, inR)
        ae(u.s._ag.wResp, inWResp)
예제 #29
0
    def _count_leading_recurse(cls, data_in: RtlSignal, bit_to_count: int):
        """
        Construct a balanced tree for counter of leading 0/1
        :atterntion: result is for

        """
        assert bit_to_count in (0, 1), bit_to_count
        in_width = data_in._dtype.bit_length()
        if in_width == 2:
            if bit_to_count == 0:
                return ~data_in[1]
            else:
                return data_in[1]
        else:
            assert in_width > 2, in_width
            lhs = data_in[:in_width // 2]
            rhs = data_in[in_width // 2:]
            if bit_to_count == 0:
                left_full = lhs._eq(0)
            else:
                left_full = lhs._eq(mask(lhs._dtype.bit_length()))

            in_ = left_full._ternary(rhs, lhs)
            half_count = cls._count_leading_recurse(in_, bit_to_count)
        return Concat(left_full, half_count)
예제 #30
0
def convertBits__val(self: Bits, val: "BitVal", toType: HdlType):
    if toType == BOOL:
        return val != self.getValueCls().from_py(self, 0)
    elif isinstance(toType, Bits):
        if self.signed != toType.signed:
            if self.strict_sign and bool(self.signed) != bool(toType.signed):
                raise TypeConversionErr(self, toType)
            val = val._convSign__val(toType.signed)

        w_from, w_to = self.bit_length(), toType.bit_length()
        if w_from != w_to:
            if self.strict_width:
                raise TypeConversionErr(self, toType)
            if w_from > w_to:
                # cut off some bits from value
                new_m = val.vld_mask & toType.all_mask()
            else:
                # w_from < w_to, extend the value to some bit length
                extra_mask_bits = mask(w_to - w_from)
                new_m = set_bit_range(val.vld_mask, w_from, w_to - w_from,
                                      extra_mask_bits)
            val = toType.from_py(val.val, new_m)

        if val._dtype != toType:
            # sign and width checked, only name, strict_* flags can be different
            val = toType.from_py(val.val, val.vld_mask)
        return val
    elif toType == INT:
        return INT.getValueCls()(INT, val.val, int(val._is_full_valid()))

    return default_auto_cast_fn(self, val, toType)