Exemplo n.º 1
0
def sign_convert_value(concrete_type: ConcreteType, value: Value) -> Value:
    """Converts the values to matched the signedness of the concrete type.

  Converts bits-typed Values contained within the given Value to match the
  signedness of the ConcreteType. Examples:

  invocation: sign_convert_value(s8, u8:64)
  returns: s8:64

  invocation: sign_convert_value(s3, u8:7)
  returns: s3:-1

  invocation: sign_convert_value((s8, u8), (u8:42, u8:10))
  returns: (s8:42, u8:10)

  This conversion functionality is required because the Values used in the DSLX
  may be signed while Values in IR interpretation and Verilog simulation are
  always unsigned.

  This function is idempotent.

  Args:
    concrete_type: ConcreteType to match.
    value: Input value.

  Returns:
    Sign-converted value.
  """
    if isinstance(concrete_type, concrete_type_mod.TupleType):
        assert value.is_tuple()
        assert len(value.tuple_members) == concrete_type.get_tuple_length()
        return Value.make_tuple(
            tuple(
                sign_convert_value(t, a) for t, a in zip(
                    concrete_type.get_unnamed_members(), value.tuple_members)))
    elif isinstance(concrete_type, concrete_type_mod.ArrayType):
        assert value.is_array()
        assert len(value.array_payload.elements) == concrete_type.size
        return Value.make_array(
            tuple(
                sign_convert_value(concrete_type.get_element_type(), v)
                for v in value.array_payload.elements))
    elif concrete_type_mod.is_sbits(concrete_type):
        return Value.make_sbits(value.get_bit_count(), value.get_bits_value())
    else:
        assert concrete_type_mod.is_ubits(concrete_type)
        return value
Exemplo n.º 2
0
def convert_interpreter_value_to_ir(
        interpreter_value: dslx_value.Value) -> ir_value.Value:
    """Recursively translates a DSLX Value into an IR Value."""
    if interpreter_value.is_bits() or interpreter_value.is_enum():
        return ir_value.Value(
            int_to_bits(interpreter_value.get_bits_value_check_sign(),
                        interpreter_value.get_bit_count()))
    elif interpreter_value.is_array():
        ir_arr = []
        for e in interpreter_value.array_payload.elements:
            ir_arr.append(convert_interpreter_value_to_ir(e))
        return ir_value.Value.make_array(ir_arr)
    elif interpreter_value.is_tuple():
        ir_tuple = []
        for e in interpreter_value.tuple_members:
            ir_tuple.append(convert_interpreter_value_to_ir(e))
        return ir_value.Value.make_tuple(ir_tuple)
    else:
        raise UnsupportedJitConversionError(
            "Can't convert to JIT value: {}".format(interpreter_value))
Exemplo n.º 3
0
def _value_compatible_with_type(module: ast.Module, type_: ConcreteType,
                                value: Value) -> bool:
    """Returns whether value is compatible with type_ (recursively)."""
    assert isinstance(value, Value), value

    if isinstance(type_, TupleType) and value.is_tuple():
        return all(
            _value_compatible_with_type(module, ct, m)
            for ct, m in zip(type_.get_unnamed_members(), value.tuple_members))

    if isinstance(type_, ArrayType) and value.is_array():
        et = type_.get_element_type()
        return all(
            _value_compatible_with_type(module, et, m)
            for m in value.array_payload.elements)

    if isinstance(type_, EnumType) and value.tag == Tag.ENUM:
        return type_.get_nominal_type(module) == value.type_

    if isinstance(type_,
                  BitsType) and not type_.signed and value.tag == Tag.UBITS:
        return value.bits_payload.bit_count == type_.get_total_bit_count()

    if isinstance(type_, BitsType) and type_.signed and value.tag == Tag.SBITS:
        return value.bits_payload.bit_count == type_.get_total_bit_count()

    if value.tag == Tag.ENUM and isinstance(type_, BitsType):
        return (value.type_.get_signedness() == type_.signed and
                value.bits_payload.bit_count == type_.get_total_bit_count())

    if value.tag == Tag.ARRAY and is_ubits(type_):
        flat_bit_count = value.array_payload.flatten().bits_payload.bit_count
        return flat_bit_count == type_.get_total_bit_count()

    if isinstance(type_, EnumType) and value.is_bits():
        return (type_.signed == (value.tag == Tag.SBITS)
                and type_.get_total_bit_count() == value.get_bit_count())

    raise NotImplementedError(type_, value)
Exemplo n.º 4
0
def concrete_type_convert_value(type_: ConcreteType, value: Value, span: Span,
                                enum_values: Optional[Tuple[Value, ...]],
                                enum_signed: Optional[bool]) -> Value:
    """Converts 'value' into a value of this concrete type."""
    logging.vlog(3, 'Converting value %s to type %s', value, type_)
    if value.tag == Tag.UBITS and isinstance(type_, ArrayType):
        bits_per_element = type_.get_element_type().get_total_bit_count()
        bits = value.bits_payload

        def bit_slice_value_at_index(i):
            return Value(
                Tag.UBITS,
                bits.slice(i * bits_per_element, (i + 1) * bits_per_element,
                           lsb_is_0=False))

        return Value.make_array(
            tuple(bit_slice_value_at_index(i) for i in range(type_.size)))

    if (isinstance(type_, EnumType)
            and value.tag in (Tag.UBITS, Tag.SBITS, Tag.ENUM)
            and value.get_bit_count() == type_.get_total_bit_count()):
        # Check that the bits we're converting from are present in the enum type
        # we're converting to.
        for enum_value in enum_values:
            if value.bits_payload == enum_value.bits_payload:
                break
        else:
            raise FailureError(
                span, 'Value is not valid for enum {}: {}'.format(
                    type_.nominal_type.identifier, value))
        return Value.make_enum(value.bits_payload, type_.nominal_type)

    if (value.tag == Tag.ENUM and isinstance(type_, BitsType)
            and type_.get_total_bit_count() == value.get_bit_count()):
        constructor = Value.make_sbits if type_.signed else Value.make_ubits  # pytype: disable=attribute-error
        bit_count = type_.get_total_bit_count()
        return constructor(bit_count, value.bits_payload.value)

    def zero_ext() -> Value:
        assert isinstance(type_, BitsType)
        constructor = Value.make_sbits if type_.signed else Value.make_ubits
        bit_count = type_.get_total_bit_count()
        return constructor(
            bit_count,
            value.get_bits_value() & bit_helpers.to_mask(bit_count))

    def sign_ext() -> Value:
        assert isinstance(type_, BitsType)
        constructor = Value.make_sbits if type_.signed else Value.make_ubits
        bit_count = type_.get_total_bit_count()
        logging.vlog(3, 'Sign extending %s to %s', value, bit_count)
        return constructor(bit_count,
                           value.bits_payload.sign_ext(bit_count).value)

    if value.tag == Tag.UBITS:
        return zero_ext()

    if value.tag == Tag.SBITS:
        return sign_ext()

    if value.tag == Tag.ENUM:
        assert enum_signed is not None
        return sign_ext() if enum_signed else zero_ext()

    # If we're converting an array into bits, flatten the array payload.
    if value.tag == Tag.ARRAY and isinstance(type_, BitsType):
        return value.array_payload.flatten()

    if concrete_type_accepts_value(type_, value):  # Vacuous conversion.
        return value

    raise FailureError(
        span,
        'Interpreter failure: cannot convert value %s (of type %s) to type %s'
        % (value, concrete_type_from_value(value), type_))
Exemplo n.º 5
0
def compare_values(interpreter_value: dslx_value.Value,
                   jit_value: ir_value.Value) -> None:
    """Asserts equality between a DSLX Value and an IR Value.

  Recursively traverses the values (for arrays/tuples) and makes assertions
  about value and length properties.

  Args:
    interpreter_value: Value that resulted from DSL interpretation.
    jit_value: Value that resulted from JIT-compiled execution.

  Raises:
    JitMiscompareError: If the dslx_value and jit_value are not equivalent.
    UnsupportedJitConversionError: If there is not JIT-supported type equivalent
      for the interpreter value.
  """
    if interpreter_value.is_bits() or interpreter_value.is_enum():
        assert jit_value.is_bits(), f'Expected bits value: {jit_value!r}'

        jit_value = jit_value.get_bits()
        bit_count = interpreter_value.get_bit_count()
        if bit_count != jit_value.bit_count():
            raise JitMiscompareError(f'Inconsistent bit counts for value -- '
                                     f'interp: {bit_count}, '
                                     f'jit: {jit_value.bit_count()}')

        if interpreter_value.is_ubits():
            interpreter_bits_value = interpreter_value.get_bits_value()
            jit_bits_value = bits_to_int(jit_value, signed=False)
        else:
            interpreter_bits_value = interpreter_value.get_bits_value_signed()
            jit_bits_value = bits_to_int(jit_value, signed=True)

        if interpreter_bits_value != jit_bits_value:
            raise JitMiscompareError(
                'Inconsistent bit values in return value -- '
                'interp: {!r}, jit: {!r}'.format(interpreter_bits_value,
                                                 jit_bits_value))

    elif interpreter_value.is_array():
        assert jit_value.is_array(), f'Expected array value: {jit_value!r}'

        interpreter_values = interpreter_value.array_payload.elements
        jit_values = jit_value.get_elements()
        interp_len = len(interpreter_values)
        jit_len = len(jit_values)
        if interp_len != jit_len:
            raise JitMiscompareError(
                f'Inconsistent array lengths in return value -- '
                f'interp: {interp_len}, jit: {jit_len}')

        for interpreter_element, jit_element in zip(interpreter_values,
                                                    jit_values):
            compare_values(interpreter_element, jit_element)
    elif interpreter_value.is_tuple():
        assert jit_value.is_tuple(), 'Expected tuple value: {jit_value!r}'

        interpreter_values = interpreter_value.tuple_members
        jit_values = jit_value.get_elements()
        interp_len = len(interpreter_values)
        jit_len = len(jit_values)
        if interp_len != jit_len:
            raise JitMiscompareError(
                f'Inconsistent tuple lengths in return value -- '
                f'interp: {interp_len}, jit: {jit_len}')

        for interpreter_element, jit_element in zip(interpreter_values,
                                                    jit_values):
            compare_values(interpreter_element, jit_element)
    else:
        raise UnsupportedJitConversionError(
            'No JIT-supported type equivalent: {}'.format(interpreter_value))