Пример #1
0
    def gen_kernel_sections(self, hart):
        if(rcs.SATP_MODE != "BARE"):
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align 2")
        self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart))
        self.instr_stream.append(".text")

        self.gen_all_trap_handler(hart)
        for mode in rcs.supported_privileged_mode:
            self.gen_interrupt_handler_section(mode, hart)
        self.instr_stream.append(pkg_ins.get_label("kernel_instr_end: nop", hart))
        self.gen_kernel_stack_section(hart)
Пример #2
0
    def trap_vector_init(self, hart):
        instr = []
        for items in rcs.supported_privileged_mode:
            if(items == "MACHINE_MODE"):
                trap_vec_reg = privileged_reg_t.MTVEC
            elif(items == "SUPERVISOR_MODE"):
                trap_vec_reg = privileged_reg_t.STVEC
            elif(items == "USER_MODE"):
                trap_vec_reg = privileged_reg_t.UTVEC
            else:
                logging.critical(
                    "[riscv_asm_program_gen] Unsupported privileged_mode {}".format(items))

            if(items == "USER_MODE" and not (rcs.support_umode_trap)):
                continue

            if(items < cfg.init_privileged_mode.name):
                continue

            tvec_name = trap_vec_reg.name
            tvec_name = tvec_name.lower()
            instr.append("la x{}, {}{}_handler".format(
                cfg.gpr[0].value, pkg_ins.hart_prefix(hart), tvec_name))
            if(rcs.SATP_MODE != "BARE" and items != "MACHINE_MODE"):
                instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0].value,
                                                          cfg.gpr[0].value, rcs.XLEN - 20) +
                             "srli x{}, x{}, {}".format(cfg.gpr[0].value,
                                                        cfg.gpr[0].value, rcs.XLEN - 20))

            instr.append("ori x{}, x{}, {}".format(
                cfg.gpr[0].value, cfg.gpr[0].value, cfg.mtvec_mode.value))
            instr.append("csrw {}, x{} # {}".format(
                hex(trap_vec_reg.value), cfg.gpr[0].value, trap_vec_reg.name))

        self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
Пример #3
0
    def trap_vector_init(self, hart):
        instr = []
        for mode in rcs.supported_privileged_mode:
            if mode == privileged_mode_t.MACHINE_MODE:
                trap_vec_reg = privileged_reg_t.MTVEC
            elif mode == privileged_mode_t.SUPERVISOR_MODE:
                trap_vec_reg = privileged_reg_t.STVEC
            elif mode == privileged_mode_t.USER_MODE:
                trap_vec_reg = privileged_reg_t.UTVEC
            else:
                logging.critical("Unsupported privileged_mode {}".format(mode.name))
                sys.exit(1)

            if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)):
                continue

            if mode < cfg.init_privileged_mode:
                continue

            tvec_name = trap_vec_reg.name
            tvec_name = tvec_name.lower()
            instr.append("la x{}, {}{}_handler".format(
                cfg.gpr[0], pkg_ins.hart_prefix(hart), tvec_name))
            if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE):
                instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20) +
                             "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20))

            instr.append("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode))
            instr.append("csrw {}, x{} # {}".format(
                hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name))

        self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
Пример #4
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)
Пример #5
0
    def pre_enter_privileged_mode(self, hart):
        instr = []
        string = []

        string.append("la x{}, {}kernel_stack_end".format(cfg.tp.value, pkg_ins.hart_prefix(hart)))
        self.gen_section(pkg_ins.get_label("kernel_sp", hart), string)

        if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE):
            self.gen_delegation(hart)
        self.trap_vector_init(hart)
        self.setup_pmp(hart)

        if(cfg.virtual_addr_translation_on):
            self.page_table_list.process_page_table(instr)
            self.gen_section(pkg_ins.get_label("process_pt", hart), instr)
        self.setup_epc(hart)
        self.gen_privileged_mode_switch_routine(hart)
Пример #6
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], 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 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)
        self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
Пример #7
0
 def gen_ecall_handler(self, hart):
     string = ""
     string = pkg_ins.format_string(pkg_ins.get_label(
         "ecall_handler:", hart), pkg_ins.LABEL_STR_LEN)
     self.instr_stream.append(string)
     self.dump_perf_stats()
     self.gen_register_dump()
     string = pkg_ins.format_string(" ", pkg_ins.LABEL_STR_LEN)
     string = string + "j write_tohost"
     self.instr_stream.append(string)
Пример #8
0
    def setup_epc(self, hart):
        instr = []
        instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart)))
        # if(cfg.virtual_addr_translation_on):
        # instr.append("slli x{}, x{}")
        # TODO
        mode_name = cfg.init_privileged_mode
        instr.append("csrw mepc, x{}".format(cfg.gpr[0].value))
        if(not rcs.support_pmp):  # TODO
            instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.name.lower()))

        self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
Пример #9
0
    def gen_kernel_stack_section(self, hart):
        hart_prefix_string = pkg_ins.hart_prefix(hart)
        if(cfg.use_push_data_section):
            self.instr_stream.append(
                ".pushsection .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string))
        else:
            self.instr_stream.append(
                ".section .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string))
        if(rcs.SATP_MODE != "BARE"):
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align 2")

        self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart))
        self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1))
        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
        self.instr_stream.append(".endr")
        self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart))
        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
        if (cfg.use_push_data_section):
            self.instr_stream.push_back(".popsection;")
Пример #10
0
 def setup_epc(self, hart):
     instr = []
     instr.append("la x{}, {}init".format(cfg.gpr[0], pkg_ins.hart_prefix(hart)))
     if cfg.virtual_addr_translation_on:
         # For supervisor and user mode, use virtual address instead of physical address.
         # Virtual address starts from address 0x0, here only the lower 12 bits are kept
         # as virtual address offset.
         instr.append("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12) +
                      "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12))
     mode_name = cfg.init_privileged_mode.name
     instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0]))
     if not rcs.support_pmp:
         instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower()))
     self.gen_section(pkg_ins.get_label("mepc_setup", 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)
Пример #12
0
 def gen_init_section(self, hart):
     string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
     self.instr_stream.append(string)
     if cfg.enable_floating_point:
         self.init_floating_point_gpr()
     self.init_gpr()
     # Init stack pointer to point to the end of the user stack
     string = "{}la x{}, {}user_stack_end".format(
         pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart))
     self.instr_stream.append(string)
     if cfg.enable_vector_extension:
         self.init_vector_engine()
     self.core_is_initialized()
     self.gen_dummy_csr_write()
     if rcs.support_pmp:
         string = pkg_ins.indent + "j main"
         self.instr_stream.append(string)
 def gen_illegal_instr_handler(self, hart):
     instr = []
     self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
                                  core_status_t.ILLEGAL_INSTR_EXCEPTION)
     self.gen_signature_handshake(instr, signature_type_t.WRITE_CSR,
                                  privileged_reg_t.MCAUSE)
     instr.extend(("csrr  x{}, {}".format(cfg.gpr[0],
                                          hex(privileged_reg_t.MEPC)),
                   "addi  x{}, x{}, 4".format(cfg.gpr[0], cfg.gpr[0]),
                   "csrw  {}, x{}".format(hex(privileged_reg_t.MEPC),
                                          cfg.gpr[0])))
     pkg_ins.pop_gpr_from_kernel_stack(privileged_reg_t.MSTATUS,
                                       privileged_reg_t.MSCRATCH,
                                       cfg.mstatus_mprv, cfg.sp, cfg.tp,
                                       instr)
     instr.append("mret")
     self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart),
                      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)
Пример #15
0
    def gen_program(self):
        # Generate program header
        self.instr_stream.clear()
        self.gen_program_header()
        for hart in range(cfg.num_of_harts):
            # Commenting out for now
            # sub_program_name = []
            self.instr_stream.append(f"h{int(hart)}_start:")
            if(not(cfg.bare_program_mode)):
                self.setup_misa()
                # Create all page tables
                self.create_page_table(hart)
                # Setup privileged mode registers and enter target privileged mode
                self.pre_enter_privileged_mode(hart)
            # Init section
            self.gen_init_section(hart)
            # To DO
            '''
            If PMP is supported, we want to generate the associated trap handlers and the test_done
            section at the start of the program so we can allow access through the pmpcfg0 CSR
            '''
            if(rcs.support_pmp and not(cfg.bare_program_mode)):
                self.gen_trap_handlers(hart)
                # Ecall handler
                self.gen_ecall_handler(hart)
                # Instruction fault handler
                self.gen_instr_fault_handler(hart)
                # Load fault handler
                self.gen_load_fault_handler(hart)
                # Store fault handler
                self.gen_store_fault_handler(hart)
                self.gen_test_done()

            # Generate main program
            gt_lbl_str = pkg_ins.get_label("main", hart)
            gt_lbl_str = riscv_instr_sequence()
            self.main_program.append(gt_lbl_str)
            self.main_program[hart].instr_cnt = cfg.main_program_instr_cnt
            self.main_program[hart].is_debug_program = 0
            self.main_program[hart].label_name = "main"
            self.main_program[hart].gen_instr(is_main_program = 1, no_branch = cfg.no_branch_jump)

            self.main_program[hart].generate_instr_stream()
            logging.info("Generating main program instruction stream...done")
            self.instr_stream.extend(self.main_program[hart].instr_string_list)
            """
            If PMP is supported, need to jump from end of main program
            to test_done section at the end of main_program, as the test_done
            will have moved to the beginning of the program
            """
            self.instr_stream.append("{}j test_done".format(pkg_ins.indent))
            '''
            Test done section
            If PMP isn't supported, generate this in the normal location
            '''
            if(hart == 0 and not(rcs.support_pmp)):
                self.gen_test_done()

            logging.info("Main/sub program generation...done")
            # program end
            self.gen_program_end(hart)
            for hart in range(cfg.num_of_harts):
                self.gen_data_page_begin(hart)
                if(cfg.no_data_page):
                    self.gen_data_page()

                    if((hart == 0) and ("RV32A" in rcs.supported_isa)):
                        self.gen_data_page(hart, amo = 1)

            self.gen_stack_section(hart)
            if(not cfg.bare_program_mode):
                self.gen_kernel_sections(hart)
Пример #16
0
    def gen_interrupt_handler_section(self, mode, hart):
        interrupt_handler_instr = []
        ls_unit = "w" if (rcs.XLEN == 32) else "d"
        # TODO
        # if(mode.value < cfg.init_privileged_mode):
        # return
        if(mode is privileged_mode_t.USER_MODE.name and not (rcs.support_umode_trap)):
            return
        if(mode == privileged_mode_t.MACHINE_MODE.name):
            mode_prefix = "m"
            status = privileged_reg_t.MSTATUS
            ip = privileged_reg_t.MIP
            ie = privileged_reg_t.MIE
            scratch = privileged_reg_t.MSCRATCH
        elif(mode is privileged_mode_t.SUPERVISOR_MODE.name):
            mode_prefix = "s"
            status = privileged_reg_t.SSTATUS
            ip = privileged_reg_t.SIP
            ie = privileged_reg_t.SIE
            scratch = privileged_reg_t.SSCRATCH
        elif(mode == privileged_mode_t.USER_MODE.name):
            mode_prefix = "u"
            status = privileged_reg_t.USTATUS
            ip = privileged_reg_t.UIP
            ie = privileged_reg_t.UIE
            scratch = privileged_reg_t.USCRATCH
        else:
            logging.critical("Unsupported mode: %0s" % (mode))

        if(cfg.enable_nested_interrupt):
            interrupt_handler_instr.append("csrr x%0d, 0x%0x" % (cfg.gpr[0].value, scratch.value))
            interrupt_handler_instr.append("bgtz x%0d, 1f" % (cfg.gpr[0].value))
            interrupt_handler_instr.append("csrwi 0x%0x, 0x1" % (scratch.value))

            if(status == privileged_reg_t.MSTATUS):
                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 8))
            elif(status == privileged_reg_t.SSTATUS):
                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 2))
            elif(status == privileged_reg_t.USTATUS):
                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 1))
            else:
                logging.critical("Unsupported status %0s" % (status.value))

            interrupt_handler_instr.append("1: csrwi 0x%0x,0" % (scratch.value))

        to_extend_interrupt_hanlder_instr = ["csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
                                                                           status.value,
                                                                           status.name),
                                             "csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
                                                                           ie.value, ie.name),
                                             "csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
                                                                           ip.value, ip.name),
                                             "csrrc x%0d, 0x%0x, x%0d # %0s;" % (cfg.gpr[0].value,
                                                                                 ip.value,
                                                                                 cfg.gpr[0].value,
                                                                                 ip.name)]
        interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
        self.gen_plic_section(interrupt_handler_instr)
        pkg_ins.pop_gpr_from_kernel_stack(status.name, scratch.name, cfg.mstatus_mprv,
                                          cfg.sp, cfg.tp, interrupt_handler_instr)
        interrupt_handler_instr.append("%0sret;" % (mode_prefix))

        if(rcs.SATP_MODE != "BARE"):
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align 2")

        self.gen_section(pkg_ins.get_label("%0smode_intr_handler" %
                                           (mode_prefix), hart), interrupt_handler_instr)
    def gen_interrupt_handler_section(self, mode, hart):
        interrupt_handler_instr = []
        # ls_unit = "w" if rcs.XLEN == 32 else "d"
        if mode < cfg.init_privileged_mode:
            return
        if (mode is privileged_mode_t.USER_MODE
                and not (rcs.support_umode_trap)):
            return
        if mode == privileged_mode_t.MACHINE_MODE:
            mode_prefix = "m"
            status = privileged_reg_t.MSTATUS
            ip = privileged_reg_t.MIP
            ie = privileged_reg_t.MIE
            scratch = privileged_reg_t.MSCRATCH
        elif mode is privileged_mode_t.SUPERVISOR_MODE:
            mode_prefix = "s"
            status = privileged_reg_t.SSTATUS
            ip = privileged_reg_t.SIP
            ie = privileged_reg_t.SIE
            scratch = privileged_reg_t.SSCRATCH
        elif mode == privileged_mode_t.USER_MODE:
            mode_prefix = "u"
            status = privileged_reg_t.USTATUS
            ip = privileged_reg_t.UIP
            ie = privileged_reg_t.UIE
            scratch = privileged_reg_t.USCRATCH
        else:
            logging.critical("Unsupported mode: {}".format(mode.name))
            sys.exit(1)

        if cfg.enable_nested_interrupt:
            interrupt_handler_instr.append("csrr x{}, {}".format(
                cfg.gpr[0], hex(scratch)))
            interrupt_handler_instr.append("bgtz x{}, 1f".format(cfg.gpr[0]))
            interrupt_handler_instr.append("csrwi {}, 0x1".format(
                hex(scratch)))

            if status == privileged_reg_t.MSTATUS:
                interrupt_handler_instr.append("csrsi {}, {}".format(
                    hex(status), hex(8)))
            elif status == privileged_reg_t.SSTATUS:
                interrupt_handler_instr.append("csrsi {}, {}".format(
                    hex(status), hex(2)))
            elif status == privileged_reg_t.USTATUS:
                interrupt_handler_instr.append("csrsi {}, {}".format(
                    hex(status), hex(1)))
            else:
                logging.critical("Unsupported status {}".format(status.name))
                sys.exit(1)

            interrupt_handler_instr.append("1: csrwi {},0".format(
                hex(scratch)))

        to_extend_interrupt_hanlder_instr = [
            "csrr  x{}, {} # {};".format(cfg.gpr[0], hex(status), status.name),
            "csrr  x{}, {} # {};".format(cfg.gpr[0], hex(ie), ie.name),
            "csrr  x{}, {} # {};".format(cfg.gpr[0], hex(ip), ip.name),
            "csrrc x{}, {}, x{} # {};".format(cfg.gpr[0], hex(ip), cfg.gpr[0],
                                              ip.name)
        ]
        interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
        self.gen_plic_section(interrupt_handler_instr)
        pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                          cfg.sp, cfg.tp,
                                          interrupt_handler_instr)
        interrupt_handler_instr.append("{}ret;".format(mode_prefix))

        if rcs.SATP_MODE != satp_mode_t.BARE:
            self.instr_stream.append(".align 12")
        else:
            self.instr_stream.append(".align 2")

        self.gen_section(
            pkg_ins.get_label("%0smode_intr_handler" % (mode_prefix), hart),
            interrupt_handler_instr)