Exemple #1
0
    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)
Exemple #3
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
Exemple #6
0
  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
Exemple #7
0
    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
Exemple #8
0
  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
Exemple #9
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
Exemple #10
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)
Exemple #11
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.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
Exemple #12
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,
        })
Exemple #14
0
    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,
        })