Exemple #1
0
 def test_sign_convert_array_value(self):
   t = ArrayType(BitsType(signed=True, size=8), 3)
   self.assertEqual(
       sample_runner.sign_convert_value(
           t,
           Value.make_array((Value.make_ubits(8,
                                              0x42), Value.make_ubits(8, 0x43),
                             Value.make_ubits(8, 0x44)))),
       Value.make_array((Value.make_sbits(8, 0x42), Value.make_sbits(8, 0x43),
                         Value.make_sbits(8, 0x44))))
Exemple #2
0
 def test_array_values(self):
   self.assertEqual(
       value_from_string('[(u8:0xff, u2:0x1), (u8:0, u2:3)]'),
       Value.make_array((
           Value.make_tuple((
               Value.make_ubits(bit_count=8, value=0xff),
               Value.make_ubits(bit_count=2, value=1),
           )),
           Value.make_tuple((
               Value.make_ubits(bit_count=8, value=0x0),
               Value.make_ubits(bit_count=2, value=3),
           )),
       )))
Exemple #3
0
def value_from_scanner(s: Scanner) -> Value:
  """Recursive call for converting a stream of tokens into a value."""
  s = _LookaheadWrapper(s)
  if s.try_pop(TokenKind.OPAREN):
    elements = []
    must_end = False
    while True:
      if s.try_pop(TokenKind.CPAREN):
        break
      if must_end:
        s.pop_or_error(TokenKind.CPAREN)
        break
      elements.append(value_from_scanner(s))
      must_end = not s.try_pop(TokenKind.COMMA)
    return Value.make_tuple(tuple(elements))

  if s.try_pop(TokenKind.OBRACK):
    elements = []
    must_end = False
    while True:
      if s.try_pop(TokenKind.CBRACK):
        break
      if must_end:
        s.pop_or_error(TokenKind.CBRACK)
        break
      elements.append(value_from_scanner(s))
      must_end = not s.try_pop(TokenKind.COMMA)
    return Value.make_array(tuple(elements))

  if s.try_pop_keyword(Keyword.BITS) or s.try_pop_keyword(Keyword.UN):
    return _bit_value_from_scanner(s, signed=False)
  if s.try_pop_keyword(Keyword.BITS) or s.try_pop_keyword(Keyword.SN):
    return _bit_value_from_scanner(s, signed=True)

  tok = s.pop()
  if tok.is_type_keyword():
    type_ = tok
    s.pop_or_error(TokenKind.COLON)
    value_tok = s.pop_or_error(TokenKind.NUMBER)
    signedness, bit_count = scanner_mod.TYPE_KEYWORDS_TO_SIGNEDNESS_AND_BITS[
        type_.value]
    constructor = Value.make_sbits if signedness else Value.make_ubits
    return constructor(
        bit_count=bit_count,
        value=ast_helpers.get_token_value_as_int(value_tok))

  raise ScanError(tok.span.start,
                  'Unexpected token in value; found {}'.format(tok.kind))
Exemple #4
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
Exemple #5
0
def ir_value_to_interpreter_value(value: ir_value_mod.Value) -> Value:
  """Converts an IR Value to an interpreter Value."""
  if value.is_bits():
    if value.get_bits().bit_count() <= 64:
      return Value.make_ubits(value.get_bits().bit_count(),
                              value.get_bits().to_uint())
    else:
      # For wide values which do not fit in 64 bits, parse value as as string.
      return value_from_string(value.to_str(FormatPreference.HEX))

  elif value.is_array():
    return Value.make_array(
        tuple(ir_value_to_interpreter_value(e) for e in value.get_elements()))
  else:
    assert value.is_tuple()
    return Value.make_tuple(
        tuple(ir_value_to_interpreter_value(e) for e in value.get_elements()))
Exemple #6
0
 def test_parse_args(self):
     self.assertEqual(sample.parse_args(''), tuple())
     self.assertEqual(sample.parse_args('bits[8]:42'),
                      (Value.make_ubits(8, 42), ))
     self.assertEqual(sample.parse_args('bits[8]:42; bits[16]:1234'),
                      (Value.make_ubits(8, 42), Value.make_ubits(16, 1234)))
     self.assertEqual(
         sample.parse_args(
             'bits[8]:42; (bits[8]:0x42, (bits[16]:0x33, bits[8]:0x44))'),
         (Value.make_ubits(8, 42),
          Value.make_tuple((Value.make_ubits(8, 0x42),
                            Value.make_tuple((Value.make_ubits(
                                16, 0x33), Value.make_ubits(8, 0x44)))))))
     self.assertEqual(
         sample.parse_args('[bits[8]:0x42, bits[8]:0x43, bits[8]:0x44]'),
         (Value.make_array(
             tuple(Value.make_ubits(8, v) for v in (0x42, 0x43, 0x44))), ))
Exemple #7
0
def generate_argument(arg_type: ConcreteType, rng: Random,
                      prior: Sequence[Value]) -> Value:
    """Generates an argument value of the same type as the concrete type."""
    if isinstance(arg_type, TupleType):
        return Value.make_tuple(
            tuple(
                generate_argument(t, rng, prior)
                for t in arg_type.get_unnamed_members()))
    elif isinstance(arg_type, ArrayType):
        return Value.make_array(
            tuple(
                generate_argument(arg_type.get_element_type(), rng, prior)
                for _ in range(arg_type.size)))
    else:
        assert isinstance(arg_type, BitsType)
        if not prior or rng.random() < 0.5:
            return _generate_unbiased_argument(arg_type, rng)

    to_mutate = rng.choice(prior)
    bit_count = arg_type.get_total_bit_count()
    if bit_count > to_mutate.get_bit_count():
        to_mutate = to_mutate.bits_payload.concat(
            _generate_bit_value(bit_count - to_mutate.get_bit_count(),
                                rng,
                                signed=False).bits_payload)
    else:
        to_mutate = to_mutate.bits_payload.slice(0, bit_count, lsb_is_0=False)

    assert to_mutate.bit_count == bit_count
    value = to_mutate.value
    mutation_count = randrange_biased_towards_zero(bit_count, rng)
    for _ in range(mutation_count):
        # Pick a random bit and flip it.
        bitno = rng.randrange(bit_count)
        value ^= 1 << bitno

    signed = arg_type.get_signedness()
    constructor = Value.make_sbits if signed else Value.make_ubits
    return constructor(value=value, bit_count=bit_count)
Exemple #8
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_))