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