Exemple #1
0
  def construct( s, EntryType, num_entries=2 ):

    # Interface

    s.enq_msg =  InPort( EntryType )
    s.deq_ret = OutPort( EntryType )

    s.wen     = InPort( Bits1 )
    s.waddr   = InPort( mk_bits( clog2( num_entries ) ) )
    s.raddr   = InPort( mk_bits( clog2( num_entries ) ) )
    s.mux_sel = InPort( Bits1 )

    # Component

    s.queue = m =RegisterFile( EntryType, num_entries )
    m.raddr[0] //= s.raddr
    m.wen[0]   //= s.wen
    m.waddr[0] //= s.waddr
    m.wdata[0] //= s.enq_msg

    s.mux = Mux( EntryType, 2 )
    s.mux.sel    //= s.mux_sel
    s.mux.in_[0] //= s.queue.rdata[0]
    s.mux.in_[1] //= s.enq_msg
    s.mux.out    //= s.deq_ret
Exemple #2
0
  def construct( s, EntryType, num_entries=2 ):

    # Interface

    s.enq_msg =  InPort( EntryType )
    s.deq_ret = OutPort( EntryType )

    s.wen   = InPort( Bits1 )
    s.waddr = InPort( mk_bits( clog2( num_entries ) ) )
    s.raddr = InPort( mk_bits( clog2( num_entries ) ) )

    # Component

    s.queue = m = RegisterFile( EntryType, num_entries )
    m.raddr[0] //= s.raddr
    m.rdata[0] //= s.deq_ret
    m.wen[0]   //= s.wen
    m.waddr[0] //= s.waddr
    m.wdata[0] //= s.enq_msg
Exemple #3
0
    def construct(s, ReqType, RespType, nregs=16):

        # Interface

        s.xcel = XcelMinionIfcRTL(ReqType, RespType)

        # Local parameters

        DataType = ReqType.get_field_type('data')
        assert DataType is RespType.get_field_type('data')

        s.nregs = nregs

        # Components

        s.req_q = NormalQueueRTL(ReqType, num_entries=1)
        s.wen = Wire(Bits1)

        s.reg_file = m = RegisterFile(DataType, nregs)
        m.raddr[0] //= s.req_q.deq.ret.addr
        m.rdata[0] //= s.xcel.resp.msg.data
        m.wen[0] //= s.wen
        m.waddr[0] //= s.req_q.deq.ret.addr
        m.wdata[0] //= s.req_q.deq.ret.data

        connect(s.xcel.req, s.req_q.enq)
        connect(s.xcel.resp.msg.type_, s.req_q.deq.ret.type_)

        @update
        def up_wen():
            s.wen @= s.req_q.deq.rdy & (s.req_q.deq.ret.type_
                                        == XcelMsgType.WRITE)

        @update
        def up_resp():
            s.xcel.resp.en @= s.req_q.deq.rdy & s.xcel.resp.rdy
            s.req_q.deq.en @= s.req_q.deq.rdy & s.xcel.resp.rdy
Exemple #4
0
    def construct(s, num_entries, Type):

        SizeType = mk_bits(clog2(num_entries + 1))
        AddrType = mk_bits(clog2(num_entries))

        s.enq_bits = InPort(Type)
        s.deq_bits = OutPort(Type)

        # Control signal (ctrl -> dpath)
        s.wen = InPort(Bits1)
        s.waddr = InPort(AddrType)
        s.raddr = InPort(AddrType)

        # Queue storage

        s.queue = RegisterFile(Type, num_entries)

        # Connect queue storage

        connect(s.queue.raddr[0], s.raddr)
        connect(s.queue.rdata[0], s.deq_bits)
        connect(s.queue.wen[0], s.wen)
        connect(s.queue.waddr[0], s.waddr)
        connect(s.queue.wdata[0], s.enq_bits)
Exemple #5
0
  def construct( s ):

    #---------------------------------------------------------------------
    # Interface
    #---------------------------------------------------------------------

    # imem ports
    s.imemreq_addr   = OutPort( Bits32 )
    s.imemresp_data  = InPort ( Bits32 )

    # dmem ports
    s.dmemreq_addr   = OutPort( Bits32 )
    s.dmemreq_data   = OutPort( Bits32 )
    s.dmemresp_data  = InPort ( Bits32 )

    # mngr ports
    s.mngr2proc_data = InPort ( Bits32 )
    s.proc2mngr_data = OutPort( Bits32 )

    # xcel ports
    s.xcelreq_addr   = OutPort( Bits5 )
    s.xcelreq_data   = OutPort( Bits32 )
    s.xcelresp_data  = InPort ( Bits32 )

    # Control signals (ctrl->dpath)

    s.reg_en_F         = InPort ( Bits1 )
    s.pc_sel_F         = InPort ( Bits1 )

    s.reg_en_D         = InPort ( Bits1 )
    s.op1_byp_sel_D    = InPort ( Bits2 )
    s.op2_byp_sel_D    = InPort ( Bits2 )
    s.op2_sel_D        = InPort ( Bits2 )
    s.imm_type_D       = InPort ( Bits3 )

    s.reg_en_X         = InPort ( Bits1 )
    s.alu_fn_X         = InPort ( Bits4 )

    s.reg_en_M         = InPort ( Bits1 )
    s.wb_result_sel_M  = InPort ( Bits2 )

    s.reg_en_W         = InPort ( Bits1 )
    s.rf_waddr_W       = InPort ( Bits5 )
    s.rf_wen_W         = InPort ( Bits1 )

    # Status signals (dpath->Ctrl)

    s.inst_D           = OutPort( Bits32 )
    s.ne_X             = OutPort( Bits1 )

    #---------------------------------------------------------------------
    # F stage
    #---------------------------------------------------------------------

    s.pc_F        = Wire( Bits32 )
    s.pc_plus4_F  = Wire( Bits32 )

    # PC+4 incrementer

    s.pc_incr_F = m = Incrementer( Bits32, amount=4 )
    m.in_ //= s.pc_F
    m.out //= s.pc_plus4_F

    # forward delaration for branch target and jal target

    s.br_target_X  = Wire( Bits32 )

    # PC sel mux

    s.pc_sel_mux_F = m = Mux( Bits32, 2 )
    m.in_[0] //= s.pc_plus4_F
    m.in_[1] //= s.br_target_X
    m.sel //= s.pc_sel_F
    m.out //= s.imemreq_addr

    # PC register

    s.pc_reg_F = m = RegEnRst( Bits32, reset_value=c_reset_vector-4 )
    m.en  //= s.reg_en_F
    m.in_ //= s.pc_sel_mux_F.out
    m.out //= s.pc_F

    #---------------------------------------------------------------------
    # D stage
    #---------------------------------------------------------------------

    # PC reg in D stage
    # This value is basically passed from F stage for the corresponding
    # instruction to use, e.g. branch to (PC+imm)

    s.pc_reg_D = m = RegEnRst( Bits32 )
    m.en  //= s.reg_en_D
    m.in_ //= s.pc_F

    # Instruction reg

    s.inst_D_reg = m = RegEnRst( Bits32, reset_value=c_reset_inst )
    m.en  //= s.reg_en_D
    m.in_ //= s.imemresp_data
    m.out //= s.inst_D # to ctrl

    # Register File
    # The rf_rdata_D wires, albeit redundant in some sense, are used to
    # remind people these data are from D stage.

    s.rf_rdata0_D = Wire( Bits32 )
    s.rf_rdata1_D = Wire( Bits32 )

    s.rf_wdata_W  = Wire( Bits32 )

    s.rf = m = RegisterFile( Bits32, nregs=32, rd_ports=2, wr_ports=1, const_zero=True )
    m.raddr[0] //= s.inst_D[ RS1 ]
    m.rdata[0] //= s.rf_rdata0_D
    m.raddr[1] //= s.inst_D[ RS2 ]
    m.rdata[1] //= s.rf_rdata1_D
    m.wen[0]   //= s.rf_wen_W
    m.waddr[0] //= s.rf_waddr_W
    m.wdata[0] //= s.rf_wdata_W

    # Immediate generator

    s.immgen_D = m = ImmGenRTL()
    m.imm_type //= s.imm_type_D
    m.inst     //= s.inst_D

    s.bypass_X = Wire( Bits32 )
    s.bypass_M = Wire( Bits32 )
    s.bypass_W = Wire( Bits32 )

    # op1 bypass mux

    s.op1_byp_mux_D = m = Mux( Bits32, 4 )
    m.in_[0] //= s.rf_rdata0_D
    m.in_[1] //= s.bypass_X
    m.in_[2] //= s.bypass_M
    m.in_[3] //= s.bypass_W
    m.sel    //= s.op1_byp_sel_D

    # op2 bypass mux

    s.op2_byp_mux_D = m = Mux( Bits32, 4 )
    m.in_[0] //= s.rf_rdata1_D
    m.in_[1] //= s.bypass_X
    m.in_[2] //= s.bypass_M
    m.in_[3] //= s.bypass_W
    m.sel    //= s.op2_byp_sel_D

    # op2 sel mux
    # This mux chooses among RS2, imm, and the mngr2proc.
    # Basically we are using two muxes here for pedagogy.

    s.op2_sel_mux_D = m = Mux( Bits32, 3 )
    m.in_[0] //= s.op2_byp_mux_D.out
    m.in_[1] //= s.immgen_D.imm
    m.in_[2] //= s.mngr2proc_data
    m.sel    //= s.op2_sel_D

    # Risc-V always calcs branch target by adding imm(generated above) to PC

    s.pc_plus_imm_D = m = Adder( Bits32 )
    m.in0 //= s.pc_reg_D.out
    m.in1 //= s.immgen_D.imm

    #---------------------------------------------------------------------
    # X stage
    #---------------------------------------------------------------------

    # br_target_reg_X
    # Since branches are resolved in X stage, we register the target,
    # which is already calculated in D stage, to X stage.

    s.br_target_reg_X = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_X
    m.in_ //= s.pc_plus_imm_D.out
    m.out //= s.br_target_X

    # op1 reg

    s.op1_reg_X = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_X
    m.in_ //= s.op1_byp_mux_D.out

    # op2 reg

    s.op2_reg_X = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_X
    m.in_ //= s.op2_sel_mux_D.out

    # Send out xcelreq msg
    s.xcelreq_data //= s.op1_reg_X.out
    s.xcelreq_addr //= s.op2_reg_X.out[0:5]

    # store data reg
    # Since the op1 is the base address and op2 is the immediate so that
    # we could utilize ALU to do address calculation, we need one more
    # register to hold the R[rs2] we want to store to memory.

    s.store_reg_X = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_X
    m.in_ //= s.op2_byp_mux_D.out # R[rs2]
    m.out //= s.dmemreq_data

    # ALU

    s.alu_X = m = AluRTL()
    m.in0    //= s.op1_reg_X.out
    m.in1    //= s.op2_reg_X.out
    m.fn     //= s.alu_fn_X
    m.ops_ne //= s.ne_X
    m.out    //= s.bypass_X
    m.out    //= s.dmemreq_addr

    #---------------------------------------------------------------------
    # M stage
    #---------------------------------------------------------------------

    # Alu execution result reg

    s.ex_result_reg_M = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_M
    m.in_ //= s.alu_X.out

    # Writeback result selection mux

    s.wb_result_sel_mux_M = m = Mux( Bits32, 3 )
    m.in_[0] //= s.ex_result_reg_M.out
    m.in_[1] //= s.dmemresp_data
    m.in_[2] //= s.xcelresp_data
    m.sel //= s.wb_result_sel_M
    m.out //= s.bypass_M

    #---------------------------------------------------------------------
    # W stage
    #---------------------------------------------------------------------

    # Writeback result reg

    s.wb_result_reg_W = m = RegEnRst( Bits32, reset_value=0 )
    m.en  //= s.reg_en_W
    m.in_ //= s.wb_result_sel_mux_M.out
    m.out //= s.bypass_W
    m.out //= s.rf_wdata_W
    m.out //= s.proc2mngr_data