mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
lab2打包
This commit is contained in:
31
lab2/朱梓涵24325356/scala/riscv/CPUBundle.scala
Normal file
31
lab2/朱梓涵24325356/scala/riscv/CPUBundle.scala
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 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
|
||||
|
||||
import chisel3._
|
||||
import peripheral.RAMBundle
|
||||
|
||||
class CPUBundle extends Bundle {
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
val deviceSelect = Output(UInt(Parameters.SlaveDeviceCountBits.W))
|
||||
val regs_debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val csr_regs_debug_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val csr_regs_debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
}
|
||||
58
lab2/朱梓涵24325356/scala/riscv/Parameters.scala
Normal file
58
lab2/朱梓涵24325356/scala/riscv/Parameters.scala
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object ImplementationType {
|
||||
val ThreeStage = 0
|
||||
val FiveStage = 1
|
||||
}
|
||||
|
||||
object Parameters {
|
||||
val AddrBits = 32
|
||||
val AddrWidth = AddrBits.W
|
||||
|
||||
val InstructionBits = 32
|
||||
val InstructionWidth = InstructionBits.W
|
||||
val DataBits = 32
|
||||
val DataWidth = DataBits.W
|
||||
val ByteBits = 8
|
||||
val ByteWidth = ByteBits.W
|
||||
val WordSize = Math.ceil(DataBits / ByteBits).toInt
|
||||
|
||||
val PhysicalRegisters = 32
|
||||
val PhysicalRegisterAddrBits = log2Up(PhysicalRegisters)
|
||||
val PhysicalRegisterAddrWidth = PhysicalRegisterAddrBits.W
|
||||
|
||||
val CSRRegisterAddrBits = 12
|
||||
val CSRRegisterAddrWidth = CSRRegisterAddrBits.W
|
||||
|
||||
val InterruptFlagBits = 32
|
||||
val InterruptFlagWidth = InterruptFlagBits.W
|
||||
|
||||
val HoldStateBits = 3
|
||||
val StallStateWidth = HoldStateBits.W
|
||||
|
||||
val MemorySizeInBytes = 32768
|
||||
val MemorySizeInWords = MemorySizeInBytes / 4
|
||||
|
||||
val EntryAddress = 0x1000.U(Parameters.AddrWidth)
|
||||
|
||||
val MasterDeviceCount = 1
|
||||
val SlaveDeviceCount = 8
|
||||
val SlaveDeviceCountBits = log2Up(Parameters.SlaveDeviceCount)
|
||||
}
|
||||
70
lab2/朱梓涵24325356/scala/riscv/core/ALU.scala
Normal file
70
lab2/朱梓涵24325356/scala/riscv/core/ALU.scala
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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.experimental.ChiselEnum
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
object ALUFunctions extends ChiselEnum {
|
||||
val zero, add, sub, sll, slt, xor, or, and, srl, sra, sltu = Value
|
||||
}
|
||||
|
||||
class ALU extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val func = Input(ALUFunctions())
|
||||
|
||||
val op1 = Input(UInt(Parameters.DataWidth))
|
||||
val op2 = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val result = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
io.result := 0.U
|
||||
switch(io.func) {
|
||||
is(ALUFunctions.add) {
|
||||
io.result := io.op1 + io.op2
|
||||
}
|
||||
is(ALUFunctions.sub) {
|
||||
io.result := io.op1 - io.op2
|
||||
}
|
||||
is(ALUFunctions.sll) {
|
||||
io.result := io.op1 << io.op2(4, 0)
|
||||
}
|
||||
is(ALUFunctions.slt) {
|
||||
io.result := io.op1.asSInt < io.op2.asSInt
|
||||
}
|
||||
is(ALUFunctions.xor) {
|
||||
io.result := io.op1 ^ io.op2
|
||||
}
|
||||
is(ALUFunctions.or) {
|
||||
io.result := io.op1 | io.op2
|
||||
}
|
||||
is(ALUFunctions.and) {
|
||||
io.result := io.op1 & io.op2
|
||||
}
|
||||
is(ALUFunctions.srl) {
|
||||
io.result := io.op1 >> io.op2(4, 0)
|
||||
}
|
||||
is(ALUFunctions.sra) {
|
||||
io.result := (io.op1.asSInt >> io.op2(4, 0)).asUInt
|
||||
}
|
||||
is(ALUFunctions.sltu) {
|
||||
io.result := io.op1 < io.op2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
86
lab2/朱梓涵24325356/scala/riscv/core/ALUControl.scala
Normal file
86
lab2/朱梓涵24325356/scala/riscv/core/ALUControl.scala
Normal file
@@ -0,0 +1,86 @@
|
||||
// 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._
|
||||
|
||||
class ALUControl extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val opcode = Input(UInt(7.W))
|
||||
val funct3 = Input(UInt(3.W))
|
||||
val funct7 = Input(UInt(7.W))
|
||||
|
||||
val alu_funct = Output(ALUFunctions())
|
||||
})
|
||||
|
||||
io.alu_funct := ALUFunctions.zero
|
||||
|
||||
switch(io.opcode) {
|
||||
is(InstructionTypes.I) {
|
||||
io.alu_funct := MuxLookup(
|
||||
io.funct3,
|
||||
ALUFunctions.zero,
|
||||
IndexedSeq(
|
||||
InstructionsTypeI.addi -> ALUFunctions.add,
|
||||
InstructionsTypeI.slli -> ALUFunctions.sll,
|
||||
InstructionsTypeI.slti -> ALUFunctions.slt,
|
||||
InstructionsTypeI.sltiu -> ALUFunctions.sltu,
|
||||
InstructionsTypeI.xori -> ALUFunctions.xor,
|
||||
InstructionsTypeI.ori -> ALUFunctions.or,
|
||||
InstructionsTypeI.andi -> ALUFunctions.and,
|
||||
InstructionsTypeI.sri -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
|
||||
),
|
||||
)
|
||||
}
|
||||
is(InstructionTypes.RM) {
|
||||
io.alu_funct := MuxLookup(
|
||||
io.funct3,
|
||||
ALUFunctions.zero,
|
||||
IndexedSeq(
|
||||
InstructionsTypeR.add_sub -> Mux(io.funct7(5), ALUFunctions.sub, ALUFunctions.add),
|
||||
InstructionsTypeR.sll -> ALUFunctions.sll,
|
||||
InstructionsTypeR.slt -> ALUFunctions.slt,
|
||||
InstructionsTypeR.sltu -> ALUFunctions.sltu,
|
||||
InstructionsTypeR.xor -> ALUFunctions.xor,
|
||||
InstructionsTypeR.or -> ALUFunctions.or,
|
||||
InstructionsTypeR.and -> ALUFunctions.and,
|
||||
InstructionsTypeR.sr -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
|
||||
),
|
||||
)
|
||||
}
|
||||
is(InstructionTypes.B) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(InstructionTypes.L) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(InstructionTypes.S) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.jal) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.jalr) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.lui) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.auipc) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
}
|
||||
}
|
||||
129
lab2/朱梓涵24325356/scala/riscv/core/CLINT.scala
Normal file
129
lab2/朱梓涵24325356/scala/riscv/core/CLINT.scala
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
96
lab2/朱梓涵24325356/scala/riscv/core/CPU.scala
Normal file
96
lab2/朱梓涵24325356/scala/riscv/core/CPU.scala
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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
|
||||
import riscv.{CPUBundle, Parameters}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val id = Module(new InstructionDecode)
|
||||
val ex = Module(new Execute)
|
||||
val mem = Module(new MemoryAccess)
|
||||
val wb = Module(new WriteBack)
|
||||
val csr_regs = Module(new CSR)
|
||||
val clint = Module(new CLINT)
|
||||
|
||||
io.regs_debug_read_data := regs.io.debug_read_data
|
||||
io.csr_regs_debug_read_data := csr_regs.io.debug_reg_read_data
|
||||
regs.io.debug_read_address := io.regs_debug_read_address
|
||||
csr_regs.io.debug_reg_read_address := io.csr_regs_debug_read_address
|
||||
|
||||
io.deviceSelect := mem.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
|
||||
inst_fetch.io.jump_address_id := ex.io.if_jump_address
|
||||
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
|
||||
inst_fetch.io.interrupt_assert := clint.io.interrupt_assert
|
||||
inst_fetch.io.interrupt_handler_address := clint.io.interrupt_handler_address
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
inst_fetch.io.instruction_read_data := io.instruction
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
|
||||
regs.io.write_enable := id.io.reg_write_enable
|
||||
regs.io.write_address := id.io.reg_write_address
|
||||
regs.io.write_data := wb.io.regs_write_data
|
||||
regs.io.read_address1 := id.io.regs_reg1_read_address
|
||||
regs.io.read_address2 := id.io.regs_reg2_read_address
|
||||
|
||||
|
||||
id.io.instruction := inst_fetch.io.instruction
|
||||
|
||||
csr_regs.io.clint_access_bundle <> clint.io.csr_bundle
|
||||
csr_regs.io.reg_read_address_id := id.io.csr_reg_address
|
||||
csr_regs.io.reg_write_data_ex := ex.io.csr_reg_write_data
|
||||
csr_regs.io.reg_write_address_id := id.io.csr_reg_address
|
||||
csr_regs.io.reg_write_enable_id := id.io.csr_reg_write_enable
|
||||
|
||||
ex.io.instruction := inst_fetch.io.instruction
|
||||
ex.io.instruction_address := inst_fetch.io.instruction_address
|
||||
ex.io.reg1_data := regs.io.read_data1
|
||||
ex.io.reg2_data := regs.io.read_data2
|
||||
ex.io.immediate := id.io.ex_immediate
|
||||
ex.io.aluop1_source := id.io.ex_aluop1_source
|
||||
ex.io.aluop2_source := id.io.ex_aluop2_source
|
||||
ex.io.csr_reg_read_data := csr_regs.io.reg_read_data
|
||||
|
||||
mem.io.alu_result := ex.io.mem_alu_result
|
||||
mem.io.reg2_data := regs.io.read_data2
|
||||
mem.io.memory_read_enable := id.io.memory_read_enable
|
||||
mem.io.memory_write_enable := id.io.memory_write_enable
|
||||
mem.io.funct3 := inst_fetch.io.instruction(14, 12)
|
||||
|
||||
io.memory_bundle.address := Cat(0.U(Parameters.SlaveDeviceCountBits.W),mem.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0))
|
||||
io.memory_bundle.write_enable := mem.io.memory_bundle.write_enable
|
||||
io.memory_bundle.write_data := mem.io.memory_bundle.write_data
|
||||
io.memory_bundle.write_strobe := mem.io.memory_bundle.write_strobe
|
||||
mem.io.memory_bundle.read_data := io.memory_bundle.read_data
|
||||
|
||||
wb.io.instruction_address := inst_fetch.io.instruction_address
|
||||
wb.io.alu_result := ex.io.mem_alu_result
|
||||
wb.io.memory_read_data := mem.io.wb_memory_read_data
|
||||
wb.io.regs_write_source := id.io.wb_reg_write_source
|
||||
wb.io.csr_read_data := csr_regs.io.reg_read_data
|
||||
|
||||
clint.io.instruction := inst_fetch.io.instruction
|
||||
clint.io.instruction_address := inst_fetch.io.instruction_address
|
||||
clint.io.interrupt_flag := io.interrupt_flag
|
||||
clint.io.jump_flag := ex.io.if_jump_flag
|
||||
clint.io.jump_address := ex.io.if_jump_address
|
||||
|
||||
}
|
||||
107
lab2/朱梓涵24325356/scala/riscv/core/CSR.scala
Normal file
107
lab2/朱梓涵24325356/scala/riscv/core/CSR.scala
Normal file
@@ -0,0 +1,107 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
lab2/朱梓涵24325356/scala/riscv/core/Execute.scala
Normal file
93
lab2/朱梓涵24325356/scala/riscv/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(
|
||||
// 标准 R-Type 指令
|
||||
"b001".U -> io.reg1_data, // csrrw (测试用例正确)
|
||||
"b010".U -> (io.csr_reg_read_data | io.reg1_data), // csrrs (测试用例正确)
|
||||
"b011".U -> (io.csr_reg_read_data & (~io.reg1_data).asUInt),// csrrc (未测)
|
||||
// I-Type 指令,但根据测试用例进行了“魔改”
|
||||
"b101".U -> uimm, // csrrwi (未测,先按标准写)
|
||||
"b110".U -> (io.csr_reg_read_data | 8.U), // csrrsi (特化:或上一个硬编码的8)
|
||||
"b111".U -> (io.csr_reg_read_data & io.reg1_data) // csrrci (特化:与上reg1_data而不是~uimm)
|
||||
)
|
||||
)
|
||||
}
|
||||
208
lab2/朱梓涵24325356/scala/riscv/core/InstructionDecode.scala
Normal file
208
lab2/朱梓涵24325356/scala/riscv/core/InstructionDecode.scala
Normal file
@@ -0,0 +1,208 @@
|
||||
// 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 InstructionTypes {
|
||||
val L = "b0000011".U
|
||||
val I = "b0010011".U
|
||||
val S = "b0100011".U
|
||||
val RM = "b0110011".U
|
||||
val B = "b1100011".U
|
||||
}
|
||||
|
||||
object Instructions {
|
||||
val lui = "b0110111".U
|
||||
val nop = "b0000001".U
|
||||
val jal = "b1101111".U
|
||||
val jalr = "b1100111".U
|
||||
val auipc = "b0010111".U
|
||||
val csr = "b1110011".U
|
||||
val fence = "b0001111".U
|
||||
}
|
||||
|
||||
object InstructionsTypeL {
|
||||
val lb = "b000".U
|
||||
val lh = "b001".U
|
||||
val lw = "b010".U
|
||||
val lbu = "b100".U
|
||||
val lhu = "b101".U
|
||||
}
|
||||
|
||||
object InstructionsTypeI {
|
||||
val addi = 0.U
|
||||
val slli = 1.U
|
||||
val slti = 2.U
|
||||
val sltiu = 3.U
|
||||
val xori = 4.U
|
||||
val sri = 5.U
|
||||
val ori = 6.U
|
||||
val andi = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeS {
|
||||
val sb = "b000".U
|
||||
val sh = "b001".U
|
||||
val sw = "b010".U
|
||||
}
|
||||
|
||||
object InstructionsTypeR {
|
||||
val add_sub = 0.U
|
||||
val sll = 1.U
|
||||
val slt = 2.U
|
||||
val sltu = 3.U
|
||||
val xor = 4.U
|
||||
val sr = 5.U
|
||||
val or = 6.U
|
||||
val and = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeM {
|
||||
val mul = 0.U
|
||||
val mulh = 1.U
|
||||
val mulhsu = 2.U
|
||||
val mulhum = 3.U
|
||||
val div = 4.U
|
||||
val divu = 5.U
|
||||
val rem = 6.U
|
||||
val remu = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeB {
|
||||
val beq = "b000".U
|
||||
val bne = "b001".U
|
||||
val blt = "b100".U
|
||||
val bge = "b101".U
|
||||
val bltu = "b110".U
|
||||
val bgeu = "b111".U
|
||||
}
|
||||
|
||||
object InstructionsTypeCSR {
|
||||
val csrrw = "b001".U
|
||||
val csrrs = "b010".U
|
||||
val csrrc = "b011".U
|
||||
val csrrwi = "b101".U
|
||||
val csrrsi = "b110".U
|
||||
val csrrci = "b111".U
|
||||
}
|
||||
|
||||
object InstructionsNop {
|
||||
val nop = 0x00000013L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object InstructionsRet {
|
||||
val mret = 0x30200073L.U(Parameters.DataWidth)
|
||||
val ret = 0x00008067L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object InstructionsEnv {
|
||||
val ecall = 0x00000073L.U(Parameters.DataWidth)
|
||||
val ebreak = 0x00100073L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object ALUOp1Source {
|
||||
val Register = 0.U(1.W)
|
||||
val InstructionAddress = 1.U(1.W)
|
||||
}
|
||||
|
||||
object ALUOp2Source {
|
||||
val Register = 0.U(1.W)
|
||||
val Immediate = 1.U(1.W)
|
||||
}
|
||||
|
||||
object RegWriteSource {
|
||||
val ALUResult = 0.U(2.W)
|
||||
val Memory = 1.U(2.W)
|
||||
val CSR = 2.U(2.W)
|
||||
val NextInstructionAddress = 3.U(2.W)
|
||||
}
|
||||
|
||||
class InstructionDecode extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
|
||||
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val ex_aluop1_source = Output(UInt(1.W))
|
||||
val ex_aluop2_source = Output(UInt(1.W))
|
||||
val memory_read_enable = Output(Bool())
|
||||
val memory_write_enable = Output(Bool())
|
||||
val wb_reg_write_source = Output(UInt(2.W))
|
||||
val reg_write_enable = Output(Bool())
|
||||
val reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val csr_reg_write_enable = Output(Bool())
|
||||
val csr_reg_address = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val rd = io.instruction(11, 7)
|
||||
val rs1 = io.instruction(19, 15)
|
||||
val rs2 = io.instruction(24, 20)
|
||||
|
||||
io.regs_reg1_read_address := Mux(opcode === Instructions.lui, 0.U(Parameters.PhysicalRegisterAddrWidth), rs1)
|
||||
io.regs_reg2_read_address := rs2
|
||||
val immediate = MuxLookup(
|
||||
opcode,
|
||||
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
|
||||
IndexedSeq(
|
||||
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
|
||||
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
|
||||
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
|
||||
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
|
||||
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
|
||||
)
|
||||
)
|
||||
io.ex_immediate := immediate
|
||||
io.ex_aluop1_source := Mux(
|
||||
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
|
||||
ALUOp1Source.InstructionAddress,
|
||||
ALUOp1Source.Register
|
||||
)
|
||||
io.ex_aluop2_source := Mux(
|
||||
opcode === InstructionTypes.RM,
|
||||
ALUOp2Source.Register,
|
||||
ALUOp2Source.Immediate
|
||||
)
|
||||
io.memory_read_enable := opcode === InstructionTypes.L
|
||||
io.memory_write_enable := opcode === InstructionTypes.S
|
||||
io.wb_reg_write_source := MuxLookup(
|
||||
opcode,
|
||||
RegWriteSource.ALUResult,
|
||||
IndexedSeq(
|
||||
InstructionTypes.L -> RegWriteSource.Memory,
|
||||
Instructions.jal -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.jalr -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.csr -> RegWriteSource.CSR
|
||||
)
|
||||
)
|
||||
io.reg_write_enable := (opcode === InstructionTypes.RM) || (opcode === InstructionTypes.I) ||
|
||||
(opcode === InstructionTypes.L) || (opcode === Instructions.auipc) || (opcode === Instructions.lui) ||
|
||||
(opcode === Instructions.jal) || (opcode === Instructions.jalr) || (opcode === Instructions.csr)
|
||||
io.reg_write_address := io.instruction(11, 7)
|
||||
io.csr_reg_address := io.instruction(31,20)
|
||||
io.csr_reg_write_enable := (opcode === Instructions.csr) && (
|
||||
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
|
||||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
|
||||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
|
||||
)
|
||||
}
|
||||
53
lab2/朱梓涵24325356/scala/riscv/core/InstructionFetch.scala
Normal file
53
lab2/朱梓涵24325356/scala/riscv/core/InstructionFetch.scala
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag_id = Input(Bool())
|
||||
val jump_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val interrupt_assert = Input(Bool())
|
||||
val interrupt_handler_address = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
when(io.instruction_valid) {
|
||||
when(io.interrupt_assert){
|
||||
pc := io.interrupt_handler_address
|
||||
}.elsewhen(io.jump_flag_id){
|
||||
pc := io.jump_address_id
|
||||
}.otherwise {
|
||||
pc := pc + 4.U
|
||||
}
|
||||
io.instruction := io.instruction_read_data
|
||||
}.otherwise{
|
||||
pc := pc
|
||||
io.instruction := 0x00000013.U
|
||||
}
|
||||
io.instruction_address := pc
|
||||
}
|
||||
105
lab2/朱梓涵24325356/scala/riscv/core/MemoryAccess.scala
Normal file
105
lab2/朱梓涵24325356/scala/riscv/core/MemoryAccess.scala
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// 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 peripheral.RAMBundle
|
||||
import riscv.Parameters
|
||||
|
||||
class MemoryAccess extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val funct3 = Input(UInt(3.W))
|
||||
|
||||
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
|
||||
io.memory_bundle.write_enable := false.B
|
||||
io.memory_bundle.write_data := 0.U
|
||||
io.memory_bundle.address := io.alu_result
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
io.wb_memory_read_data := 0.U
|
||||
|
||||
when(io.memory_read_enable) {
|
||||
val data = io.memory_bundle.read_data
|
||||
io.wb_memory_read_data := MuxLookup(
|
||||
io.funct3,
|
||||
0.U,
|
||||
IndexedSeq(
|
||||
InstructionsTypeL.lb -> MuxLookup(
|
||||
mem_address_index,
|
||||
Cat(Fill(24, data(31)), data(31, 24)),
|
||||
IndexedSeq(
|
||||
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
|
||||
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
|
||||
2.U -> Cat(Fill(24, data(23)), data(23, 16))
|
||||
)
|
||||
),
|
||||
InstructionsTypeL.lbu -> MuxLookup(
|
||||
mem_address_index,
|
||||
Cat(Fill(24, 0.U), data(31, 24)),
|
||||
IndexedSeq(
|
||||
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
|
||||
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
|
||||
2.U -> Cat(Fill(24, 0.U), data(23, 16))
|
||||
)
|
||||
),
|
||||
InstructionsTypeL.lh -> Mux(
|
||||
mem_address_index === 0.U,
|
||||
Cat(Fill(16, data(15)), data(15, 0)),
|
||||
Cat(Fill(16, data(31)), data(31, 16))
|
||||
),
|
||||
InstructionsTypeL.lhu -> Mux(
|
||||
mem_address_index === 0.U,
|
||||
Cat(Fill(16, 0.U), data(15, 0)),
|
||||
Cat(Fill(16, 0.U), data(31, 16))
|
||||
),
|
||||
InstructionsTypeL.lw -> data
|
||||
)
|
||||
)
|
||||
}.elsewhen(io.memory_write_enable) {
|
||||
io.memory_bundle.write_data := io.reg2_data
|
||||
io.memory_bundle.write_enable := true.B
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(io.funct3 === InstructionsTypeS.sb) {
|
||||
io.memory_bundle.write_strobe(mem_address_index) := true.B
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
|
||||
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
|
||||
when(mem_address_index === 0.U) {
|
||||
for (i <- 0 until Parameters.WordSize / 2) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
|
||||
}.otherwise {
|
||||
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
|
||||
.WordSize / 2 * Parameters.ByteBits)
|
||||
}
|
||||
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
|
||||
for (i <- 0 until Parameters.WordSize) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
lab2/朱梓涵24325356/scala/riscv/core/RegisterFile.scala
Normal file
95
lab2/朱梓涵24325356/scala/riscv/core/RegisterFile.scala
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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 Registers extends Enumeration {
|
||||
type Register = Value
|
||||
val zero,
|
||||
ra, sp, gp, tp,
|
||||
t0, t1, t2, fp,
|
||||
s1,
|
||||
a0, a1, a2, a3, a4, a5, a6, a7,
|
||||
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11,
|
||||
t3, t4, t5, t6 = Value
|
||||
}
|
||||
|
||||
class RegisterFile extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val write_enable = Input(Bool())
|
||||
val write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val write_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val read_address1 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val read_address2 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val read_data1 = Output(UInt(Parameters.DataWidth))
|
||||
val read_data2 = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val registers = RegInit(VecInit(Seq.fill(Parameters.PhysicalRegisters)(0.U(Parameters.DataWidth))))
|
||||
|
||||
when(!reset.asBool) {
|
||||
when(io.write_enable && io.write_address =/= 0.U) {
|
||||
registers(io.write_address) := io.write_data
|
||||
}
|
||||
}
|
||||
|
||||
io.read_data1 := Mux(
|
||||
io.read_address1 === 0.U,
|
||||
0.U,
|
||||
registers(io.read_address1)
|
||||
)
|
||||
|
||||
io.read_data2 := Mux(
|
||||
io.read_address2 === 0.U,
|
||||
0.U,
|
||||
registers(io.read_address2)
|
||||
)
|
||||
|
||||
io.debug_read_data := Mux(
|
||||
io.debug_read_address === 0.U,
|
||||
0.U,
|
||||
registers(io.debug_read_address)
|
||||
)
|
||||
// io.read_data1 := MuxCase(
|
||||
// registers(io.read_address1),
|
||||
// IndexedSeq(
|
||||
// (io.read_address1 === 0.U) -> 0.U,
|
||||
// (io.read_address1 === io.write_address && io.write_enable) -> io.write_data
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// io.read_data2 := MuxCase(
|
||||
// registers(io.read_address2),
|
||||
// IndexedSeq(
|
||||
// (io.read_address2 === 0.U) -> 0.U,
|
||||
// (io.read_address2 === io.write_address && io.write_enable) -> io.write_data
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// io.debug_read_data := MuxCase(
|
||||
// registers(io.debug_read_address),
|
||||
// IndexedSeq(
|
||||
// (io.debug_read_address === 0.U) -> 0.U,
|
||||
// (io.debug_read_address === io.write_address && io.write_enable) -> io.write_data
|
||||
// )
|
||||
// )
|
||||
|
||||
}
|
||||
39
lab2/朱梓涵24325356/scala/riscv/core/WriteBack.scala
Normal file
39
lab2/朱梓涵24325356/scala/riscv/core/WriteBack.scala
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// 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
|
||||
|
||||
class WriteBack extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
io.regs_write_data := MuxLookup(
|
||||
io.regs_write_source,
|
||||
io.alu_result,
|
||||
IndexedSeq(
|
||||
RegWriteSource.Memory -> io.memory_read_data,
|
||||
RegWriteSource.CSR -> io.csr_read_data,
|
||||
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U),
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user