Exemplo n.º 1
0
 def check_bitwidth(self, concrete_type: ConcreteType) -> None:
   # TODO(leary): 2019-04-19 Because we punt on typechecking symbolic concrete
   # types here we'll need to do another pass to check whether numerical values
   # fit once the parametric symbols are instantiated as integers.
   if (isinstance(concrete_type, BitsType) and
       isinstance(concrete_type.get_total_bit_count(), int) and
       not bit_helpers.fits_in_bits(self.get_value_as_int(),
                                    concrete_type.get_total_bit_count())):
     msg = 'value {!r} does not fit in the bitwidth of a {} ({})'.format(
         self.value, concrete_type, concrete_type.get_total_bit_count())
     raise TypeInferenceError(span=self.span, type_=concrete_type, suffix=msg)
Exemplo n.º 2
0
def _deduce_slice_type(self: ast.Index, ctx: DeduceCtx,
                       lhs_type: ConcreteType) -> ConcreteType:
    """Deduces the concrete type of an Index AST node with a slice spec."""
    index_slice = self.index
    assert isinstance(index_slice, (ast.Slice, ast.WidthSlice)), index_slice

    # TODO(leary): 2019-10-28 Only slicing bits types for now, and only with
    # number ast nodes, generalize to arrays and constant expressions.
    if not isinstance(lhs_type, BitsType):
        raise XlsTypeError(self.span, lhs_type, None,
                           'Value to slice is not of "bits" type.')

    bit_count = lhs_type.get_total_bit_count()

    if isinstance(index_slice, ast.WidthSlice):
        start = index_slice.start
        if isinstance(start, ast.Number) and start.type_ is None:
            start_type = lhs_type.to_ubits()
            resolved_start_type = resolve(start_type, ctx)
            if not bit_helpers.fits_in_bits(
                    start.get_value_as_int(),
                    resolved_start_type.get_total_bit_count()):
                raise TypeInferenceError(
                    start.span, resolved_start_type,
                    'Cannot fit {} in {} bits (inferred from bits to slice).'.
                    format(start.get_value_as_int(),
                           resolved_start_type.get_total_bit_count()))
            ctx.type_info[start] = start_type
        else:
            start_type = deduce(start, ctx)

        # Check the start is unsigned.
        if start_type.signed:
            raise TypeInferenceError(
                start.span,
                type_=start_type,
                suffix='Start index for width-based slice must be unsigned.')

        width_type = deduce(index_slice.width, ctx)
        if isinstance(width_type.get_total_bit_count(), int) and isinstance(
                lhs_type.get_total_bit_count(),
                int) and width_type.get_total_bit_count(
                ) > lhs_type.get_total_bit_count():
            raise XlsTypeError(
                start.span, lhs_type, width_type,
                'Slice type must have <= original number of bits; attempted slice from {} to {} bits.'
                .format(lhs_type.get_total_bit_count(),
                        width_type.get_total_bit_count()))

        # Check the width type is bits-based (no enums, since value could be out
        # of range of the enum values).
        if not isinstance(width_type, BitsType):
            raise TypeInferenceError(
                self.span,
                type_=width_type,
                suffix='Require a bits-based type for width-based slice.')

        # The width type is the thing returned from the width-slice.
        return width_type

    assert isinstance(index_slice, ast.Slice), index_slice
    limit = index_slice.limit.get_value_as_int() if index_slice.limit else None
    # PyType has trouble figuring out that start is definitely an Number at this
    # point.
    start = index_slice.start
    assert isinstance(start, (ast.Number, type(None)))
    start = start.get_value_as_int() if start else None

    _, fn_symbolic_bindings = ctx.fn_stack[-1]
    if isinstance(bit_count, ParametricExpression):
        bit_count = bit_count.evaluate(fn_symbolic_bindings)
    start, width = bit_helpers.resolve_bit_slice_indices(
        bit_count, start, limit)
    key = tuple(fn_symbolic_bindings.items())
    ctx.type_info.add_slice_start_width(index_slice, key, (start, width))
    return BitsType(signed=False, size=width)
Exemplo n.º 3
0
    def test_fits_in_bits(self):
        self.assertTrue(bit_helpers.fits_in_bits(value=0xf, bit_count=4))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x7, bit_count=3))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x3, bit_count=2))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x1, bit_count=1))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x0, bit_count=0))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x0, bit_count=1))
        self.assertTrue(bit_helpers.fits_in_bits(value=0x0, bit_count=2))
        self.assertTrue(bit_helpers.fits_in_bits(value=0b110, bit_count=3))

        self.assertFalse(bit_helpers.fits_in_bits(value=0xf, bit_count=3))
        self.assertFalse(bit_helpers.fits_in_bits(value=0xf, bit_count=0))
        self.assertFalse(bit_helpers.fits_in_bits(value=0x7, bit_count=2))
        self.assertFalse(bit_helpers.fits_in_bits(value=0x3, bit_count=1))
        self.assertFalse(bit_helpers.fits_in_bits(value=0x1, bit_count=0))

        # Note: negative numbers that become too negative (large absolute value)
        # will not be expressible in a given bit count.
        self.assertTrue(bit_helpers.fits_in_bits(value=-1, bit_count=4))
        self.assertTrue(bit_helpers.fits_in_bits(value=-1, bit_count=3))
        self.assertTrue(bit_helpers.fits_in_bits(value=-1, bit_count=2))
        self.assertTrue(bit_helpers.fits_in_bits(value=-1, bit_count=1))

        self.assertTrue(bit_helpers.fits_in_bits(value=-1, bit_count=0))
        self.assertFalse(bit_helpers.fits_in_bits(value=-2, bit_count=1))
        self.assertFalse(bit_helpers.fits_in_bits(value=-3, bit_count=2))

        self.assertFalse(
            bit_helpers.fits_in_bits(value=0x100000000, bit_count=32))