def construct(s): MemReqMsg, MemRespMsg = mk_mem_msg(8, 32, 32) # Interface s.xcel = XcelMinionIfcCL(XcelReqMsg, XcelRespMsg) s.mem = MemMasterIfcCL(*mk_mem_msg(8, 32, 32))
def construct( s ): MemReqMsg, MemRespMsg = mk_mem_msg( 8,32,32 ) MEM_TYPE_READ = b4(MemMsgType.READ) MEM_TYPE_WRITE = b4(MemMsgType.WRITE) # Interface s.xcel = XcelMinionIfcRTL( XcelReqMsg, XcelRespMsg ) s.mem = MemMasterIfcRTL( *mk_mem_msg(8,32,32) )
def construct(s, proc, imem, dmem, xcel): CacheReqType, CacheRespType = mk_mem_msg(8, 32, 32) MemReqType, MemRespType = mk_mem_msg(8, 32, 128) # interface to outside ProcMemXcel s.go = InPort() s.stats_en = OutPort() s.mngr2proc = RecvIfcRTL(Bits32) s.proc2mngr = SendIfcRTL(Bits32) s.imem = MemMasterIfcRTL(MemReqType, MemRespType) s.dmem = MemMasterIfcRTL(MemReqType, MemRespType) s.proc = proc s.xcel = xcel s.icache = imem s.dcache = dmem s.funnel = Funnel(CacheReqType, 2)( in_={ 0: s.proc.dmem.req, 1: s.xcel.mem.req }, out=s.dcache.cache.req, ) s.router = Router(CacheRespType, 2)(in_=s.dcache.cache.resp, out={ 0: s.proc.dmem.resp, 1: s.xcel.mem.resp }) # connect signals s.stats_en //= s.proc.stats_en s.proc2mngr //= s.proc.proc2mngr s.mngr2proc //= s.proc.mngr2proc # proc s.proc.core_id //= 0 s.xcel.xcel //= s.proc.xcel s.icache.cache //= s.proc.imem # mem s.imem //= s.icache.mem s.dmem //= s.dcache.mem
def construct(s): # Interface s.xcel = XcelMinionIfcRTL(XcelReqMsg, XcelRespMsg) s.mem = MemMasterIfcRTL(*mk_mem_msg(8, 32, 32)) from os import path s.config_placeholder = VerilogPlaceholderConfigs( # Path to the Verilog source file src_file=path.dirname(__file__) + '/SortXcelVRTL.v', # Name of the Verilog top level module top_module='lab2_xcel_SortXcelVRTL', # Port name map port_map={ 'xcel.req.en': 'xcelreq_en', 'xcel.req.rdy': 'xcelreq_rdy', 'xcel.req.msg': 'xcelreq_msg', 'xcel.resp.en': 'xcelresp_en', 'xcel.resp.rdy': 'xcelresp_rdy', 'xcel.resp.msg': 'xcelresp_msg', 'mem.req.en': 'memreq_en', 'mem.req.rdy': 'memreq_rdy', 'mem.req.msg': 'memreq_msg', 'mem.resp.en': 'memresp_en', 'mem.resp.rdy': 'memresp_rdy', 'mem.resp.msg': 'memresp_msg', }, ) s.config_verilog_import = VerilatorImportConfigs( # Enable native Verilog line trace through Verilator vl_line_trace=True, )
def construct( s, nbits=32 ): dtype = mk_bits(nbits) # Interface s.xcel = XcelMinionIfcRTL( XcelReqMsg, XcelRespMsg ) s.mem = MemMasterIfcRTL( *mk_mem_msg(8,nbits,32) ) # Queues s.xcelreq_q = NormalQueueRTL( XcelReqMsg, 2 )( enq = s.xcel.req ) # Single accelerator register s.xr0 = RegEn( Bits32 ) # Direct connections for xcelreq/xcelresp s.xr0.in_ //= s.xcelreq_q.deq.ret.data s.xcel.resp.msg.type_ //= s.xcelreq_q.deq.ret.type_ # Even though memreq/memresp interface is not hooked up, we still # need to set the output ports correctly. s.mem.req.en //= 0 s.mem.req.msg //= mk_mem_msg(8,nbits,32)[0]() s.mem.resp.rdy //= 0 # Combinational block @s.update def block(): # Mux to force xcelresp data to zero on a write if s.xcelreq_q.deq.ret.type_ == XCEL_TYPE_WRITE: s.xcel.resp.msg.data = dtype(0) else: s.xcel.resp.msg.data = s.xr0.out # Logic for register enable both_rdy = s.xcelreq_q.deq.rdy & s.xcel.resp.rdy s.xr0.en = (s.xcelreq_q.deq.ret.type_ == XCEL_TYPE_WRITE) & both_rdy s.xcelreq_q.deq.en = both_rdy s.xcel.resp.en = both_rdy
def construct( s, image_column,image_row,window_size,window_size_ext): #def construct( s ): # Interface s.xcel = XcelMinionIfcRTL( XcelReqMsg, XcelRespMsg ) s.mem = MemMasterIfcRTL( *mk_mem_msg(8,32,32) ) from os import path s.config_placeholder = VerilogPlaceholderConfigs( # Path to the Verilog source file src_file = path.dirname(__file__) + '/Optical_flowVRTL.v', # Name of the Verilog top level module top_module = 'Final_Project_Optical_flowVRTL', # Port name map params={ 'image_column':image_column, 'image_row' :image_row, 'window_size' :window_size, 'window_size_ext':window_size_ext, }, port_map = { 'xcel.req.en' : 'xcelreq_en', 'xcel.req.rdy' : 'xcelreq_rdy', 'xcel.req.msg' : 'xcelreq_msg', 'xcel.resp.en' : 'xcelresp_en', 'xcel.resp.rdy' : 'xcelresp_rdy', 'xcel.resp.msg' : 'xcelresp_msg', 'mem.req.en' : 'memreq_en', 'mem.req.rdy' : 'memreq_rdy', 'mem.req.msg' : 'memreq_msg', 'mem.resp.en' : 'memresp_en', 'mem.resp.rdy' : 'memresp_rdy', 'mem.resp.msg' : 'memresp_msg', }, ) s.config_verilog_import = VerilatorImportConfigs( # Enable native Verilog line trace through Verilator vl_line_trace = True, )
def construct( s ): MemReqMsg, MemRespMsg = mk_mem_msg( 8,32,32 ) MEM_TYPE_READ = b4(MemMsgType.READ) MEM_TYPE_WRITE = b4(MemMsgType.WRITE) # Interface s.xcel = XcelMinionIfcRTL( XcelReqMsg, XcelRespMsg ) s.mem = MemMasterIfcRTL( *mk_mem_msg(8,32,32) ) # ''' LAB TASK '''''''''''''''''''''''''''''''''''''''''''''''''''''' # Create RTL model for sorting xcel # '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/ # Queues s.xcelreq_q = PipeQueueRTL( XcelReqMsg, 1 )( enq = s.xcel.req ) s.memresp_q = PipeQueueRTL( MemRespMsg, 1 )( enq = s.mem.resp ) # Internal state s.base_addr = Reg( Bits32 ) s.size = Reg( Bits32 ) s.inner_count = Reg( Bits32 ) s.outer_count = Reg( Bits32 ) s.a = Reg( Bits32 ) # Line tracing s.prev_state = 0 s.xcfg_trace = " " #===================================================================== # State Update #===================================================================== s.STATE_XCFG = b8(0) s.STATE_FIRST0 = b8(1) s.STATE_FIRST1 = b8(2) s.STATE_BUBBLE0 = b8(3) s.STATE_BUBBLE1 = b8(4) s.STATE_LAST = b8(5) s.state = Wire(Bits8) s.go = Wire() @s.update_ff def block0(): if s.reset: s.state <<= s.STATE_XCFG elif s.state == s.STATE_XCFG: if s.go & s.xcel.resp.rdy: s.state <<= s.STATE_FIRST0 elif s.state == s.STATE_FIRST0: if s.mem.req.rdy: s.state <<= s.STATE_FIRST1 elif s.state == s.STATE_FIRST1: if s.mem.req.rdy and s.memresp_q.deq.rdy: s.state <<= s.STATE_BUBBLE0 elif s.state == s.STATE_BUBBLE0: if s.mem.req.rdy and s.memresp_q.deq.rdy: s.state <<= s.STATE_BUBBLE1 elif s.state == s.STATE_BUBBLE1: if s.mem.req.rdy and s.memresp_q.deq.rdy: if s.inner_count.out+1 < s.size.out: s.state <<= s.STATE_BUBBLE0 else: s.state <<= s.STATE_LAST elif s.state == s.STATE_LAST: if s.mem.req.rdy and s.memresp_q.deq.rdy: if s.outer_count.out+1 < s.size.out: s.state <<= s.STATE_FIRST1 else: s.state <<= s.STATE_XCFG #===================================================================== # State Outputs #===================================================================== @s.update def block1(): s.xcelreq_q.deq.en = b1(0) s.xcel.resp.en = b1(0) s.mem.req.en = b1(0) s.mem.req.msg = MemReqMsg() s.memresp_q.deq.en = b1(0) s.go = b1(0) s.outer_count.in_ = s.outer_count.out s.inner_count.in_ = s.inner_count.out s.a.in_ = s.a.out s.size.in_ = s.size.out s.base_addr.in_ = s.base_addr.out #------------------------------------------------------------------- # STATE: XCFG #------------------------------------------------------------------- if s.state == s.STATE_XCFG: if s.xcelreq_q.deq.rdy & s.xcel.resp.rdy: s.xcelreq_q.deq.en = b1(1) s.xcel.resp.en = b1(1) if s.xcelreq_q.deq.ret.type_ == XCEL_TYPE_WRITE: if s.xcelreq_q.deq.ret.addr == b5(0): s.outer_count.in_ = b32(0) s.inner_count.in_ = b32(0) s.go = b1(1) elif s.xcelreq_q.deq.ret.addr == b5(1): s.base_addr.in_ = s.xcelreq_q.deq.ret.data elif s.xcelreq_q.deq.ret.addr == b5(2): s.size.in_ = s.xcelreq_q.deq.ret.data # Send xcel response message s.xcel.resp.msg = XcelRespMsg( XCEL_TYPE_WRITE, b32(0) ) else: # Send xcel response message, obviously you only want to # send the response message when accelerator is done s.xcel.resp.msg = XcelRespMsg( XCEL_TYPE_READ, b32(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.mem.req.rdy: s.mem.req.en = s.mem.req.rdy s.mem.req.msg = MemReqMsg( MEM_TYPE_READ, b8(0), s.base_addr.out + 4*s.inner_count.out, b2(0), b32(0) ) s.inner_count.in_ = b32(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.mem.req.rdy and s.memresp_q.deq.rdy: s.memresp_q.deq.en = b1(1) s.mem.req.en = b1(1) s.a.in_ = s.memresp_q.deq.ret.data s.mem.req.msg = MemReqMsg( MEM_TYPE_READ, b8(0), s.base_addr.out + 4*s.inner_count.out, b2(0), b32(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.mem.req.rdy and s.memresp_q.deq.rdy: s.memresp_q.deq.en = b1(1) s.mem.req.en = b1(1) if s.a.out > s.memresp_q.deq.ret.data: s.a.in_ = s.a.out s.mem.req.msg = MemReqMsg( MEM_TYPE_WRITE, b8(0), s.base_addr.out + 4*(s.inner_count.out-1), b2(0), s.memresp_q.deq.ret.data ) else: s.a.in_ = s.memresp_q.deq.ret.data s.mem.req.msg = MemReqMsg( MEM_TYPE_WRITE, b8(0), s.base_addr.out + 4*(s.inner_count.out-1), b2(0), s.a.out ) #------------------------------------------------------------------- # 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.mem.req.rdy and s.memresp_q.deq.rdy: s.memresp_q.deq.en = b1(1) s.mem.req.en = b1(1) s.inner_count.in_ = s.inner_count.out + 1 if s.inner_count.out+1 < s.size.out: s.mem.req.msg = MemReqMsg( MEM_TYPE_READ, b8(0), s.base_addr.out + 4*(s.inner_count.out+1), b2(0), b32(0) ) else: s.mem.req.msg = MemReqMsg( MEM_TYPE_WRITE, b8(0), s.base_addr.out + 4*s.inner_count.out, b2(0), 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.mem.req.rdy and s.memresp_q.deq.rdy: s.memresp_q.deq.en = b1(1) s.outer_count.in_ = s.outer_count.out + b32(1) if s.outer_count.out + b32(1) < s.size.out: s.mem.req.en = b1(1) s.mem.req.msg = MemReqMsg( MEM_TYPE_READ, b8(0), s.base_addr.out, b2(0), b32(0) ) s.inner_count.in_ = b32(1)
def construct( s ): MemReqMsg, MemRespMsg = mk_mem_msg( 8,32,32 ) # Interface s.xcel = XcelMinionIfcCL( XcelReqMsg, XcelRespMsg ) s.mem = MemMasterIfcCL( *mk_mem_msg(8,32,32) ) # ''' LAB TASK '''''''''''''''''''''''''''''''''''''''''''''''''''''' # Create CL model for sorting xcel # '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/ # Components s.xcelreq_q = PipeQueueCL( num_entries=1 )( enq = s.xcel.req ) s.memresp_q = PipeQueueCL( num_entries=1 )( enq = s.mem.resp ) # Internal state s.base_addr = 0 s.size = 0 s.inner_count = 0 s.outer_count = 0 s.a = b32(0) s.b = b32(0) # State 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 = s.STATE_XCFG # Line tracing s.prev_state = 0 s.xcfg_trace = " " # logic @s.update def block(): # 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 s.xcelreq_q.deq.rdy() and s.xcel.resp.rdy(): xcelreq_msg = s.xcelreq_q.deq() if xcelreq_msg.type_ == XCEL_TYPE_WRITE: assert xcelreq_msg.addr in [0,1,2], \ "Only reg writes to 0,1,2 allowed during setup!" if xcelreq_msg.addr == 0: s.xcfg_trace = "X0" s.outer_count = 0 s.state = s.STATE_FIRST0 elif xcelreq_msg.addr == 1: s.xcfg_trace = "X1" s.base_addr = xcelreq_msg.data.uint() elif xcelreq_msg.addr == 2: s.xcfg_trace = "X2" s.size = xcelreq_msg.data.uint() # Send xcel response message s.xcel.resp( XcelRespMsg(XCEL_TYPE_WRITE, 0) ) else: s.xcfg_trace = "x0" assert xcelreq_msg.addr == 0 # Send xcel response message, obviously you only want to # send the response message when accelerator is done s.xcel.resp( XcelRespMsg(XCEL_TYPE_READ, 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.mem.req.rdy(): s.mem.req( MemReqMsg( MemMsgType.READ, 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 s.mem.req.rdy() and s.memresp_q.deq.rdy(): s.a = s.memresp_q.deq().data addr = s.base_addr + 4*s.inner_count s.mem.req( MemReqMsg( MemMsgType.READ, 4, 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 s.mem.req.rdy() and s.memresp_q.deq.rdy(): 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.mem.req( MemReqMsg( MemMsgType.WRITE, 4, 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 s.mem.req.rdy() and s.memresp_q.deq.rdy(): s.memresp_q.deq() s.inner_count += 1 if s.inner_count < s.size: addr = s.base_addr + 4*s.inner_count s.mem.req( MemReqMsg( MemMsgType.READ, 4, addr, 0 ) ) s.state = s.STATE_BUBBLE0 else: addr = s.base_addr + 4*s.inner_count s.mem.req( MemReqMsg( MemMsgType.WRITE, 4, 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 s.mem.req.rdy() and s.memresp_q.deq.rdy(): s.memresp_q.deq() s.outer_count += 1 if s.outer_count < s.size: s.mem.req( MemReqMsg( MemMsgType.READ, 4, s.base_addr, 0 ) ) s.inner_count = 1 s.state = s.STATE_FIRST1 else: s.state = s.STATE_XCFG