• 【RISC-V设计-09】- RISC-V处理器设计K0A之CIC


    【RISC-V设计-09】- RISC-V处理器设计K0A之CIC

    1.简介

    核内中断控制器(Core Interrupt Controller,简称CIC)是管理和仲裁中断的模块,能够根据预设的优先级规则,逐一上报中断请求的序号。本模块具有如下几点功能:

    1. 根据全局中断使能,控制中断序号的上报;
    2. 根据独立中断使能,控制对应的中断请求;
    3. 记录中断状态,根据中断状态向指令译码单元发出中断请求;
    4. 根据指令译码单元发出中断应答,清除中断请求;
    5. 通过软件、硬件结合的方式,支持晚到中断、咬尾中断;

    2.顶层设计

    3.端口说明

    序号端口位宽方向说明
    1core_clk1input内核时钟
    2core_rstn1input内核复位信号,低有效
    3irq_lines16input外部中断信号,高电平/脉冲触发
    4csr2cic_gie1input全局中断使能
    5csr2cic_mie16input独立控制的中断使能
    6csr2cic_mip16input中断请求等待
    7cic2csr_irq16output外部中断信号,高电平/脉冲触发
    8cic2csr_mcause5output中断原因记录
    9cic2idu_int_req1output向译码单元发送的中断请求
    10idu2cic_int_ack1input译码单元返回的中断应答
    11idu2cic_int_mret1input译码单元执行中断返回指令

    4.代码设计

    // -------------------------------------------------------------------------------------------------
    // Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    // 
    //     http://www.apache.org/licenses/LICENSE-2.0
    // 
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    // -------------------------------------------------------------------------------------------------
    // Description :
    //             1. Core Interrupt Controller
    // -------------------------------------------------------------------------------------------------
    
    module k0a_core_cic (
        input  wire         core_clk        ,
        input  wire         core_rstn       ,
    
        input  wire [15:0]  irq_lines       ,
    
        input  wire         csr2cic_gie     ,
        input  wire [15:0]  csr2cic_mie     ,
        input  wire [15:0]  csr2cic_mip     ,
        output wire [15:0]  cic2csr_irq     ,
        output reg  [4:0]   cic2csr_mcause  ,
    
        output reg          cic2idu_int_req ,
        input  wire         idu2cic_int_ack ,
        input  wire         idu2cic_int_mret
    );
    
    reg     status_irq;
    
    wire cic_int_hit = cic2idu_int_req & idu2cic_int_ack;
    
    wire [15:0] irq_src = csr2cic_mip & csr2cic_mie;
    
    assign cic2csr_irq = irq_lines;
    
    always @(posedge core_clk or negedge core_rstn)
    begin
        if(!core_rstn)
            status_irq <= 1'b0;
        else if(cic_int_hit)
            status_irq <= 1'b1;
        else if(idu2cic_int_mret)
            status_irq <= 1'b0;
    end
    
    always @(posedge core_clk)
    begin
        if(csr2cic_gie) begin
            case(1'b1)
                irq_src[ 0] : cic2csr_mcause <= {1'b1, 4'h0};
                irq_src[ 1] : cic2csr_mcause <= {1'b1, 4'h1};
                irq_src[ 2] : cic2csr_mcause <= {1'b1, 4'h2};
                irq_src[ 3] : cic2csr_mcause <= {1'b1, 4'h3};
                irq_src[ 4] : cic2csr_mcause <= {1'b1, 4'h4};
                irq_src[ 5] : cic2csr_mcause <= {1'b1, 4'h5};
                irq_src[ 6] : cic2csr_mcause <= {1'b1, 4'h6};
                irq_src[ 7] : cic2csr_mcause <= {1'b1, 4'h7};
                irq_src[ 8] : cic2csr_mcause <= {1'b1, 4'h8};
                irq_src[ 9] : cic2csr_mcause <= {1'b1, 4'h9};
                irq_src[10] : cic2csr_mcause <= {1'b1, 4'ha};
                irq_src[11] : cic2csr_mcause <= {1'b1, 4'hb};
                irq_src[12] : cic2csr_mcause <= {1'b1, 4'hc};
                irq_src[13] : cic2csr_mcause <= {1'b1, 4'hd};
                irq_src[14] : cic2csr_mcause <= {1'b1, 4'he};
                irq_src[15] : cic2csr_mcause <= {1'b1, 4'hf};
                default     : cic2csr_mcause <= 5'd0;
            endcase
        end
    end
    
    always @(posedge core_clk or negedge core_rstn)
    begin
        if(!core_rstn)
            cic2idu_int_req <= 1'b0;
        else if(cic_int_hit)
            cic2idu_int_req <= 1'b0;
        else if(~status_irq & (|irq_src))
            cic2idu_int_req <= 1'b1;
    end
    
    endmodule
    

    5.仲裁代码

    # -------------------------------------------------------------------------------------------------
    # Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    # 
    #     http://www.apache.org/licenses/LICENSE-2.0
    # 
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    # -------------------------------------------------------------------------------------------------
    
    	.section .init, "ax", @progbits
    	.globl  _start
    	.align  2
    _start:
    	.option norvc;
        j       handler_reset
        .word   handler_irq0
        .word   handler_irq1
        .word   handler_irq2
        .word   handler_irq3
        .word   handler_irq4
        .word   handler_irq5
        .word   handler_irq6
        .word   handler_irq7
        .word   handler_irq8
        .word   handler_irq9
        .word   handler_irq10
        .word   handler_irq11
        .word   handler_irq12
        .word   handler_irq13
        .word   handler_irq14
        .word   handler_irq15
    
    	.section .text.handler_isr, "ax", @progbits
    	.align    2
    handler_isr:
        addi sp, sp, -56
        sw x1 , 0(sp)
        sw x4 , 4(sp)
        sw x5 , 8(sp)
        sw x6 , 12(sp)
        sw x7 , 16(sp)
        sw x8 , 20(sp)
        sw x9 , 24(sp)
        sw x10, 28(sp)
        sw x11, 32(sp)
        sw x12, 36(sp)
        sw x13, 40(sp)
        sw x14, 44(sp)
        sw x15, 48(sp)
    1:
        csrr a0, mcause
        beq x0, a0, 2f
        andi a0, a0, 15
        addi a1, x0, 1
        sll a2, a1, a0
        csrrc a2, mip, a2
        slli a0, a0, 2
        lw a1, 4(a0)
        jalr ra, a1, 0
        jal x0, 1b
    2:
        lw x15, 48(sp)
        lw x14, 44(sp)
        lw x13, 40(sp)
        lw x12, 36(sp)
        lw x11, 32(sp)
        lw x10, 28(sp)
        lw x9 , 24(sp)
        lw x8 , 20(sp)
        lw x7 , 16(sp)
        lw x6 , 12(sp)
        lw x5 , 8(sp)
        lw x4 , 4(sp)
        lw x1 , 0(sp)
        addi sp, sp, 56
        mret
    
    	.section .text.handler_default, "ax", @progbits
    	.align    2
    	.weak   handler_irq0
    	.weak   handler_irq1
    	.weak   handler_irq2
    	.weak   handler_irq3
    	.weak   handler_irq4
    	.weak   handler_irq5
    	.weak   handler_irq6
    	.weak   handler_irq7
    	.weak   handler_irq8
    	.weak   handler_irq9
    	.weak   handler_irq10
    	.weak   handler_irq11
    	.weak   handler_irq12
    	.weak   handler_irq13
    	.weak   handler_irq14
    	.weak   handler_irq15
    handler_irq0:
    handler_irq1:
    handler_irq2:
    handler_irq3:
    handler_irq4:
    handler_irq5:
    handler_irq6:
    handler_irq7:
    handler_irq8:
    handler_irq9:
    handler_irq10:
    handler_irq11:
    handler_irq12:
    handler_irq13:
    handler_irq14:
    handler_irq15:
    loop_isr:
    	j loop_isr
    
    	.section  .text.handler_reset, "ax", @progbits
    	.align    2
    handler_reset:
    .option push
    .option norelax
    	la gp, __global_pointer$
    .option pop
    1:
    	la sp, _eusrstack
    2:
    	la a0, _data_lma
    	la a1, _data_vma
    	la a2, _edata
    	bgeu a1, a2, 2f
    1:
    	lw a3, 0(a0)
    	sw a3, 0(a1)
    	addi a0, a0, 4
    	addi a1, a1, 4
    	bgeu a1, a2, 2f
    	lw a3, 0(a0)
    	sw a3, 0(a1)
    	addi a0, a0, 4
    	addi a1, a1, 4
    	bltu a1, a2, 1b
    2:
        la a0, _sbss
        la a1, _ebss
        bgeu a0, a1, 2f
    1:
        sw x0, 0(a0)
        addi a0, a0, 4
        bgeu a0, a1, 2f
        sw x0, 0(a0)
        addi a0, a0, 4
        bgeu a0, a1, 2f
        sw x0, 0(a0)
        addi a0, a0, 4
        bltu a0, a1, 1b
    2:
        la a3, handler_isr
        csrw mtvec, a3
    
        j main
    

    这段代码是开始运行时初始化的代码,同时还存在中断处理相关的操作,通过读取中断原因、进行一些位操作确定中断序号。如果中断原因不为 0,根据中断序号查找到中断向量表,跳转到特定的地址执行相应的中断处理程序。

    6.总结

    本文阐述了一种极为简洁的中断控制模块。该模块采用软件与硬件相结合的方式,来达成中断的处理。并且,它还能够支持晚到中断和咬尾中断,一次进出栈就能够处置多个现存的中断。如此一来,节省了中断处理的时间,提高了中断处理的效率。

  • 相关阅读:
    MySQL基于GTID搭建主从
    为什么有的测试员路越走越窄?原因在这里
    深度学习基础知识 最近邻插值法、双线性插值法、双三次插值算法
    基于北方苍鹰算法的无人机航迹规划-附代码
    NFC隐藏功能大公开:乘车刷门禁,NFC实用无风险
    网络通信错误代码列表 HTTP 、FTP
    python_爬虫
    groupnorm_backward反向公式推导
    vue安装使用swiper
    C#基础总结三
  • 原文地址:https://blog.csdn.net/kearnchen/article/details/141037831