def construct( s, PacketType, QueueType=None ):

    # Local parameter
    # gating_out = PacketType()
    # TODO: add data gating support

    # Interface
    s.recv = RecvIfcRTL( PacketType )
    s.send = SendIfcRTL( PacketType )

    s.QueueType = QueueType

    #---------------------------------------------------------------------
    # If no queue type is assigned
    #---------------------------------------------------------------------

    if s.QueueType != None:

      # Component
      s.queue = QueueType( PacketType )

      # Connections
      s.recv       //= s.queue.recv
      s.queue.send //= s.send

    #---------------------------------------------------------------------
    # No ouput queue
    #---------------------------------------------------------------------

    else:

      s.send //= s.recv
    def construct(
        s,
        PacketType,
        PositionType,
        k_ary,
        n_fly,
        InputUnitType=InputUnitRTL,
        RouteUnitType=DTRBflyRouteUnitRTL,
        SwitchUnitType=SwitchUnitRTL,
        OutputUnitType=OutputUnitRTL,
    ):

        s.dim = PhysicalDimension()
        s.num_inports = k_ary
        s.num_outports = k_ary

        # Interface

        s.pos = InPort(PositionType)
        s.recv = [RecvIfcRTL(PacketType) for _ in range(s.num_inports)]
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_outports)]

        # Components

        s.input_units = [
            InputUnitType(PacketType) for _ in range(s.num_inports)
        ]

        s.route_units = [
            RouteUnitType(PacketType,
                          PositionType,
                          s.num_outports,
                          n_fly=n_fly) for i in range(s.num_inports)
        ]

        s.switch_units = [
            SwitchUnitType(PacketType, s.num_inports)
            for _ in range(s.num_outports)
        ]

        s.output_units = [
            OutputUnitType(PacketType) for _ in range(s.num_outports)
        ]

        # Connection

        for i in range(s.num_inports):
            s.recv[i] //= s.input_units[i].recv
            s.input_units[i].send //= s.route_units[i].recv
            s.pos //= s.route_units[i].pos

        for i in range(s.num_inports):
            for j in range(s.num_outports):
                s.route_units[i].send[j] //= s.switch_units[j].recv[i]

        for j in range(s.num_outports):
            s.switch_units[j].send //= s.output_units[j].recv
            s.output_units[j].send //= s.send[j]
    def construct(s, Type, num_inports=1):

        assert num_inports == 1, 'Null switch unit can only be used for single-input router!'

        # Interface

        s.recv = [RecvIfcRTL(Type) for _ in range(num_inports)]
        s.hold = [InPort() for _ in range(num_inports)]
        s.send = SendIfcRTL(Type)

        connect(s.send, s.recv[0])
    def construct(s, PacketType, QueueType=NormalQueueRTL):

        # Interface

        s.recv = RecvIfcRTL(PacketType)
        s.send = SendIfcRTL(PacketType)

        # Component

        s.queue = QueueType(PacketType)
        s.queue.recv //= s.recv
        s.queue.send //= s.send
Exemple #5
0
  def construct( s,
    PacketType,
    num_inports    = 2,
    num_outports   = 2,
    InputUnitType  = InputUnitRTL,
    RouteUnitType  = XbarRouteUnitRTL,
    SwitchUnitType = SwitchUnitRTL,
    OutputUnitType = OutputUnitRTL,
  ):

    # Local parameter

    s.num_inports  = num_inports
    s.num_outports = num_outports

    # Special case for num_inports = 1
    if num_inports == 1: SwitchUnitType = SwitchUnitNullRTL

    # Interface

    s.recv = [ RecvIfcRTL( PacketType ) for _ in range( s.num_inports  ) ]
    s.send = [ SendIfcRTL( PacketType ) for _ in range( s.num_outports ) ]

    # Components

    s.input_units = [ InputUnitType( PacketType )
                      for _ in range( s.num_inports )  ]

    s.route_units  = [ RouteUnitType( PacketType, s.num_outports )
                       for i in range( s.num_inports ) ]

    s.switch_units = [ SwitchUnitType( PacketType, s.num_inports )
                       for _ in range( s.num_outports ) ]

    s.output_units = [ OutputUnitType( PacketType )
                       for _ in range( s.num_outports ) ]

    # Connections

    for i in range( s.num_inports ):
      s.recv[i]             //= s.input_units[i].recv
      s.input_units[i].send //= s.route_units[i].recv

    for i in range( s.num_inports ):
      for j in range( s.num_outports ):
        s.route_units[i].send[j] //= s.switch_units[j].recv[i]

    for j in range( s.num_outports ):
      s.switch_units[j].send //= s.output_units[j].recv
      s.output_units[j].send //= s.send[j]
Exemple #6
0
    def construct(s, PacketType, PositionType, num_outports=8):

        # Constants

        s.num_outports = num_outports
        TType = mk_bits(clog2(num_outports))

        # Interface

        s.recv = RecvIfcRTL(PacketType)
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_outports)]
        s.pos = InPort(PositionType)

        # Componets

        s.out_dir = Wire(mk_bits(clog2(num_outports)))
        s.send_rdy = Wire(mk_bits(num_outports))

        # Connections

        for i in range(num_outports):
            s.recv.msg //= s.send[i].msg
            s.send_rdy[i] //= s.send[i].rdy

        # Routing logic

        @update
        def up_ru_routing():

            s.out_dir @= 0
            for i in range(s.num_outports):
                s.send[i].val @= Bits1(0)

            if s.recv.val:
                if (s.pos.pos_x == s.recv.msg.dst_x) & (s.pos.pos_y
                                                        == s.recv.msg.dst_y):
                    s.out_dir @= SELF + zext(s.recv.msg.dst_ter, TType)
                elif s.recv.msg.dst_x < s.pos.pos_x:
                    s.out_dir @= WEST
                elif s.recv.msg.dst_x > s.pos.pos_x:
                    s.out_dir @= EAST
                elif s.recv.msg.dst_y < s.pos.pos_y:
                    s.out_dir @= SOUTH
                else:
                    s.out_dir @= NORTH
                s.send[s.out_dir].val @= Bits1(1)

        @update
        def up_ru_recv_rdy():
            s.recv.rdy @= s.send_rdy[s.out_dir]
Exemple #7
0
    def construct(s, MsgType, vc=2, credit_line=1):
        assert vc > 1

        # Interface

        s.recv = RecvIfcRTL(MsgType)
        s.send = CreditSendIfcRTL(MsgType, vc)

        s.MsgType = MsgType
        s.vc = vc

        # Components

        CreditType = mk_bits(clog2(credit_line + 1))

        # FIXME: use multiple buffers to avoid deadlock.
        # s.buffer = BypassQueueRTL( MsgType, num_entries=1 )
        s.credit = [Counter(CreditType, credit_line) for _ in range(vc)]

        # s.recv           //=  s.buffer.enq
        # s.buffer.deq.ret //=  s.send.msg
        s.recv.msg //= s.send.msg

        @update
        def up_credit_send():
            s.send.en @= 0
            s.recv.rdy @= 0
            # NOTE: recv.rdy depends on recv.val.
            #       Be careful about combinationl loop.
            if s.recv.val:
                for i in range(vc):
                    if (i == s.recv.msg.vc_id) & (s.credit[i].count > 0):
                        s.send.en @= 1
                        s.recv.rdy @= 1

        @update
        def up_counter_decr():
            for i in range(vc):
                s.credit[i].decr @= s.send.en & (i == s.send.msg.vc_id)

        for i in range(vc):
            s.credit[i].incr //= s.send.yum[i]
            s.credit[i].load //= 0
            s.credit[i].load_value //= 0
Exemple #8
0
  def construct( s,
    PacketType,
    PositionType,
    num_routers=4,
    chl_lat=0,
    vc=2,
    credit_line=2,
   ):

    # Constants
    s.num_routers = num_routers
#    IDType = mk_bits(clogs(num_routers))

    # Interface
    s.recv = [ RecvIfcRTL(PacketType) for _ in range(s.num_routers)]
    s.send = [ SendIfcRTL(PacketType) for _ in range(s.num_routers)]

    # Components
    s.routers = [ RingRouterRTL( PacketType, PositionType, num_routers, vc=vc )
                     for i in range( num_routers ) ]

    s.recv_adp = [ RecvRTL2CreditSendRTL( PacketType, vc=vc, credit_line=credit_line )
                        for _ in range( num_routers ) ]
    s.send_adp = [ CreditRecvRTL2SendRTL( PacketType, vc=vc, credit_line=credit_line )
                        for _ in range( num_routers ) ]

    # Connect s.routers together in ring

    for i in range( s.num_routers ):
      next_id = (i+1) % num_routers
      s.routers[i].send[RIGHT]      //= s.routers[next_id].recv[LEFT]
      s.routers[next_id].send[LEFT] //= s.routers[i].recv[RIGHT]
      # Connect the self port (with Network Interface)
      s.recv[i]                     //= s.recv_adp[i].recv
      s.recv_adp[i].send            //= s.routers[i].recv[SELF]
      s.routers[i].send[SELF]       //= s.send_adp[i].recv
      s.send_adp[i].send            //= s.send[i]

    @update
    def up_pos():
      for r in range( s.num_routers ):
        s.routers[r].pos @= r
Exemple #9
0
    def construct(s, PacketType, QueueType=NormalQueueRTL, latency=0):

        # Constant
        s.dim = PhysicalDimension()
        s.QueueType = QueueType
        s.latency = latency
        s.num_entries = 2

        # Interface
        s.recv = RecvIfcRTL(PacketType)
        s.send = SendIfcRTL(PacketType)

        #---------------------------------------------------------------------
        # If latency > 0 and channel queue exists
        #---------------------------------------------------------------------

        if s.QueueType != None and s.latency > 0:

            # Component

            s.queues = [
                s.QueueType(PacketType, s.num_entries)
                for _ in range(s.latency)
            ]

            # Connections

            s.recv //= s.queues[0].recv

            for i in range(s.latency - 1):
                s.queues[i + 1].recv //= s.queues[i].send
            s.queues[-1].send //= s.send

        #---------------------------------------------------------------------
        # If latency==0 simply bypass
        #---------------------------------------------------------------------

        else:

            s.recv //= s.send
Exemple #10
0
  def construct( s, PacketType, num_inports=5 ):

    # Local parameters

    s.num_inports = num_inports
    s.sel_width   = clog2( num_inports )

    # Interface

    s.recv = [ RecvIfcRTL( PacketType ) for _ in range( s.num_inports ) ]
    s.send = SendIfcRTL( PacketType )

    # Components

    s.arbiter = RoundRobinArbiterEn( num_inports )
    s.arbiter.en //= 1

    s.mux = Mux( PacketType, num_inports )
    s.mux.out //= s.send.msg

    s.encoder = Encoder( num_inports, s.sel_width )
    s.encoder.in_ //= s.arbiter.grants
    s.encoder.out //= s.mux.sel

    # Connections

    for i in range( num_inports ):
      s.recv[i].val //= s.arbiter.reqs[i]
      s.recv[i].msg //= s.mux.in_[i]

    @update
    def up_send_val():
      s.send.val @= s.arbiter.grants > 0

    # TODO: assert at most one rdy bit
    @update
    def up_get_en():
      for i in range( num_inports ):
        s.recv[i].rdy @= s.send.rdy & ( s.mux.sel == i )
  def construct( s, PacketType, num_outports ):

    # Local parameters

    dir_nbits = 1 if num_outports==1 else clog2( num_outports )
    DirT      = mk_bits( dir_nbits )
    BitsN     = mk_bits( num_outports )

    # Interface

    s.recv = RecvIfcRTL( PacketType )
    s.send = [ SendIfcRTL( PacketType ) for _ in range( num_outports ) ]

    # Componets

    s.out_dir  = Wire( DirT  )
    s.send_val = Wire( BitsN )

    # Connections

    for i in range( num_outports ):
      s.recv.msg    //= s.send[i].msg
      s.send_val[i] //= s.send[i].val

    # Routing logic

    @update
    def up_ru_routing():
      s.out_dir @= trunc( s.recv.msg.dst, dir_nbits )

      for i in range( num_outports ):
        s.send[i].val @= b1(0)

      if s.recv.val:
        s.send[ s.out_dir ].val @= b1(1)

    @update
    def up_ru_recv_rdy():
      s.recv.rdy @= s.send[ s.out_dir ].rdy > 0
    def construct(s, MsgType, vc=2, credit_line=2):
        assert vc > 1

        # Interface
        s.recv = RecvIfcRTL(MsgType)
        s.send = CreditSendIfcRTL(MsgType, vc)

        s.MsgType = MsgType
        s.vc = vc

        # Loval types
        credit_type = mk_bits(clog2(credit_line + 1))

        s.credit = [Counter(credit_type, credit_line) for _ in range(vc)]

        s.recv.msg //= s.send.msg

        @update
        def up_credit_send():
            s.send.en @= 0
            s.recv.rdy @= 0
            # NOTE: Here the recv.rdy depends on recv.val.
            #       Be careful about combinational loop.
            if s.recv.val:
                for i in range(vc):
                    if (i == s.recv.msg.vc_id) & (s.credit[i].count > 0):
                        s.send.en @= 1
                        s.recv.rdy @= 1

        @update
        def up_counter_decr():
            for i in range(vc):
                s.credit[i].decr @= s.send.en & (i == s.send.msg.vc_id)

        for i in range(vc):
            s.credit[i].incr //= s.send.yum[i]
            s.credit[i].load //= 0
            s.credit[i].load_value //= 0
  def construct( s, Type, msgs, initial_delay=0, interval_delay=0,
                 arrival_time=None, cmp_fn=lambda a, b : a == b ):

    # Interface

    s.recv = RecvIfcRTL( Type )

    # Data

    # [msgs] and [arrival_time] must have the same length.
    if arrival_time is None:
      s.arrival_time = None
    else:
      assert len( msgs ) == len( arrival_time )
      s.arrival_time = list( arrival_time )

    s.idx          = 0
    s.count        = 0
    s.cycle_count  = 0
    s.msgs         = list( msgs )
    s.nmsgs        = len( msgs )

    s.error_msg    = ''

    s.received = False
    s.all_msg_recved = False
    s.done_flag      = False

    @update_ff
    def up_sink():
      # Raise exception at the start of next cycle so that the errored
      # line trace gets printed out
      if s.error_msg:
        raise PyMTLTestSinkError( s.error_msg )

      # Tick one more cycle after all message is received so that the
      # exception gets thrown
      if s.all_msg_recved:
        s.done_flag = True

      if s.idx >= s.nmsgs:
        s.all_msg_recved = True

      s.received = False

      if s.reset:
        s.cycle_count = 0

        s.idx = 0
        s.count = initial_delay
        s.recv.rdy <<= (s.idx < s.nmsgs) & (s.count == 0)

      else:
        s.cycle_count += 1

        # This means at least previous cycle count = 0
        if s.recv.val & s.recv.rdy:
          msg = s.recv.msg

          # Sanity check
          if s.idx >= s.nmsgs:
            s.error_msg = ( 'Test Sink received more msgs than expected!\n'
                           f'Received : {msg}' )

          else:
            # Check correctness first
            if not [ m for m in s.msgs if cmp_fn( msg, m ) ]:
              s.error_msg = (
                f'Test sink {s} received WRONG message!\n'
                f'Expected : { s.msgs }\n'
                f'Received : { msg }'
              )

            # Check timing if performance regeression is turned on
            elif s.arrival_time and s.cycle_count > s.arrival_time[ s.idx ]:
              s.error_msg = (
                f'Test sink {s} received message LATER than expected!\n'
                f'Expected msg : {s.msgs[ s.idx ]}\n'
                f'Expected at  : {s.arrival_time[ s.idx ]}\n'
                f'Received msg : {msg}\n'
                f'Received at  : {s.cycle_count}'
              )

            # No error
            else:
              for m in s.msgs:
                if cmp_fn( msg, m ):
                  s.msgs.remove( m )
                  break

          s.idx += 1
          s.count = interval_delay


        if s.count > 0:
          s.count -= 1
          s.recv.rdy <<= 0
        else: # s.count == 0
          s.recv.rdy <<= (s.idx < s.nmsgs)
  def construct( s, PacketType, PositionType, num_routers=4 ):

    # Constants
    s.num_outports = 3
    s.num_routers  = num_routers

    DistType  = mk_bits( clog2( num_routers ) )
    s.last_idx = DistType( num_routers-1 )

    # Interface

    s.recv = RecvIfcRTL( PacketType )
    s.send = [ SendIfcRTL (PacketType) for _ in range ( s.num_outports ) ]
    s.pos  = InPort( PositionType )

    # Componets

    s.out_dir  = Wire( mk_bits( clog2( s.num_outports ) ) )
    s.send_rdy = Wire( mk_bits( s.num_outports ) )

    s.left_dist     = Wire( DistType )
    s.right_dist    = Wire( DistType )
    s.send_msg_wire = Wire( PacketType )

    # Connections

    for i in range( s.num_outports ):
      s.send_rdy[i] //= s.send[i].rdy

    # Routing logic
    @update
    def up_left_right_dist():
      if s.recv.msg.dst < s.pos:
        s.left_dist  @= zext(s.pos, DistType) - zext(s.recv.msg.dst, DistType)
        s.right_dist @= zext(s.last_idx, DistType) - zext(s.pos, DistType) + zext(s.recv.msg.dst, DistType) + 1
      else:
        s.left_dist  @= 1 + zext(s.last_idx, DistType) + zext(s.pos, DistType) - zext(s.recv.msg.dst, DistType)
        s.right_dist @= zext(s.recv.msg.dst, DistType) - zext(s.pos, DistType)

    @update
    def up_ru_routing():

      s.out_dir @= 0
      s.send_msg_wire @= s.recv.msg
      for i in range( s.num_outports ):
        s.send[i].val @= 0

      if s.recv.val:
        if s.pos == s.recv.msg.dst:
          s.out_dir @= SELF
        elif s.left_dist < s.right_dist:
          s.out_dir @= LEFT
        else:
          s.out_dir @= RIGHT

        if ( s.pos == s.last_idx ) & ( s.out_dir == RIGHT ):
          s.send_msg_wire.vc_id @= 1
        elif ( s.pos == 0 ) & ( s.out_dir == LEFT ):
          s.send_msg_wire.vc_id @= 1

        s.send[ s.out_dir ].val @= 1
        s.send[ s.out_dir ].msg @= s.send_msg_wire

    @update
    def up_ru_recv_rdy():
      s.recv.rdy @= s.send_rdy[ s.out_dir ]
    def construct(s,
                  PacketType,
                  PositionType,
                  ncols=4,
                  nrows=4,
                  chl_lat=0,
                  vc=2,
                  credit_line=2):

        # Constants

        s.ncols = ncols
        s.nrows = nrows
        s.num_routers = ncols * nrows
        s.num_terminals = s.num_routers
        XType = mk_bits(clog2(ncols))
        YType = mk_bits(clog2(nrows))

        # Interface

        s.recv = [RecvIfcRTL(PacketType) for _ in range(s.num_terminals)]
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_terminals)]

        # Components

        s.routers = [
            TorusRouterRTL(PacketType,
                           PositionType,
                           ncols=ncols,
                           nrows=nrows,
                           vc=vc,
                           credit_line=credit_line)
            for i in range(s.num_routers)
        ]

        s.recv_adapters = [
            RecvRTL2CreditSendRTL(PacketType, vc=vc, credit_line=credit_line)
            for _ in range(s.num_routers)
        ]
        s.send_adapters = [
            CreditRecvRTL2SendRTL(PacketType, vc=vc, credit_line=credit_line)
            for _ in range(s.num_routers)
        ]

        # Connect s.routers together in Torus

        chl_id = 0
        for i in range(s.num_routers):
            s_idx = (i - nrows + s.num_routers) % s.num_routers
            s.routers[i].send[SOUTH] //= s.routers[s_idx].recv[NORTH]
            s.routers[i].send[NORTH] //=\
              s.routers[(i+ncols+s.num_routers)%s.num_routers].recv[SOUTH]
            s.routers[i].send[WEST]  //=\
              s.routers[i-(i%ncols-(i-1)%ncols)].recv[EAST]
            s.routers[i].send[EAST]  //=\
              s.routers[i+(i+1)%ncols-i%ncols].recv[WEST]

            # Connect the self port (with Network Interface)
            s.recv[i] //= s.recv_adapters[i].recv
            s.recv_adapters[i].send //= s.routers[i].recv[SELF]

            s.routers[i].send[SELF] //= s.send_adapters[i].recv
            s.send_adapters[i].send //= s.send[i]


#    @update
#    def up_pos():
        for y in range(nrows):
            for x in range(ncols):
                #          idx = y * ncols + x
                #          s.routers[idx].pos = PositionType( x, y )
                s.routers[y * ncols + x].pos.pos_x //= XType(x)
                s.routers[y * ncols + x].pos.pos_y //= YType(y)
    def construct(s, PacketType, PositionType, k_ary, n_fly, chl_lat=0):

        # Constants

        s.dim = PhysicalDimension()
        s.k_ary = k_ary
        s.n_fly = n_fly
        s.r_rows = k_ary**(n_fly - 1)
        s.num_routers = n_fly * (s.r_rows)
        s.num_terminals = k_ary**n_fly
        num_channels = (n_fly - 1) * (s.r_rows) * k_ary

        # Interface

        s.recv = [RecvIfcRTL(PacketType) for _ in range(s.num_terminals)]
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_terminals)]

        # Components

        s.routers = [
            BflyRouterRTL(PacketType, PositionType, k_ary, n_fly)
            for i in range(s.num_routers)
        ]

        s.channels = [
            ChannelRTL(PacketType, latency=chl_lat)
            for _ in range(num_channels)
        ]

        s.pos = [
            PositionType(r % s.r_rows, r // s.r_rows)
            for r in range(s.num_routers)
        ]

        # Connect routers together in Butterfly

        for r in range(s.num_routers):
            s.routers[r].pos.row //= s.pos[r].row
            s.routers[r].pos.stage //= s.pos[r].stage

        chl_id = 0
        terminal_id_recv = 0
        terminal_id_send = 0
        group_size = s.r_rows

        for f in range(n_fly - 1):
            num_group = s.r_rows // group_size
            for g in range(num_group):
                for gs in range(group_size):
                    for k in range(k_ary):
                        index = g * group_size + gs
                        base = g * group_size
                        interval = group_size // k_ary * k

                        router_left = f * s.r_rows + index
                        router_right = (f + 1) * s.r_rows + base + (
                            gs + interval) % group_size
                        group_left = router_left % s.r_rows
                        group_right = router_right % s.r_rows
                        group_left_x = group_left % k_ary
                        group_right_x = group_right % k_ary
                        group_left_y = group_left // k_ary
                        group_right_y = group_right // k_ary

                        rtr_idx = f * s.r_rows + index
                        ifc_tdx = (k + gs // (group_size // k_ary)) % k_ary
                        rtr_idx_n = (f + 1) * s.r_rows + base + (
                            gs + interval) % group_size

                        s.routers[rtr_idx].send[ifc_tdx] //= s.channels[
                            chl_id].recv
                        s.channels[chl_id].send //= s.routers[rtr_idx_n].recv[
                            k]

                        chl_id += 1
            group_size = group_size // k_ary

        # Connect the router ports with Network Interfaces

        for i in range(s.num_routers):
            if i < s.r_rows:
                for j in range(k_ary):
                    s.recv[terminal_id_recv] //= s.routers[i].recv[j]
                    terminal_id_recv += 1

            if i >= s.num_routers - s.r_rows:
                for j in range(k_ary):
                    s.send[terminal_id_send] //= s.routers[i].send[j]
                    terminal_id_send += 1
    def construct(s, PacketType, PositionType, ncols=2, nrows=2):

        # Constants

        num_outports = 5
        s.ncols = ncols
        s.nrows = nrows

        # Here we add 1 to avoid overflow

        posx_type = mk_bits(clog2(ncols))
        posy_type = mk_bits(clog2(nrows))
        ns_dist_type = mk_bits(clog2(nrows + 1))
        we_dist_type = mk_bits(clog2(ncols + 1))

        s.last_row_id = nrows - 1
        s.last_col_id = ncols - 1

        # Interface

        s.recv = RecvIfcRTL(PacketType)
        s.send = [SendIfcRTL(PacketType) for _ in range(num_outports)]
        s.pos = InPort(PositionType)

        # Componets

        s.out_dir = Wire(Bits3)
        s.send_rdy = Wire(Bits5)
        s.turning = Wire(Bits1)
        s.north_dist = Wire(ns_dist_type)
        s.south_dist = Wire(ns_dist_type)
        s.west_dist = Wire(we_dist_type)
        s.east_dist = Wire(we_dist_type)
        s.send_msg_wire = Wire(PacketType)

        # Connections

        for i in range(num_outports):
            s.send_rdy[i] //= s.send[i].rdy
            s.send_msg_wire //= s.send[i].msg

        # Calculate distance

        @update
        def up_ns_dist():
            if s.recv.msg.dst_y < s.pos.pos_y:
                s.south_dist @= zext(s.pos.pos_y, ns_dist_type) - zext(
                    s.recv.msg.dst_y, ns_dist_type)
                s.north_dist @= s.last_row_id - zext(
                    s.pos.pos_y, ns_dist_type) + 1 + zext(
                        s.recv.msg.dst_y, ns_dist_type)
            else:
                s.south_dist @= zext(s.pos.pos_y,
                                     ns_dist_type) + 1 + s.last_row_id - zext(
                                         s.recv.msg.dst_y, ns_dist_type)
                s.north_dist @= zext(s.recv.msg.dst_y, ns_dist_type) - zext(
                    s.pos.pos_y, ns_dist_type)

        @update
        def up_we_dist():
            if s.recv.msg.dst_x < s.pos.pos_x:
                s.west_dist @= zext(s.pos.pos_x, we_dist_type) - zext(
                    s.recv.msg.dst_x, we_dist_type)
                s.east_dist @= s.last_col_id - zext(
                    s.pos.pos_x, we_dist_type) + 1 + zext(
                        s.recv.msg.dst_x, we_dist_type)
            else:
                s.west_dist @= zext(s.pos.pos_x,
                                    we_dist_type) + 1 + s.last_col_id - zext(
                                        s.recv.msg.dst_x, we_dist_type)
                s.east_dist @= zext(s.recv.msg.dst_x, we_dist_type) - zext(
                    s.pos.pos_x, we_dist_type)

        # Routing logic

        @update
        def up_ru_routing():

            s.send_msg_wire @= s.recv.msg
            s.out_dir @= 0
            s.turning @= 0

            for i in range(num_outports):
                s.send[i].val @= 0

            if s.recv.val:
                if (s.pos.pos_x == s.recv.msg.dst_x) & (s.pos.pos_y
                                                        == s.recv.msg.dst_y):
                    s.out_dir @= SELF
                elif s.recv.msg.dst_y != s.pos.pos_y:
                    s.out_dir @= NORTH if s.north_dist < s.south_dist else SOUTH
                else:
                    s.out_dir @= WEST if s.west_dist < s.east_dist else EAST

                # Turning logic

                s.turning @= ( s.recv.msg.src_x == s.pos.pos_x ) & \
                             ( s.recv.msg.src_y != s.pos.pos_y ) & \
                             ( s.out_dir == WEST ) | ( s.out_dir == EAST )

                # Dateline logic

                if s.turning:
                    s.send_msg_wire.vc_id @= 0

                if (s.pos.pos_x == 0) & (s.out_dir == WEST):
                    s.send_msg_wire.vc_id @= 1
                elif (s.pos.pos_x == s.last_col_id) & (s.out_dir == EAST):
                    s.send_msg_wire.vc_id @= 1
                elif (s.pos.pos_y == 0) & (s.out_dir == SOUTH):
                    s.send_msg_wire.vc_id @= 1
                elif (s.pos.pos_y == s.last_row_id) & (s.out_dir == NORTH):
                    s.send_msg_wire.vc_id @= 1

                s.send[s.out_dir].val @= 1

        @update
        def up_ru_recv_rdy():
            s.recv.rdy @= s.send[s.out_dir].rdy
Exemple #18
0
    def construct(s,
                  PacketType,
                  PositionType,
                  ncols=4,
                  nrows=4,
                  num_nodes_each=4,
                  chl_lat=0):

        # Constants

        s.num_routers = ncols * nrows
        s.num_terminals = s.num_routers * num_nodes_each
        num_channels = (nrows * (ncols - 1) + ncols * (nrows - 1)) * 2
        num_inports = 4 + num_nodes_each
        num_outports = 4 + num_nodes_each
        XType = mk_bits(clog2(ncols))
        YType = mk_bits(clog2(nrows))

        # Interface

        s.recv = [RecvIfcRTL(PacketType) for _ in range(s.num_terminals)]
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_terminals)]

        # Components

        s.routers = [
            CMeshRouterRTL(PacketType, PositionType, num_inports, num_outports)
            for i in range(s.num_routers)
        ]

        s.channels = [
            ChannelRTL(PacketType, latency=chl_lat)
            for _ in range(num_channels)
        ]

        # Connect s.routers together in Mesh
        # FIXME: we need to calculate the bit width for directions. Currently
        # the translation pass may throw an error.

        chl_id = 0
        for i in range(s.num_routers):
            if i // ncols > 0:
                s.routers[i].send[SOUTH] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i - ncols].recv[NORTH]
                chl_id += 1

            if i // ncols < nrows - 1:
                s.routers[i].send[NORTH] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i + ncols].recv[SOUTH]
                chl_id += 1

            if i % ncols > 0:
                s.routers[i].send[WEST] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i - 1].recv[EAST]
                chl_id += 1

            if i % ncols < ncols - 1:
                s.routers[i].send[EAST] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i + 1].recv[WEST]
                chl_id += 1

            # Connect the self port (with Network Interface)

            for j in range(num_nodes_each):
                ifc_idx = i * num_nodes_each + j
                s.recv[ifc_idx] //= s.routers[i].recv[4 + j]
                s.send[ifc_idx] //= s.routers[i].send[4 + j]

            # Connect the unused ports

            if i // ncols == 0:
                s.routers[i].send[SOUTH].rdy //= 0
                s.routers[i].recv[SOUTH].val //= 0
                s.routers[i].recv[SOUTH].msg.payload //= 0

            if i // ncols == nrows - 1:
                s.routers[i].send[NORTH].rdy //= 0
                s.routers[i].recv[NORTH].val //= 0
                s.routers[i].recv[NORTH].msg.payload //= 0

            if i % ncols == 0:
                s.routers[i].send[WEST].rdy //= 0
                s.routers[i].recv[WEST].val //= 0
                s.routers[i].recv[WEST].msg.payload //= 0

            if i % ncols == ncols - 1:
                s.routers[i].send[EAST].rdy //= 0
                s.routers[i].recv[EAST].val //= 0
                s.routers[i].recv[EAST].msg.payload //= 0

        for y in range(nrows):
            for x in range(ncols):
                s.routers[y * ncols + x].pos //= PositionType(x, y)
Exemple #19
0
    def construct(s, PacketType, PositionType, ncols=4, nrows=4, chl_lat=0):

        # Local parameters

        s.num_routers = ncols * nrows
        s.num_terminals = s.num_routers
        num_channels = (nrows * (ncols - 1) + ncols * (nrows - 1)) * 2
        XType = mk_bits(clog2(ncols))
        YType = mk_bits(clog2(nrows))

        # Interface

        s.recv = [RecvIfcRTL(PacketType) for _ in range(s.num_terminals)]
        s.send = [SendIfcRTL(PacketType) for _ in range(s.num_terminals)]

        # Components

        s.routers = [
            MeshRouterRTL(PacketType, PositionType)
            for _ in range(s.num_routers)
        ]

        s.channels = [
            ChannelRTL(PacketType, latency=chl_lat)
            for _ in range(num_channels)
        ]

        # Wire the position ports of router

        for y in range(nrows):
            for x in range(ncols):
                s.routers[y * ncols + x].pos.pos_x //= x
                s.routers[y * ncols + x].pos.pos_y //= y

        # Connect routers together in Mesh
        # NOTE: for now we put all channels in a single list. In the future we
        # may want to divide channels into different groups so that it is
        # easier to configure.

        chl_id = 0
        for i in range(s.num_routers):
            if i // ncols > 0:
                s.routers[i].send[SOUTH] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i - ncols].recv[NORTH]
                chl_id += 1

            if i // ncols < nrows - 1:
                s.routers[i].send[NORTH] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i + ncols].recv[SOUTH]
                chl_id += 1

            if i % ncols > 0:
                s.routers[i].send[WEST] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i - 1].recv[EAST]
                chl_id += 1

            if i % ncols < ncols - 1:
                s.routers[i].send[EAST] //= s.channels[chl_id].recv
                s.channels[chl_id].send //= s.routers[i + 1].recv[WEST]
                chl_id += 1

            # Connect the self port (with Network Interface)

            s.recv[i] //= s.routers[i].recv[SELF]
            s.send[i] //= s.routers[i].send[SELF]

            # Connect the unused ports
            # FIXME: for now we hackily ground the payload field so that pymtl
            # won't complain about net need driver.

            if i // ncols == 0:
                s.routers[i].send[SOUTH].rdy //= 0
                s.routers[i].recv[SOUTH].val //= 0
                s.routers[i].recv[SOUTH].msg.payload //= 0

            if i // ncols == nrows - 1:
                s.routers[i].send[NORTH].rdy //= 0
                s.routers[i].recv[NORTH].val //= 0
                s.routers[i].recv[NORTH].msg.payload //= 0

            if i % ncols == 0:
                s.routers[i].send[WEST].rdy //= 0
                s.routers[i].recv[WEST].val //= 0
                s.routers[i].recv[WEST].msg.payload //= 0

            if i % ncols == ncols - 1:
                s.routers[i].send[EAST].rdy //= 0
                s.routers[i].recv[EAST].val //= 0
                s.routers[i].recv[EAST].msg.payload //= 0