Exemplo n.º 1
0
    def construct(s):

        MemReqMsg, MemRespMsg = mk_mem_msg(8, 32, 32)

        # Interface

        s.xcel = XcelMinionIfcCL(XcelReqMsg, XcelRespMsg)

        s.mem = MemMasterIfcCL(*mk_mem_msg(8, 32, 32))
    def construct(s, ProcClass, XcelClass):

        req_class, resp_class = mk_mem_msg(8, 32, 32)

        s.commit_inst = OutPort(Bits1)

        # Instruction Memory Request/Response Interface

        s.proc = ProcClass()(commit_inst=s.commit_inst)
        s.xcel = XcelClass()(xcel=s.proc.xcel)

        if isinstance(s.proc.imem, MemMasterIfcRTL):  # RTL proc
            s.mngr2proc = RecvIfcRTL(Bits32)
            s.proc2mngr = SendIfcRTL(Bits32)
            s.imem = MemMasterIfcRTL(req_class, resp_class)
            s.dmem = MemMasterIfcRTL(req_class, resp_class)

        elif isinstance(s.proc.imem, MemMasterIfcCL):  # CL proc
            s.mngr2proc = NonBlockingCalleeIfc(Bits32)
            s.proc2mngr = NonBlockingCallerIfc(Bits32)
            s.imem = MemMasterIfcCL(req_class, resp_class)
            s.dmem = MemMasterIfcCL(req_class, resp_class)

        elif isinstance(s.proc.imem, MemMasterIfcFL):  # FL proc
            s.mngr2proc = GetIfcFL()
            s.proc2mngr = SendIfcFL()
            s.imem = MemMasterIfcFL()
            s.dmem = MemMasterIfcFL()

        s.connect_pairs(
            s.mngr2proc,
            s.proc.mngr2proc,
            s.proc2mngr,
            s.proc.proc2mngr,
            s.imem,
            s.proc.imem,
            s.dmem,
            s.proc.dmem,
        )
    def construct(s):

        memreq_cls, memresp_cls = mk_mem_msg(8, 32, 32)
        xreq_class, xresp_class = mk_xcel_msg(5, 32)

        # Interface

        s.commit_inst = OutPort(Bits1)

        s.imem = MemMasterIfcCL(memreq_cls, memresp_cls)
        s.dmem = MemMasterIfcCL(memreq_cls, memresp_cls)

        s.xcel = XcelMasterIfcCL(xreq_class, xresp_class)

        s.proc2mngr = NonBlockingCallerIfc()
        s.mngr2proc = NonBlockingCalleeIfc()

        # Buffers to hold input messages

        s.imemresp_q = DelayPipeDeqCL(0)(enq=s.imem.resp)
        s.dmemresp_q = DelayPipeDeqCL(1)(enq=s.dmem.resp)
        s.mngr2proc_q = DelayPipeDeqCL(1)(enq=s.mngr2proc)
        s.xcelresp_q = DelayPipeDeqCL(0)(enq=s.xcel.resp)

        s.pc = b32(0x200)
        s.R = RegisterFile(32)

        s.F_DXM_queue = PipeQueueCL(1)
        s.DXM_W_queue = PipeQueueCL(1)

        s.F_status = PipelineStatus.idle
        s.DXM_status = PipelineStatus.idle
        s.W_status = PipelineStatus.idle

        @s.update
        def F():
            s.F_status = PipelineStatus.idle

            if s.reset:
                s.pc = b32(0x200)
                return

            if s.imem.req.rdy() and s.F_DXM_queue.enq.rdy():
                if s.redirected_pc_DXM >= 0:
                    s.imem.req(
                        memreq_cls(MemMsgType.READ, 0, s.redirected_pc_DXM))
                    s.pc = s.redirected_pc_DXM
                else:
                    s.imem.req(memreq_cls(MemMsgType.READ, 0, s.pc))

                s.F_DXM_queue.enq(s.pc)
                s.F_status = PipelineStatus.work
                s.pc += 4
            else:
                s.F_status = PipelineStatus.stall

        s.redirected_pc_DXM = -1

        s.raw_inst = b32(0)

        @s.update
        def DXM():
            s.redirected_pc_DXM = -1
            s.DXM_status = PipelineStatus.idle

            if s.F_DXM_queue.deq.rdy() and s.imemresp_q.deq.rdy():

                if not s.DXM_W_queue.enq.rdy():
                    s.DXM_status = PipelineStatus.stall
                else:
                    pc = s.F_DXM_queue.peek()

                    s.raw_inst = s.imemresp_q.peek().data
                    inst = TinyRV0Inst(s.raw_inst)
                    inst_name = inst.name

                    s.DXM_status = PipelineStatus.work

                    if inst_name == "nop":
                        pass
                    elif inst_name == "add":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] + s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "sub":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] - s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "mul":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] * s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "sll":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] <<
                             (s.R[inst.rs2] & 0x1F), DXM_W.arith))
                    elif inst_name == "slt":
                        s.DXM_W_queue.enq(
                            (inst.rd,
                             s.R[inst.rs1].int() < s.R[inst.rs2].int(),
                             DXM_W.arith))
                    elif inst_name == "sltu":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] < s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "sra":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1].int() >>
                             (s.R[inst.rs2].uint() & 0x1F), DXM_W.arith))
                    elif inst_name == "srl":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] >>
                             (s.R[inst.rs2].uint() & 0x1F), DXM_W.arith))

                    # ''' TUTORIAL TASK ''''''''''''''''''''''''''''''''''''''''''''
                    # Implement instruction AND in CL processor
                    # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/
                    # ; Make an "elif" statement here to implement instruction AND
                    # ; that applies bit-wise "and" operator to rs1 and rs2 and
                    # ; pass the result to the pipeline.

                    elif inst_name == "and":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] & s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "or":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] | s.R[inst.rs2],
                             DXM_W.arith))
                    elif inst_name == "xor":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] ^ s.R[inst.rs2],
                             DXM_W.arith))

                    # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''/\

                    elif inst_name == "addi":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] + inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "andi":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] & inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "ori":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] | inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "xori":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] ^ inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "slli":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] << inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "srli":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] >> inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "srai":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1].int() >>
                             (inst.i_imm.uint() & 0x1F), DXM_W.arith))
                    elif inst_name == "slti":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1].int() < inst.i_imm.int(),
                             DXM_W.arith))
                    elif inst_name == "sltiu":
                        s.DXM_W_queue.enq(
                            (inst.rd, s.R[inst.rs1] < sext(inst.i_imm, 32),
                             DXM_W.arith))

                    elif inst_name == "auipc":
                        s.DXM_W_queue.enq((inst.rd, (s.pc - 4) + inst.u_imm,
                                           DXM_W.arith))  #not elegant
                    elif inst_name == "lui":
                        s.DXM_W_queue.enq((inst.rd, inst.u_imm, DXM_W.arith))

                    elif inst_name == "sh":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.WRITE, 0,
                                           s.R[inst.rs1] + inst.s_imm.int(), 2,
                                           s.R[inst.rs2][0:16]))
                            s.DXM_W_queue.enq((0, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall
                    elif inst_name == "sb":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.WRITE, 0,
                                           s.R[inst.rs1] + inst.s_imm.int(), 1,
                                           s.R[inst.rs2][0:8]))
                            s.DXM_W_queue.enq((0, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall
                    elif inst_name == "sw":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.WRITE, 0,
                                           s.R[inst.rs1] + inst.s_imm.int(), 0,
                                           s.R[inst.rs2]))
                            s.DXM_W_queue.enq((0, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall
                    elif inst_name == "lw":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.READ, 0,
                                           s.R[inst.rs1] + inst.i_imm.int(),
                                           0))
                            s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall

                    elif inst_name == "lb":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.READ, 0,
                                           s.R[inst.rs1] + inst.i_imm.int(),
                                           1))
                            s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem_signed))
                        else:
                            s.DXM_status = PipelineStatus.stall

                    elif inst_name == "lh":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.READ, 0,
                                           s.R[inst.rs1] + inst.i_imm.int(),
                                           2))
                            s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem_signed))
                        else:
                            s.DXM_status = PipelineStatus.stall

                    elif inst_name == "lbu":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.READ, 0,
                                           s.R[inst.rs1] + inst.i_imm.int(),
                                           1))

                            s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall

                    elif inst_name == "lhu":
                        if s.dmem.req.rdy():
                            s.dmem.req(
                                memreq_cls(MemMsgType.READ, 0,
                                           s.R[inst.rs1] + inst.i_imm.int(),
                                           2))

                            s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem))
                        else:
                            s.DXM_status = PipelineStatus.stall

                    elif inst_name == "jal":
                        s.DXM_W_queue.enq((inst.rd, s.pc, DXM_W.arith))
                        s.pc = s.pc + sext(inst.j_imm, 32) - 4
                    elif inst_name == "jalr":
                        s.DXM_W_queue.enq((inst.rd, s.pc, DXM_W.arith))
                        s.pc = (s.R[inst.rs1] +
                                sext(inst.i_imm, 32)) & 0xFFFFFFFE

                    elif inst_name == "bne":
                        if s.R[inst.rs1] != s.R[inst.rs2]:
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "beq":
                        if s.R[inst.rs1] == s.R[inst.rs2]:
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "blt":
                        if s.R[inst.rs1].int() < s.R[inst.rs2].int():
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "bge":
                        if s.R[inst.rs1].int() >= s.R[inst.rs2].int():
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "bltu":
                        if s.R[inst.rs1] < s.R[inst.rs2]:
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "bgeu":
                        if s.R[inst.rs1] >= s.R[inst.rs2]:
                            s.redirected_pc_DXM = pc + inst.b_imm.int()
                        s.DXM_W_queue.enq(None)
                    elif inst_name == "csrw":
                        if inst.csrnum == 0x7C0:  # CSR: proc2mngr
                            # We execute csrw in W stage
                            s.DXM_W_queue.enq((0, s.R[inst.rs1], DXM_W.mngr))

                        elif 0x7E0 <= inst.csrnum <= 0x7FF:
                            if s.xcel.req.rdy():
                                s.xcel.req(
                                    xreq_class(XcelMsgType.WRITE,
                                               inst.csrnum[0:5],
                                               s.R[inst.rs1]))
                                s.DXM_W_queue.enq((0, 0, DXM_W.xcel))
                            else:
                                s.DXM_status = PipelineStatus.stall
                    elif inst_name == "csrr":
                        if inst.csrnum == 0xFC0:  # CSR: mngr2proc
                            if s.mngr2proc_q.deq.rdy():
                                s.DXM_W_queue.enq(
                                    (inst.rd, s.mngr2proc_q.deq(),
                                     DXM_W.arith))
                            else:
                                s.DXM_status = PipelineStatus.stall
                        elif 0x7E0 <= inst.csrnum <= 0x7FF:
                            if s.xcel.req.rdy():
                                s.xcel.req(
                                    xreq_class(XcelMsgType.READ,
                                               inst.csrnum[0:5],
                                               s.R[inst.rs1]))
                                s.DXM_W_queue.enq((inst.rd, 0, DXM_W.xcel))
                            else:
                                s.DXM_status = PipelineStatus.stall

                    # If we execute any instruction, we pop from queues
                    if s.DXM_status == PipelineStatus.work:
                        s.F_DXM_queue.deq()
                        s.imemresp_q.deq()

        s.rd = b5(0)

        @s.update
        def W():
            s.commit_inst = Bits1(0)
            s.W_status = PipelineStatus.idle

            if s.DXM_W_queue.deq.rdy():
                entry = s.DXM_W_queue.peek()
                if entry is not None:
                    rd, data, entry_type = entry
                    s.rd = rd

                    if entry_type == DXM_W.mem:
                        if s.dmemresp_q.deq.rdy():
                            if rd > 0:  # load
                                s.R[rd] = Bits32(s.dmemresp_q.deq().data)
                            else:  # store
                                s.dmemresp_q.deq()

                            s.W_status = PipelineStatus.work

                        else:
                            s.W_status = PipelineStatus.stall

                    elif entry_type == DXM_W.mem_signed:
                        if s.dmemresp_q.deq.rdy():
                            if rd > 0:  # load
                                s.R[rd] = Bits32(
                                    sext(s.dmemresp_q.deq().data, 32))
                            else:  # store
                                s.dmemresp_q.deq()

                            s.W_status = PipelineStatus.work

                        else:
                            s.W_status = PipelineStatus.stall
                    elif entry_type == DXM_W.xcel:
                        if s.xcelresp_q.deq.rdy():
                            if rd > 0:  # csrr
                                s.R[rd] = Bits32(s.xcelresp_q.deq().data)
                            else:  # csrw
                                s.xcelresp_q.deq()

                            s.W_status = PipelineStatus.work
                        else:
                            s.W_status = PipelineStatus.stall

                    elif entry_type == DXM_W.mngr:
                        if s.proc2mngr.rdy():
                            s.proc2mngr(data)
                            s.W_status = PipelineStatus.work
                        else:
                            s.W_status = PipelineStatus.stall

                    else:  # other WB insts
                        assert entry_type == DXM_W.arith
                        if rd > 0: s.R[rd] = Bits32(data)
                        s.W_status = PipelineStatus.work

                else:  # non-WB insts
                    s.W_status = PipelineStatus.work

            if s.W_status == PipelineStatus.work:
                s.DXM_W_queue.deq()
                s.commit_inst = Bits1(1)
Exemplo n.º 4
0
  def construct( s ):

    MemReqMsg, MemRespMsg = mk_mem_msg( 8,32,32 )

    # Interface

    s.xcel = XcelMinionIfcCL( XcelReqMsg, XcelRespMsg )

    s.mem  = MemMasterIfcCL( *mk_mem_msg(8,32,32) )

    # ''' LAB TASK ''''''''''''''''''''''''''''''''''''''''''''''''''''''
    # Create CL model for sorting xcel
    # '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/

    # Components

    s.xcelreq_q = PipeQueueCL( num_entries=1 )( enq = s.xcel.req )
    s.memresp_q = PipeQueueCL( num_entries=1 )( enq = s.mem.resp )

    # Internal state

    s.base_addr   = 0
    s.size        = 0
    s.inner_count = 0
    s.outer_count = 0
    s.a           = b32(0)
    s.b           = b32(0)

    # State

    s.STATE_XCFG    = 0
    s.STATE_FIRST0  = 1
    s.STATE_FIRST1  = 2
    s.STATE_BUBBLE0 = 3
    s.STATE_BUBBLE1 = 4
    s.STATE_LAST    = 5
    s.state         = s.STATE_XCFG

    # Line tracing

    s.prev_state = 0
    s.xcfg_trace = "  "

    # logic

    @s.update
    def block():

      # Line tracing string

      s.prev_state = s.state

      #-------------------------------------------------------------------
      # STATE: XCFG
      #-------------------------------------------------------------------
      # In this state we handle the accelerator configuration protocol,
      # where we write the base address, size, and then tell the
      # accelerator to start. We also handle responding when the
      # accelerator is done.

      if s.state == s.STATE_XCFG:
        s.xcfg_trace = "  "
        if s.xcelreq_q.deq.rdy() and s.xcel.resp.rdy():

          xcelreq_msg = s.xcelreq_q.deq()

          if xcelreq_msg.type_ == XCEL_TYPE_WRITE:

            assert xcelreq_msg.addr in [0,1,2], \
              "Only reg writes to 0,1,2 allowed during setup!"

            if   xcelreq_msg.addr == 0:
              s.xcfg_trace = "X0"
              s.outer_count = 0
              s.state = s.STATE_FIRST0

            elif xcelreq_msg.addr == 1:
              s.xcfg_trace = "X1"
              s.base_addr = xcelreq_msg.data.uint()

            elif xcelreq_msg.addr == 2:
              s.xcfg_trace = "X2"
              s.size = xcelreq_msg.data.uint()

            # Send xcel response message

            s.xcel.resp( XcelRespMsg(XCEL_TYPE_WRITE, 0) )

          else:

            s.xcfg_trace = "x0"

            assert xcelreq_msg.addr == 0

            # Send xcel response message, obviously you only want to
            # send the response message when accelerator is done

            s.xcel.resp( XcelRespMsg(XCEL_TYPE_READ, 1) )

      #-------------------------------------------------------------------
      # STATE: FIRST0
      #-------------------------------------------------------------------
      # Send the first memory read request for the very first
      # element in the array.

      elif s.state == s.STATE_FIRST0:
        if s.mem.req.rdy():
          s.mem.req( MemReqMsg( MemMsgType.READ, 0, s.base_addr, 0 ) )
          s.inner_count = 1
          s.state = s.STATE_FIRST1

      #-------------------------------------------------------------------
      # STATE: FIRST1
      #-------------------------------------------------------------------
      # Wait for the memory response for the first element in the array,
      # and once it arrives store this element in a, and send the memory
      # read request for the second element.

      elif s.state == s.STATE_FIRST1:
        if s.mem.req.rdy() and s.memresp_q.deq.rdy():
          s.a = s.memresp_q.deq().data
          addr = s.base_addr + 4*s.inner_count
          s.mem.req( MemReqMsg( MemMsgType.READ, 4, addr, 0 ) )
          s.state = s.STATE_BUBBLE0

      #-------------------------------------------------------------------
      # STATE: BUBBLE0
      #-------------------------------------------------------------------
      # Wait for the memory read response to get the next element,
      # compare the new value to the previous max value, update b with
      # the new max value, and send a memory request to store the new min
      # value. Notice how we decrement the write address by four since we
      # want to store to the new min value _previous_ element.

      elif s.state == s.STATE_BUBBLE0:
        if s.mem.req.rdy() and s.memresp_q.deq.rdy():
          s.b = deepcopy( s.memresp_q.deq().data )
          max_value = max( s.a, s.b )
          min_value = min( s.a, s.b )
          s.a = max_value
          addr = s.base_addr + 4*s.inner_count
          s.mem.req( MemReqMsg( MemMsgType.WRITE, 4, addr-4, 0, min_value ) )
          s.state = s.STATE_BUBBLE1

      #-------------------------------------------------------------------
      # STATE: BUBBLE1
      #-------------------------------------------------------------------
      # Wait for the memory write response, and then check to see if we
      # have reached the end of the array. If we have not reached the end
      # of the array, then make a new memory read request for the next
      # element; if we have reached the end of the array, then make a
      # final write request (with value from a) to update the final
      # element in the array.

      elif s.state == s.STATE_BUBBLE1:
        if s.mem.req.rdy() and s.memresp_q.deq.rdy():
          s.memresp_q.deq()
          s.inner_count += 1
          if s.inner_count < s.size:

            addr = s.base_addr + 4*s.inner_count
            s.mem.req( MemReqMsg( MemMsgType.READ, 4, addr, 0 ) )
            s.state = s.STATE_BUBBLE0

          else:

            addr = s.base_addr + 4*s.inner_count
            s.mem.req( MemReqMsg( MemMsgType.WRITE, 4, addr-4, 0, s.a ) )
            s.state = s.STATE_LAST

      #-------------------------------------------------------------------
      # STATE: LAST
      #-------------------------------------------------------------------
      # Wait for the last response, and then check to see if we need to
      # go through the array again. If we do need to go through array
      # again, then make a new memory read request for the very first
      # element in the array; if we do not need to go through the array
      # again, then we are all done and we can go back to accelerator
      # configuration.

      elif s.state == s.STATE_LAST:
        if s.mem.req.rdy() and s.memresp_q.deq.rdy():
          s.memresp_q.deq()
          s.outer_count += 1
          if s.outer_count < s.size:

            s.mem.req( MemReqMsg( MemMsgType.READ, 4, s.base_addr, 0 ) )
            s.inner_count = 1
            s.state = s.STATE_FIRST1

          else:
            s.state = s.STATE_XCFG