def visit_UnaryOp( s, node ):
   if isinstance( node.op, bir.Not ):
     dtype = node.operand.Type.get_dtype()
     if not rdt.Bool()( dtype ):
       raise PyMTLTypeError( s.blk, node.ast,
         'the operand of "Logic-not" cannot be cast to bool!' )
     if dtype.get_length() != 1:
       raise PyMTLTypeError( s.blk, node.ast,
         'the operand of "Logic-not" is not a single bit!' )
     node.Type = rt.NetWire( rdt.Bool() )
   else:
     node.Type = node.operand.Type
   if hasattr( node.operand, '_value' ):
     opmap = {
         bir.Invert : '~',
         bir.Not    : 'not',
         bir.UAdd   : '+',
         bir.USub   : '-',
     }
     try:
       op = opmap[node.op.__class__]
       operand = node.operand._value.uint()
       node._value = eval(f"Bits32({op}{operand})")
     except:
       pass
 def visit_BoolOp(s, node):
     for value in node.values:
         if not isinstance(value.Type, rt.Signal) or not rdt.Bool()(
                 value.Type.get_dtype()):
             raise PyMTLTypeError(
                 s.blk, node.ast,
                 f"{value} of {value.Type} cannot be cast into bool!")
     node.Type = rt.NetWire(rdt.Bool())
 def visit_UnaryOp( s, node ):
   if isinstance( node.op, bir.Not ):
     dtype = node.operand.Type.get_dtype()
     if not rdt.Bool()( dtype ):
       raise PyMTLTypeError( s.blk, node.ast,
         'the operand of "Logic-not" cannot be cast to bool!' )
     if dtype.get_length() != 1:
       raise PyMTLTypeError( s.blk, node.ast,
         'the operand of "Logic-not" is not a single bit!' )
     node.Type = rt.NetWire( rdt.Bool() )
   else:
     node.Type = node.operand.Type
 def visit_Compare( s, node ):
   l_type = node.left.Type.get_dtype()
   r_type = node.right.Type.get_dtype()
   if l_type != r_type:
     raise PyMTLTypeError( s.blk, node.ast,
       f"LHS and RHS of {node.op.__class__.__name__} have different types ({l_type} vs {r_type})!" )
   node.Type = rt.NetWire( rdt.Bool() )
    def visit_IfExp(s, node):
        # Can the type of condition be cast into bool?
        if not rdt.Bool()(node.cond.Type.get_dtype()):
            raise PyMTLTypeError(
                s.blk, node.ast,
                'the condition of "if-exp" cannot be converted to bool!')

        # body and orelse must have the same type
        # if node.body.Type != node.orelse.Type:
        if not node.body.Type.get_dtype()(node.orelse.Type.get_dtype()):
            raise PyMTLTypeError(
                s.blk, node.ast,
                'the body and orelse of "if-exp" must have the same type!')

        lhs_dtype, rhs_dtype = node.body.Type.get_dtype(
        ), node.orelse.Type.get_dtype()
        lhs_is_vector = isinstance(lhs_dtype, rdt.Vector)
        rhs_is_vector = isinstance(rhs_dtype, rdt.Vector)
        lhs_nbits, rhs_nbits = lhs_dtype.get_length(), rhs_dtype.get_length()

        # Unify body and orelse if both are rdt.Vector
        if lhs_is_vector and rhs_is_vector and lhs_nbits != rhs_nbits:
            is_lhs_inferred = not node.body._is_explicit
            is_rhs_inferred = not node.orelse._is_explicit

            # Both sides are explicit
            if not is_lhs_inferred and not is_rhs_inferred:
                raise PyMTLTypeError(
                    s.blk, node.ast,
                    f'the body and orelse of "if-exp" have different bitwidth {lhs_nbits} vs {rhs_nbits}!'
                )

            # Both sides are implicit
            elif is_lhs_inferred and is_rhs_inferred:
                if lhs_nbits >= rhs_nbits:
                    target_nbits = lhs_nbits
                    op = node.body
                else:
                    target_nbits = rhs_nbits
                    op = node.orelse
                context = rt.NetWire(rdt.Vector(target_nbits))
                s.enforcer.enter(s.blk, context, op)

            else:
                # One side is explicit and the other implicit
                if is_lhs_inferred:
                    exp_str, imp_str = "or-else", "body"
                    context, op, explicit, implicit = node.orelse.Type, node.body, rhs_nbits, lhs_nbits
                else:
                    exp_str, imp_str = "body", "or-else"
                    context, op, explicit, implicit = node.body.Type, node.orelse, lhs_nbits, rhs_nbits
                if explicit < implicit:
                    raise PyMTLTypeError(
                        s.blk, node.ast,
                        f"The {exp_str} side of if-exp has {explicit} bits but "
                        f"the {imp_str} side requires more bits ({implicit})!")
                s.enforcer.enter(s.blk, context, op)

        node.Type = node.body.Type
        node._is_explicit = node.body._is_explicit or node.orelse._is_explicit
Пример #6
0
  def visit_Compare( s, node ):
    l_type = node.left.Type.get_dtype()
    r_type = node.right.Type.get_dtype()
    l_explicit, r_explicit = node.left._is_explicit, node.right._is_explicit
    l_nbits, r_nbits = l_type.get_length(), r_type.get_length()

    if l_explicit and r_explicit:
      if l_type != r_type:
        raise PyMTLTypeError( s.blk, node.ast,
          f"LHS and RHS of {node.op.__class__.__name__} have different types ({l_type} vs {r_type})!" )

    elif not l_explicit and not r_explicit:
      if l_nbits >= r_nbits:
        target_nbits = l_nbits
        op = node.right
      else:
        target_nbits = r_nbits
        op = node.left
      context = rt.NetWire(rdt.Vector(target_nbits))
      s.enforcer.enter( s.blk, context, op )

    else:
      context, op, explicit, implicit = node.left.Type, node.right, l_nbits, r_nbits
      if not l_explicit:
        context, op, explicit, implicit = node.right.Type, node.left, r_nbits, l_nbits
      # Check if any implicit truncation happens
      if explicit < implicit:
        raise PyMTLTypeError( s.blk, node.ast,
            f"The explicitly sized side of comparison has {explicit} bits but "
            f"the integer literal requires more bits ({implicit}) to hold!" )
      s.enforcer.enter( s.blk, context, op )

    node.Type = rt.NetWire( rdt.Bool() )
    node._is_explicit = True
 def visit_If(s, node):
     # Can the type of condition be cast into bool?
     dtype = node.cond.Type.get_dtype()
     if not rdt.Bool()(dtype):
         raise PyMTLTypeError(
             s.blk, node.ast,
             'the condition of "if" cannot be converted to bool!')
     node.Type = None
  def visit_IfExp( s, node ):
    # Can the type of condition be cast into bool?
    if not rdt.Bool()( node.cond.Type.get_dtype() ):
      raise PyMTLTypeError( s.blk, node.ast,
        'the condition of "if-exp" cannot be converted to bool!' )

    # body and orelse must have the same type
    # if node.body.Type != node.orelse.Type:
    if not node.body.Type.get_dtype()( node.orelse.Type.get_dtype() ):
      raise PyMTLTypeError( s.blk, node.ast,
        'the body and orelse of "if-exp" must have the same type!' )
    node.Type = node.body.Type