def visit_Attribute(s, node): if isinstance(node.value.Type, rt.Signal): dtype = node.value.Type.get_dtype() if not isinstance(dtype, rdt.Struct): raise PyMTLTypeError( s.blk, node.ast, 'attribute base should be a struct signal!') if not dtype.has_property(node.attr): raise PyMTLTypeError( s.blk, node.ast, f'{dtype.get_name()} does not have field {node.attr}!') dtype = dtype.get_property(node.attr) if isinstance(node.value.Type, rt.Port): rtype = rt.Port(node.value.Type.get_direction(), dtype) elif isinstance(node.value.Type, rt.Wire): rtype = rt.Wire(dtype) elif isinstance(node.value.Type, rt.Const): obj = node.value.Type.get_object() if obj is None: rtype = rt.Const(dtype) else: try: rtype = rt.Const(dtype, getattr(obj, node.attr)) except AttributeError: rtype = rt.Const(dtype) else: raise PyMTLTypeError( s.blk, node.ast, f'unrecognized signal type {node.value.Type}!') node.Type = rtype else: super().visit_Attribute(node)
def test_pymtl3_list_wires(): class A(dsl.Component): def construct(s): s.in_ = [dsl.Wire(Bits32) for _ in range(5)] a = A() a.elaborate() assert rt.is_rtlir_convertible(a.in_) assert rt.Array([5], rt.Wire(rdt.Vector(32))) == rt.get_rtlir(a.in_)
def __init__(s, index_base, index): base_rtype = index_base.get_rtype() dtype = base_rtype.get_dtype() if isinstance(base_rtype, rt.Port): rtype = rt.Port(base_rtype.get_direction(), rdt.Vector(1)) elif isinstance(base_rtype, rt.Wire): rtype = rt.Wire(rdt.Vector(1)) else: assert False, f"unrecognized signal type {base_rtype} for indexing" super().__init__(index_base, index, rtype)
def _visit_Assign_single_target( s, node, target, i ): rhs_type = node.value.Type lhs_type = target.Type if isinstance( target, bir.TmpVar ): tmpvar_id = (target.name, target.upblk_name) if lhs_type != rt.NoneType() and lhs_type.get_dtype() != rhs_type.get_dtype(): raise PyMTLTypeError( s.blk, node.ast, f'conflicting type {rhs_type} for temporary variable {node.targets[i].name}(LHS target#{i} of {lhs_type})!' ) # Creating a temporaray variable # Reminder that a temporary variable is essentially a wire. So we use # rt.Wire here instead of rt.NetWire target.Type = rt.Wire( rhs_type.get_dtype() ) s.tmpvars[ tmpvar_id ] = rt.Wire( rhs_type.get_dtype() ) else: # non-temporary assignment is an L1 thing super()._visit_Assign_single_target( node, target, i )
def __init__( s, attr_base, attr ): base_rtype = attr_base.get_rtype() dtype = base_rtype.get_dtype() if isinstance( base_rtype, rt.Port ): rtype = rt.Port( base_rtype.get_direction(), dtype.get_property( attr ) ) elif isinstance( base_rtype, rt.Wire ): rtype = rt.Wire( dtype.get_property( attr ) ) else: assert False, f"unrecognized signal type {base_rtype} for field selection" super().__init__( attr_base, attr, rtype )
def __init__( s, slice_base, start, stop ): base_rtype = slice_base.get_rtype() dtype = base_rtype.get_dtype() if isinstance( base_rtype, rt.Port ): rtype = rt.Port( base_rtype.get_direction(), rdt.Vector( stop-start ) ) elif isinstance( base_rtype, rt.Wire ): rtype = rt.Wire( rdt.Vector( stop-start ) ) else: assert False, f"unrecognized signal type {base_rtype} for slicing" super().__init__( rtype ) s.base = slice_base s.slice = ( start, stop )
def __init__(s, index_base, index): base_rtype = index_base.get_rtype() dtype = base_rtype.get_dtype() if isinstance(base_rtype, rt.Port): rtype = rt.Port(base_rtype.get_direction(), dtype.get_next_dim_type()) elif isinstance(base_rtype, rt.Wire): rtype = rt.Wire(dtype.get_next_dim_type()) else: assert False, \ "unrecognized signal type {} for indexing".format( base_rtype ) super().__init__(index_base, index, rtype)
def test_tmp_wire( do_test ): class A( dsl.Component ): def construct( s ): s.in_ = dsl.InPort( Bits32 ) s.out = dsl.OutPort( Bits32 ) @s.update def upblk(): u = s.in_ + Bits32(42) s.out = u a = A() a.elaborate() a._rtlir_tmpvar_ref = {('u', 'upblk') : rt.Wire(rdt.Vector(32))} do_test( a )
def visit_Assign(s, node): # RHS should have the same type as LHS rhs_type = node.value.Type lhs_type = node.target.Type if isinstance(node.target, bir.TmpVar): tmpvar_id = (node.target.name, node.target.upblk_name) if lhs_type != rt.NoneType() and lhs_type.get_dtype( ) != rhs_type.get_dtype(): raise PyMTLTypeError( s.blk, node.ast, f'conflicting type {rhs_type} for temporary variable {node.target.name}({lhs_type})!' ) # Creating a temporaray variable # Reminder that a temporary variable is essentially a wire. So we use # rt.Wire here instead of rt.NetWire node.target.Type = rt.Wire(rhs_type.get_dtype()) s.tmpvars[tmpvar_id] = rt.Wire(rhs_type.get_dtype()) node.Type = None else: # non-temporary assignment is an L1 thing super().visit_Assign(node)
def test_tmp_wire_struct( do_test ): @bitstruct class B: foo: Bits32 class A( dsl.Component ): def construct( s ): s.in_ = dsl.InPort( B ) s.out = dsl.OutPort( Bits32 ) @s.update def upblk(): u = s.in_ s.out = u.foo a = A() a.elaborate() a._rtlir_tmpvar_ref = \ {('u', 'upblk') : rt.Wire(rdt.Struct('B', {'foo':rdt.Vector(32)}))} do_test( a )
def test_tmp_wire_struct(do_test): a = CaseStructTmpWireComp.DUT() a.elaborate() a._rtlir_tmpvar_ref = \ {('u', 'upblk') : rt.Wire(rdt.Struct('Bits32Foo', {'foo':rdt.Vector(32)}))} do_test(a)
def test_tmp_wire(do_test): a = CaseBits32TmpWireComp.DUT() a.elaborate() a._rtlir_tmpvar_ref = {('u', 'upblk'): rt.Wire(rdt.Vector(32))} do_test(a)
def test_pymtl3_list_wires(): a = CaseBits32x5WireOnly.DUT() a.elaborate() assert rt.is_rtlir_convertible(a.in_) assert rt.get_rtlir(a.in_) == rt.Array([5], rt.Wire(rdt.Vector(32)))