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

108 lines
4.8 KiB
Scala
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 CSRRegister {
// Refer to Spec. Vol.II Page 8-10
val MSTATUS = 0x300.U(Parameters.CSRRegisterAddrWidth)
val MIE = 0x304.U(Parameters.CSRRegisterAddrWidth)
val MTVEC = 0x305.U(Parameters.CSRRegisterAddrWidth)
val MSCRATCH = 0x340.U(Parameters.CSRRegisterAddrWidth)
val MEPC = 0x341.U(Parameters.CSRRegisterAddrWidth)
val MCAUSE = 0x342.U(Parameters.CSRRegisterAddrWidth)
val CycleL = 0xc00.U(Parameters.CSRRegisterAddrWidth)
val CycleH = 0xc80.U(Parameters.CSRRegisterAddrWidth)
}
class CSR extends Module {
val io = IO(new Bundle {
val reg_read_address_id = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_enable_id= Input(Bool())
val reg_write_address_id = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_data_ex= Input(UInt(Parameters.DataWidth))
val debug_reg_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val debug_reg_read_data = Output(UInt(Parameters.DataWidth))
val reg_read_data = Output(UInt(Parameters.DataWidth))
val clint_access_bundle = Flipped(new CSRDirectAccessBundle)
})
val mstatus = RegInit(UInt(Parameters.DataWidth), 0.U)
val mie = RegInit(UInt(Parameters.DataWidth), 0.U)
val mtvec = RegInit(UInt(Parameters.DataWidth), 0.U)
val mscratch = RegInit(UInt(Parameters.DataWidth), 0.U)
val mepc = RegInit(UInt(Parameters.DataWidth), 0.U)
val mcause = RegInit(UInt(Parameters.DataWidth), 0.U)
val cycles = RegInit(UInt(64.W), 0.U)
val regLUT =
IndexedSeq(
CSRRegister.MSTATUS -> mstatus,
CSRRegister.MIE -> mie,
CSRRegister.MTVEC -> mtvec,
CSRRegister.MSCRATCH -> mscratch,
CSRRegister.MEPC -> mepc,
CSRRegister.MCAUSE -> mcause,
CSRRegister.CycleL -> cycles(31, 0),
CSRRegister.CycleH -> cycles(63, 32),
)
cycles := cycles + 1.U
// If the pipeline and the CLINT are going to read and write the CSR at the same time, let the pipeline write first.
// This is implemented in a single cycle by passing reg_write_data_ex to clint and writing the data from the CLINT to the CSR.
io.reg_read_data := MuxLookup(io.reg_read_address_id, 0.U, regLUT)
io.debug_reg_read_data := MuxLookup(io.debug_reg_read_address, 0.U,regLUT)
//lab2(CLINTCSR)
val mstatus_next = Mux(io.reg_write_enable_id && io.reg_write_address_id === CSRRegister.MSTATUS, io.reg_write_data_ex, mstatus)
val mepc_next = Mux(io.reg_write_enable_id && io.reg_write_address_id === CSRRegister.MEPC, io.reg_write_data_ex, mepc)
val mcause_next = Mux(io.reg_write_enable_id && io.reg_write_address_id === CSRRegister.MCAUSE, io.reg_write_data_ex, mcause)
val mtvec_next = Mux(io.reg_write_enable_id && io.reg_write_address_id === CSRRegister.MTVEC, io.reg_write_data_ex, mtvec)
// 步骤2将计算好的 "next" 值连接到CLINT的访问端口
io.clint_access_bundle.mstatus := mstatus_next
io.clint_access_bundle.mepc := mepc_next
io.clint_access_bundle.mcause := mcause_next
io.clint_access_bundle.mtvec := mtvec_next
// 步骤3在下一个时钟上升沿更新所有CSR寄存器。
// 这里的逻辑必须统一确保正确的优先级CLINT写入 > 流水线写入
when(io.clint_access_bundle.direct_write_enable) {
// CLINT的写入拥有最高优先级用于陷阱处理
mstatus := io.clint_access_bundle.mstatus_write_data
mepc := io.clint_access_bundle.mepc_write_data
mcause := io.clint_access_bundle.mcause_write_data
}.elsewhen(io.reg_write_enable_id) {
// 如果CLINT不写入则处理来自流水线的正常CSR指令写入
when(io.reg_write_address_id === CSRRegister.MSTATUS) {
mstatus := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MEPC) {
mepc := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MCAUSE) {
mcause := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MTVEC) { // <-- 把MTVEC合并到这里
mtvec := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MIE) {
mie := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MSCRATCH) {
mscratch := io.reg_write_data_ex
}
}
}