コード例 #1
0
  def __init__( s ):

    #---------------------------------------------------------------------
    # Interfaces
    #---------------------------------------------------------------------

    s.xcelreq  = InValRdyBundle ( XcelReqMsg()  )
    s.xcelresp = OutValRdyBundle( XcelRespMsg() )

    #---------------------------------------------------------------------
    # Gcd XcelHLS
    #---------------------------------------------------------------------

    s.gcd_xcel  = GcdXcelHLS()

    s.connect( s.gcd_xcel.xcelreq.msg, s.xcelreq.msg )

    #---------------------------------------------------------------------
    # Send stage
    #---------------------------------------------------------------------
    # send the configuration message or the iterator message

    s.do_send = Wire( 1 )

    @s.combinational
    def send_request():

      s.gcd_xcel.xcelreq.val.value = ~s.pipe_stg.prev_stall & s.xcelreq.val

      s.xcelreq.rdy.value = s.gcd_xcel.xcelreq.rdy & ~s.pipe_stg.prev_stall

      s.do_send.value = s.xcelreq.val & s.xcelreq.rdy

    #---------------------------------------------------------------------
    # Receive stage
    #---------------------------------------------------------------------
    # receive response messages

    s.pipe_stg = PipeCtrlFuture()

    s.connect( s.pipe_stg.next_squash, 0 )
    s.connect( s.pipe_stg.next_stall,  0 )
    s.connect( s.pipe_stg.curr_squash, 0 )

    s.connect( s.pipe_stg.prev_val, s.do_send )

    s.xcelresp_q = SingleElementPipelinedQueue( XcelRespMsg() )

    s.connect( s.gcd_xcel.xcelresp,  s.xcelresp_q.enq )
    s.connect( s.xcelresp_q.deq.msg, s.xcelresp.msg   )

    @s.combinational
    def receive_response():

      s.xcelresp_q.deq.rdy.value = s.pipe_stg.curr_val & s.xcelresp.rdy

      s.xcelresp.val.value = s.pipe_stg.curr_val & s.xcelresp_q.deq.val

      s.pipe_stg.curr_stall.value = \
        s.pipe_stg.curr_val & ( ~s.xcelresp.rdy | ~s.xcelresp_q.deq.val )
コード例 #2
0
def resp(type_, data):
    msg = XcelRespMsg()

    if type_ == 'rd': msg.type_ = XcelRespMsg.TYPE_READ
    elif type_ == 'wr': msg.type_ = XcelRespMsg.TYPE_WRITE

    msg.data = data
    return msg
コード例 #3
0
def resp( type_, data ):
  msg = XcelRespMsg()

  if   type_ == 'rd': msg.type_ = XcelRespMsg.TYPE_READ
  elif type_ == 'wr': msg.type_ = XcelRespMsg.TYPE_WRITE

  msg.data  = data
  return msg
コード例 #4
0
def resp( opaque, type_, data, id ):
  msg = XcelRespMsg()

  msg.opaque = opaque

  if   type_ == 'rd': msg.type_ = XcelRespMsg.TYPE_READ
  elif type_ == 'wr': msg.type_ = XcelRespMsg.TYPE_WRITE

  msg.data  = data
  msg.id    = id
  return msg
コード例 #5
0
    def __init__(s,
                 xcel,
                 src_msgs,
                 sink_msgs,
                 dump_vcd=False,
                 test_verilog=False):

        # Instantiate models

        s.src = TestSource(XcelReqMsg(), src_msgs)
        s.xcel = xcel
        s.mem = TestMemory(MemMsg(8, 32, 32), 1)
        s.sink = TestSink(XcelRespMsg(), sink_msgs)

        # Dump VCD

        if dump_vcd:
            s.xcel.vcd_file = dump_vcd

        # Translation

        if test_verilog:
            s.xcel = TranslationTool(s.xcel)

        # Connect

        s.connect(s.src.out, s.xcel.xcelreq)
        s.connect(s.xcel.memreq, s.mem.reqs[0])
        s.connect(s.xcel.memresp, s.mem.resps[0])
        s.connect(s.xcel.xcelresp, s.sink.in_)
コード例 #6
0
    def __init__(s,
                 xcel,
                 src_msgs,
                 sink_msgs,
                 src_delay,
                 sink_delay,
                 dump_vcd=False,
                 test_verilog=False):

        # Instantiate models

        s.src = TestSource(XcelReqMsg(), src_msgs, src_delay)
        s.xcel = xcel
        s.sink = TestSink(XcelRespMsg(), sink_msgs, sink_delay)

        # Dump VCD

        if dump_vcd:
            s.xcel.vcd_file = dump_vcd

        # Translation

        if test_verilog:
            s.xcel = TranslationTool(s.xcel)

        # Connect

        s.connect(s.src.out, s.xcel.xcelreq)
        s.connect(s.xcel.xcelresp, s.sink.in_)
コード例 #7
0
def resp(opaque, type_, data, id):
    msg = XcelRespMsg()

    msg.opaque = opaque

    if type_ == 'rd': msg.type_ = XcelRespMsg.TYPE_READ
    elif type_ == 'wr': msg.type_ = XcelRespMsg.TYPE_WRITE

    msg.data = data
    msg.id = id
    return msg
コード例 #8
0
  def __init__( s ):

    s.xcelreq  = InValRdyBundle ( XcelReqMsg()  )
    s.xcelresp = OutValRdyBundle( XcelRespMsg() )

    s.set_ports({
      'ap_clk'                    : s.clk,
      'ap_rst'                    : s.reset,
      'xcelreq_V_bits_V'          : s.xcelreq.msg,
      'xcelreq_V_bits_V_ap_vld'   : s.xcelreq.val,
      'xcelreq_V_bits_V_ap_ack'   : s.xcelreq.rdy,
      'xcelresp_V_bits_V'         : s.xcelresp.msg,
      'xcelresp_V_bits_V_ap_vld'  : s.xcelresp.val,
      'xcelresp_V_bits_V_ap_ack'  : s.xcelresp.rdy
    })
コード例 #9
0
    def block():

      go = False
      while not go:

        xcelreq_msg = s.xcelreq_q.popleft()

        if xcelreq_msg.type_ == XcelReqMsg.TYPE_WRITE:

          assert  xcelreq_msg.raddr in [1,2], \
            "Only reg writes to 1,2 allowed during setup!"

          # Use xcel register address to configure accelerator

          if   xcelreq_msg.raddr == 1: s.operandA = xcelreq_msg.data
          elif xcelreq_msg.raddr == 2: s.operandB = xcelreq_msg.data

          # Send xcel response message

          xcelresp_msg        = XcelRespMsg()
          xcelresp_msg.opaque = xcelreq_msg.opaque
          xcelresp_msg.type_  = XcelRespMsg.TYPE_WRITE
          s.xcelresp_q.append( xcelresp_msg )

        elif xcelreq_msg.type_ == XcelReqMsg.TYPE_READ:

          assert  xcelreq_msg.raddr in [0], \
            "Only reg read to 0 allowed!"

          go = True

      # Compute Gcd of the operands

      s.result = gcd( s.operandA, s.operandB )

      # Send xcel response message indicating xcel is done

      xcelresp_msg        = XcelRespMsg()
      xcelresp_msg.opaque = xcelreq_msg.opaque
      xcelresp_msg.type_  = XcelRespMsg.TYPE_READ
      xcelresp_msg.data   = s.result
      xcelresp_msg.id     = xcelreq_msg.id
      s.xcelresp_q.append( xcelresp_msg )
コード例 #10
0
def run_test(test_num, data_in_addr, data_in, data_out_addr, data_out):

    # Convert test data into byte array

    data_in_bytes = struct.pack("<{}I".format(len(data_in)), *data_in)

    # Protocol messages

    msg = XcelReqMsg()
    msg.type_ = XcelReqMsg.TYPE_WRITE
    msg.raddr = 0
    msg.data = test_num
    msg.opaque = 0x88
    xreqs = [msg]

    msg = XcelRespMsg()
    msg.type_ = XcelRespMsg.TYPE_WRITE
    msg.data = 0
    msg.opaque = 0x88
    xresps = [msg]

    # Create test harness with protocol messagse

    th = TestHarness(MemProxyHLS(), xreqs, xresps)

    # Load the data into the test memory

    th.mem.write_mem(data_in_addr, data_in_bytes)

    # Run the test

    run_sim(th, dump_vcd=False, max_cycles=20000)

    # Retrieve data from test memory

    result_bytes = th.mem.read_mem(data_out_addr, len(data_out) * 4)

    # Convert result bytes into list of ints

    result = list(
        struct.unpack("<{}I".format(len(data_out)), buffer(result_bytes)))

    # Compare result to sorted reference

    assert result == data_out
コード例 #11
0
ファイル: SortXcelCL.py プロジェクト: nmtrmail/pymtl-tut-hls
        def block():

            # Tick adapters

            s.xcelreq_q.xtick()
            s.xcelresp_q.xtick()
            s.memreq_q.xtick()
            s.memresp_q.xtick()

            # Line tracing string

            s.prev_state = s.state

            #-------------------------------------------------------------------
            # STATE: XCFG
            #-------------------------------------------------------------------
            # In this state we handle the accelerator configuration protocol,
            # where we write the base address, size, and then tell the
            # accelerator to start. We also handle responding when the
            # accelerator is done.

            if s.state == s.STATE_XCFG:
                s.xcfg_trace = "  "
                if not s.xcelreq_q.empty() and not s.xcelresp_q.full():

                    xcelreq_msg = s.xcelreq_q.deq()

                    if xcelreq_msg.type_ == XcelReqMsg.TYPE_WRITE:

                        assert xcelreq_msg.raddr in [0,1,2], \
                          "Only reg writes to 0,1,2 allowed during setup!"

                        if xcelreq_msg.raddr == 0:
                            s.xcfg_trace = "X0"
                            s.outer_count = 0
                            s.state = s.STATE_FIRST0

                        elif xcelreq_msg.raddr == 1:
                            s.xcfg_trace = "X1"
                            s.base_addr = xcelreq_msg.data.uint()

                        elif xcelreq_msg.raddr == 2:
                            s.xcfg_trace = "X2"
                            s.size = xcelreq_msg.data.uint()

                        # Send xcel response message

                        xcelresp_msg = XcelRespMsg()
                        xcelresp_msg.type_ = XcelRespMsg.TYPE_WRITE
                        s.xcelresp_q.enq(xcelresp_msg)

                    else:

                        s.xcfg_trace = "x0"

                        assert xcelreq_msg.raddr == 0

                        # Send xcel response message, obviously you only want to
                        # send the response message when accelerator is done

                        xcelresp_msg = XcelRespMsg()
                        xcelresp_msg.type_ = XcelRespMsg.TYPE_READ
                        xcelresp_msg.data = 1
                        s.xcelresp_q.enq(xcelresp_msg)

            #-------------------------------------------------------------------
            # STATE: FIRST0
            #-------------------------------------------------------------------
            # Send the first memory read request for the very first
            # element in the array.

            elif s.state == s.STATE_FIRST0:
                if not s.memreq_q.full():
                    s.memreq_q.enq(s.mk_rd(0, s.base_addr, 0))
                    s.inner_count = 1
                    s.state = s.STATE_FIRST1

            #-------------------------------------------------------------------
            # STATE: FIRST1
            #-------------------------------------------------------------------
            # Wait for the memory response for the first element in the array,
            # and once it arrives store this element in a, and send the memory
            # read request for the second element.

            elif s.state == s.STATE_FIRST1:
                if not s.memreq_q.full() and not s.memresp_q.empty():
                    s.a = deepcopy(s.memresp_q.deq().data)
                    addr = s.base_addr + 4 * s.inner_count
                    s.memreq_q.enq(s.mk_rd(0, addr, 0))
                    s.state = s.STATE_BUBBLE0

            #-------------------------------------------------------------------
            # STATE: BUBBLE0
            #-------------------------------------------------------------------
            # Wait for the memory read response to get the next element,
            # compare the new value to the previous max value, update b with
            # the new max value, and send a memory request to store the new min
            # value. Notice how we decrement the write address by four since we
            # want to store to the new min value _previous_ element.

            elif s.state == s.STATE_BUBBLE0:
                if not s.memreq_q.full() and not s.memresp_q.empty():
                    s.b = deepcopy(s.memresp_q.deq().data)
                    max_value = max(s.a, s.b)
                    min_value = min(s.a, s.b)
                    s.a = max_value
                    addr = s.base_addr + 4 * s.inner_count
                    s.memreq_q.enq(s.mk_wr(0, addr - 4, 0, min_value))
                    s.state = s.STATE_BUBBLE1

            #-------------------------------------------------------------------
            # STATE: BUBBLE1
            #-------------------------------------------------------------------
            # Wait for the memory write response, and then check to see if we
            # have reached the end of the array. If we have not reached the end
            # of the array, then make a new memory read request for the next
            # element; if we have reached the end of the array, then make a
            # final write request (with value from a) to update the final
            # element in the array.

            elif s.state == s.STATE_BUBBLE1:
                if not s.memreq_q.full() and not s.memresp_q.empty():
                    s.memresp_q.deq()
                    s.inner_count += 1
                    if s.inner_count < s.size:

                        addr = s.base_addr + 4 * s.inner_count
                        s.memreq_q.enq(s.mk_rd(0, addr, 0))
                        s.state = s.STATE_BUBBLE0

                    else:

                        addr = s.base_addr + 4 * s.inner_count
                        s.memreq_q.enq(s.mk_wr(0, addr - 4, 0, s.a))
                        s.state = s.STATE_LAST

            #-------------------------------------------------------------------
            # STATE: LAST
            #-------------------------------------------------------------------
            # Wait for the last response, and then check to see if we need to
            # go through the array again. If we do need to go through array
            # again, then make a new memory read request for the very first
            # element in the array; if we do not need to go through the array
            # again, then we are all done and we can go back to accelerator
            # configuration.

            elif s.state == s.STATE_LAST:
                if not s.memreq_q.full() and not s.memresp_q.empty():
                    s.memresp_q.deq()
                    s.outer_count += 1
                    if s.outer_count < s.size:

                        s.memreq_q.enq(s.mk_rd(0, s.base_addr, 0))
                        s.inner_count = 1
                        s.state = s.STATE_FIRST1

                    else:
                        s.state = s.STATE_XCFG
コード例 #12
0
    def block():

      # We loop handling accelerator requests. We are only expecting
      # writes to xr0-2, so any other requests are an error. We exit the
      # loop when we see the write to xr0.

      go = False
      while not go:

        xcelreq_msg = s.xcelreq_q.popleft()

        # Only expecting writes to xr0-2, so any other request is an xcel
        # protocol error.

        assert xcelreq_msg.type_ == XcelReqMsg.TYPE_WRITE, \
          "Only reg writes allowed during setup!"

        assert xcelreq_msg.raddr in [0,1,2], \
          "Only reg writes to 0,1,2 allowed during setup!"

        # Use xcel register address to configure accelerator

        if   xcelreq_msg.raddr == 0: go = True
        elif xcelreq_msg.raddr == 1: s.data.set_base( xcelreq_msg.data )
        elif xcelreq_msg.raddr == 2: s.data.set_size( xcelreq_msg.data )

        # Send xcel response message

        xcelresp_msg = XcelRespMsg()
        xcelresp_msg.type_ = XcelRespMsg.TYPE_WRITE
        s.xcelresp_q.append( xcelresp_msg )

      # Now that we have setup the list memory port adapter, we can use
      # the data as a standard Python list. The adapter handles turning
      # reads and writes to the list into the corresponding read/write
      # memory requests, and also waiting for the responses. So we first
      # create a sorted version of the list ...

      data_sorted = sorted(s.data)

      # And then we copy the result out to memory

      for i in xrange(len(data_sorted)):
        s.data[i] = data_sorted[i]

      # Now wait for read of xr0

      xcelmsg = s.xcelreq_q.popleft()

      # Only expecting read from xr0, so any other request is an xcel
      # protocol error.

      assert xcelreq_msg.type_ == XcelReqMsg.TYPE_READ, \
        "Only reg reads allowed during done phase!"

      assert xcelreq_msg.raddr == 0, \
        "Only reg writes to 0,1,2 allowed during done phase!"

      # Send xcel response message indicating xcel is done

      xcelresp_msg = XcelRespMsg()
      xcelresp_msg.type_ = XcelRespMsg.TYPE_READ
      xcelresp_msg.data  = 1
      s.xcelresp_q.append( xcelresp_msg )
コード例 #13
0
    def block():

      # Tick adapters

      s.xcelreq_q.xtick()
      s.xcelresp_q.xtick()
      s.memreq_q.xtick()
      s.memresp_q.xtick()

      # Line tracing string

      s.prev_state = s.state

      #-------------------------------------------------------------------
      # STATE: XCFG
      #-------------------------------------------------------------------
      # In this state we handle the accelerator configuration protocol,
      # where we write the base address, size, and then tell the
      # accelerator to start. We also handle responding when the
      # accelerator is done.

      if s.state == s.STATE_XCFG:
        s.xcfg_trace = "  "
        if not s.xcelreq_q.empty() and not s.xcelresp_q.full():

          xcelreq_msg = s.xcelreq_q.deq()

          if xcelreq_msg.type_ == XcelReqMsg.TYPE_WRITE:

            assert xcelreq_msg.raddr in [0,1,2], \
              "Only reg writes to 0,1,2 allowed during setup!"

            if   xcelreq_msg.raddr == 0:
              s.xcfg_trace = "X0"
              s.outer_count = 0
              s.state = s.STATE_FIRST0

            elif xcelreq_msg.raddr == 1:
              s.xcfg_trace = "X1"
              s.base_addr = xcelreq_msg.data.uint()

            elif xcelreq_msg.raddr == 2:
              s.xcfg_trace = "X2"
              s.size = xcelreq_msg.data.uint()

            # Send xcel response message

            xcelresp_msg = XcelRespMsg()
            xcelresp_msg.type_ = XcelRespMsg.TYPE_WRITE
            s.xcelresp_q.enq( xcelresp_msg )

          else:

            s.xcfg_trace = "x0"

            assert xcelreq_msg.raddr == 0

            # Send xcel response message, obviously you only want to
            # send the response message when accelerator is done

            xcelresp_msg = XcelRespMsg()
            xcelresp_msg.type_ = XcelRespMsg.TYPE_READ
            xcelresp_msg.data  = 1
            s.xcelresp_q.enq( xcelresp_msg )

      #-------------------------------------------------------------------
      # STATE: FIRST0
      #-------------------------------------------------------------------
      # Send the first memory read request for the very first
      # element in the array.

      elif s.state == s.STATE_FIRST0:
        if not s.memreq_q.full():
          s.memreq_q.enq( s.mk_rd( 0, s.base_addr, 0 ) )
          s.inner_count = 1
          s.state = s.STATE_FIRST1

      #-------------------------------------------------------------------
      # STATE: FIRST1
      #-------------------------------------------------------------------
      # Wait for the memory response for the first element in the array,
      # and once it arrives store this element in a, and send the memory
      # read request for the second element.

      elif s.state == s.STATE_FIRST1:
        if not s.memreq_q.full() and not s.memresp_q.empty():
          s.a = deepcopy( s.memresp_q.deq().data )
          addr = s.base_addr + 4*s.inner_count
          s.memreq_q.enq( s.mk_rd( 0, addr, 0 ) )
          s.state = s.STATE_BUBBLE0

      #-------------------------------------------------------------------
      # STATE: BUBBLE0
      #-------------------------------------------------------------------
      # Wait for the memory read response to get the next element,
      # compare the new value to the previous max value, update b with
      # the new max value, and send a memory request to store the new min
      # value. Notice how we decrement the write address by four since we
      # want to store to the new min value _previous_ element.

      elif s.state == s.STATE_BUBBLE0:
        if not s.memreq_q.full() and not s.memresp_q.empty():
          s.b = deepcopy( s.memresp_q.deq().data )
          max_value = max( s.a, s.b )
          min_value = min( s.a, s.b )
          s.a = max_value
          addr = s.base_addr + 4*s.inner_count
          s.memreq_q.enq( s.mk_wr( 0, addr-4, 0, min_value ) )
          s.state = s.STATE_BUBBLE1

      #-------------------------------------------------------------------
      # STATE: BUBBLE1
      #-------------------------------------------------------------------
      # Wait for the memory write response, and then check to see if we
      # have reached the end of the array. If we have not reached the end
      # of the array, then make a new memory read request for the next
      # element; if we have reached the end of the array, then make a
      # final write request (with value from a) to update the final
      # element in the array.

      elif s.state == s.STATE_BUBBLE1:
        if not s.memreq_q.full() and not s.memresp_q.empty():
          s.memresp_q.deq()
          s.inner_count += 1
          if s.inner_count < s.size:

            addr = s.base_addr + 4*s.inner_count
            s.memreq_q.enq( s.mk_rd( 0, addr, 0 ) )
            s.state = s.STATE_BUBBLE0

          else:

            addr = s.base_addr + 4*s.inner_count
            s.memreq_q.enq( s.mk_wr( 0, addr-4, 0, s.a ) )
            s.state = s.STATE_LAST

      #-------------------------------------------------------------------
      # STATE: LAST
      #-------------------------------------------------------------------
      # Wait for the last response, and then check to see if we need to
      # go through the array again. If we do need to go through array
      # again, then make a new memory read request for the very first
      # element in the array; if we do not need to go through the array
      # again, then we are all done and we can go back to accelerator
      # configuration.

      elif s.state == s.STATE_LAST:
        if not s.memreq_q.full() and not s.memresp_q.empty():
          s.memresp_q.deq()
          s.outer_count += 1
          if s.outer_count < s.size:

            s.memreq_q.enq( s.mk_rd( 0, s.base_addr, 0 ) )
            s.inner_count = 1
            s.state = s.STATE_FIRST1

          else:
            s.state = s.STATE_XCFG
コード例 #14
0
ファイル: SortXcelRTL.py プロジェクト: nmtrmail/pymtl-tut-hls
    def __init__(s, mem_ifc_types=MemMsg(8, 32, 32)):

        # Interface

        s.xcelreq = InValRdyBundle(XcelReqMsg())
        s.xcelresp = OutValRdyBundle(XcelRespMsg())

        s.memreq = OutValRdyBundle(mem_ifc_types.req)
        s.memresp = InValRdyBundle(mem_ifc_types.resp)

        # Queues

        s.xcelreq_q = SingleElementPipelinedQueue(XcelReqMsg())
        s.connect(s.xcelreq, s.xcelreq_q.enq)

        s.memreq_q = SingleElementBypassQueue(MemReqMsg(8, 32, 32))
        s.connect(s.memreq, s.memreq_q.deq)

        s.memresp_q = SingleElementPipelinedQueue(MemRespMsg(8, 32))
        s.connect(s.memresp, s.memresp_q.enq)

        # Internal state

        s.base_addr = Reg(32)
        s.size = Reg(32)
        s.inner_count = Reg(32)
        s.outer_count = Reg(32)
        s.a = Reg(32)

        # Line tracing

        s.prev_state = 0
        s.xcfg_trace = "  "

        # Helpers to make memory read/write requests

        s.mk_rd = mem_ifc_types.req.mk_rd
        s.mk_wr = mem_ifc_types.req.mk_wr

        #=====================================================================
        # State Update
        #=====================================================================

        s.STATE_XCFG = 0
        s.STATE_FIRST0 = 1
        s.STATE_FIRST1 = 2
        s.STATE_BUBBLE0 = 3
        s.STATE_BUBBLE1 = 4
        s.STATE_LAST = 5

        s.state = Wire(8)

        s.go = Wire(1)

        @s.tick_rtl
        def block0():

            if s.reset:
                s.state.next = s.STATE_XCFG
            else:
                s.state.next = s.state

                if s.state == s.STATE_XCFG:
                    if s.go & s.xcelresp.val & s.xcelresp.rdy:
                        s.state.next = s.STATE_FIRST0

                elif s.state == s.STATE_FIRST0:
                    if s.memreq_q.enq.rdy:
                        s.state.next = s.STATE_FIRST1

                elif s.state == s.STATE_FIRST1:
                    if s.memreq_q.enq.rdy and s.memresp_q.deq.rdy:
                        s.state.next = s.STATE_BUBBLE0

                elif s.state == s.STATE_BUBBLE0:
                    if s.memreq_q.enq.rdy and s.memresp_q.deq.rdy:
                        s.state.next = s.STATE_BUBBLE1

                elif s.state == s.STATE_BUBBLE1:
                    if s.memreq_q.enq.rdy and s.memresp_q.deq.rdy:
                        if s.inner_count.out + 1 < s.size.out:
                            s.state.next = s.STATE_BUBBLE0
                        else:
                            s.state.next = s.STATE_LAST

                elif s.state == s.STATE_LAST:
                    if s.memreq_q.enq.rdy and s.memresp_q.deq.rdy:
                        if s.outer_count.out + 1 < s.size.out:
                            s.state.next = s.STATE_FIRST1
                        else:
                            s.state.next = s.STATE_XCFG

        #=====================================================================
        # State Outputs
        #=====================================================================

        @s.combinational
        def block1():

            s.xcelreq_q.deq.rdy.value = 0
            s.xcelresp.val.value = 0
            s.memreq_q.enq.val.value = 0
            s.memresp_q.deq.rdy.value = 0
            s.go.value = 0

            s.outer_count.in_.value = s.outer_count.out
            s.inner_count.in_.value = s.inner_count.out

            #-------------------------------------------------------------------
            # STATE: XCFG
            #-------------------------------------------------------------------

            if s.state == s.STATE_XCFG:
                s.xcelreq_q.deq.rdy.value = s.xcelresp.rdy
                s.xcelresp.val.value = s.xcelreq_q.deq.val

                if s.xcelreq_q.deq.val:

                    if s.xcelreq_q.deq.msg.type_ == XcelReqMsg.TYPE_WRITE:

                        if s.xcelreq_q.deq.msg.raddr == 0:
                            s.outer_count.in_.value = 0
                            s.go.value = 1

                        elif s.xcelreq_q.deq.msg.raddr == 1:
                            s.base_addr.in_.value = s.xcelreq_q.deq.msg.data

                        elif s.xcelreq_q.deq.msg.raddr == 2:
                            s.size.in_.value = s.xcelreq_q.deq.msg.data

                        # Send xcel response message

                        s.xcelresp.msg.type_.value = XcelRespMsg.TYPE_WRITE

                    else:

                        # Send xcel response message, obviously you only want to
                        # send the response message when accelerator is done

                        s.xcelresp.msg.type_.value = XcelRespMsg.TYPE_READ
                        s.xcelresp.msg.data.value = 1

            #-------------------------------------------------------------------
            # STATE: FIRST0
            #-------------------------------------------------------------------
            # Send the first memory read request for the very first
            # element in the array.

            elif s.state == s.STATE_FIRST0:
                if s.memreq_q.enq.rdy:

                    s.memreq_q.enq.val.value = 1
                    s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_READ
                    s.memreq_q.enq.msg.opaque.value = 0
                    s.memreq_q.enq.msg.addr.value = s.base_addr.out + 4 * s.inner_count.out
                    s.memreq_q.enq.msg.len.value = 0

                    s.inner_count.in_.value = 1

            #-------------------------------------------------------------------
            # STATE: FIRST1
            #-------------------------------------------------------------------
            # Wait for the memory response for the first element in the array,
            # and once it arrives store this element in a, and send the memory
            # read request for the second element.

            elif s.state == s.STATE_FIRST1:
                if s.memreq_q.enq.rdy and s.memresp_q.deq.val:
                    s.memresp_q.deq.rdy.value = 1
                    s.a.in_.value = s.memresp_q.deq.msg.data

                    s.memreq_q.enq.val.value = 1
                    s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_READ
                    s.memreq_q.enq.msg.opaque.value = 0
                    s.memreq_q.enq.msg.addr.value = s.base_addr.out + 4 * s.inner_count.out
                    s.memreq_q.enq.msg.len.value = 0

            #-------------------------------------------------------------------
            # STATE: BUBBLE0
            #-------------------------------------------------------------------
            # Wait for the memory read response to get the next element,
            # compare the new value to the previous max value, update b with
            # the new max value, and send a memory request to store the new min
            # value. Notice how we decrement the write address by four since we
            # want to store to the new min value _previous_ element.

            elif s.state == s.STATE_BUBBLE0:
                if s.memreq_q.enq.rdy and s.memresp_q.deq.val:
                    s.memresp_q.deq.rdy.value = 1

                    if s.a.out > s.memresp_q.deq.msg:
                        s.a.in_.value = s.a.out
                        s.memreq_q.enq.msg.data.value = s.memresp_q.deq.msg
                    else:
                        s.a.in_.value = s.memresp_q.deq.msg
                        s.memreq_q.enq.msg.data.value = s.a.out

                    s.memreq_q.enq.val.value = 1
                    s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_WRITE
                    s.memreq_q.enq.msg.opaque.value = 0
                    s.memreq_q.enq.msg.addr.value = (s.base_addr.out + 4 *
                                                     (s.inner_count.out - 1))
                    s.memreq_q.enq.msg.len.value = 0

            #-------------------------------------------------------------------
            # STATE: BUBBLE1
            #-------------------------------------------------------------------
            # Wait for the memory write response, and then check to see if we
            # have reached the end of the array. If we have not reached the end
            # of the array, then make a new memory read request for the next
            # element; if we have reached the end of the array, then make a
            # final write request (with value from a) to update the final
            # element in the array.

            elif s.state == s.STATE_BUBBLE1:
                if s.memreq_q.enq.rdy and s.memresp_q.deq.val:
                    s.memresp_q.deq.rdy.value = 1

                    s.inner_count.in_.value = s.inner_count.out + 1
                    if s.inner_count.out + 1 < s.size.out:

                        s.memreq_q.enq.val.value = 1
                        s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_READ
                        s.memreq_q.enq.msg.opaque.value = 0
                        s.memreq_q.enq.msg.addr.value = s.base_addr.out + 4 * (
                            s.inner_count.out + 1)
                        s.memreq_q.enq.msg.len.value = 0

                    else:

                        s.memreq_q.enq.val.value = 1
                        s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_WRITE
                        s.memreq_q.enq.msg.opaque.value = 0
                        s.memreq_q.enq.msg.addr.value = (s.base_addr.out + 4 *
                                                         (s.inner_count.out))
                        s.memreq_q.enq.msg.len.value = 0
                        s.memreq_q.enq.msg.data.value = s.a.out

            #-------------------------------------------------------------------
            # STATE: LAST
            #-------------------------------------------------------------------
            # Wait for the last response, and then check to see if we need to
            # go through the array again. If we do need to go through array
            # again, then make a new memory read request for the very first
            # element in the array; if we do not need to go through the array
            # again, then we are all done and we can go back to accelerator
            # configuration.

            elif s.state == s.STATE_LAST:
                if s.memreq_q.enq.rdy and s.memresp_q.deq.val:
                    s.memresp_q.deq.rdy.value = 1

                    s.outer_count.in_.value = s.outer_count.out + 1
                    if s.outer_count.out + 1 < s.size.out:

                        s.memreq_q.enq.val.value = 1
                        s.memreq_q.enq.msg.type_.value = MemReqMsg.TYPE_READ
                        s.memreq_q.enq.msg.opaque.value = 0
                        s.memreq_q.enq.msg.addr.value = s.base_addr.out
                        s.memreq_q.enq.msg.len.value = 0

                        s.inner_count.in_.value = 1
コード例 #15
0
        def block():

            # We loop handling accelerator requests. We are only expecting
            # writes to xr0-2, so any other requests are an error. We exit the
            # loop when we see the write to xr0.

            go = False
            while not go:

                xcelreq_msg = s.xcelreq_q.popleft()

                # Only expecting writes to xr0-2, so any other request is an xcel
                # protocol error.

                assert xcelreq_msg.type_ == XcelReqMsg.TYPE_WRITE, \
                  "Only reg writes allowed during setup!"

                assert xcelreq_msg.raddr in [0,1,2], \
                  "Only reg writes to 0,1,2 allowed during setup!"

                # Use xcel register address to configure accelerator

                if xcelreq_msg.raddr == 0: go = True
                elif xcelreq_msg.raddr == 1: s.data.set_base(xcelreq_msg.data)
                elif xcelreq_msg.raddr == 2: s.data.set_size(xcelreq_msg.data)

                # Send xcel response message

                xcelresp_msg = XcelRespMsg()
                xcelresp_msg.type_ = XcelRespMsg.TYPE_WRITE
                s.xcelresp_q.append(xcelresp_msg)

            # Now that we have setup the list memory port adapter, we can use
            # the data as a standard Python list. The adapter handles turning
            # reads and writes to the list into the corresponding read/write
            # memory requests, and also waiting for the responses. So we first
            # create a sorted version of the list ...

            data_sorted = sorted(s.data)

            # And then we copy the result out to memory

            for i in xrange(len(data_sorted)):
                s.data[i] = data_sorted[i]

            # Now wait for read of xr0

            xcelmsg = s.xcelreq_q.popleft()

            # Only expecting read from xr0, so any other request is an xcel
            # protocol error.

            assert xcelreq_msg.type_ == XcelReqMsg.TYPE_READ, \
              "Only reg reads allowed during done phase!"

            assert xcelreq_msg.raddr == 0, \
              "Only reg writes to 0,1,2 allowed during done phase!"

            # Send xcel response message indicating xcel is done

            xcelresp_msg = XcelRespMsg()
            xcelresp_msg.type_ = XcelRespMsg.TYPE_READ
            xcelresp_msg.data = 1
            s.xcelresp_q.append(xcelresp_msg)