示例#1
0
  def __init__(s, dispatch_interface):
    UseInterface(s, dispatch_interface)
    preg_nbits = IssueMsg().rs1.nbits
    data_nbits = DispatchMsg().rs1.nbits

    s.require(
        # Methods needed from dflow:
        MethodSpec(
            'read',
            args={'tag': preg_nbits},
            rets={
                'value': data_nbits,
            },
            call=False,
            rdy=False,
            count=2,
        ),)

    s.connect(s.process_accepted, 1)
    s.dispatched_ = Wire(DispatchMsg())
    s.connect(s.process_out, s.dispatched_)

    # connect the register file read
    s.connect(s.read_tag[0], s.process_in_.rs1)
    s.connect(s.read_tag[1], s.process_in_.rs2)

    @s.combinational
    def set_output():
      s.dispatched_.v = 0
      s.dispatched_.hdr.v = s.process_in_.hdr
      if s.process_in_.hdr_status != PipelineMsgStatus.PIPELINE_MSG_STATUS_VALID:
        s.dispatched_.exception_info.v = s.process_in_.exception_info
        # Copy exception info
        s.dispatched_.exception_info.v = s.process_in_.exception_info
      else:
        s.dispatched_.rs1.v = s.read_value[0]
        s.dispatched_.rs1_val.v = s.process_in_.rs1_val
        s.dispatched_.rs2.v = s.read_value[1]
        s.dispatched_.rs2_val.v = s.process_in_.rs2_val
        s.dispatched_.rd.v = s.process_in_.rd
        s.dispatched_.rd_val.v = s.process_in_.rd_val
        s.dispatched_.areg_d.v = s.process_in_.areg_d
        s.dispatched_.execution_data.v = s.process_in_.execution_data
示例#2
0
    def __init__(s):
        # the order above (0 for CSR 1 for ALU comes from this array
        # This is bad
        UseInterface(
            s,
            PipelineSplitterInterface(
                DispatchMsg(), ['csr', 'alu', 'branch', 'm_pipe', 'mem_data']))
        s.require(
            MethodSpec(
                'in_peek',
                args=None,
                rets={
                    'msg': DispatchMsg(),
                },
                call=False,
                rdy=True,
            ),
            MethodSpec(
                'in_take',
                args=None,
                rets=None,
                call=True,
                rdy=False,
            ),
        )

        s.splitter = PipelineSplitter(s.interface)
        s.controller = PipeSelectorController()
        s.connect_m(s.splitter.sort, s.controller.sort)
        s.connect_m(s.splitter.in_peek, s.in_peek)
        s.connect_m(s.splitter.in_take, s.in_take)
        for client in s.interface.clients:
            s.connect_m(getattr(s.splitter, '{}_peek'.format(client)),
                        getattr(s, '{}_peek'.format(client)))
            s.connect_m(getattr(s.splitter, '{}_take'.format(client)),
                        getattr(s, '{}_take'.format(client)))
示例#3
0
    def __init__(s):
        UseInterface(s, PipelineSplitterControllerInterface(DispatchMsg(), 5))

        @s.combinational
        def handle_sort():
            if s.sort_msg.hdr_status != PipelineMsgStatus.PIPELINE_MSG_STATUS_VALID:
                s.sort_pipe.v = 0  # CSR pipe
            elif s.sort_msg.op_class == OpClass.OP_CLASS_CSR or s.sort_msg.op_class == OpClass.OP_CLASS_SYSTEM:
                s.sort_pipe.v = 0  # CSR pipe
            elif s.sort_msg.op_class == OpClass.OP_CLASS_ALU:
                s.sort_pipe.v = 1  # ALU pipe
            elif s.sort_msg.op_class == OpClass.OP_CLASS_BRANCH or s.sort_msg.op_class == OpClass.OP_CLASS_JUMP:
                s.sort_pipe.v = 2  # Branch pipe
            elif s.sort_msg.op_class == OpClass.OP_CLASS_MUL:
                s.sort_pipe.v = 3  # Mul pipe
            elif s.sort_msg.op_class == OpClass.OP_CLASS_MEM:
                s.sort_pipe.v = 4  # Mem data pipe
            else:
                s.sort_pipe.v = 0  # Error CSR pipe
示例#4
0
文件: m_pipe.py 项目: stwendy/lizard
    def __init__(s):
        UseInterface(s, MPipeInterface())

        # Require the methods of an incoming pipeline stage
        # Name the methods in_peek, in_take
        s.require(*[
            m.variant(name='in_{}'.format(m.name)) for m in
            PipelineStageInterface(DispatchMsg(), None).methods.values()
        ])

        s.div = Div()
        s.mult = Mult()

        s.connect(s.div.in_peek_msg, s.in_peek_msg)
        s.connect(s.mult.in_peek_msg, s.in_peek_msg)
        s.connect_m(s.div.kill_notify, s.kill_notify)
        s.connect_m(s.mult.kill_notify, s.kill_notify)

        @s.combinational
        def route_input():
            if s.in_peek_msg.m_msg_func == MFunc.M_FUNC_MUL:
                s.mult.in_peek_rdy.v = s.in_peek_rdy
                s.in_take_call.v = s.mult.in_take_call
                s.div.in_peek_rdy.v = 0
            else:
                s.div.in_peek_rdy.v = s.in_peek_rdy
                s.in_take_call.v = s.div.in_take_call
                s.mult.in_peek_rdy.v = 0

        @s.combinational
        def route_output():
            if s.div.peek_rdy:
                s.peek_rdy.v = s.div.peek_rdy
                s.peek_msg.v = s.div.peek_msg
                s.div.take_call.v = s.take_call
                s.mult.take_call.v = 0
            else:
                s.peek_rdy.v = s.mult.peek_rdy
                s.peek_msg.v = s.mult.peek_msg
                s.mult.take_call.v = s.take_call
                s.div.take_call.v = 0
示例#5
0
    def __init__(s, interface):
        UseInterface(s, interface)

        s.require(
            MethodSpec(
                'in_peek',
                args=None,
                rets={
                    'msg': DispatchMsg(),
                },
                call=False,
                rdy=True,
            ),
            MethodSpec(
                'in_take',
                args=None,
                rets=None,
                call=True,
                rdy=False,
            ),
            MethodSpec(
                'enter_store_data',
                args={
                    'id_': STORE_IDX_NBITS,
                    'data': XLEN,
                },
                rets=None,
                call=True,
                rdy=False,
            ),
        )

        s.connect(s.in_take_call, s.in_peek_rdy)
        s.connect(s.enter_store_data_id_, s.in_peek_msg.hdr_store_id)
        s.connect(s.enter_store_data_data, s.in_peek_msg.rs2)
        s.connect(s.enter_store_data_call, s.in_peek_rdy)
示例#6
0
文件: branch.py 项目: stwendy/lizard
def BranchInterface():
    return StageInterface(DispatchMsg(), ExecuteMsg())
示例#7
0
文件: csr.py 项目: stwendy/lizard
def CSRInterface():
    return StageInterface(DispatchMsg(), ExecuteMsg()())
示例#8
0
    def __init__(s):
        UseInterface(s, ALUInterface())

        imm_len = DispatchMsg().imm.nbits
        data_len = XLEN

        OP_LUT_MAP = {
            AluFunc.ALU_FUNC_ADD: alu.ALUFunc.ALU_ADD,
            AluFunc.ALU_FUNC_SUB: alu.ALUFunc.ALU_SUB,
            AluFunc.ALU_FUNC_AND: alu.ALUFunc.ALU_AND,
            AluFunc.ALU_FUNC_OR: alu.ALUFunc.ALU_OR,
            AluFunc.ALU_FUNC_XOR: alu.ALUFunc.ALU_XOR,
            AluFunc.ALU_FUNC_SLL: alu.ALUFunc.ALU_SLL,
            AluFunc.ALU_FUNC_SRL: alu.ALUFunc.ALU_SRL,
            AluFunc.ALU_FUNC_SRA: alu.ALUFunc.ALU_SRA,
            AluFunc.ALU_FUNC_SLT: alu.ALUFunc.ALU_SLT,
            AluFunc.ALU_FUNC_AUIPC:
            alu.ALUFunc.ALU_ADD,  # We are just adding to the PC
            AluFunc.ALU_FUNC_LUI: alu.ALUFunc.ALU_OR,
        }

        s.op_lut_ = LookupTable(
            LookupTableInterface(DispatchMsg().alu_msg_func.nbits,
                                 alu.ALUFunc.bits), OP_LUT_MAP)

        s.alu_ = alu.ALU(alu.ALUInterface(data_len))
        s.msg_ = Wire(DispatchMsg())
        s.msg_imm_ = Wire(imm_len)

        # PYMTL_BROKEN, cant do msg.src1[:32]
        s.src1_ = Wire(data_len)
        s.src1_32_ = Wire(32)
        s.src2_ = Wire(data_len)
        s.src2_32_ = Wire(32)
        s.imm_ = Wire(data_len)
        s.imm_l20_ = Wire(data_len)

        s.res_ = Wire(data_len)
        s.res_32_ = Wire(32)

        # Connect up lookup table
        s.connect(s.op_lut_.lookup_in_, s.msg_.alu_msg_func)
        s.connect(s.alu_.exec_func, s.op_lut_.lookup_out)

        # Connect to disptach get method
        s.connect(s.msg_, s.process_in_)
        s.connect(s.process_accepted, 1)

        # Connect up alu call
        s.connect(s.alu_.exec_unsigned, s.msg_.alu_msg_unsigned)
        s.connect(s.alu_.exec_call, s.process_call)

        # PYMTL_BROKEN
        s.rs1_ = Wire(data_len)
        s.rs2_ = Wire(data_len)
        s.res_ = Wire(data_len)
        s.res_trunc_ = Wire(data_len)
        s.connect_wire(s.rs1_, s.msg_.rs1)
        s.connect_wire(s.rs2_, s.msg_.rs2)
        s.connect(s.res_, s.alu_.exec_res)

        @s.combinational
        def slice32():
            s.src1_32_.v = s.rs1_[:32]
            s.src2_32_.v = s.rs2_[:32]
            s.res_32_.v = s.res_[:32]

        @s.combinational
        def set_src_res():
            if s.msg_.alu_msg_op32:
                if s.msg_.alu_msg_unsigned or s.msg_.alu_msg_func == AluFunc.ALU_FUNC_SRL:
                    s.src1_.v = zext(s.src1_32_, data_len)
                    s.src2_.v = zext(s.src2_32_, data_len)
                else:
                    s.src1_.v = sext(s.src1_32_, data_len)
                    s.src2_.v = sext(s.src2_32_, data_len)

                # If op32 shift w, need to ignore bit 5
                s.src2_[5].v &= not (
                    s.msg_.alu_msg_func == AluFunc.ALU_FUNC_SLL
                    or s.msg_.alu_msg_func == AluFunc.ALU_FUNC_SRL
                    or s.msg_.alu_msg_func == AluFunc.ALU_FUNC_SRA)

                s.res_trunc_.v = zext(
                    s.res_32_, data_len) if s.msg_.alu_msg_unsigned else sext(
                        s.res_32_, data_len)
            else:
                s.src1_.v = s.rs1_
                s.src2_.v = s.rs2_
                s.res_trunc_.v = s.res_
                if s.msg_.alu_msg_func == AluFunc.ALU_FUNC_AUIPC:
                    s.src1_.v = s.msg_.hdr_pc
                elif s.msg_.alu_msg_func == AluFunc.ALU_FUNC_LUI:  # LUI is a special case
                    s.src1_.v = 0

        @s.combinational
        def set_inputs():
            # PYMTL_BROKEN: sext, concat, and zext only work with wires and constants
            s.msg_imm_.v = s.msg_.imm
            s.imm_.v = sext(s.msg_imm_, data_len)
            if s.msg_.alu_msg_func == AluFunc.ALU_FUNC_AUIPC or s.msg_.alu_msg_func == AluFunc.ALU_FUNC_LUI:
                s.imm_.v = s.imm_ << 12
            s.alu_.exec_src0.v = s.src1_
            s.alu_.exec_src1.v = s.src2_ if s.msg_.rs2_val else s.imm_

        @s.combinational
        def set_process_out():
            s.process_out.v = 0
            s.process_out.hdr.v = s.msg_.hdr
            s.process_out.result.v = s.res_trunc_
            s.process_out.rd.v = s.msg_.rd
            s.process_out.rd_val.v = s.msg_.rd_val
            s.process_out.areg_d.v = s.msg_.areg_d
示例#9
0
文件: divide.py 项目: stwendy/lizard
    def __init__(s):
        UseInterface(s, DivInterface())

        # Require the methods of an incoming pipeline stage
        # Name the methods in_peek, in_take
        s.require(*[
            m.variant(name='in_{}'.format(m.name)) for m in
            PipelineStageInterface(DispatchMsg(), None).methods.values()
        ])

        s.divider = NonRestoringDivider(DivideInterface(XLEN), DIV_NSTEPS)

        s.vvm = gen_valid_value_manager(MultDropController)()
        s.can_take_input = Wire(1)
        s.output_rdy = Wire(1)
        s.connect_m(s.vvm.kill_notify, s.kill_notify)

        @s.combinational
        def handle_control():
            s.can_take_input.v = s.in_peek_rdy and s.divider.div_rdy
            s.output_rdy.v = s.divider.result_rdy and s.vvm.peek_rdy

        s.connect(s.in_take_call, s.can_take_input)
        s.connect(s.divider.div_call, s.can_take_input)
        s.connect(s.vvm.add_call, s.can_take_input)
        s.connect(s.peek_rdy, s.output_rdy)
        s.connect(s.divider.preempt_call, s.vvm.dropping_out)
        s.connect(s.vvm.take_call, s.take_call)
        s.connect(s.divider.result_call, s.take_call)

        s.rs1_32 = Wire(32)
        s.rs2_32 = Wire(32)

        # PYMTL_BROKEN
        # Cannot double-slice so must first assign parts
        s.workaround_rs1 = Wire(XLEN)
        s.workaround_rs2 = Wire(XLEN)
        s.connect(s.workaround_rs1, s.in_peek_msg.rs1)
        s.connect(s.workaround_rs2, s.in_peek_msg.rs2)

        @s.combinational
        def handle_add():
            s.rs1_32.v = s.workaround_rs1[:32]
            s.rs2_32.v = s.workaround_rs2[:32]

            s.divider.div_dividend.v = s.in_peek_msg.rs1
            s.divider.div_divisor.v = s.in_peek_msg.rs2
            s.divider.div_signed.v = s.in_peek_msg.m_msg_variant == MVariant.M_VARIANT_N
            if s.in_peek_msg.m_msg_op32:
                if s.in_peek_msg.m_msg_variant == MVariant.M_VARIANT_N:  # signed
                    s.divider.div_dividend.v = sext(s.rs1_32, XLEN)
                    s.divider.div_divisor.v = sext(s.rs2_32, XLEN)
                else:
                    s.divider.div_dividend.v = zext(s.rs1_32, XLEN)
                    s.divider.div_divisor.v = zext(s.rs2_32, XLEN)

        @s.combinational
        def handle_vvm_add_msg():
            s.vvm.add_msg.v = 0
            s.vvm.add_msg.hdr.v = s.in_peek_msg.hdr
            s.vvm.add_msg.result.v = zext(s.in_peek_msg.m_msg, XLEN)
            s.vvm.add_msg.rd.v = s.in_peek_msg.rd
            s.vvm.add_msg.rd_val.v = s.in_peek_msg.rd_val
            s.vvm.add_msg.areg_d.v = s.in_peek_msg.areg_d

        s.mul_msg = Wire(MMsg())
        s.res_32 = Wire(32)
        num_bits = MMsg().nbits
        # PYMTL_BROKEN
        # can't slice a bitstrut (illegal verilog double array)
        s.peek_msg_result = Wire(XLEN)
        s.connect(s.peek_msg_result, s.vvm.peek_msg.result)

        @s.combinational
        def handle_output_msg(msg_bits=num_bits):
            s.peek_msg.v = s.vvm.peek_msg
            s.mul_msg.v = s.peek_msg_result[:msg_bits]

            s.res_32.v = s.divider.result_quotient[:32]
            s.peek_msg.result.v = s.divider.result_quotient
            if s.mul_msg.func == MFunc.M_FUNC_REM:
                s.res_32.v = s.divider.result_rem[:32]
                s.peek_msg.result.v = s.divider.result_rem

            if s.mul_msg.op32:
                s.peek_msg.result.v = sext(s.res_32, XLEN)
示例#10
0
def MemInputPipelineAdapter():
    return BranchMaskInputPipelineAdapter(
        BranchMaskInputPipelineAdapterInterface(DispatchMsg()))
示例#11
0
    def __init__(s, interface):
        UseInterface(s, interface)
        s.mem_request = MemRequest(MemRequestInterface())
        s.mem_response = MemResponse(MemResponseInterface())
        s.require(
            MethodSpec(
                'recv_load',
                args=None,
                rets={
                    'data': XLEN,
                },
                call=True,
                rdy=True,
            ),
            MethodSpec(
                'store_pending',
                args={
                    'live_mask': Bits(STORE_QUEUE_SIZE),
                    'addr': XLEN,
                    'size': MEM_SIZE_NBITS,
                },
                rets={
                    'pending': Bits(1),
                },
                call=False,
                rdy=False,
            ),
            MethodSpec(
                'send_load',
                args={
                    'addr': XLEN,
                    'size': MEM_SIZE_NBITS,
                },
                rets=None,
                call=True,
                rdy=True,
            ),
            MethodSpec(
                'enter_store_address',
                args={
                    'id_': STORE_IDX_NBITS,
                    'addr': XLEN,
                    'size': MEM_SIZE_NBITS,
                },
                rets=None,
                call=True,
                rdy=False,
            ),
            MethodSpec(
                'valid_store_mask',
                args=None,
                rets={
                    'mask': STORE_QUEUE_SIZE,
                },
                call=False,
                rdy=False,
            ),
        )
        s.connect_m(s.mem_request.store_pending, s.store_pending)
        s.connect_m(s.mem_request.send_load, s.send_load)
        s.connect_m(s.mem_request.enter_store_address, s.enter_store_address)
        s.connect_m(s.mem_request.valid_store_mask, s.valid_store_mask)
        s.connect_m(s.mem_response.recv_load, s.recv_load)

        # Require the methods of an incoming pipeline stage
        # Name the methods in_peek, in_take
        s.require(*[
            m.variant(name='in_{}'.format(m.name)) for m in
            PipelineStageInterface(DispatchMsg(), None).methods.values()
        ])

        s.connect_m(s.mem_request.in_peek, s.in_peek)
        s.connect_m(s.mem_request.in_take, s.in_take)
        s.connect_m(s.mem_response.in_peek, s.mem_request.peek)
        s.connect_m(s.mem_response.in_take, s.mem_request.take)
        s.connect_m(s.peek, s.mem_response.peek)
        s.connect_m(s.take, s.mem_response.take)
示例#12
0
def MemResponseInterface():
    return StageInterface(DispatchMsg(), ExecuteMsg())
示例#13
0
def DispatchDropController():
  return PipelineKillDropController(
      DropControllerInterface(DispatchMsg(), DispatchMsg(),
                              KillType(MAX_SPEC_DEPTH)))
示例#14
0
文件: branch.py 项目: stwendy/lizard
    def __init__(s, branch_interface):
        UseInterface(s, branch_interface)
        imm_len = DispatchMsg().imm.nbits
        data_len = XLEN
        spec_idx_len = DispatchMsg().hdr_spec.nbits
        seq_idx_nbits = DispatchMsg().hdr_seq.nbits
        speculative_mask_nbits = DispatchMsg().hdr_branch_mask.nbits

        s.require(
            MethodSpec(
                'cflow_redirect',
                args={
                    'seq': Bits(seq_idx_nbits),
                    'spec_idx': Bits(spec_idx_len),
                    'branch_mask': Bits(speculative_mask_nbits),
                    'target': Bits(data_len),
                    'force': Bits(1),
                },
                rets={},
                call=True,
                rdy=False,
            ),
            MethodSpec(
                'btb_write',
                args={
                    'key': XLEN,
                    'remove': Bits(1),
                    'value': XLEN,
                },
                rets=None,
                call=True,
                rdy=False,
            ),
        )

        s.connect(s.process_accepted, 1)

        s.cmp_ = Comparator(ComparatorInterface(data_len))
        s.msg_ = Wire(DispatchMsg())
        s.msg_imm_ = Wire(imm_len)
        s.imm_ = Wire(data_len)

        s.take_branch_ = Wire(1)
        s.branch_target_ = Wire(data_len)
        s.branch_target_pcimm_ = Wire(data_len)
        s.branch_target_rs1imm_ = Wire(data_len)
        s.branch_target_fallthrough_ = Wire(data_len)

        OP_LUT_MAP = {
            BranchType.BRANCH_TYPE_EQ: CMPFunc.CMP_EQ,
            BranchType.BRANCH_TYPE_NE: CMPFunc.CMP_NE,
            BranchType.BRANCH_TYPE_LT: CMPFunc.CMP_LT,
            BranchType.BRANCH_TYPE_GE: CMPFunc.CMP_GE,
        }
        s.op_lut_ = LookupTable(
            LookupTableInterface(DispatchMsg().branch_msg_type_.nbits,
                                 CMPFunc.bits), OP_LUT_MAP)

        # Connect to disptach get method
        s.connect(s.msg_, s.process_in_)

        # Connect lookup opmap
        s.connect(s.op_lut_.lookup_in_, s.msg_.branch_msg_type_)
        s.connect(s.cmp_.exec_func, s.op_lut_.lookup_out)
        # Connect up cmp call
        s.connect(s.cmp_.exec_src0, s.msg_.rs1)
        s.connect(s.cmp_.exec_src1, s.msg_.rs2)
        s.connect(s.cmp_.exec_unsigned, s.msg_.branch_msg_unsigned)
        s.connect(s.cmp_.exec_call, s.process_call)

        # Connect up to controlflow redirect method
        s.connect(s.cflow_redirect_spec_idx, s.msg_.hdr_spec)
        s.connect(s.cflow_redirect_seq, s.msg_.hdr_seq)
        s.connect(s.cflow_redirect_branch_mask, s.msg_.hdr_branch_mask)
        s.connect(s.cflow_redirect_target, s.branch_target_)
        s.connect(s.cflow_redirect_force, 0)
        s.connect(s.cflow_redirect_call, s.process_call)

        @s.combinational
        def set_take_branch():
            s.take_branch_.v = s.cmp_.exec_res or s.msg_.op_class == OpClass.OP_CLASS_JUMP

        @s.combinational
        def compute_target():
            s.msg_imm_.v = s.msg_.imm
            # PYMTL_BROKEN: sext(s.msg_.imm) does not create valid verilog
            # Vivado errors: "range is not allowed in prefix"
            s.imm_.v = sext(s.msg_imm_, data_len)
            s.branch_target_pcimm_.v = s.msg_.hdr_pc + s.imm_
            s.branch_target_rs1imm_.v = s.msg_.rs1 + s.imm_
            s.branch_target_rs1imm_[0].v = 0
            s.branch_target_fallthrough_.v = s.msg_.hdr_pc + ILEN_BYTES

            if s.take_branch_:
                # Branch or JAL
                if s.msg_.op_class == OpClass.OP_CLASS_BRANCH or not s.msg_.rs1_val:
                    s.branch_target_.v = s.branch_target_pcimm_
                else:
                    s.branch_target_.v = s.branch_target_rs1imm_
            else:
                s.branch_target_.v = s.branch_target_fallthrough_

        @s.combinational
        def set_value_reg_input():
            s.process_out.v = 0
            s.process_out.hdr.v = s.msg_.hdr
            s.process_out.result.v = s.msg_.hdr_pc + ILEN_BYTES
            s.process_out.rd.v = s.msg_.rd
            s.process_out.rd_val.v = s.msg_.rd_val
            s.process_out.areg_d.v = s.msg_.areg_d

        @s.combinational
        def update_btb():
            s.btb_write_key.v = s.msg_.hdr_pc
            s.btb_write_value.v = s.branch_target_
            s.btb_write_remove.v = not s.take_branch_
            s.btb_write_call.v = s.process_call
示例#15
0
def MemRequestInterface():
    return StageInterface(DispatchMsg(), DispatchMsg())
示例#16
0
def MultInputPipelineAdapterInterface():
    return InputPipelineAdapterInterface(DispatchMsg(), MultIn(), ExecuteMsg())
示例#17
0
def DispatchInterface():
  return StageInterface(IssueMsg(), DispatchMsg())