예제 #1
0
    def construct(s, nbits=32):

        dtype = mk_bits(32)
        xreq_class, xresp_class = mk_xcel_msg(5, nbits)

        s.xcel = XcelMinionIfcRTL(xreq_class, xresp_class)

        s.xcelreq_q = NormalQueueRTL(xreq_class, 2)
        s.xcelreq_q.enq //= s.xcel.req

        s.xr0 = RegEn(dtype)
        s.xr0.in_ //= s.xcelreq_q.deq.ret.data

        @update
        def up_null_xcel():

            if s.xcelreq_q.deq.rdy & s.xcel.resp.rdy:
                s.xcelreq_q.deq.en @= 1
                s.xcel.resp.en @= 1
                s.xcel.resp.msg.type_ @= s.xcelreq_q.deq.ret.type_

                if s.xcelreq_q.deq.ret.type_ == XcelMsgType.WRITE:
                    s.xr0.en @= 1
                    s.xcel.resp.msg.data @= 0
                else:
                    s.xr0.en @= 0
                    s.xcel.resp.msg.data @= s.xr0.out
            else:
                s.xcelreq_q.deq.en @= 0
                s.xcel.resp.en @= 0
                s.xr0.en @= 0
                s.xcel.resp.msg.data @= 0
                s.xcel.resp.msg.type_ @= 0
예제 #2
0
  def construct( s, nbits=32 ):

    dtype = mk_bits(32)
    XcelMsgType_WRITE = XcelMsgType.WRITE
    xreq_class, xresp_class = mk_xcel_msg( 5,nbits )

    s.xcel = XcelMinionIfcRTL( xreq_class, xresp_class )

    s.xcelreq_q = NormalQueueRTL( xreq_class, 2 )( enq = s.xcel.req )

    s.xr0 = RegEn( dtype )( in_ = s.xcelreq_q.deq.msg.data )

    @s.update
    def up_null_xcel():

      if s.xcelreq_q.deq.rdy & s.xcel.resp.rdy:
        s.xcelreq_q.deq.en = b1(1)
        s.xcel.resp.en     = b1(1)
        s.xcel.resp.msg.type_ = s.xcelreq_q.deq.msg.type_

        if s.xcelreq_q.deq.msg.type_ == XcelMsgType_WRITE:
          s.xr0.en             = b1(1)
          s.xcel.resp.msg.data = dtype(0)
        else:
          s.xr0.en            = b1(0)
          s.xcel.resp.msg.data = s.xr0.out
      else:
        s.xcelreq_q.deq.en   = b1(0)
        s.xcel.resp.en       = b1(0)
        s.xr0.en             = b1(0)
        s.xcel.resp.msg.data = dtype(0)
        s.xcel.resp.msg.type_ = b1(0)
예제 #3
0
  def construct( s ):

    # Interface, Buffers to hold request/response messages

    s.commit_inst = OutPort( Bits1 )

    s.imem = MemMasterIfcFL()
    s.dmem = MemMasterIfcFL()
    s.xcel = XcelMasterIfcFL( *mk_xcel_msg( 5, 32 ) )

    s.proc2mngr = SendIfcFL()
    s.mngr2proc = GetIfcFL()

    # Internal data structures

    s.PC = b32( 0x200 )

    s.R = RegisterFile(32)
    s.raw_inst = None

    @s.update
    def up_ProcFL():
      if s.reset:
        s.PC = b32( 0x200 )
        return

      s.commit_inst = Bits1( 0 )

      try:
        s.raw_inst = s.imem.read( s.PC, 4 ) # line trace

        inst = TinyRV0Inst( s.raw_inst )
        inst_name = inst.name
        
  #-----------------------------------------------------------------------
  # Register-register arithmetic, logical, and comparison instructions
  #-----------------------------------------------------------------------        
        if   inst_name == "nop":
          s.PC += 4
        elif inst_name == "add":
          s.R[inst.rd] = s.R[inst.rs1] + s.R[inst.rs2]
          s.PC += 4
        elif inst_name == "sub":
          s.R[inst.rd] = s.R[inst.rs1] - s.R[inst.rs2]
          s.PC += 4
        elif inst_name == "mul":
          s.R[ inst.rd ] = s.R[inst.rs1] * s.R[inst.rs2]
          s.PC += 4
        elif inst_name == "sll":
          s.R[inst.rd] = s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F)
          s.PC += 4
        elif inst_name == "slt":
          s.R[inst.rd] = s.R[inst.rs1].int() < s.R[inst.rs2].int()
          s.PC += 4
        elif inst_name == "sltu":  
          s.R[inst.rd] = s.R[inst.rs1] < s.R[inst.rs2]
          s.PC += 4
        elif inst_name == "sra":  
          s.R[inst.rd] = s.R[inst.rs1].int() >> (s.R[inst.rs2].uint() & 0x1F) 
          s.PC += 4  
        elif inst_name == "srl":
          s.R[inst.rd] = s.R[inst.rs1] >> (s.R[inst.rs2].uint() & 0x1F)
          s.PC += 4
        elif inst_name == "and":
          s.R[inst.rd] = s.R[inst.rs1] & s.R[inst.rs2]
          s.PC += 4
        elif inst_name == "or":
          s.R[inst.rd] = s.R[inst.rs1] | s.R[inst.rs2]
          s.PC += 4  
        elif inst_name == "xor":  
          s.R[inst.rd] = s.R[inst.rs1] ^ s.R[inst.rs2]
          s.PC += 4  
  #-----------------------------------------------------------------------
  # Register-immediate arithmetic, logical, and comparison instructions
  #-----------------------------------------------------------------------  
        elif inst_name == "addi":
          s.R[inst.rd] = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          s.PC += 4
        elif inst_name == "andi":
          s.R[inst.rd] = s.R[inst.rs1] & sext( inst.i_imm, 32 )
          s.PC += 4 
        elif inst_name == "ori":  
          s.R[inst.rd] = s.R[inst.rs1] | sext( inst.i_imm, 32 )
          s.PC += 4
        elif inst_name == "xori":
          s.R[inst.rd] = s.R[inst.rs1] ^ sext( inst.i_imm, 32 )
          s.PC += 4
        elif inst_name == "slli":
          s.R[inst.rd] = s.R[inst.rs1] << inst.shamt
          s.PC += 4
        elif inst_name == "srli":
          s.R[inst.rd] = s.R[inst.rs1] >> inst.shamt
          s.PC += 4
        elif inst_name == "srai":
          s.R[inst.rd] = s.R[inst.rs1].int() >> inst.shamt.uint()
          s.PC += 4
        elif inst_name == "slti":
          s.R[inst.rd] = s.R[inst.rs1].int() < inst.i_imm.int()
          s.PC += 4
        elif inst_name == "sltiu":
          s.R[inst.rd] = s.R[inst.rs1] < sext( inst.i_imm, 32 )
          s.PC += 4
  #-----------------------------------------------------------------------
  # Other instructions
  #-----------------------------------------------------------------------    
        elif inst_name == "auipc":
          s.R[inst.rd] = inst.u_imm + s.PC
          s.PC += 4
        elif inst_name == "lui":
          s.R[inst.rd] = inst.u_imm
          s.PC += 4
  #-----------------------------------------------------------------------
  # Load/store instructions
  #----------------------------------------------------------------------- 
        elif inst_name == "sh":
          addr = s.R[inst.rs1] + sext( inst.s_imm, 32 )
          #s.M[addr:addr+2] = s.R[inst.rs2][0:16]
          s.dmem.write(addr, 2, s.R[inst.rs2][0:16])
          s.PC += 4
        elif inst_name == "sb":
          addr = s.R[inst.rs1] + sext( inst.s_imm, 32 )
          #s.M[addr] = s.R[inst.rs2][0:8]
          s.dmem.write(addr, 1, s.R[inst.rs2][0:8])
          s.PC += 4
        elif inst_name == "sw":
          addr = s.R[inst.rs1] + sext( inst.s_imm, 32 )
          s.dmem.write( addr, 4, s.R[inst.rs2] )
          s.PC += 4
        elif inst_name == "lw":
          addr = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          s.R[inst.rd] = s.dmem.read( addr, 4 )
          s.PC += 4
        elif inst_name == "lb":
          addr = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          dmem_data = s.dmem.read( addr, 1 )[0:8]
          s.R[inst.rd] = sext( dmem_data, 32 )
          s.PC += 4
        elif inst_name == "lbu":
          addr = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          dmem_data = s.dmem.read( addr, 1 )[0:8]
          s.R[inst.rd] = zext( dmem_data, 32 )
          s.PC += 4 
        elif inst_name == "lh":
          addr = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          dmem_data = s.dmem.read( addr, 2 )[0:16]
          s.R[inst.rd] = sext( dmem_data, 32 )
          s.PC += 4
        elif inst_name == "lhu": 
          addr = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          dmem_data = s.dmem.read( addr, 2 )[0:16]
          s.R[inst.rd] = zext( dmem_data, 32 )
          s.PC += 4    
  #-----------------------------------------------------------------------
  # Unconditional jump instructions
  #-----------------------------------------------------------------------   
        elif inst_name == "jal":
          s.R[inst.rd] = s.PC + 4
          s.PC = s.PC + sext( inst.j_imm, 32 )
        elif inst_name == "jalr":
          temp = s.R[inst.rs1] + sext( inst.i_imm, 32 )
          s.R[inst.rd] = s.PC + 4
          s.PC = temp & 0xFFFFFFFE
  #-----------------------------------------------------------------------
  # Conditional branch instructions
  #-----------------------------------------------------------------------
        elif inst_name == "bne":
          if s.R[inst.rs1] != s.R[inst.rs2]:
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "beq":
          if s.R[inst.rs1] == s.R[inst.rs2]:
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "blt":
          if s.R[inst.rs1].int() < s.R[inst.rs2].int():
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "bge":
          if s.R[inst.rs1].int() >= s.R[inst.rs2].int():
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "bltu":
          if s.R[inst.rs1] < s.R[inst.rs2]:
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "bgeu":
          if s.R[inst.rs1] >= s.R[inst.rs2]:
            s.PC = s.PC + sext( inst.b_imm, 32 )
          else:
            s.PC += 4
        elif inst_name == "csrw":
          if   inst.csrnum == 0x7C0:
            s.proc2mngr( s.R[inst.rs1] )
          elif 0x7E0 <= inst.csrnum <= 0x7FF:
            s.xcel.write( inst.csrnum[0:5], s.R[inst.rs1] )
          else:
            raise TinyRV2Semantics.IllegalInstruction(
              "Unrecognized CSR register ({}) for csrw at PC={}" \
                .format(inst.csrnum.uint(),s.PC) )
          s.PC += 4
        elif inst_name == "csrr":
          if   inst.csrnum == 0xFC0:
            s.R[inst.rd] = s.mngr2proc()
          elif 0x7E0 <= inst.csrnum <= 0x7FF:
            s.R[inst.rd] = s.xcel.read( inst.csrnum[0:5] )
          else:
            raise TinyRV2Semantics.IllegalInstruction(
              "Unrecognized CSR register ({}) for csrr at PC={}" \
                .format(inst.csrnum.uint(),s.PC) )

          s.PC += 4

      except:
        print( "Unexpected error at PC={:0>8s}!".format( str(s.PC) ) )
        raise

      s.commit_inst = b1( 1 )
    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)
예제 #5
0
    def construct(s):

        # Interface, Buffers to hold request/response messages

        s.commit_inst = OutPort(Bits1)

        s.imem = MemMasterIfcFL()
        s.dmem = MemMasterIfcFL()
        s.xcel = XcelMasterIfcFL(*mk_xcel_msg(5, 32))

        s.proc2mngr = SendIfcFL()
        s.mngr2proc = GetIfcFL()

        # Internal data structures

        s.PC = b32(0x200)

        s.R = RegisterFile(32)
        s.raw_inst = None

        @s.update
        def up_ProcFL():
            if s.reset:
                s.PC = b32(0x200)
                return

            s.commit_inst = Bits1(0)

            try:
                s.raw_inst = s.imem.read(s.PC, 4)  # line trace

                inst = TinyRV0Inst(s.raw_inst)
                inst_name = inst.name

                if inst_name == "nop":
                    s.PC += 4
                elif inst_name == "add":
                    s.R[inst.rd] = s.R[inst.rs1] + s.R[inst.rs2]
                    s.PC += 4
                elif inst_name == "sll":
                    s.R[inst.rd] = s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F)
                    s.PC += 4
                elif inst_name == "srl":
                    s.R[inst.rd] = s.R[inst.rs1] >> (s.R[inst.rs2].uint()
                                                     & 0x1F)
                    s.PC += 4

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

                elif inst_name == "and":
                    s.R[inst.rd] = s.R[inst.rs1] & s.R[inst.rs2]
                    s.PC += 4

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

                elif inst_name == "addi":
                    s.R[inst.rd] = s.R[inst.rs1] + sext(inst.i_imm, 32)
                    s.PC += 4
                elif inst_name == "sw":
                    addr = s.R[inst.rs1] + sext(inst.s_imm, 32)
                    s.dmem.write(addr, 4, s.R[inst.rs2])
                    s.PC += 4
                elif inst_name == "lw":
                    addr = s.R[inst.rs1] + sext(inst.i_imm, 32)
                    s.R[inst.rd] = s.dmem.read(addr, 4)
                    s.PC += 4
                elif inst_name == "bne":
                    if s.R[inst.rs1] != s.R[inst.rs2]:
                        s.PC = s.PC + sext(inst.b_imm, 32)
                    else:
                        s.PC += 4

                elif inst_name == "csrw":
                    if inst.csrnum == 0x7C0:
                        s.proc2mngr(s.R[inst.rs1])
                    elif 0x7E0 <= inst.csrnum <= 0x7FF:
                        s.xcel.write(inst.csrnum[0:5], s.R[inst.rs1])
                    else:
                        raise TinyRV2Semantics.IllegalInstruction(
                          "Unrecognized CSR register ({}) for csrw at PC={}" \
                            .format(inst.csrnum.uint(),s.PC) )
                    s.PC += 4

                elif inst_name == "csrr":
                    if inst.csrnum == 0xFC0:
                        s.R[inst.rd] = s.mngr2proc()
                    elif 0x7E0 <= inst.csrnum <= 0x7FF:
                        s.R[inst.rd] = s.xcel.read(inst.csrnum[0:5])
                    else:
                        raise TinyRV2Semantics.IllegalInstruction(
                          "Unrecognized CSR register ({}) for csrr at PC={}" \
                            .format(inst.csrnum.uint(),s.PC) )

                    s.PC += 4

            except:
                print("Unexpected error at PC={:0>8s}!".format(str(s.PC)))
                raise

            s.commit_inst = b1(1)
예제 #6
0
#  +------+-------+-----------+
#  | type | raddr | data      |
#  +------+-------+-----------+
#

#-------------------------------------------------------------------------
# XcelRespMsg
#-------------------------------------------------------------------------
# Accelerator response messages can either be from a read or write of an
# accelerator register. Read requests include the actual value read from
# the accelerator register, while write requests currently include
# nothing other than the type.
#
# Message Format:
#
#    1b     32b
#  +------+-----------+
#  | type | data      |
#  +------+-----------+
#

XcelReqMsg, XcelRespMsg = mk_xcel_msg(5, 32)

XCEL_TYPE_READ = b1(0)
XCEL_TYPE_WRITE = b1(1)


class XcelMsgs:
    req = XcelReqMsg
    resp = XcelRespMsg