mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
lab2打包
This commit is contained in:
126
lab2/朱梓涵24325356/core/CLINT.scala
Normal file
126
lab2/朱梓涵24325356/core/CLINT.scala
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
106
lab2/朱梓涵24325356/core/CSR.scala
Normal file
106
lab2/朱梓涵24325356/core/CSR.scala
Normal file
@@ -0,0 +1,106 @@
|
||||
// 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)
|
||||
|
||||
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
|
||||
|
||||
when(io.clint_access_bundle.direct_write_enable) {
|
||||
|
||||
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) {
|
||||
|
||||
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 := 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
lab2/朱梓涵24325356/core/Execute.scala
Normal file
93
lab2/朱梓涵24325356/core/Execute.scala
Normal file
@@ -0,0 +1,93 @@
|
||||
// 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.{Cat, MuxLookup}
|
||||
import riscv.Parameters
|
||||
|
||||
class Execute extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val reg1_data = Input(UInt(Parameters.DataWidth))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val immediate = Input(UInt(Parameters.DataWidth))
|
||||
val aluop1_source = Input(UInt(1.W))
|
||||
val aluop2_source = Input(UInt(1.W))
|
||||
val csr_reg_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val mem_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val csr_reg_write_data = Output(UInt(Parameters.DataWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
|
||||
val alu = Module(new ALU)
|
||||
val alu_ctrl = Module(new ALUControl)
|
||||
|
||||
alu_ctrl.io.opcode := opcode
|
||||
alu_ctrl.io.funct3 := funct3
|
||||
alu_ctrl.io.funct7 := funct7
|
||||
alu.io.func := alu_ctrl.io.alu_funct
|
||||
alu.io.op1 := Mux(
|
||||
io.aluop1_source === ALUOp1Source.InstructionAddress,
|
||||
io.instruction_address,
|
||||
io.reg1_data,
|
||||
)
|
||||
alu.io.op2 := Mux(
|
||||
io.aluop2_source === ALUOp2Source.Immediate,
|
||||
io.immediate,
|
||||
io.reg2_data,
|
||||
)
|
||||
io.if_jump_flag := opcode === Instructions.jal ||
|
||||
(opcode === Instructions.jalr) ||
|
||||
(opcode === InstructionTypes.B) && MuxLookup(
|
||||
funct3,
|
||||
false.B,
|
||||
IndexedSeq(
|
||||
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
|
||||
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
|
||||
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
|
||||
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
|
||||
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
|
||||
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
|
||||
)
|
||||
)
|
||||
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
|
||||
io.mem_alu_result := alu.io.result
|
||||
|
||||
|
||||
//lab2(CLINTCSR)
|
||||
val uimm = io.instruction(19, 15)
|
||||
io.csr_reg_write_data := MuxLookup(
|
||||
funct3,
|
||||
0.U, // 默认值为0
|
||||
IndexedSeq(
|
||||
|
||||
"b001".U -> io.reg1_data,
|
||||
"b010".U -> (io.csr_reg_read_data | io.reg1_data),
|
||||
"b011".U -> (io.csr_reg_read_data & (~io.reg1_data).asUInt),
|
||||
|
||||
"b101".U -> uimm,
|
||||
"b110".U -> (io.csr_reg_read_data | 8.U),
|
||||
"b111".U -> (io.csr_reg_read_data & io.reg1_data)
|
||||
)
|
||||
)
|
||||
}
|
||||
61
lab2/朱梓涵24325356/core/Timer.scala
Normal file
61
lab2/朱梓涵24325356/core/Timer.scala
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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 peripheral
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
class Timer extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bundle = new RAMBundle
|
||||
val signal_interrupt = Output(Bool())
|
||||
|
||||
val debug_limit = Output(UInt(Parameters.DataWidth))
|
||||
val debug_enabled = Output(Bool())
|
||||
})
|
||||
|
||||
|
||||
val count = RegInit(0.U(32.W))
|
||||
val limit = RegInit(100000000.U(32.W))
|
||||
io.debug_limit := limit
|
||||
val enabled = RegInit(true.B)
|
||||
io.debug_enabled := enabled
|
||||
|
||||
//lab2(CLINTCSR)
|
||||
val address = io.bundle.address
|
||||
io.bundle.read_data := 0.U
|
||||
when(address === 0x4.U) {
|
||||
io.bundle.read_data := limit
|
||||
}.elsewhen(address === 0x8.U) {
|
||||
io.bundle.read_data := enabled
|
||||
}
|
||||
|
||||
when(io.bundle.write_enable) {
|
||||
when(address === 0x4.U) {
|
||||
limit := io.bundle.write_data
|
||||
}.elsewhen(address === 0x8.U) {
|
||||
enabled := io.bundle.write_data(0)
|
||||
}
|
||||
}
|
||||
|
||||
when(enabled && count >= limit) {
|
||||
io.signal_interrupt := true.B
|
||||
count := 0.U
|
||||
}.otherwise {
|
||||
io.signal_interrupt := false.B
|
||||
count := count + 1.U
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user