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, CacheReqType, CacheRespType): # src -> | | -> cache # requests and responses s.proc = MemMinionIfcRTL(CacheReqType, CacheRespType) s.cache = MemMasterIfcRTL(CacheReqType, CacheRespType) s.cache.req.msg //= s.proc.req.msg s.cache.req.en //= s.proc.req.en s.proc.req.rdy //= s.cache.req.rdy s.proc.resp.msg //= s.cache.resp.msg s.proc.resp.en //= s.cache.resp.en # s.cache.resp.rdy //= s.proc.resp.rdy s.trans_in_flight = RegRst( Bits2) # keeps track of transactions in flight @s.update def signal_model(): # If the cache request is not ready, then the processor's response rdy is # low. if s.trans_in_flight.out == b2(0): s.cache.resp.rdy = s.proc.resp.rdy & s.cache.req.rdy else: s.cache.resp.rdy = s.proc.resp.rdy # s.proc.req.rdy = s.cache.req.rdy & s.proc.resp.rdy @s.update def update_trans_in_flight(): s.trans_in_flight.in_ = s.trans_in_flight.out if s.cache.req.en and ~s.cache.resp.en: s.trans_in_flight.in_ = s.trans_in_flight.out + b2(1) elif ~s.cache.req.en and s.cache.resp.en: s.trans_in_flight.in_ = s.trans_in_flight.out - b2(1)
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 ): 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, ProcClass, XcelClass): req_class, resp_class = mk_mem_msg(8, 32, 32) s.commit_inst = OutPort(Bits1) # Instruction Memory Request/Response Interface s.proc = ProcClass()(commit_inst=s.commit_inst) s.xcel = XcelClass()(xcel=s.proc.xcel) if isinstance(s.proc.imem, MemMasterIfcRTL): # RTL proc s.mngr2proc = RecvIfcRTL(Bits32) s.proc2mngr = SendIfcRTL(Bits32) s.imem = MemMasterIfcRTL(req_class, resp_class) s.dmem = MemMasterIfcRTL(req_class, resp_class) elif isinstance(s.proc.imem, MemMasterIfcCL): # CL proc s.mngr2proc = NonBlockingCalleeIfc(Bits32) s.proc2mngr = NonBlockingCallerIfc(Bits32) s.imem = MemMasterIfcCL(req_class, resp_class) s.dmem = MemMasterIfcCL(req_class, resp_class) elif isinstance(s.proc.imem, MemMasterIfcFL): # FL proc s.mngr2proc = GetIfcFL() s.proc2mngr = SendIfcFL() s.imem = MemMasterIfcFL() s.dmem = MemMasterIfcFL() s.connect_pairs( s.mngr2proc, s.proc.mngr2proc, s.proc2mngr, s.proc.proc2mngr, s.imem, s.proc.imem, s.dmem, s.proc.dmem, )
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, num_banks=0): CacheReqType, CacheRespType = mk_mem_msg(8, 32, 32) MemReqType, MemRespType = mk_mem_msg(8, 32, 128) if num_banks <= 0: idx_shamt = 0 else: idx_shamt = clog2(num_banks) # Proc <-> Cache s.cache = MemMinionIfcRTL(CacheReqType, CacheRespType) # Cache <-> Mem s.mem = MemMasterIfcRTL(MemReqType, MemRespType) s.ctrl = BlockingCacheCtrlPRTL(idx_shamt)( # Cache request cachereq_en=s.cache.req.en, cachereq_rdy=s.cache.req.rdy, # Cache response cacheresp_en=s.cache.resp.en, cacheresp_rdy=s.cache.resp.rdy, # Memory request memreq_en=s.mem.req.en, memreq_rdy=s.mem.req.rdy, # Memory response memresp_en=s.mem.resp.en, memresp_rdy=s.mem.resp.rdy, ) s.dpath = BlockingCacheDpathPRTL(idx_shamt)( # Cache request cachereq_msg=s.cache.req.msg, # Cache response cacheresp_msg=s.cache.resp.msg, # Memory request memreq_msg=s.mem.req.msg, # Memory response memresp_msg=s.mem.resp.msg, ) # control signals (ctrl->dpath) s.dpath.amo_sel //= s.ctrl.amo_sel s.dpath.cachereq_enable //= s.ctrl.cachereq_enable s.dpath.memresp_enable //= s.ctrl.memresp_enable s.dpath.is_refill //= s.ctrl.is_refill s.dpath.tag_array_0_wen //= s.ctrl.tag_array_0_wen s.dpath.tag_array_0_ren //= s.ctrl.tag_array_0_ren s.dpath.tag_array_1_wen //= s.ctrl.tag_array_1_wen s.dpath.tag_array_1_ren //= s.ctrl.tag_array_1_ren s.dpath.way_sel //= s.ctrl.way_sel s.dpath.way_sel_current //= s.ctrl.way_sel_current s.dpath.data_array_wen //= s.ctrl.data_array_wen s.dpath.data_array_ren //= s.ctrl.data_array_ren s.dpath.skip_read_data_reg //= s.ctrl.skip_read_data_reg # width of cacheline divided by number of bits per byte s.dpath.data_array_wben //= s.ctrl.data_array_wben s.dpath.read_data_reg_en //= s.ctrl.read_data_reg_en s.dpath.read_tag_reg_en //= s.ctrl.read_tag_reg_en s.dpath.read_byte_sel //= s.ctrl.read_byte_sel s.dpath.memreq_type //= s.ctrl.memreq_type s.dpath.cacheresp_type //= s.ctrl.cacheresp_type s.dpath.cacheresp_hit //= s.ctrl.cacheresp_hit # status signals (dpath->ctrl) s.ctrl.cachereq_type //= s.dpath.cachereq_type s.ctrl.cachereq_addr //= s.dpath.cachereq_addr s.ctrl.tag_match_0 //= s.dpath.tag_match_0 s.ctrl.tag_match_1 //= s.dpath.tag_match_1
def construct(s): req_class, resp_class = mk_mem_msg(8, 32, 32) # Proc/Mngr Interface s.mngr2proc = RecvIfcRTL(Bits32) s.proc2mngr = SendIfcRTL(Bits32) # Instruction Memory Request/Response Interface s.imem = MemMasterIfcRTL(req_class, resp_class) # Data Memory Request/Response Interface s.dmem = MemMasterIfcRTL(req_class, resp_class) # Xcel Request/Response Interface xreq_class, xresp_class = mk_xcel_msg(5, 32) s.xcel = XcelMasterIfcRTL(xreq_class, xresp_class) # val_W port used for counting commited insts. s.commit_inst = OutPort(Bits1) # imem drop unit s.imemresp_drop = m = DropUnitRTL(Bits32) connect_pairs( m.in_.en, s.imem.resp.en, m.in_.rdy, s.imem.resp.rdy, m.in_.msg, s.imem.resp.msg.data, ) # Bypass queues s.imemreq_q = BypassQueue2RTL(req_class, 2)(deq=s.imem.req) # We have to turn input receive interface into get interface s.imemresp_q = BypassQueueRTL(Bits32, 1)(enq=s.imemresp_drop.out) s.dmemresp_q = BypassQueueRTL(resp_class, 1)(enq=s.dmem.resp) s.mngr2proc_q = BypassQueueRTL(Bits32, 1)(enq=s.mngr2proc) s.xcelresp_q = BypassQueueRTL(xresp_class, 1)(enq=s.xcel.resp) # Control s.ctrl = ProcCtrl()( # imem port imemresp_drop=s.imemresp_drop.drop, imemreq_en=s.imemreq_q.enq.en, imemreq_rdy=s.imemreq_q.enq.rdy, imemresp_en=s.imemresp_q.deq.en, imemresp_rdy=s.imemresp_q.deq.rdy, # dmem port dmemreq_en=s.dmem.req.en, dmemreq_rdy=s.dmem.req.rdy, dmemreq_type=s.dmem.req.msg.type_, dmemresp_en=s.dmemresp_q.deq.en, dmemresp_rdy=s.dmemresp_q.deq.rdy, # xcel port xcelreq_en=s.xcel.req.en, xcelreq_rdy=s.xcel.req.rdy, xcelresp_en=s.xcelresp_q.deq.en, xcelresp_rdy=s.xcelresp_q.deq.rdy, # proc2mngr and mngr2proc proc2mngr_en=s.proc2mngr.en, proc2mngr_rdy=s.proc2mngr.rdy, mngr2proc_en=s.mngr2proc_q.deq.en, mngr2proc_rdy=s.mngr2proc_q.deq.rdy, # commit inst for counting commit_inst=s.commit_inst) # Dpath s.dpath = ProcDpath()( # imem ports imemreq_addr=s.imemreq_q.enq.msg.addr, imemresp_data=s.imemresp_q.deq.msg, # dmem ports dmemreq_addr=s.dmem.req.msg.addr, dmemreq_data=s.dmem.req.msg.data, dmemresp_data=s.dmemresp_q.deq.msg.data, # xcel ports xcelresp_data=s.xcelresp_q.deq.msg.data, # mngr mngr2proc_data=s.mngr2proc_q.deq.msg, proc2mngr_data=s.proc2mngr.msg, ) @s.update def up_xcelreq(): s.xcel.req.msg = xreq_class( s.ctrl.xcelreq_type, s.dpath.xcelreq_addr, s.dpath.xcelreq_data, ) # Ctrl <-> Dpath connect_pairs( s.ctrl.reg_en_F, s.dpath.reg_en_F, s.ctrl.pc_sel_F, s.dpath.pc_sel_F, s.ctrl.reg_en_D, s.dpath.reg_en_D, s.ctrl.op1_byp_sel_D, s.dpath.op1_byp_sel_D, s.ctrl.op2_byp_sel_D, s.dpath.op2_byp_sel_D, s.ctrl.op1_sel_D, s.dpath.op1_sel_D, s.ctrl.op2_sel_D, s.dpath.op2_sel_D, s.ctrl.imm_type_D, s.dpath.imm_type_D, s.ctrl.reg_en_X, s.dpath.reg_en_X, s.ctrl.alu_fn_X, s.dpath.alu_fn_X, s.ctrl.reg_en_M, s.dpath.reg_en_M, s.ctrl.wb_result_sel_M, s.dpath.wb_result_sel_M, s.ctrl.mask_sel_W, s.dpath.mask_sel_W, s.ctrl.reg_en_W, s.dpath.reg_en_W, s.ctrl.rf_waddr_W, s.dpath.rf_waddr_W, s.ctrl.rf_wen_W, s.dpath.rf_wen_W, s.dpath.inst_D, s.ctrl.inst_D, s.dpath.ne_X, s.ctrl.ne_X, )
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, num_cores=1): MemReqMsg, MemRespMsg = mk_mem_msg(8, 32, 32) #--------------------------------------------------------------------- # Interface #--------------------------------------------------------------------- # Starting F16 we turn core_id into input ports to # enable module reusability. In the past it was passed as arguments. s.core_id = InPort(Bits32) # Proc/Mngr Interface s.mngr2proc = RecvIfcRTL(Bits32) s.proc2mngr = SendIfcRTL(Bits32) # Instruction Memory Request/Response Interface s.imem = MemMasterIfcRTL(MemReqMsg, MemRespMsg) # Data Memory Request/Response Interface s.dmem = MemMasterIfcRTL(MemReqMsg, MemRespMsg) # Accelerator Request/Response Interface s.xcel = XcelMasterIfcRTL(XcelReqMsg, XcelRespMsg) # val_W port used for counting commited insts. s.commit_inst = OutPort() # stats_en s.stats_en = OutPort() #--------------------------------------------------------------------- # Structural composition #--------------------------------------------------------------------- # Bypass queues s.imemreq_q = BypassQueueRTL(MemReqMsg, 2) s.imemreq_q.deq.ret //= s.imem.req.msg @s.update def send_imemreq(): both_rdy = s.imem.req.rdy & s.imemreq_q.deq.rdy s.imemreq_q.deq.en = both_rdy s.imem.req.en = both_rdy # We have to turn input receive interface into get interface s.imemresp_q = BypassQueueRTL(MemRespMsg, 1)(enq=s.imem.resp) s.dmemresp_q = BypassQueueRTL(MemRespMsg, 1)(enq=s.dmem.resp) s.mngr2proc_q = BypassQueueRTL(Bits32, 1)(enq=s.mngr2proc) s.xcelresp_q = BypassQueueRTL(XcelRespMsg, 1)(enq=s.xcel.resp) # imem drop unit s.imemresp_drop_unit = DropUnitPRTL(MemRespMsg)(in_=s.imemresp_q.deq, ) # control logic s.ctrl = ProcCtrlPRTL()( # imem port imemresp_drop=s.imemresp_drop_unit.drop, imemreq_en=s.imemreq_q.enq.en, imemreq_rdy=s.imemreq_q.enq.rdy, imemresp_en=s.imemresp_drop_unit.out.en, imemresp_rdy=s.imemresp_drop_unit.out.rdy, # dmem port dmemreq_en=s.dmem.req.en, dmemreq_rdy=s.dmem.req.rdy, dmemresp_en=s.dmemresp_q.deq.en, dmemresp_rdy=s.dmemresp_q.deq.rdy, # xcel port xcelreq_en=s.xcel.req.en, xcelreq_rdy=s.xcel.req.rdy, xcelresp_en=s.xcelresp_q.deq.en, xcelresp_rdy=s.xcelresp_q.deq.rdy, # proc2mngr and mngr2proc proc2mngr_en=s.proc2mngr.en, proc2mngr_rdy=s.proc2mngr.rdy, mngr2proc_en=s.mngr2proc_q.deq.en, mngr2proc_rdy=s.mngr2proc_q.deq.rdy, # commit inst for counting commit_inst=s.commit_inst, ) # data path s.dpath = ProcDpathPRTL(num_cores)( core_id=s.core_id, stats_en=s.stats_en, # imem ports imemreq_msg=s.imemreq_q.enq.msg, imemresp_msg=s.imemresp_drop_unit.out.ret, # dmem ports dmemresp_msg=s.dmemresp_q.deq.ret, # xcel ports xcelresp_msg=s.xcelresp_q.deq.ret, # mngr mngr2proc_data=s.mngr2proc_q.deq.ret, proc2mngr_data=s.proc2mngr.msg, ) # Connect parameters s.xcel.req.msg //= lambda: XcelReqMsg( s.ctrl.xcelreq_type, s.dpath.xcelreq_addr, s.dpath.xcelreq_data) s.dmem.req.msg //= lambda: MemReqMsg(s.ctrl.dmemreq_type, b8( 0), s.dpath.dmemreq_addr, b2(0), s.dpath.dmemreq_data) # Ctrl <-> Dpath s.ctrl.reg_en_F //= s.dpath.reg_en_F s.ctrl.pc_sel_F //= s.dpath.pc_sel_F s.ctrl.reg_en_D //= s.dpath.reg_en_D s.ctrl.csrr_sel_D //= s.dpath.csrr_sel_D s.ctrl.op1_byp_sel_D //= s.dpath.op1_byp_sel_D s.ctrl.op2_byp_sel_D //= s.dpath.op2_byp_sel_D s.ctrl.op1_sel_D //= s.dpath.op1_sel_D s.ctrl.op2_sel_D //= s.dpath.op2_sel_D s.ctrl.imm_type_D //= s.dpath.imm_type_D s.ctrl.imul_req_en_D //= s.dpath.imul_req_en_D s.ctrl.imul_req_rdy_D //= s.dpath.imul_req_rdy_D s.ctrl.reg_en_X //= s.dpath.reg_en_X s.ctrl.alu_fn_X //= s.dpath.alu_fn_X s.ctrl.ex_result_sel_X //= s.dpath.ex_result_sel_X s.ctrl.imul_resp_en_X //= s.dpath.imul_resp_en_X s.ctrl.imul_resp_rdy_X //= s.dpath.imul_resp_rdy_X s.ctrl.reg_en_M //= s.dpath.reg_en_M s.ctrl.wb_result_sel_M //= s.dpath.wb_result_sel_M s.ctrl.reg_en_W //= s.dpath.reg_en_W s.ctrl.rf_waddr_W //= s.dpath.rf_waddr_W s.ctrl.rf_wen_W //= s.dpath.rf_wen_W s.ctrl.stats_en_wen_W //= s.dpath.stats_en_wen_W s.dpath.inst_D //= s.ctrl.inst_D s.dpath.br_cond_eq_X //= s.ctrl.br_cond_eq_X s.dpath.br_cond_lt_X //= s.ctrl.br_cond_lt_X s.dpath.br_cond_ltu_X //= s.ctrl.br_cond_ltu_X
def construct( s, CacheReqType, CacheRespType, MemReqType, MemRespType, num_bytes = 4096, associativity = 1 ): """ Parameters ---------- CacheReqType : type Request type for mem_minion_ifc (e.g. between processor and cache) CacheRespType : type Response type for mem_minion_ifc MemReqType : type Request type for mem_master_ifc (e.g. between this cache and memory) MemRespType : type Response type for mem_master_ifc num_bytes : int Cache size in bytes associativity : int """ # Generate additional constants and bitstructs from the given parameters s.param = p = CacheDerivedParams( CacheReqType, CacheRespType, MemReqType, MemRespType, num_bytes, associativity ) # For translation s.config_verilog_translate = TranslationConfigs( explicit_module_name = 'BlockingCache_{}_{}_{}_{}_{}'.format(num_bytes, p.bitwidth_cacheline, p.bitwidth_addr, p.bitwidth_data, associativity), ) #--------------------------------------------------------------------- # Interface #--------------------------------------------------------------------- # Memory-Minion Interface (e.g. proc <-> cache) s.mem_minion_ifc = MemMinionIfcRTL( CacheReqType, CacheRespType ) # Memory-Master Interface (e.g. cache <-> main memory or lower-level cache) s.mem_master_ifc = MemMasterIfcRTL( MemReqType, MemRespType ) #--------------------------------------------------------------------- # Structural Composition #--------------------------------------------------------------------- s.ctrl_bypass = Wire(p.StructCtrl) # pass the ctrl signals back to dpath s.cacheDpath = BlockingCacheDpathRTL( p )( cachereq_Y = s.mem_minion_ifc.req.msg, memresp_Y = s.mem_master_ifc.resp.msg, ctrl = s.ctrl_bypass ) s.cacheCtrl = BlockingCacheCtrlRTL( p )( cachereq_en = s.mem_minion_ifc.req.en, cachereq_rdy = s.mem_minion_ifc.req.rdy, memresp_en = s.mem_master_ifc.resp.en, memresp_rdy = s.mem_master_ifc.resp.rdy, cacheresp_en = s.mem_minion_ifc.resp.en, cacheresp_rdy = s.mem_minion_ifc.resp.rdy, memreq_en = s.mem_master_ifc.req.en, memreq_rdy = s.mem_master_ifc.req.rdy, status = s.cacheDpath.status, ctrl = s.ctrl_bypass ) # Cache Response Message s.mem_minion_ifc.resp.msg.opaque //= s.cacheDpath.status.cacheresp_opaque_M2 s.mem_minion_ifc.resp.msg.type_ //= s.cacheDpath.status.cacheresp_type_M2 s.mem_minion_ifc.resp.msg.data //= s.cacheDpath.status.cacheresp_data_M2 s.mem_minion_ifc.resp.msg.len //= s.cacheDpath.status.cacheresp_len_M2 s.mem_minion_ifc.resp.msg.test //= s.cacheCtrl.ctrl.hit_M2 # Memory Request Message s.mem_master_ifc.req.msg.opaque //= s.cacheDpath.status.memreq_opaque_M2 s.mem_master_ifc.req.msg.type_ //= s.cacheCtrl.ctrl.memreq_type # Bits32 # StructAddr connect_bits2bitstruct( s.mem_master_ifc.req.msg.addr, s.cacheDpath.status.memreq_addr_M2 ) s.mem_master_ifc.req.msg.data //= s.cacheDpath.status.memreq_data_M2
def construct(s, num_cores=1): # Configurations MemReqMsg, MemRespMsg = mk_mem_msg(8, 32, 32) #--------------------------------------------------------------------- # Interface #--------------------------------------------------------------------- # Starting F16 we turn core_id into input ports to # enable module reusability. In the past it was passed as arguments. s.core_id = InPort(Bits32) # Proc/Mngr Interface s.mngr2proc = RecvIfcRTL(Bits32) s.proc2mngr = SendIfcRTL(Bits32) # Instruction Memory Request/Response Interface s.imem = MemMasterIfcRTL(MemReqMsg, MemRespMsg) # Data Memory Request/Response Interface s.dmem = MemMasterIfcRTL(MemReqMsg, MemRespMsg) # Accelerator Request/Response Interface s.xcel = XcelMasterIfcRTL(XcelReqMsg, XcelRespMsg) # val_W port used for counting commited insts. s.commit_inst = OutPort() # stats_en s.stats_en = OutPort() from os import path s.config_placeholder = VerilogPlaceholderConfigs( # Path to the Verilog source file src_file=path.dirname(__file__) + '/ProcVRTL.v', # Name of the Verilog top level module top_module='proc_ProcVRTL', # Parameters of the Verilog module params={'p_num_cores': num_cores}, # Port name map port_map={ 'core_id': 'core_id', 'commit_inst': 'commit_inst', 'stats_en': 'stats_en', 'imem.req.en': 'imemreq_en', 'imem.req.rdy': 'imemreq_rdy', 'imem.req.msg': 'imemreq_msg', 'imem.resp.en': 'imemresp_en', 'imem.resp.rdy': 'imemresp_rdy', 'imem.resp.msg': 'imemresp_msg', 'dmem.req.en': 'dmemreq_en', 'dmem.req.rdy': 'dmemreq_rdy', 'dmem.req.msg': 'dmemreq_msg', 'dmem.resp.en': 'dmemresp_en', 'dmem.resp.rdy': 'dmemresp_rdy', 'dmem.resp.msg': 'dmemresp_msg', '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', 'proc2mngr.en': 'proc2mngr_en', 'proc2mngr.rdy': 'proc2mngr_rdy', 'proc2mngr.msg': 'proc2mngr_msg', 'mngr2proc.en': 'mngr2proc_en', 'mngr2proc.rdy': 'mngr2proc_rdy', 'mngr2proc.msg': 'mngr2proc_msg', }, ) s.config_verilog_import = VerilatorImportConfigs( # Enable native Verilog line trace through Verilator vl_line_trace=True, )