Esempio n. 1
0
 def test_equality(self):
     fake_pos = span.Pos('<fake>', 0, 0)
     fake_span = span.Span(fake_pos, fake_pos)
     p = BitsType(signed=False, size=ParametricSymbol('N', fake_span))
     c = BitsType(signed=False, size=32)
     self.assertTrue(p.__ne__(c))
     self.assertFalse(p.__eq__(c))
Esempio n. 2
0
 def test_generate_tuple_argument(self):
     rng = random.Random(0)
     args = sample_generator.generate_arguments((TupleType((BitsType(
         signed=False, size=123), BitsType(signed=True, size=22))), ), rng)
     self.assertLen(args, 1)
     self.assertTrue(args[0].is_tuple())
     self.assertEqual(args[0].tuple_members[0].get_bit_count(), 123)
     self.assertEqual(args[0].tuple_members[1].get_bit_count(), 22)
Esempio n. 3
0
 def test_generate_mixed_bits_arguments(self):
     rng = random.Random(0)
     args = sample_generator.generate_arguments(
         (BitsType(signed=False, size=123), BitsType(signed=True, size=22)),
         rng)
     self.assertLen(args, 2)
     self.assertTrue(args[0].is_ubits())
     self.assertEqual(args[0].get_bit_count(), 123)
     self.assertTrue(args[1].is_sbits())
     self.assertEqual(args[1].get_bit_count(), 22)
Esempio n. 4
0
    def test_arrayness(self):
        tabular = [
            # (type, is_array, element_count)
            (TupleType(members=()), False, None),
            (BitsType(signed=False, size=5), False, None),
            (ArrayType(BitsType(False, 5), 7), True, 7),
            (ArrayType(TupleType(members=()), 7), True, 7),
        ]

        for t, is_array, element_count in tabular:
            self.assertEqual(isinstance(t, ArrayType), is_array, msg=str(t))
            if is_array:
                self.assertEqual(t.size, element_count, msg=str(t))
Esempio n. 5
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    _Checker(arg_types, name, span).len(2).is_uN((0, 1))
    return_type = BitsType(signed=False,
                           size=arg_types[0].get_total_bit_count() +
                           arg_types[1].get_total_bit_count())
    return FunctionType(arg_types, return_type)
Esempio n. 6
0
 def test_generate_single_bits_arguments(self):
     rng = random.Random(0)
     args = sample_generator.generate_arguments(
         (BitsType(signed=False, size=42), ), rng)
     self.assertLen(args, 1)
     self.assertTrue(args[0].is_ubits())
     self.assertEqual(args[0].get_bit_count(), 42)
Esempio n. 7
0
def _deduce_Concat(self: ast.Binop, ctx: DeduceCtx) -> ConcreteType:
    """Deduces the concrete type of a concatenate Binop AST node."""
    lhs_type = deduce(self.lhs, ctx)
    resolved_lhs_type = resolve(lhs_type, ctx)
    rhs_type = deduce(self.rhs, ctx)
    resolved_rhs_type = resolve(rhs_type, ctx)

    # Array-ness must be the same on both sides.
    if (isinstance(resolved_lhs_type, ArrayType) != isinstance(
            resolved_rhs_type, ArrayType)):
        raise XlsTypeError(
            self.span, resolved_lhs_type, resolved_rhs_type,
            'Attempting to concatenate array/non-array values together.')

    if (isinstance(resolved_lhs_type, ArrayType)
            and resolved_lhs_type.get_element_type() !=
            resolved_rhs_type.get_element_type()):
        raise XlsTypeError(
            self.span, resolved_lhs_type, resolved_rhs_type,
            'Array concatenation requires element types to be the same.')

    new_size = resolved_lhs_type.size + resolved_rhs_type.size  # pytype: disable=attribute-error
    if isinstance(resolved_lhs_type, ArrayType):
        return ArrayType(resolved_lhs_type.get_element_type(), new_size)

    return BitsType(signed=False, size=new_size)
Esempio n. 8
0
    def test_array_vs_multidim_bits_equality(self):
        a = ArrayType(BitsType(signed=False, size=5), 7)
        self.assertEqual(str(a), 'uN[5][7]')
        self.assertEqual(7 * 5, a.get_total_bit_count())
        self.assertEqual(7, a.size)
        self.assertEqual(5, a.get_element_type().size)  # pytype: disable=attribute-error
        self.assertEqual((7, 5), a.get_all_dims())

        self.assertEqual((), TupleType(()).get_all_dims())
Esempio n. 9
0
 def test_generate_array_argument(self):
     rng = random.Random(0)
     args = sample_generator.generate_arguments(
         (ArrayType(BitsType(signed=True, size=4), 24), ), rng)
     self.assertLen(args, 1)
     self.assertTrue(args[0].is_array())
     self.assertLen(args[0].array_payload.elements, 24)
     self.assertTrue(args[0].array_payload.index(0).is_sbits())
     self.assertTrue(args[0].array_payload.index(0).get_bit_count(), 4)
Esempio n. 10
0
    def _verify_constraints(self) -> None:
        """Verifies that all parametrics adhere to signature constraints.

    Take the following function signature for example:
      fn [X: u32, Y: u32 = X + X] f(x: bits[X], y: bits[Y]) -> bits[Y]

    The parametric Y has two constraints based only off the signature:
    it must match the bitwidth of the argument y and it must be equal to
    X + X. This function is responsible for computing any derived parametrics
    and asserting that their values are consistent with other constraints
    (arg types).
    """
        for binding, constraint in self.constraints.items():
            if constraint is None:
                # e.g. [X: u32]
                continue
            try:
                fn_name, fn_symbolic_bindings = self.ctx.fn_stack[-1]
                fn_ctx = (self.ctx.module.name, fn_name,
                          tuple(fn_symbolic_bindings.items()))
                result = self.ctx.interpret_expr(self.ctx.module,
                                                 self.ctx.type_info,
                                                 self.symbolic_bindings,
                                                 self.bit_widths,
                                                 constraint,
                                                 fn_ctx=fn_ctx)
            except KeyError as e:
                # We haven't seen enough bindings to evaluate this constraint.
                continue

            if binding in self.symbolic_bindings.keys():
                if result != self.symbolic_bindings[binding]:
                    raise XlsTypeError(
                        self.span,
                        BitsType(signed=False,
                                 size=self.symbolic_bindings[binding]),
                        BitsType(signed=False, size=result),
                        suffix=
                        f'Parametric constraint violated, saw {binding} = {constraint} = {result}; '
                        f'then {binding} = {self.symbolic_bindings[binding]}')
            else:
                self.symbolic_bindings[binding] = result
Esempio n. 11
0
 def test_stringify(self):
     u32 = BitsType(signed=False, size=32)
     tabular = [
         # type size total_bit_count str
         (ArrayType(u32, 7), 7, 32 * 7, 'uN[32][7]'),
         (u32, 32, 32, 'uN[32]'),
     ]
     for t, size, total_bit_count, s in tabular:
         self.assertEqual(t.size, size)
         self.assertEqual(t.get_total_bit_count(), total_bit_count)
         self.assertEqual(str(t), s)
Esempio n. 12
0
def _deduce_ArrayTypeAnnotation(self: ast.ArrayTypeAnnotation,
                                ctx: DeduceCtx) -> ConcreteType:
    """Deduces the concrete type of an Array type annotation."""
    dim = _dim_to_parametric_or_int(self, self.dim, ctx)
    if (isinstance(self.element_type, ast.BuiltinTypeAnnotation)
            and self.element_type.bits == 0):
        # No-volume builtin types like bits, uN, and sN.
        return BitsType(self.element_type.signedness, dim)
    element_type = deduce(self.element_type, ctx)
    result = ArrayType(element_type, dim)
    logging.vlog(4, 'array type annotation: %s => %s', self, result)
    return result
Esempio n. 13
0
def _strength_reduce_enum(type_: ast.Enum,
                          bit_count: int) -> ConcreteType[int]:
    """Turns an enum to corresponding (bits) concrete type (w/signedness).

  For example, used in conversion checks.

  Args:
    type_: AST node (enum definition) to convert.
    bit_count: The bit count of the underlying bits type for the enum
      definition, as determined by type inference or interpretation.

  Returns:
    The concrete type that represents the enum's underlying bits type.
  """
    assert isinstance(type_, ast.Enum), type_
    signed = type_.get_signedness()
    return BitsType(signed, bit_count)
Esempio n. 14
0
    def _symbolic_bind_dims(self, param_type: ConcreteType,
                            arg_type: ConcreteType) -> None:
        """Binds parametric symbols in param_type according to arg_type."""
        # Create bindings for symbolic parameter dimensions based on argument
        # values passed.
        param_dim = param_type.size  # pytype: disable=attribute-error
        arg_dim = arg_type.size  # pytype: disable=attribute-error
        if not isinstance(param_dim, parametric_expression.ParametricSymbol):
            return

        pdim_name = param_dim.identifier
        if (pdim_name in self.symbolic_bindings
                and self.symbolic_bindings[pdim_name] != arg_dim):
            if self.constraints[pdim_name]:
                # Error on violated constraint.
                raise XlsTypeError(
                    self.span,
                    BitsType(signed=False,
                             size=self.symbolic_bindings[pdim_name]),
                    arg_type,
                    suffix=f'Parametric constraint violated, saw {pdim_name} '
                    f'= {self.constraints[pdim_name]} '
                    f'= {self.symbolic_bindings[pdim_name]}; '
                    f'then {pdim_name} = {arg_dim}')
            else:
                # Error on conflicting argument types.
                raise XlsTypeError(
                    self.span,
                    param_type,
                    arg_type,
                    suffix=
                    'Parametric value {} was bound to different values at '
                    'different places in invocation; saw: {!r}; then: {!r}'.
                    format(pdim_name, self.symbolic_bindings[pdim_name],
                           arg_dim))

        logging.vlog(2, 'Binding %r to %s', pdim_name, arg_dim)
        self.symbolic_bindings[pdim_name] = arg_dim
Esempio n. 15
0
def concrete_type_from_value(value: Value) -> ConcreteType[int]:
    """Returns the concrete type of 'value'.

  Note that:
  * Non-zero-length arrays are assumed (for zero length arrays we can't
    currently deduce the type from the value because the concrete element type
    is not reified in the array value.
  * Enums are strength-reduced to their underlying bits (storage) type.

  Args:
    value: Value to determine the concrete type for.
  """
    if value.tag in (Tag.UBITS, Tag.SBITS):
        signed = value.tag == Tag.SBITS
        return BitsType(signed, value.bits_payload.bit_count)
    elif value.tag == Tag.ARRAY:
        element_type = concrete_type_from_value(value.array_payload.index(0))
        return ArrayType(element_type, len(value))
    elif value.tag == Tag.TUPLE:
        return TupleType(
            tuple(concrete_type_from_value(m) for m in value.tuple_members))
    else:
        assert value.tag == Tag.ENUM, value
        return _strength_reduce_enum(value.type_, value.bits_payload.bit_count)
Esempio n. 16
0
def _deduce_BuiltinTypeAnnotation(
        self: ast.BuiltinTypeAnnotation,
        ctx: DeduceCtx,  # pylint: disable=unused-argument
) -> ConcreteType:
    signedness, bits = self.signedness_and_bits
    return BitsType(signedness, bits)
Esempio n. 17
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)
Esempio n. 18
0
 def test_array_bit_count(self):
     e = BitsType(signed=False, size=4)
     a = ArrayType(e, 3)
     self.assertEqual(a.get_total_bit_count(), 12)