Example #1
0
    def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc,
                                 scratch, status, ie, ip):
        is_interrupt = 1
        tvec_name = ""
        instr = []
        if (cfg.mtvec_mode == mtvec_mode_t.VECTORED):
            self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip,
                                            scratch, instr)
        else:
            # Push user mode GPR to kernel stack before executing exception handling,
            # this is to avoid exception handling routine modify user program state
            # unexpectedly
            # TODO
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, instr)
        # The trap handler will occupy one 4KB page, it will be allocated one entry in
        # the page table with a specific privileged mode.

        if (rcs.SATP_MODE != "BARE"):
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align {}".format(cfg.tvec_alignment))

        tvec_name = tvec.name
        self.gen_section(
            pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart),
            instr)
    def gen_interrupt_vector_table(self, hart, mode, status, cause, ie, ip,
                                   scratch, instr):
        '''In vector mode, the BASE address is shared between interrupt 0 and exception handling.
           When vectored interrupts are enabled, interrupt cause 0, which corresponds to user-mode
           software interrupts, are vectored to the same location as synchronous exceptions. This
           ambiguity does not arise in practice, since user-mode software interrupts are either
           disabled or delegated'''
        instr.extend(
            (".option norvc;",
             "j {}{}mode_exception_handler".format(pkg_ins.hart_prefix(hart),
                                                   mode)))
        # Redirect the interrupt to the corresponding interrupt handler
        for i in range(1, rcs.max_interrupt_vector_num):
            instr.append("j {}{}mode_intr_vector_{}".format(
                pkg_ins.hart_prefix(hart), mode, i))
        if not cfg.disable_compressed_instr:
            instr.append(".option rvc;")
        for i in range(1, rcs.max_interrupt_vector_num):
            intr_handler = []
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, intr_handler)
            self.gen_signature_handshake(
                instr=intr_handler,
                signature_type=signature_type_t.CORE_STATUS,
                core_status=core_status_t.HANDLING_IRQ)
            intr_handler.extend((
                "csrr x{}, {} # {}".format(cfg.gpr[0], hex(cause), cause.name),
                # Terminate the test if xCause[31] != 0 (indicating exception)
                "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0],
                                           hex(rcs.XLEN - 1)),
                "beqz x{}, 1f".format(cfg.gpr[0])))
            csr_list = [status, cause, ie, ip]
            for csr_t in csr_list:
                self.gen_signature_handshake(
                    instr=intr_handler,
                    signature_type=signature_type_t.WRITE_CSR,
                    csr=csr_t)

            # Jump to commmon interrupt handling routine
            intr_handler.extend(
                ("j {}{}mode_intr_handler".format(pkg_ins.hart_prefix(hart),
                                                  mode),
                 "1: la x{}, test_done".format(cfg.scratch_reg),
                 "jalr x0, x{}, 0".format(cfg.scratch_reg)))
            self.gen_section(
                pkg_ins.get_label("{}mode_intr_vector_{}".format(mode, i),
                                  hart), intr_handler)
Example #3
0
    def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc,
                                 scratch, status, ie, ip):
        is_interrupt = 1
        tvec_name = ""
        instr = []
        if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
            self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip,
                                            scratch, instr)
        else:
            # Push user mode GPR to kernel stack before executing exception handling,
            # this is to avoid exception handling routine modify user program state
            # unexpectedly
            # TODO
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, instr)
            # Checking xStatus can be optional if ISS (like spike) has different implementation of
            # certain fields compared with the RTL processor.
            if cfg.check_xstatus:
                instr.append("csrr x{}, {} # {}".format(
                    cfg.gpr[0].value, hex(status.value), status.name))
            instr.append("csrr x{}, {} # {}\n".format(
                cfg.gpr[0].value, hex(cause.value), cause.name) +
                         "{}srli x{}, x{}, {}\n".format(
                             pkg_ins.indent, cfg.gpr[0].value,
                             cfg.gpr[0].value, rcs.XLEN - 1) +
                         "{}bne x{}, x0, {}{}mode_instr_handler".format(
                             pkg_ins.indent, cfg.gpr[0].value,
                             pkg_ins.hart_prefix(hart), mode))
        # The trap handler will occupy one 4KB page, it will be allocated one entry in
        # the page table with a specific privileged mode.

        if rcs.SATP_MODE != satp_mode_t.BARE:
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align {}".format(cfg.tvec_alignment))

        tvec_name = tvec.name
        self.gen_section(
            pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart),
            instr)

        # TODO Exception handler
        instr = []
        if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, instr)
    def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc,
                                 scratch, status, ie, ip):
        # is_interrupt = 1
        tvec_name = ""
        instr = []
        if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
            self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip,
                                            scratch, instr)
        else:
            # Push user mode GPR to kernel stack before executing exception handling,
            # this is to avoid exception handling routine modify user program state
            # unexpectedly
            # TODO
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, instr)
            # Checking xStatus can be optional if ISS (like spike) has different implementation of
            # certain fields compared with the RTL processor.
            if cfg.check_xstatus:
                instr.append("csrr x{}, {} # {}".format(
                    cfg.gpr[0], hex(status), status.name))
            instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(
                cause), cause.name) + "{}srli x{}, x{}, {}\n".format(
                    pkg_ins.indent, cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 1) +
                         "{}bne x{}, x0, {}{}mode_intr_handler".format(
                             pkg_ins.indent, cfg.gpr[0],
                             pkg_ins.hart_prefix(hart), mode))
        # The trap handler will occupy one 4KB page, it will be allocated one entry in
        # the page table with a specific privileged mode.

        if rcs.SATP_MODE != satp_mode_t.BARE:
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align {}".format(cfg.tvec_alignment))

        tvec_name = tvec.name
        self.gen_section(
            pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart),
            instr)
        # TODO Exception handlers
        instr = []
        if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
            pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                             cfg.sp, cfg.tp, instr)
        self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
                                     core_status_t.HANDLING_EXCEPTION)
        # The trap is caused by an exception, read back xCAUSE, xEPC to see if these
        # CSR values are set properly. The checking is done by comparing against the log
        # generated by ISA simulator (spike).
        instr.extend((
            "csrr x{}, 0x{} # {}".format(cfg.gpr[0], epc, epc.name),
            "csrr x{}, 0x{} # {}".format(cfg.gpr[0], cause, cause.name),
            # Illegal instruction exception
            "li x{}, {} # ILLEGAL_INSTRUCTION".format(
                cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)),
            "beq x{}, x{}, {}illegal_instr_handler".format(
                cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)),
            # Skip checking tval for illegal instruction as it's implementation specific
            "csrr x{}, {} # {}".format(cfg.gpr[1], hex(tval), tval.name),
            # use JALR to jump to test_done.
            "1: la x{}, test_done".format(cfg.scratch_reg),
            "jalr x1, x{}, 0".format(cfg.scratch_reg)))
        self.gen_section(
            pkg_ins.get_label("{}mode_exception_handler".format(mode), hart),
            instr)