Files
2025-yatcpu/lab2/朱梓涵24325356/scala/riscv/core/CLINT.scala
2025-11-18 20:25:21 +08:00

129 lines
4.8 KiB
Scala

// Copyright 2021 Howard Lau
//
// 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.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object InterruptCode {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
object InterruptEntry {
val Timer0 = 0x4.U(8.W)
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data= Output(UInt(Parameters.DataWidth))
val mepc_write_data= Output(UInt(Parameters.DataWidth))
val mcause_write_data= Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
// Interrupt signals from peripherals
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
io.instruction_address + 4.U,
)
//lab2(CLINTCSR)
val mstatus = io.csr_bundle.mstatus
val mie = mstatus(3)
val mpie = mstatus(7)
// 优先级顺序至关重要:
// 1. 外部硬件中断具有最高优先级,可以“覆盖”当前指令的行为。
// 2. 如果没有外部中断,再判断当前指令是否是陷阱指令 (mret, ecall, ebreak)。
when(io.interrupt_flag =/= InterruptCode.None && interrupt_enable) {
// 处理硬件中断 (最高优先级)
io.interrupt_assert := true.B
io.csr_bundle.direct_write_enable := true.B
io.interrupt_handler_address := io.csr_bundle.mtvec // 跳转到中断向量
io.csr_bundle.mepc_write_data := instruction_address // 保存下一条指令地址
io.csr_bundle.mcause_write_data := Mux(
io.interrupt_flag === InterruptCode.Timer0,
"h80000007".U(Parameters.DataWidth),
"h8000000B".U(Parameters.DataWidth)
)
// 更新 mstatus: MIE <- 0, MPIE <- MIE
val new_mpie = mie << 7
io.csr_bundle.mstatus_write_data := (mstatus & (~(1.U << 3)).asUInt) | new_mpie | (3.U << 11)
}.elsewhen(io.instruction === InstructionsRet.mret) {
// 处理 mret
io.interrupt_assert := true.B
io.csr_bundle.direct_write_enable := true.B
io.interrupt_handler_address := io.csr_bundle.mepc // 跳转回 mepc
// mstatus 更新: MIE <- MPIE, MPIE <- 1
val new_mie = mpie << 3
io.csr_bundle.mstatus_write_data := (mstatus & (~(1.U << 7)).asUInt) | new_mie | (1.U << 7) | (3.U << 11)
// mret 不更新 mepc 和 mcause
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
}.elsewhen(io.instruction === InstructionsEnv.ecall) {
// 处理 ecall
io.interrupt_assert := true.B
io.csr_bundle.direct_write_enable := true.B
io.interrupt_handler_address := io.csr_bundle.mtvec
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := 11.U
val new_mpie = mie << 7
io.csr_bundle.mstatus_write_data := (mstatus & (~(1.U << 3)).asUInt) | new_mpie | (3.U << 11)
}.elsewhen(io.instruction === InstructionsEnv.ebreak) {
// 处理 ebreak
io.interrupt_assert := true.B
io.csr_bundle.direct_write_enable := true.B
io.interrupt_handler_address := io.csr_bundle.mtvec
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := 3.U
val new_mpie = mie << 7
io.csr_bundle.mstatus_write_data := (mstatus & (~(1.U << 3)).asUInt) | new_mpie | (3.U << 11)
}.otherwise {
// 默认情况,所有信号都设为默认值
io.interrupt_assert := false.B
io.csr_bundle.direct_write_enable := false.B
io.interrupt_handler_address := 0.U
io.csr_bundle.mstatus_write_data := mstatus
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
}
}