def __init__(s): # Interface ports s.in_val = InPort(1) s.in_rdy = OutPort(1) s.out_val = OutPort(1) s.out_rdy = InPort(1) # Control signals (ctrl -> dpath) s.a_mux_sel = OutPort(A_MUX_SEL_NBITS) s.a_reg_en = OutPort(1) s.b_mux_sel = OutPort(1) s.b_reg_en = OutPort(1) # Status signals (dpath -> ctrl) s.is_b_zero = InPort(B_MUX_SEL_NBITS) s.is_a_lt_b = InPort(1) # State element s.STATE_IDLE = 0 s.STATE_CALC = 1 s.STATE_DONE = 2 s.state = RegRst(2, reset_value=s.STATE_IDLE)
def __init__(s): # interface s.in_control = InValRdyBundle(inst_msg()) # control word s.memresp = InValRdyBundle(MemMsg(32, nWid).resp) # 0,1: right/left neighbors # 2,3: length-2 right/left PEs # 4,5: length-4 right/left PEs s.in_neighbor = InValRdyBundle[6](nWid) s.memreq = OutValRdyBundle(MemMsg(32, nWid).req) s.out_fsm = OutValRdyBundle(1) # response to FSM s.out_neighbor = OutValRdyBundle[6](nWid) # Queues s.memreq_q = SingleElementBypassQueue(MemReqMsg(32, nWid)) s.connect(s.memreq, s.memreq_q.deq) #s.memresp_q = SingleElementPipelinedQueue( MemRespMsg(16) ) s.memresp_q = SingleElementBypassQueue(MemRespMsg(nWid)) s.connect(s.memresp, s.memresp_q.enq) # temporarily store destination for non-blocking loads s.memdes_q = NormalQueue(nMemInst, nDesField) # PE local register file s.rf = RegisterFile(nWid, nReg, 2) # 2 read ports # approx_mul # input is done by reqMsg(src0, src1) done in control plane. s.approx_mul = CombinationalApproxMult(nWid / 2, 4) s.mul_msg = MymultReqMsg(nWid / 2) # temporary variables s.src0_tmp = Wire(nWid) s.src1_tmp = Wire(nWid) s.des_tmp = Wire(nWid) s.go = Wire(1) s.go_req = Wire(1) s.go_resp = Wire(1) s.go_mul = Wire(1) s.reqsent = RegRst(1, 0)
def elaborate_logic( s ): s.connect( s.in_.msg, s.out.msg ) s.snoop_state = RegRst( 1, reset_value = 0 ) #------------------------------------------------------------------ # state_transitions #------------------------------------------------------------------ @s.combinational def state_transitions(): in_go = s.in_.rdy and s.in_.val do_wait = s.drop and not in_go if s.snoop_state.out.value == SNOOP: if do_wait: s.snoop_state.in_.value = WAIT else: s.snoop_state.in_.value = SNOOP elif s.snoop_state.out == WAIT: if in_go: s.snoop_state.in_.value = SNOOP else: s.snoop_state.in_.value = WAIT #------------------------------------------------------------------ # set_outputs #------------------------------------------------------------------ @s.combinational def set_outputs(): if s.snoop_state.out == SNOOP: s.out.val.value = s.in_.val and not s.drop s.in_.rdy.value = s.out.rdy elif s.snoop_state.out == WAIT: s.out.val.value = 0 s.in_.rdy.value = 1
def __init__(s): s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) s.req_msg_type = InPort(1) # Control signals (ctrl -> dpath) s.en_test = OutPort(1) s.en_train = OutPort(1) s.en_out = OutPort(1) s.sel_out = OutPort(1) s.sel = OutPort(6) # State element s.STATE_IDLE = 0 s.STATE_INIT = 1 s.STATE_CALC = 2 s.STATE_DONE = 3 s.state = RegRst(2, reset_value=s.STATE_IDLE) s.counter = Reg(DATA_NBITS) # State Transition Logic @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out # Transition out of IDLE state if (curr_state == s.STATE_IDLE): if ((s.req_val and s.req_rdy) and (s.req_msg_type == 1)): next_state = s.STATE_INIT elif ((s.req_val and s.req_rdy) and (s.req_msg_type == 0)): next_state = s.STATE_CALC # Transition out of INIT state if (curr_state == s.STATE_INIT): if ((s.req_val and s.req_rdy) and (s.req_msg_type == 0)): next_state = s.STATE_CALC # Transition out of CALC state if (curr_state == s.STATE_CALC): if ((s.counter.out + 1) == DATA_NBITS): next_state = s.STATE_DONE # Transition out of DONE state if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state # State Output Logic @s.combinational def state_outputs(): current_state = s.state.out # IDLE state if current_state == s.STATE_IDLE: s.req_rdy.value = 1 s.resp_val.value = 0 s.en_out.value = 0 s.en_test.value = 1 s.en_train.value = 1 s.sel.value = 0 s.sel_out.value = 0 s.counter.in_.value = 0 # INIT state elif current_state == s.STATE_INIT: s.req_rdy.value = 1 s.resp_val.value = 0 s.en_out.value = 0 s.en_test.value = 0 s.en_train.value = 1 s.sel.value = 0 s.sel_out.value = 0 s.counter.in_.value = 0 # CALC state elif current_state == s.STATE_CALC: s.req_rdy.value = 0 s.resp_val.value = 0 s.en_out.value = 1 if (s.counter.out == 0): s.sel_out.value = 0 else: s.sel_out.value = 1 s.en_test.value = 0 s.en_train.value = 0 s.sel.value = s.counter.out s.counter.in_.value = s.counter.out + 1 # DONE state elif current_state == s.STATE_DONE: s.req_rdy.value = 0 s.resp_val.value = 1 s.en_out.value = 0 s.en_test.value = 0 s.en_train.value = 0 s.sel.value = 0 s.sel_out.value = 0 s.counter.in_.value = 0
def __init__(s, mapper_num=10, reducer_num=1, train_size=600): TRAIN_DATA = train_size TRAIN_LOG = int(math.ceil(math.log(TRAIN_DATA, 2))) # import training data and store them into array training_data = [] for i in xrange(DIGIT): count = 0 filename = 'data/training_set_' + str(i) + '.dat' with open(filename, 'r') as f: for L in f: if (count > TRAIN_DATA - 1): break training_data.append(int(L.replace(',\n', ''), 16)) count = count + 1 # Top Level Interface s.in_ = InValRdyBundle(digitrecReqMsg()) s.out = OutValRdyBundle(digitrecRespMsg()) s.base = InPort(32) s.size = InPort(32) # Global Memory Interface s.gmem_req = OutValRdyBundle(MemReqMsg(8, 32, 64)) s.gmem_resp = InValRdyBundle(MemRespMsg(8, 64)) # Register File Interface s.regf_addr = OutPort[DIGIT](TRAIN_LOG) s.regf_data = OutPort[DIGIT](DATA_BITS) s.regf_wren = OutPort[DIGIT](1) s.regf_rdaddr = OutPort[mapper_num / reducer_num](TRAIN_LOG) # Mapper Interface s.map_req = OutPort[mapper_num](DATA_BITS) # Reducer Reset s.red_rst = OutPort(1) # Merger Interface s.merger_resp = InPort(DIGIT_LOG) # States s.STATE_IDLE = 0 # Idle state, scheduler waiting for top level to start s.STATE_SOURCE = 1 # Source state, handling with Test Source, getting base, size, ref info s.STATE_INIT = 2 # Init state, scheduler assigns input info to each Mapper s.STATE_START = 3 # Start state, scheduler gets test data, starts distributing and sorting s.STATE_WRITE = 4 # Write state, scheduler writes merger data to memory s.STATE_END = 5 # End state, shceduler loads all task from global memory and it is done s.state = RegRst(4, reset_value=s.STATE_IDLE) # Counters s.input_count = Wire(TEST_LOG) s.result_count = Wire(TEST_LOG) s.train_count_rd = Wire(TRAIN_LOG) s.train_count_wr = Wire(32) s.train_data_wr = Wire(1) s.train_data_rd = Wire(1) # Logic to Increment Counters @s.tick def counter(): if (s.gmem_req.val and s.gmem_req.msg.type_ == TYPE_READ): s.input_count.next = s.input_count + 1 if (s.gmem_req.val and s.gmem_req.msg.type_ == TYPE_WRITE): s.result_count.next = s.result_count + 1 if s.rst: s.train_count_rd.next = 0 elif s.train_data_rd: s.train_count_rd.next = s.train_count_rd + (mapper_num / DIGIT) if (s.train_data_wr): s.train_count_wr.next = s.train_count_wr + 1 # Signals s.go = Wire(1) # go signal tells scheduler to start scheduling s.done = Wire(1) # done signal indicates everything is done s.rst = Wire(1) # reset train count every test data processed # Reference data s.reference = Reg(dtype=DATA_BITS) # reference stores test data #--------------------------------------------------------------------- # Initialize Register File for Training data #--------------------------------------------------------------------- @s.combinational def traindata(): if s.train_data_wr: for i in xrange(DIGIT): s.regf_addr[i].value = s.train_count_wr s.regf_data[i].value = training_data[i * TRAIN_DATA + s.train_count_wr] s.regf_wren[i].value = 1 else: for i in xrange(DIGIT): s.regf_wren[i].value = 0 #--------------------------------------------------------------------- # Assign Task to Mapper Combinational Logic #--------------------------------------------------------------------- @s.combinational def mapper(): # broadcast train data to mapper for i in xrange(DIGIT): for j in xrange(mapper_num / DIGIT): if (s.train_data_rd): s.map_req[j * 10 + i].value = s.reference.out s.regf_rdaddr[j].value = s.train_count_rd + j #--------------------------------------------------------------------- # Task State Transition Logic #--------------------------------------------------------------------- @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out if (curr_state == s.STATE_IDLE): if (s.in_.val): next_state = s.STATE_SOURCE if (curr_state == s.STATE_SOURCE): if (s.go): next_state = s.STATE_INIT elif (s.done): next_state = s.STATE_IDLE if (curr_state == s.STATE_INIT): if (s.train_count_wr == TRAIN_DATA - 1): next_state = s.STATE_START if (curr_state == s.STATE_START): if (s.train_count_rd == TRAIN_DATA - (mapper_num / DIGIT)): next_state = s.STATE_WRITE if (curr_state == s.STATE_WRITE): if (s.input_count == s.size): next_state = s.STATE_END else: next_state = s.STATE_START if (curr_state == s.STATE_END): if s.gmem_resp.val: next_state = s.STATE_SOURCE s.state.in_.value = next_state #--------------------------------------------------------------------- # Task State Output Logic #--------------------------------------------------------------------- @s.combinational def state_outputs(): current_state = s.state.out s.gmem_req.val.value = 0 s.gmem_resp.rdy.value = 0 s.in_.rdy.value = 0 s.out.val.value = 0 # In IDLE state if (current_state == s.STATE_IDLE): s.input_count.value = 0 s.train_count_rd.value = 0 s.train_count_wr.value = 0 s.reference.value = 0 s.go.value = 0 s.train_data_rd.value = 0 s.train_data_wr.value = 0 s.done.value = 0 s.rst.value = 0 s.red_rst.value = 0 # In SOURCE state if (current_state == s.STATE_SOURCE): if (s.in_.val and s.out.rdy): if (s.in_.msg.type_ == digitrecReqMsg.TYPE_WRITE): if (s.in_.msg.addr == 0): # start computing s.go.value = 1 elif (s.in_.msg.addr == 1): # base address s.base.value = s.in_.msg.data elif (s.in_.msg.addr == 2): # size s.size.value = s.in_.msg.data # Send xcel response message s.in_.rdy.value = 1 s.out.msg.type_.value = digitrecReqMsg.TYPE_WRITE s.out.msg.data.value = 0 s.out.val.value = 1 elif (s.in_.msg.type_ == digitrecReqMsg.TYPE_READ): # the computing is done, send response message if (s.done): s.out.msg.type_.value = digitrecReqMsg.TYPE_READ s.out.msg.data.value = 1 s.in_.rdy.value = 1 s.out.val.value = 1 # In INIT state if (current_state == s.STATE_INIT): s.train_data_wr.value = 1 s.go.value = 0 # at the end of init, send read req to global memory if s.train_count_wr == TRAIN_DATA - 1: if s.gmem_req.rdy: s.gmem_req.msg.addr.value = s.base + (8 * s.input_count) s.gmem_req.msg.type_.value = TYPE_READ s.gmem_req.val.value = 1 s.red_rst.value = 1 # In START state if (current_state == s.STATE_START): s.train_data_wr.value = 0 s.train_data_rd.value = 1 s.rst.value = 0 s.red_rst.value = 0 if s.gmem_resp.val: # if response type is read, stores test data to reference, hold response val # until everything is done, which is set in WRITE state if s.gmem_resp.msg.type_ == TYPE_READ: s.gmem_resp.rdy.value = 1 s.reference.in_.value = s.gmem_resp.msg.data else: # if response tyle is write, set response rdy, send another req to # read test data s.gmem_resp.rdy.value = 1 s.gmem_req.msg.addr.value = s.base + (8 * s.input_count) s.gmem_req.msg.type_.value = TYPE_READ s.gmem_req.val.value = 1 s.red_rst.value = 1 s.train_data_rd.value = 0 # In WRITE state if (current_state == s.STATE_WRITE): s.train_data_rd.value = 0 # one test data done processed, write result from merger to memory if (s.gmem_req.rdy): s.gmem_req.msg.addr.value = 0x2000 + (8 * s.result_count) s.gmem_req.msg.data.value = s.merger_resp s.gmem_req.msg.type_.value = TYPE_WRITE s.gmem_req.val.value = 1 s.rst.value = 1 # In END state if (current_state == s.STATE_END): if s.gmem_resp.val: s.gmem_resp.rdy.value = 1 s.done.value = 1
def __init__( s ): # Interface s.in_ = InValRdyBundle [nPE]( 1 ) s.out = OutValRdyBundle[nPE]( inst_msg() ) # Register definition s.state = RegRst(LOG_NUM_STATE, 0) # State definition LOAD_TEST_DATA = 0 REQ_SIZE = 1 RETURN_SIZE = 2 SIZE_COPY = 3 READ_ELEMENT_1 = 4 READ_ELEMENT_2 = 5 COMPARE = 6 COMPARE_RESULT = 7 DEC_COUNTER = 8 CHECK_COUNTER = 9 OUTER_LOOP_DEC = 10 EXIT_CHECK = 11 EXIT_TRANSFER = 12 EXIT_DEC = 13 END_CHECK = 14 # Mux selects s.in_mux_sel = OutPort ( 1 ) s.out_mux_sel = OutPort ( 1 ) @s.combinational def combinational_module(): #------------------------------------------------------------------ # INIT_S0 state #------------------------------------------------------------------ # read the first operand from memory if s.state.out == INIT_S0: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = INIT_S0 # LOAD to register 0 s.out[0].msg.ctl.value = LOAD s.out[0].msg.des.value = 16 + 0 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = INIT_S1 #------------------------------------------------------------------ # REQ_SIZE #------------------------------------------------------------------ # read the size from memory if s.state.out == REQ_SIZE: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = REQ_SIZE s.out[0].msg.ctl.value = MEMREQ s.out[0].msg.des.value = 0 # Check what to do with this s.out[0].msg.addr.value = s.read_pointer s.out[0].msg.type.value = 0 # read if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = RETURN_SIZE s.read_pointer.value = s.read_pointer + 1 #------------------------------------------------------------------ # RETURN_SIZE state #------------------------------------------------------------------ # get the size back from memory; also send to PE 1's reg 0 if s.state.out == RETURN_SIZE: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = RETURN_SIZE s.out[0].msg.ctl.value = MEMRESP s.out[0].msg.des.value = 16 + 8 # Store size in PE 0 reg 0, also send to right PE if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = RETURN_SIZE #------------------------------------------------------------------ # SIZE_COPY state #------------------------------------------------------------------ # copy the size into PE 0's reg 1 as well if s.state.out == SIZE_COPY: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = SIZE_COPY if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = READ_ELEMENT_1 #------------------------------------------------------------------ # READ_ELEMENT_1 state #------------------------------------------------------------------ # load the first element of the array from the memory if s.state.out == READ_ELEMENT_1: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.out[0].msg.ctl.value = MEMREQ s.out[0].msg.addr.value = s.read_pointer s.out[0].msg.type.value = 0 # read s.state.in_.value = READ_ELEMENT_1 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = READ_ELEMENT_2 s.read_pointer.value = s.read_pointer + 1 #------------------------------------------------------------------ # WAIT_RESP state #------------------------------------------------------------------ # load the first element of the array from the memory if s.state.out == WAIT_RESP: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.out[0].msg.ctl.value = MEMRESP s.state.in_.value = WAIT_RESP if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = READ_ELEMENT_2 #------------------------------------------------------------------ # READ_ELEMENT_2 state #------------------------------------------------------------------ # load the second element of the array from the memory (send request from PE 1 if s.state.out == READ_ELEMENT_2: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.out[1].msg.ctl.value = MEMREQ s.out[1].msg.addr.value = s.read_pointer s.out[1].msg.type.value = 0 # read s.state.in_.value = READ_ELEMENT_2 if s.out[1].rdy: s.out[1].val.value = 1 s.state.in_.value = RESP_COMPARE s.read_pointer.value = s.read_pointer + 1 #------------------------------------------------------------------ # RESP_COMPARE state #------------------------------------------------------------------ # load the first element of the array from the memory, compare in PE0 in parallel if s.state.out == RESP_COMPARE: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.out[1].msg.ctl.value = MEMRESP # Right PE accepts response s.out[1].msg.des.value = 8 # send to left PE s.out[0].msg.ctl.value = CGT # Left PE performs compare greater than s.out[0].msg.src0.value = 2 # Pick first element from own reg file s.out[0].msg.src1.value = 4 + 1 # Pick second element from right PE s.state.in_.value = RESP_COMPARE if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = WRITE_SMALL #------------------------------------------------------------------ # WRITE_SMALL state #------------------------------------------------------------------ # get comparision result, write smaller value to mem if s.state.out == WRITE_SMALL: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 if s.in_[0].val and (s.in_[0].msg == 1): s.out[1].msg.ctl.value = MEMRESP s.out[1].msg.des.value = 8 # send to left PE s.state.in_.value = WRITE_SMALL if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = DEC_INNER #------------------------------------------------------------------ # CALC_S0 state #------------------------------------------------------------------ # send out CGT instruction if s.state.out == CALC_S0: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = CALC_S0 s.in_[1].rdy.value = 1 # find out what this is # termination condition if s.in_[1].val and (s.in_[1].msg == 1): s.state.in_.value = DONE else: # CGT r0 > r1 ? s.out[0].msg.ctl.value = CGT s.out[0].msg.src0.value = 0 s.out[0].msg.src1.value = 1 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = CALC_S1 #------------------------------------------------------------------ # CALC_S1 state #------------------------------------------------------------------ # send out SUB instruction if s.state.out == CALC_S1: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = CALC_S1 s.in_[1].rdy.value = 1 # termination condition if s.in_[1].val and (s.in_[1].msg == 1): s.state.in_.value = DONE else: # send out SUB instruction based on the result from CGT if s.in_[0].val: if s.in_[0].msg == 1: # r0 > r1: do r0-r1 --> r0 s.out[0].msg.ctl.value = SUB s.out[0].msg.src0.value = 0 s.out[0].msg.src1.value = 1 s.out[0].msg.des.value = 16 + 4 + 0 elif s.in_[0].msg == 0: # r0 < r1: do r1-r0 --> r1 s.out[0].msg.ctl.value = SUB s.out[0].msg.src0.value = 1 s.out[0].msg.src1.value = 0 s.out[0].msg.des.value = 16 + 4 + 1 # also send out CEZ instruction s.out[1].msg.ctl.value = CEZ s.out[1].msg.src0.value = 5 if s.out[0].rdy and s.out[1].rdy: # only goes to the next state when both SUB and CEZ are successfully issued s.in_[0].rdy.value = 1 s.out[0].val.value = 1 s.out[1].val.value = 1 s.state.in_.value = CALC_S0 #------------------------------------------------------------------ # DONE state #------------------------------------------------------------------ # send out STORE instruction if s.state.out == DONE: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = DONE # STORE value of register 0 to memory s.out[0].msg.ctl.value = STORE s.out[0].msg.src0.value = 1 if s.out[0].rdy: s.state.in_.value = INIT_S0 s.out[0].val.value = 1
def __init__(s, mapper_num=2, reducer_num=1): # Top Level Interface s.in_ = InValRdyBundle(WordcountReqMsg()) s.out = OutValRdyBundle(WordcountRespMsg()) s.reference = InPort(32) s.base = InPort(32) s.size = InPort(32) # Global Memory Interface s.gmem_req = OutValRdyBundle(MemReqMsg(8, 32, 32)) s.gmem_resp = InValRdyBundle(MemRespMsg(8, 32)) # Local Memory Interface s.lmem_req = OutValRdyBundle(MemReqMsg(8, 32, 32)) s.lmem_resp = InValRdyBundle(MemRespMsg(8, 32)) # Mapper Interface s.map_req = OutValRdyBundle[mapper_num](MapperReqMsg()) s.map_resp = InValRdyBundle[mapper_num](MapperRespMsg()) # Reducer Interface s.red_req = OutValRdyBundle[reducer_num](ReducerReqMsg()) s.red_resp = InValRdyBundle[reducer_num](ReducerRespMsg()) # Task Queue s.task_queue = NormalQueue(2, Bits(32)) # Idle Queue storing mapper ID s.idle_queue = NormalQueue(2, Bits(2)) # States s.STATE_IDLE = 0 # Idle state, scheduler waiting for top level to start s.STATE_SOURCE = 1 # Source state, handling with Test Source, getting base, size, ref info s.STATE_INIT = 2 # Init state, scheduler assigns input info to each Mapper s.STATE_START = 3 # Start state, scheduler starts scheduling s.STATE_END = 4 # End state, shceduler loads all task from global memory and it is done s.state = RegRst(4, reset_value=s.STATE_IDLE) # Counters s.init_count = Wire(2) s.input_count = Wire(32) @s.tick def counter(): if (s.idle_queue.enq.val and s.init): s.init_count.next = s.init_count + 1 if (s.gmem_req.val): s.input_count.next = s.input_count + 1 # Signals s.go = Wire(1) # go signal tells scheduler to start scheduling s.mapper_done = Wire(1) # if one or more mapper is done and send resp s.init = Wire(1) # init signal indicates scheduler at initial state s.end = Wire(1) # end signal indicates all task are loaded s.done = Wire(1) # done signal indicates everything is done s.num_task_queue = Wire(2) s.connect(s.task_queue.num_free_entries, s.num_task_queue) @s.combinational def logic(): s.mapper_done.value = s.map_resp[0].val | s.map_resp[1].val #--------------------------------------------------------------------- # Assign Task to Mapper Combinational Logic #--------------------------------------------------------------------- @s.combinational def mapper(): # initialize mapper req and resp handshake signals for i in xrange(mapper_num): s.map_req[i].val.value = 0 s.task_queue.deq.rdy.value = 0 s.idle_queue.deq.rdy.value = 0 if s.init: s.map_req[s.init_count].msg.data.value = s.reference s.map_req[s.init_count].msg.type_.value = 1 s.map_req[s.init_count].val.value = 1 s.idle_queue.enq.msg.value = s.init_count s.idle_queue.enq.val.value = 1 else: # assign task to mapper if task queue is ready to dequeue # idle queue is ready to dequeue and mapper is ready to take request if (s.task_queue.deq.val and s.idle_queue.deq.val and s.map_req[s.idle_queue.deq.msg].rdy): s.map_req[s.idle_queue.deq. msg].msg.data.value = s.task_queue.deq.msg[0:8] s.map_req[s.idle_queue.deq.msg].msg.type_.value = 0 s.map_req[s.idle_queue.deq.msg].val.value = 1 s.task_queue.deq.rdy.value = 1 s.idle_queue.deq.rdy.value = 1 #--------------------------------------------------------------------- # Send Mapper Resp to Reducer Combinational Logic #--------------------------------------------------------------------- @s.combinational def reducer(): # initialize mapper and reducer handshake signals for i in xrange(mapper_num): s.map_resp[i].rdy.value = 0 for i in xrange(reducer_num): s.red_req[i].val.value = 0 #s.idle_queue.enq.val.value = 0 # get the mapper response, assign the response to reducer if (s.mapper_done): # Check each mapper response, add it to idle queue, send its response # to Reducer, mark its response ready for i in xrange(mapper_num): if (s.map_resp[i].val): if ~s.init: if s.idle_queue.enq.rdy: s.idle_queue.enq.msg.value = i s.idle_queue.enq.val.value = 1 if s.red_req[0].rdy: if s.end and s.num_task_queue == 2: s.red_req[0].msg.data.value = s.map_resp[ i].msg.data s.red_req[0].msg.type_.value = 1 s.red_req[0].val.value = 1 s.done.value = 1 else: s.red_req[0].msg.data.value = s.map_resp[ i].msg.data s.red_req[0].msg.type_.value = 0 s.red_req[0].val.value = 1 s.map_resp[i].rdy.value = 1 break #--------------------------------------------------------------------- # Task State Transition Logic #--------------------------------------------------------------------- @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out if (curr_state == s.STATE_IDLE): if (s.in_.val): next_state = s.STATE_SOURCE if (curr_state == s.STATE_SOURCE): if (s.go): next_state = s.STATE_INIT elif (s.done and s.red_resp[0].val): next_state = s.STATE_IDLE if (curr_state == s.STATE_INIT): if (s.init_count == mapper_num - 1): next_state = s.STATE_START if (curr_state == s.STATE_START): if (s.input_count == s.size - 1): next_state = s.STATE_END if (curr_state == s.STATE_END): if (s.done): next_state = s.STATE_SOURCE s.state.in_.value = next_state #--------------------------------------------------------------------- # Task State Output Logic #--------------------------------------------------------------------- @s.combinational def state_outputs(): current_state = s.state.out s.gmem_req.val.value = 0 s.gmem_resp.rdy.value = 0 s.in_.rdy.value = 0 s.out.val.value = 0 s.task_queue.enq.val.value = 0 # In IDLE state if (current_state == s.STATE_IDLE): s.init_count.value = 0 s.input_count.value = 0 s.end.value = 0 s.go.value = 0 s.init.value = 0 s.done.value = 0 if s.in_.val: if (s.in_.msg.addr == 1): s.base.value = s.in_.msg.data s.in_.rdy.value = 1 s.out.msg.type_.value = WordcountReqMsg.TYPE_WRITE s.out.msg.data.value = 0 s.out.val.value = 1 #In SOURCE state if (current_state == s.STATE_SOURCE): if (s.in_.val and s.out.rdy): if (s.in_.msg.type_ == WordcountReqMsg.TYPE_WRITE): if (s.in_.msg.addr == 0): s.go.value = 1 elif (s.in_.msg.addr == 2): s.size.value = s.in_.msg.data elif (s.in_.msg.addr == 3): s.reference.value = s.in_.msg.data # Send xcel response message s.in_.rdy.value = 1 s.out.msg.type_.value = WordcountReqMsg.TYPE_WRITE s.out.msg.data.value = 0 s.out.val.value = 1 elif (s.in_.msg.type_ == WordcountReqMsg.TYPE_READ): if (s.done and s.red_resp[0].val): s.out.msg.type_.value = WordcountReqMsg.TYPE_READ s.out.msg.data.value = s.red_resp[0].msg.data s.red_resp[0].rdy.value = 1 s.in_.rdy.value = 1 s.out.val.value = 1 # In INIT state if (current_state == s.STATE_INIT): s.init.value = 1 s.go.value = 0 # at the last 2 cycle of init, send read req to global memory if s.init_count == mapper_num - 2: if s.gmem_req.rdy: s.gmem_req.msg.addr.value = s.base + (4 * s.input_count) s.gmem_req.msg.type_.value = TYPE_READ s.gmem_req.val.value = 1 # at the last cycle of init, receive read resp to global memory, put it in task queue # send another read req to global memory if s.init_count == mapper_num - 1: if s.gmem_resp.val and s.gmem_req.rdy: s.task_queue.enq.msg.value = s.gmem_resp.msg s.task_queue.enq.val.value = 1 s.gmem_resp.rdy.value = 1 s.gmem_req.msg.addr.value = s.base + (4 * s.input_count) s.gmem_req.msg.type_.value = TYPE_READ s.gmem_req.val.value = 1 # In START state if (current_state == s.STATE_START): s.init.value = 0 if s.gmem_resp.val and s.gmem_req.rdy: s.task_queue.enq.msg.value = s.gmem_resp.msg s.task_queue.enq.val.value = 1 s.gmem_resp.rdy.value = 1 s.gmem_req.msg.addr.value = s.base + (4 * s.input_count) s.gmem_req.msg.type_.value = TYPE_READ s.gmem_req.val.value = 1 # In END state if (current_state == s.STATE_END): if s.gmem_resp.val: s.task_queue.enq.msg.value = s.gmem_resp.msg s.task_queue.enq.val.value = 1 s.gmem_resp.rdy.value = 1 s.end.value = 1
def __init__( s ): s.req_val = InPort (1) s.req_rdy = OutPort (1) s.resp_val = OutPort (1) s.resp_rdy = InPort (1) s.req_msg_type = InPort (1) s.sel = OutPort (1) s.en = OutPort (1) # State element s.STATE_IDLE = 0 s.STATE_CALC = 1 s.STATE_DONE = 2 s.state = RegRst( 2, reset_value = s.STATE_IDLE ) # State Transition Logic @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out # Transition out of IDLE state if ( curr_state == s.STATE_IDLE ): if ( (s.req_val and s.req_rdy) and (s.req_msg_type == 0) ): next_state = s.STATE_CALC elif ( (s.req_val and s.req_rdy) and (s.req_msg_type == 1) ): next_state = s.STATE_DONE # Transition out of CALC state if ( curr_state == s.STATE_CALC ): if ( (s.req_val and s.req_rdy) and (s.req_msg_type == 1) ): next_state = s.STATE_DONE # Transition out of DONE state if ( curr_state == s.STATE_DONE ): if ( s.resp_val and s.resp_rdy ): next_state = s.STATE_IDLE s.state.in_.value = next_state # State Output Logic @s.combinational def state_outputs(): current_state = s.state.out # IDLE state if current_state == s.STATE_IDLE: s.req_rdy.value = 1 s.resp_val.value = 0 s.en.value = 1 s.sel.value = 0 # CALC state elif current_state == s.STATE_CALC: s.req_rdy.value = 1 s.resp_val.value = 0 s.en.value = 1 s.sel.value = 1 # DONE state elif current_state == s.STATE_DONE: s.req_rdy.value = 0 s.resp_val.value = 1 s.en.value = 0 s.sel.value = 0
def __init__(s): #--------------------------------------------------------------------- # Interface #--------------------------------------------------------------------- s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) # Control signals (ctrl -> dpath) s.a_mux_sel = OutPort(A_MUX_SEL_NBITS) s.a_reg_en = OutPort(1) s.b_mux_sel = OutPort(1) s.b_reg_en = OutPort(1) # Status signals (dpath -> ctrl) s.is_b_zero = InPort(B_MUX_SEL_NBITS) s.is_a_lt_b = InPort(1) # State element s.STATE_IDLE = 0 s.STATE_CALC = 1 s.STATE_DONE = 2 s.state = RegRst(2, reset_value=s.STATE_IDLE) #--------------------------------------------------------------------- # State Transition Logic #--------------------------------------------------------------------- @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out # Transitions out of IDLE state if (curr_state == s.STATE_IDLE): if (s.req_val): next_state = s.STATE_CALC # Transitions out of CALC state if (curr_state == s.STATE_CALC): if (not s.is_a_lt_b and s.is_b_zero): next_state = s.STATE_DONE # Transitions out of DONE state if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state #--------------------------------------------------------------------- # State Output Logic #--------------------------------------------------------------------- s.do_swap = Wire(1) s.do_sub = Wire(1) @s.combinational def state_outputs(): current_state = s.state.out # In IDLE state we simply wait for inputs to arrive and latch them if current_state == s.STATE_IDLE: s.req_rdy.value = 1 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_IN s.a_reg_en.value = 1 s.b_mux_sel.value = B_MUX_SEL_IN s.b_reg_en.value = 1 # In CALC state we iteratively swap/sub to calculate GCD elif current_state == s.STATE_CALC: s.do_swap.value = s.is_a_lt_b s.do_sub.value = ~s.is_b_zero s.req_rdy.value = 0 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_B if s.do_swap else A_MUX_SEL_SUB s.a_reg_en.value = 1 s.b_mux_sel.value = B_MUX_SEL_A s.b_reg_en.value = s.do_swap # In DONE state we simply wait for output transaction to occur elif current_state == s.STATE_DONE: s.req_rdy.value = 0 s.resp_val.value = 1 s.a_mux_sel.value = A_MUX_SEL_X s.a_reg_en.value = 0 s.b_mux_sel.value = B_MUX_SEL_X s.b_reg_en.value = 0
def __init__(s, nbits=6, k=3): # Interface s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) # dpath->ctrl s.isLarger = InPort(1) # ctrl->dapth s.max_reg_en = OutPort(1) s.idx_reg_en = OutPort(1) s.knn_mux_sel = OutPort(1) s.knn_counter = OutPort(int(math.ceil(math.log(k, 2)))) # max 3 # internal signal s.count_go = Wire(Bits(1)) # states s.STATE_IDLE = 0 s.STATE_CMP = 1 # do compare or store reference data s.STATE_DONE = 2 # return max value and its index s.state = RegRst(2, reset_value=s.STATE_IDLE) # Counters s.knn_count = Wire(int(math.ceil(math.log(k, 2)))) # max 3 @s.tick def counter(): if (s.count_go == 1): s.knn_count.next = s.knn_count + 1 else: s.knn_count.next = 0 #------------------------------------------------------ # state transtion logic #------------------------------------------------------ @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out if (curr_state == s.STATE_IDLE): if (s.req_val and s.req_rdy): next_state = s.STATE_CMP if (curr_state == s.STATE_CMP): if (s.knn_count == k - 1): next_state = s.STATE_DONE if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state #------------------------------------------------------ # state output logic #------------------------------------------------------ @s.combinational def state_outputs(): current_state = s.state.out if (current_state == s.STATE_IDLE): s.req_rdy.value = 1 s.resp_val.value = 0 s.max_reg_en.value = 1 s.idx_reg_en.value = 1 s.knn_mux_sel.value = 0 if (s.req_val and s.req_rdy): s.count_go.value = 1 else: s.count_go.value = 0 elif (current_state == s.STATE_CMP): s.resp_val.value = 0 s.count_go.value = 1 s.req_rdy.value = 1 s.knn_mux_sel.value = 1 if (s.isLarger == 1): s.idx_reg_en.value = 1 s.max_reg_en.value = 1 else: s.idx_reg_en.value = 0 s.max_reg_en.value = 0 elif (current_state == s.STATE_DONE): s.req_rdy.value = 0 s.resp_val.value = 1 s.max_reg_en.value = 0 s.idx_reg_en.value = 0 s.knn_mux_sel.value = 0 s.count_go.value = 0 s.connect(s.knn_count, s.knn_counter)
def __init__(s): #================================================================== # Interface #================================================================== s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) # Control signals s.a_mux_sel = OutPort(A_MUX_SEL_NBITS) s.b_mux_sel = OutPort(B_MUX_SEL_NBITS) s.result_mux_sel = OutPort(RES_MUX_SEL_NBITS) s.add_mux_sel = OutPort(ADD_MUX_SEL_NBITS) s.result_en = OutPort(1) s.result_sign = OutPort(OUT_MUX_SEL_NBITS) # Status signals s.shamt = InPort(6) s.b_lsb = InPort(1) s.a_msb = InPort(1) s.b_msb = InPort(1) # State elements s.STATE_IDLE = 0 s.STATE_CALC = 1 s.STATE_DONE = 2 s.state = RegRst(2, reset_value=s.STATE_IDLE) # Counter: how many bits have already been scanned s.counter = RegRst(6, reset_value=1) # Sign register s.result_sign_reg = RegRst(1, reset_value=0) # Store the sign of the result at I state then use it as MUX # selection during output @s.combinational def result_sign_out_block(): s.result_sign.value = s.result_sign_reg.out #================================================================== # State Transistion Logic #================================================================== @s.combinational def state_transistions(): curr_state = s.state.out next_state = s.state.out # Transistions out of IDLE state if (curr_state == s.STATE_IDLE): if (s.req_val and s.req_rdy): next_state = s.STATE_CALC # Transistions out of CALC state if (curr_state == s.STATE_CALC): if (s.counter.out >= 32): next_state = s.STATE_DONE # Transistions out of DONE state if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state #================================================================== # Output Logic #================================================================== s.add_mux_sel_value = Wire(ADD_MUX_SEL_NBITS) # Genereate add MUX selection value @s.combinational def add_mux_sel_block(): if (s.counter.out >= 32): s.add_mux_sel_value.value = ADD_MUX_SEL_RES else: if (s.b_lsb): s.add_mux_sel_value.value = ADD_MUX_SEL_ADD else: s.add_mux_sel_value.value = ADD_MUX_SEL_RES # Generate control signals @s.combinational def state_outputs(): curr_state = s.state.out if (curr_state == s.STATE_IDLE): s.req_rdy.value = 1 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_IN s.b_mux_sel.value = B_MUX_SEL_IN s.result_mux_sel.value = RES_MUX_SEL_ZERO s.add_mux_sel.value = ADD_MUX_SEL_ADD s.result_en.value = 1 s.counter.in_.value = 0 s.result_sign_reg.in_.value = s.a_msb ^ s.b_msb elif (curr_state == s.STATE_CALC): s.req_rdy.value = 0 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_SHIFT s.b_mux_sel.value = B_MUX_SEL_SHIFT s.result_mux_sel.value = RES_MUX_SEL_ADD s.add_mux_sel.value = s.add_mux_sel_value s.result_en.value = 1 s.counter.in_.value = s.counter.out + s.shamt s.result_sign_reg.in_.value = s.result_sign_reg.out elif (curr_state == s.STATE_DONE): s.req_rdy.value = 0 s.resp_val.value = 1 s.a_mux_sel.value = A_MUX_SEL_X s.b_mux_sel.value = B_MUX_SEL_X s.result_mux_sel.value = RES_MUX_SEL_X s.add_mux_sel.value = ADD_MUX_SEL_X s.result_en.value = 0 s.counter.in_.value = s.counter.out s.result_sign_reg.in_.value = s.result_sign_reg.out # Complete all cases to avoid inferring latches else: s.req_rdy.value = 0 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_X s.b_mux_sel.value = B_MUX_SEL_X s.result_mux_sel.value = RES_MUX_SEL_X s.add_mux_sel.value = ADD_MUX_SEL_X s.result_en.value = 0 s.counter.in_.value = 0 s.result_sign_reg.in_.value = 0
def __init__(s): #================================================================== # Interface #================================================================== s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) # Control signals s.a_mux_sel = OutPort(A_MUX_SEL_NBITS) s.b_mux_sel = OutPort(B_MUX_SEL_NBITS) s.result_mux_sel = OutPort(RES_MUX_SEL_NBITS) s.add_mux_sel = OutPort(ADD_MUX_SEL_NBITS) s.result_en = OutPort(1) s.result_sign = OutPort(OUT_MUX_SEL_NBITS) # Status signals s.b_lsb = InPort(1) s.a_msb = InPort(1) s.b_msb = InPort(1) # State elements s.STATE_IDLE = 0 s.STATE_CALC = 1 s.STATE_DONE = 2 s.state = RegRst(2, reset_value=s.STATE_IDLE) # Calculation counter s.counter = RegRst(10, reset_value=1) # Sign register s.result_sign_reg = RegRst(1, reset_value=0) @s.combinational def result_sign_out_block(): s.result_sign.value = s.result_sign_reg.out #================================================================== # State Transistion Logic #================================================================== @s.combinational def state_transistions(): curr_state = s.state.out next_state = s.state.out # Transistions out of IDLE state if (curr_state == s.STATE_IDLE): if (s.req_val and s.req_rdy): next_state = s.STATE_CALC # Transistions out of CALC state if (curr_state == s.STATE_CALC): if (s.counter.out == 32): next_state = s.STATE_DONE # Transistions out of DONE state if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state #================================================================== # Output Logic #================================================================== s.add_mux_sel_value = Wire(ADD_MUX_SEL_NBITS) # Generate the add MUX selection value @s.combinational def add_mux_sel_block(): if (s.counter.out == 32): s.add_mux_sel_value.value = ADD_MUX_SEL_RES else: if (s.b_lsb): s.add_mux_sel_value.value = ADD_MUX_SEL_ADD else: s.add_mux_sel_value.value = ADD_MUX_SEL_RES # Generate the control signals @s.combinational def state_outputs(): curr_state = s.state.out if (curr_state == s.STATE_IDLE): s.req_rdy.value = 1 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_IN s.b_mux_sel.value = B_MUX_SEL_IN s.result_mux_sel.value = RES_MUX_SEL_ZERO s.add_mux_sel.value = ADD_MUX_SEL_ADD s.result_en.value = 1 s.counter.in_.value = 0 s.result_sign_reg.in_.value = s.a_msb ^ s.b_msb if (curr_state == s.STATE_CALC): s.req_rdy.value = 0 s.resp_val.value = 0 s.a_mux_sel.value = A_MUX_SEL_SHIFT s.b_mux_sel.value = B_MUX_SEL_SHIFT s.result_mux_sel.value = RES_MUX_SEL_ADD s.add_mux_sel.value = s.add_mux_sel_value s.result_en.value = 1 s.counter.in_.value = s.counter.out + 1 s.result_sign_reg.in_.value = s.result_sign_reg.out if (curr_state == s.STATE_DONE): s.req_rdy.value = 0 s.resp_val.value = 1 s.a_mux_sel.value = A_MUX_SEL_X s.b_mux_sel.value = B_MUX_SEL_X s.result_mux_sel.value = RES_MUX_SEL_X s.add_mux_sel.value = ADD_MUX_SEL_X s.result_en.value = 0 s.counter.in_.value = s.counter.out s.result_sign_reg.in_.value = s.result_sign_reg.out
def __init__(s, mbits=1): # Interface s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) s.req_msg_type = InPort(mbits) s.resp_msg_type = OutPort(mbits) s.result_reg_en = OutPort(1) s.reference_reg_en = OutPort(1) s.msg_type_reg_en = Wire(Bits(1)) s.STATE_IDLE = 0 s.STATE_CMP = 1 # do compare or store reference data s.state = RegRst(1, reset_value=s.STATE_IDLE) #------------------------------------------------------ # state transtion logic #------------------------------------------------------ @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out if (curr_state == s.STATE_IDLE): if (s.req_val and s.req_rdy): next_state = s.STATE_CMP if (curr_state == s.STATE_CMP): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state #------------------------------------------------------ # state output logic #------------------------------------------------------ @s.combinational def state_outputs(): current_state = s.state.out if (current_state == s.STATE_IDLE): s.req_rdy.value = 1 s.resp_val.value = 0 s.result_reg_en.value = 1 s.reference_reg_en.value = s.req_msg_type s.msg_type_reg_en.value = 1 elif (current_state == s.STATE_CMP): s.req_rdy.value = 0 s.resp_val.value = 1 s.result_reg_en.value = 0 s.reference_reg_en.value = 0 s.msg_type_reg_en.value = 0 # Register for resp msg type s.Reg_msg_type = m = RegEnRst(1) s.connect_dict({ m.en: s.msg_type_reg_en, m.in_: s.req_msg_type, m.out: s.resp_msg_type, })
def __init__(s): # Interface s.in_ = InValRdyBundle[nPE](1) s.out = OutValRdyBundle[nPE](inst_msg()) # Register definition s.state = RegRst(LOG_NUM_STATE, 0) # State definition INIT_S0 = 0 INIT_S1 = 1 CALC_S0 = 2 CALC_S1 = 3 DONE = 4 # Mux selects s.in_mux_sel = OutPort(1) s.out_mux_sel = OutPort(1) @s.combinational def combinational_module(): #------------------------------------------------------------------ # INIT_S0 state #------------------------------------------------------------------ # read the first operand from memory if s.state.out == INIT_S0: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = INIT_S0 # LOAD to register 0 s.out[0].msg.ctl.value = LOAD s.out[0].msg.des.value = 16 + 0 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = INIT_S1 #------------------------------------------------------------------ # INIT_S1 state #------------------------------------------------------------------ # read the second operand from memory if s.state.out == INIT_S1: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = INIT_S1 # LOAD to register 1 s.out[0].msg.ctl.value = LOAD s.out[0].msg.des.value = 16 + 1 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = CALC_S0 #------------------------------------------------------------------ # CALC_S0 state #------------------------------------------------------------------ # send out CGT instruction if s.state.out == CALC_S0: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = CALC_S0 s.in_[1].rdy.value = 1 # find out what this is # termination condition if s.in_[1].val and (s.in_[1].msg == 1): s.state.in_.value = DONE else: # CGT r0 > r1 ? s.out[0].msg.ctl.value = CGT s.out[0].msg.src0.value = 0 s.out[0].msg.src1.value = 1 if s.out[0].rdy: s.out[0].val.value = 1 s.state.in_.value = CALC_S1 #------------------------------------------------------------------ # CALC_S1 state #------------------------------------------------------------------ # send out SUB instruction if s.state.out == CALC_S1: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = CALC_S1 s.in_[1].rdy.value = 1 # termination condition if s.in_[1].val and (s.in_[1].msg == 1): s.state.in_.value = DONE else: # send out SUB instruction based on the result from CGT if s.in_[0].val: if s.in_[0].msg == 1: # r0 > r1: do r0-r1 --> r0 s.out[0].msg.ctl.value = SUB s.out[0].msg.src0.value = 0 s.out[0].msg.src1.value = 1 s.out[0].msg.des.value = 16 + 4 + 0 elif s.in_[0].msg == 0: # r0 < r1: do r1-r0 --> r1 s.out[0].msg.ctl.value = SUB s.out[0].msg.src0.value = 1 s.out[0].msg.src1.value = 0 s.out[0].msg.des.value = 16 + 4 + 1 # also send out CEZ instruction s.out[1].msg.ctl.value = CEZ s.out[1].msg.src0.value = 5 if s.out[0].rdy and s.out[1].rdy: # only goes to the next state when both SUB and CEZ are successfully issued s.in_[0].rdy.value = 1 s.out[0].val.value = 1 s.out[1].val.value = 1 s.state.in_.value = CALC_S0 #------------------------------------------------------------------ # DONE state #------------------------------------------------------------------ # send out STORE instruction if s.state.out == DONE: for x in range(nPE): s.in_[x].rdy.value = 0 s.out[x].val.value = 0 s.out[x].msg.value = 0 s.state.in_.value = DONE # STORE value of register 0 to memory s.out[0].msg.ctl.value = STORE s.out[0].msg.src0.value = 1 if s.out[0].rdy: s.state.in_.value = INIT_S0 s.out[0].val.value = 1
def __init__(s, k=3): # ctrl to toplevel s.req_val = InPort(1) s.req_rdy = OutPort(1) s.resp_val = OutPort(1) s.resp_rdy = InPort(1) s.req_msg_digit = InPort(4) s.req_msg_type = InPort(2) s.resp_msg_type = OutPort(2) # ctrl->dpath s.knn_wr_data_mux_sel = OutPort(1) s.knn_wr_addr = OutPort(int(math.ceil(math.log(k * DIGIT, 2)))) # max 30 s.knn_rd_addr = OutPort(int(math.ceil(math.log(k * DIGIT, 2)))) # max 30 s.knn_wr_en = OutPort(1) s.vote_wr_data_mux_sel = OutPort(1) s.vote_wr_addr = OutPort(int(math.ceil(math.log(DIGIT, 2)))) # max 10 s.vote_rd_addr = OutPort(int(math.ceil(math.log(DIGIT, 2)))) # max 10 s.vote_wr_en = OutPort(1) s.FindMax_req_val = OutPort(1) s.FindMax_resp_rdy = OutPort(1) s.FindMin_req_val = OutPort(1) s.FindMin_resp_rdy = OutPort(1) s.msg_data_reg_en = OutPort(1) s.msg_idx_reg_en = OutPort(1) # dpath->ctrl s.FindMax_req_rdy = InPort(1) s.FindMax_resp_val = InPort(1) s.FindMax_resp_idx = InPort(int(math.ceil(math.log(k, 2)))) # max 10 s.FindMin_req_rdy = InPort(1) s.FindMin_resp_val = InPort(1) s.isSmaller = InPort(1) s.msg_type_reg_en = Wire(Bits(1)) s.msg_digit_reg_en = Wire(Bits(1)) s.req_msg_digit_q = Wire(Bits(4)) s.init_go = Wire(Bits(1)) s.max_go = Wire(Bits(1)) s.min_go = Wire(Bits(1)) # State element s.STATE_IDLE = 0 s.STATE_INIT = 1 s.STATE_MAX = 2 s.STATE_MIN = 3 s.STATE_DONE = 4 s.state = RegRst(3, reset_value=s.STATE_IDLE) # Counters s.init_count = Wire(int(math.ceil(math.log(k * DIGIT, 2)))) # max 30 s.knn_count = Wire(int(math.ceil(math.log(k * DIGIT, 2)))) # max 30 s.vote_count = Wire(int(math.ceil(math.log(DIGIT, 2)))) # max 10 @s.tick def counter(): if (s.init_go == 1): s.init_count.next = s.init_count + 1 else: s.init_count.next = 0 if (s.max_go == 1): s.knn_count.next = s.knn_count + 1 else: s.knn_count.next = s.req_msg_digit * k if (s.min_go == 1): s.vote_count.next = s.vote_count + 1 else: s.vote_count.next = 0 # State Transition Logic @s.combinational def state_transitions(): curr_state = s.state.out next_state = s.state.out # Transition out of IDLE state if (curr_state == s.STATE_IDLE): if ((s.req_val and s.req_rdy) and (s.req_msg_type == 1)): next_state = s.STATE_INIT elif ((s.req_val and s.req_rdy) and (s.req_msg_type == 0) and (s.FindMax_req_val and s.FindMax_req_rdy)): next_state = s.STATE_MAX elif ((s.req_val and s.req_rdy) and (s.req_msg_type == 2) and (s.FindMin_req_val and s.FindMin_req_rdy)): next_state = s.STATE_MIN # Transition out of INIT state if (curr_state == s.STATE_INIT): if (s.init_count == k * DIGIT - 1): next_state = s.STATE_DONE # Transition out of MAX state if (curr_state == s.STATE_MAX): if (s.FindMax_resp_val and s.FindMax_resp_rdy): next_state = s.STATE_DONE # Transition out of MIN state if (curr_state == s.STATE_MIN): if (s.FindMin_resp_val and s.FindMin_resp_rdy): next_state = s.STATE_DONE # Transition out of DONE state if (curr_state == s.STATE_DONE): if (s.resp_val and s.resp_rdy): next_state = s.STATE_IDLE s.state.in_.value = next_state # State Output Logic @s.combinational def state_outputs(): current_state = s.state.out # IDLE state if current_state == s.STATE_IDLE: s.req_rdy.value = 1 s.resp_val.value = 0 s.msg_data_reg_en.value = 1 s.msg_digit_reg_en.value = 1 s.msg_type_reg_en.value = 1 s.msg_idx_reg_envalue = 0 s.init_go.value = 0 s.knn_wr_data_mux_sel.value = 0 s.knn_wr_en.value = 0 s.knn_wr_addr.value = 0 if ((s.req_val and s.req_rdy) and (s.req_msg_type == 0)): s.max_go.value = 1 s.FindMax_req_val.value = 1 s.FindMax_resp_rdy.value = 0 s.knn_rd_addr.value = s.knn_count s.min_go.value = 0 s.FindMin_req_val.value = 0 s.FindMin_resp_rdy.value = 0 s.vote_rd_addr.value = s.req_msg_digit_q elif ((s.req_val and s.req_rdy) and (s.req_msg_type == 2)): s.max_go.value = 0 s.FindMax_req_val.value = 0 s.FindMax_resp_rdy.value = 0 s.knn_rd_addr.value = 0 s.min_go.value = 1 s.FindMin_req_val.value = 1 s.FindMin_resp_rdy.value = 0 s.vote_rd_addr.value = s.vote_count else: s.max_go.value = 0 s.FindMax_req_val.value = 0 s.FindMax_resp_rdy.value = 0 s.knn_rd_addr.value = 0 s.min_go.value = 0 s.FindMin_req_val.value = 0 s.FindMin_resp_rdy.value = 0 s.vote_rd_addr.value = s.req_msg_digit_q s.vote_wr_data_mux_sel.value = 1 s.vote_wr_en.value = 0 s.vote_wr_addr.value = s.req_msg_digit_q # INI state elif current_state == s.STATE_INIT: s.req_rdy.value = 0 s.resp_val.value = 0 s.msg_data_reg_en.value = 0 s.msg_digit_reg_en.value = 0 s.msg_type_reg_en.value = 0 s.msg_idx_reg_en.value = 0 s.init_go.value = 1 s.max_go.value = 0 s.min_go.value = 0 s.FindMin_req_val.value = 0 s.FindMin_resp_rdy.value = 0 s.knn_wr_data_mux_sel.value = 0 s.knn_wr_en.value = 1 s.knn_wr_addr.value = s.init_count s.FindMax_req_val.value = 0 s.FindMax_resp_rdy.value = 0 # knn_rd for debugging if s.init_count == 0: s.knn_rd_addr.value = 0 else: s.knn_rd_addr.value = s.init_count - 1 if (s.init_count < DIGIT): s.vote_wr_data_mux_sel.value = 0 s.vote_wr_en.value = 1 s.vote_wr_addr.value = s.init_count # vote_rd for debugging if s.init_count == 0: s.vote_rd_addr.value = 0 else: s.vote_rd_addr.value = s.init_count - 1 else: s.vote_wr_data_mux_sel.value = 1 s.vote_wr_en.value = 0 s.vote_wr_addr.value = 0 s.vote_rd_addr.value = 0 # MAX state elif current_state == s.STATE_MAX: s.req_rdy.value = 0 s.resp_val.value = 0 s.msg_data_reg_en.value = 0 s.msg_digit_reg_en.value = 0 s.msg_type_reg_en.value = 0 s.msg_idx_reg_en.value = 0 s.init_go.value = 0 s.max_go.value = 1 s.min_go.value = 0 s.FindMin_req_val.value = 0 s.FindMin_resp_rdy.value = 0 s.FindMax_req_val.value = 1 s.FindMax_resp_rdy.value = 1 if (s.knn_count > s.req_msg_digit_q * k + 2): s.knn_rd_addr.value = 0 s.knn_wr_addr.value = s.req_msg_digit_q * k + s.FindMax_resp_idx if (s.isSmaller == 1): s.knn_wr_data_mux_sel.value = 1 s.knn_wr_en.value = 1 s.vote_wr_en.value = 1 else: s.knn_wr_data_mux_sel.value = 0 s.knn_wr_en.value = 0 else: s.knn_wr_data_mux_sel.value = 0 s.knn_rd_addr.value = s.knn_count s.knn_wr_en.value = 0 s.knn_wr_addr.value = 0 s.vote_wr_en.value = 0 s.vote_wr_data_mux_sel.value = 1 s.vote_wr_addr.value = s.req_msg_digit_q s.vote_rd_addr.value = s.req_msg_digit_q # MIN state elif current_state == s.STATE_MIN: s.req_rdy.value = 0 s.resp_val.value = 0 s.msg_data_reg_en.value = 0 s.msg_digit_reg_en.value = 0 s.msg_type_reg_en.value = 0 s.init_go.value = 0 s.max_go.value = 0 s.FindMax_req_val.value = 0 s.FindMax_resp_rdy.value = 0 s.min_go.value = 1 s.FindMin_req_val.value = 1 s.FindMin_resp_rdy.value = 1 s.vote_wr_data_mux_sel.value = 1 s.vote_wr_en.value = 0 s.vote_wr_addr.value = 0 if (s.vote_count > DIGIT - 1): s.msg_idx_reg_en.value = 1 s.vote_rd_addr.value = 0 else: s.msg_idx_reg_en.value = 0 s.vote_rd_addr.value = s.vote_count s.knn_wr_en.value = 0 s.knn_wr_data_mux_sel.value = 1 s.knn_wr_addr.value = 0 s.knn_rd_addr.value = 0 # DONE state elif current_state == s.STATE_DONE: s.req_rdy.value = 0 s.resp_val.value = 1 s.msg_data_reg_en.value = 0 s.msg_digit_reg_en.value = 0 s.msg_type_reg_en.value = 0 s.msg_idx_reg_en.value = 0 s.init_go.value = 0 s.max_go.value = 0 s.min_go.value = 0 s.FindMin_req_val.value = 0 s.FindMin_resp_rdy.value = 0 s.knn_wr_data_mux_sel.value = 0 s.knn_wr_en.value = 0 s.knn_wr_addr.value = 0 s.FindMax_req_val.value = 0 s.FindMax_resp_rdy.value = 0 s.knn_rd_addr.value = 0x1b s.vote_wr_data_mux_sel.value = 1 s.vote_wr_en.value = 0 s.vote_wr_addr.value = s.req_msg_digit_q s.vote_rd_addr.value = s.req_msg_digit_q # Register for resp msg type s.Reg_msg_type = m = RegEnRst(2) s.connect_dict({ m.en: s.msg_type_reg_en, m.in_: s.req_msg_type, m.out: s.resp_msg_type, }) # Register for req msg digit s.Reg_msg_digit = m = RegEnRst(4) s.connect_dict({ m.en: s.msg_digit_reg_en, m.in_: s.req_msg_digit, m.out: s.req_msg_digit_q, })