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
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
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
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
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 )
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
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 )
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
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)