mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
126 lines
4.5 KiB
Scala
126 lines
4.5 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)
|
|
|
|
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)
|
|
)
|
|
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
|
|
}
|
|
} |