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 )
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 __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_)
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_)
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 __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 })
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 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
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 __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
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)