mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
实验报告检查
This commit is contained in:
69
lab3/朱梓涵24325356/core/ALU.scala
Normal file
69
lab3/朱梓涵24325356/core/ALU.scala
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
87
lab3/朱梓涵24325356/core/ALUControl.scala
Normal file
87
lab3/朱梓涵24325356/core/ALUControl.scala
Normal file
@@ -0,0 +1,87 @@
|
||||
// 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.core.threestage.{InstructionTypes, Instructions, InstructionsTypeI, InstructionsTypeR}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
40
lab3/朱梓涵24325356/core/CPU.scala
Normal file
40
lab3/朱梓涵24325356/core/CPU.scala
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.core
|
||||
|
||||
import chisel3._
|
||||
import riscv.ImplementationType
|
||||
import riscv.core.fivestage_final.{CPU => FiveStageCPUFinal}
|
||||
import riscv.core.fivestage_forward.{CPU => FiveStageCPUForward}
|
||||
import riscv.core.fivestage_stall.{CPU => FiveStageCPUStall}
|
||||
import riscv.core.threestage.{CPU => ThreeStageCPU}
|
||||
|
||||
class CPU(val implementation: Int = ImplementationType.FiveStageFinal) extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
implementation match {
|
||||
case ImplementationType.ThreeStage =>
|
||||
val cpu = Module(new ThreeStageCPU)
|
||||
cpu.io <> io
|
||||
case ImplementationType.FiveStageStall =>
|
||||
val cpu = Module(new FiveStageCPUStall)
|
||||
cpu.io <> io
|
||||
case ImplementationType.FiveStageForward =>
|
||||
val cpu = Module(new FiveStageCPUForward)
|
||||
cpu.io <> io
|
||||
case _ =>
|
||||
val cpu = Module(new FiveStageCPUFinal)
|
||||
cpu.io <> io
|
||||
}
|
||||
}
|
||||
30
lab3/朱梓涵24325356/core/CPUBundle.scala
Normal file
30
lab3/朱梓涵24325356/core/CPUBundle.scala
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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.core
|
||||
|
||||
import chisel3._
|
||||
import peripheral.RAMBundle
|
||||
import riscv.Parameters
|
||||
|
||||
class CPUBundle extends Bundle {
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
val device_select = Output(UInt(Parameters.SlaveDeviceCountBits.W))
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
}
|
||||
99
lab3/朱梓涵24325356/core/CSR.scala
Normal file
99
lab3/朱梓涵24325356/core/CSR.scala
Normal file
@@ -0,0 +1,99 @@
|
||||
// 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
|
||||
import riscv.core.threestage.CSRDirectAccessBundle
|
||||
|
||||
|
||||
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_ex = Input(Bool())
|
||||
val reg_write_address_ex = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val reg_write_data_ex = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val id_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.id_reg_read_data := MuxLookup(io.reg_read_address_id, 0.U, regLUT)
|
||||
|
||||
io.clint_access_bundle.mstatus := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MSTATUS, io.reg_write_data_ex, mstatus)
|
||||
io.clint_access_bundle.mtvec := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MTVEC, io.reg_write_data_ex, mtvec)
|
||||
io.clint_access_bundle.mcause := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MCAUSE, io.reg_write_data_ex, mcause)
|
||||
io.clint_access_bundle.mepc := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MEPC, io.reg_write_data_ex, mepc)
|
||||
|
||||
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_ex) {
|
||||
when(io.reg_write_address_ex === CSRRegister.MSTATUS) {
|
||||
mstatus := io.reg_write_data_ex
|
||||
}.elsewhen(io.reg_write_address_ex === CSRRegister.MEPC) {
|
||||
mepc := io.reg_write_data_ex
|
||||
}.elsewhen(io.reg_write_address_ex === CSRRegister.MCAUSE) {
|
||||
mcause := io.reg_write_data_ex
|
||||
}
|
||||
}
|
||||
|
||||
when(io.reg_write_enable_ex) {
|
||||
when(io.reg_write_address_ex === CSRRegister.MIE) {
|
||||
mie := io.reg_write_data_ex
|
||||
}.elsewhen(io.reg_write_address_ex === CSRRegister.MTVEC) {
|
||||
mtvec := io.reg_write_data_ex
|
||||
}.elsewhen(io.reg_write_address_ex === CSRRegister.MSCRATCH) {
|
||||
mscratch := io.reg_write_data_ex
|
||||
}
|
||||
}
|
||||
}
|
||||
39
lab3/朱梓涵24325356/core/PipelineRegister.scala
Normal file
39
lab3/朱梓涵24325356/core/PipelineRegister.scala
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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
|
||||
|
||||
class PipelineRegister(width: Int = Parameters.DataBits, defaultValue: UInt = 0.U) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall = Input(Bool())
|
||||
val flush = Input(Bool())
|
||||
val in = Input(UInt(width.W))
|
||||
val out = Output(UInt(width.W))
|
||||
})
|
||||
// Lab3(PipelineRegister)
|
||||
val register = RegInit(defaultValue)
|
||||
|
||||
when(io.flush) {
|
||||
register := defaultValue
|
||||
}.elsewhen(io.stall) {
|
||||
}.otherwise {
|
||||
register := io.in
|
||||
}
|
||||
|
||||
io.out := register
|
||||
// Lab3(PipelineRegister) End
|
||||
}
|
||||
78
lab3/朱梓涵24325356/core/RegisterFile.scala
Normal file
78
lab3/朱梓涵24325356/core/RegisterFile.scala
Normal file
@@ -0,0 +1,78 @@
|
||||
// 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 = Reg(Vec(Parameters.PhysicalRegisters, UInt(Parameters.DataWidth)))
|
||||
|
||||
when(!reset.asBool) {
|
||||
when(io.write_enable && io.write_address =/= 0.U) {
|
||||
registers(io.write_address) := io.write_data
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
101
lab3/朱梓涵24325356/core/fivestage_final/CLINT.scala
Normal file
101
lab3/朱梓涵24325356/core/fivestage_final/CLINT.scala
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxLookup
|
||||
import riscv.Parameters
|
||||
|
||||
object InterruptStatus {
|
||||
val None = 0x0.U(8.W)
|
||||
val Timer0 = 0x1.U(8.W)
|
||||
val Ret = 0xFF.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 {
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val instruction_id = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val jump_flag = Input(Bool())
|
||||
val jump_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val id_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
|
||||
val id_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_if,
|
||||
)
|
||||
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
|
||||
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
|
||||
|
||||
when(io.instruction_id === InstructionsEnv.ecall || io.instruction_id === InstructionsEnv.ebreak) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := MuxLookup(
|
||||
io.instruction_id,
|
||||
10.U,
|
||||
IndexedSeq(
|
||||
InstructionsEnv.ecall -> 11.U,
|
||||
InstructionsEnv.ebreak -> 3.U,
|
||||
)
|
||||
)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.id_interrupt_assert := true.B
|
||||
io.id_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.id_interrupt_assert := true.B
|
||||
io.id_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.instruction_id === InstructionsRet.mret) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.id_interrupt_assert := true.B
|
||||
io.id_interrupt_handler_address := io.csr_bundle.mepc
|
||||
}.otherwise {
|
||||
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := false.B
|
||||
io.id_interrupt_assert := false.B
|
||||
io.id_interrupt_handler_address := 0.U
|
||||
}
|
||||
}
|
||||
169
lab3/朱梓涵24325356/core/fivestage_final/CPU.scala
Normal file
169
lab3/朱梓涵24325356/core/fivestage_final/CPU.scala
Normal file
@@ -0,0 +1,169 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{CPUBundle, CSR, RegisterFile}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val ctrl = Module(new Control)
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val if2id = Module(new IF2ID)
|
||||
val id = Module(new InstructionDecode)
|
||||
val id2ex = Module(new ID2EX)
|
||||
val ex = Module(new Execute)
|
||||
val ex2mem = Module(new EX2MEM)
|
||||
val mem = Module(new MemoryAccess)
|
||||
val mem2wb = Module(new MEM2WB)
|
||||
val wb = Module(new WriteBack)
|
||||
val forwarding = Module(new Forwarding)
|
||||
val clint = Module(new CLINT)
|
||||
val csr_regs = Module(new CSR)
|
||||
|
||||
ctrl.io.jump_flag := id.io.if_jump_flag
|
||||
ctrl.io.jump_instruction_id := id.io.ctrl_jump_instruction
|
||||
ctrl.io.rs1_id := id.io.regs_reg1_read_address
|
||||
ctrl.io.rs2_id := id.io.regs_reg2_read_address
|
||||
ctrl.io.memory_read_enable_ex := id2ex.io.output_memory_read_enable
|
||||
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
|
||||
ctrl.io.memory_read_enable_mem := ex2mem.io.output_memory_read_enable
|
||||
ctrl.io.rd_mem := ex2mem.io.output_regs_write_address
|
||||
|
||||
regs.io.write_enable := mem2wb.io.output_regs_write_enable
|
||||
regs.io.write_address := mem2wb.io.output_regs_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
|
||||
|
||||
regs.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := regs.io.debug_read_data
|
||||
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
|
||||
inst_fetch.io.jump_flag_id := id.io.if_jump_flag
|
||||
inst_fetch.io.jump_address_id := id.io.if_jump_address
|
||||
inst_fetch.io.rom_instruction := io.instruction
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
|
||||
if2id.io.stall := ctrl.io.if2id_stall
|
||||
if2id.io.flush := ctrl.io.if2id_flush
|
||||
if2id.io.instruction := inst_fetch.io.id_instruction
|
||||
if2id.io.instruction_address := inst_fetch.io.instruction_address
|
||||
if2id.io.interrupt_flag := io.interrupt_flag
|
||||
|
||||
id.io.instruction := if2id.io.output_instruction
|
||||
id.io.instruction_address := if2id.io.output_instruction_address
|
||||
id.io.reg1_data := regs.io.read_data1
|
||||
id.io.reg2_data := regs.io.read_data2
|
||||
id.io.forward_from_mem := mem.io.forward_data
|
||||
id.io.forward_from_wb := wb.io.regs_write_data
|
||||
id.io.reg1_forward := forwarding.io.reg1_forward_id
|
||||
id.io.reg2_forward := forwarding.io.reg2_forward_id
|
||||
id.io.interrupt_assert := clint.io.id_interrupt_assert
|
||||
id.io.interrupt_handler_address := clint.io.id_interrupt_handler_address
|
||||
|
||||
id2ex.io.flush := ctrl.io.id2ex_flush
|
||||
id2ex.io.instruction := if2id.io.output_instruction
|
||||
id2ex.io.instruction_address := if2id.io.output_instruction_address
|
||||
id2ex.io.reg1_data := regs.io.read_data1
|
||||
id2ex.io.reg2_data := regs.io.read_data2
|
||||
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
|
||||
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
|
||||
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
|
||||
id2ex.io.regs_write_address := id.io.ex_reg_write_address
|
||||
id2ex.io.regs_write_source := id.io.ex_reg_write_source
|
||||
id2ex.io.immediate := id.io.ex_immediate
|
||||
id2ex.io.aluop1_source := id.io.ex_aluop1_source
|
||||
id2ex.io.aluop2_source := id.io.ex_aluop2_source
|
||||
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
|
||||
id2ex.io.csr_address := id.io.ex_csr_address
|
||||
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
|
||||
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
|
||||
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
|
||||
|
||||
ex.io.instruction := id2ex.io.output_instruction
|
||||
ex.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex.io.reg1_data := id2ex.io.output_reg1_data
|
||||
ex.io.reg2_data := id2ex.io.output_reg2_data
|
||||
ex.io.immediate := id2ex.io.output_immediate
|
||||
ex.io.aluop1_source := id2ex.io.output_aluop1_source
|
||||
ex.io.aluop2_source := id2ex.io.output_aluop2_source
|
||||
ex.io.csr_read_data := id2ex.io.output_csr_read_data
|
||||
ex.io.forward_from_mem := mem.io.forward_data
|
||||
ex.io.forward_from_wb := wb.io.regs_write_data
|
||||
ex.io.reg1_forward := forwarding.io.reg1_forward_ex
|
||||
ex.io.reg2_forward := forwarding.io.reg2_forward_ex
|
||||
|
||||
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
|
||||
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
|
||||
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
|
||||
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
|
||||
ex2mem.io.reg2_data := ex.io.mem_reg2_data
|
||||
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
|
||||
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
|
||||
ex2mem.io.alu_result := ex.io.mem_alu_result
|
||||
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
|
||||
|
||||
mem.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem.io.reg2_data := ex2mem.io.output_reg2_data
|
||||
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
|
||||
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
|
||||
mem.io.funct3 := ex2mem.io.output_funct3
|
||||
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
io.memory_bundle <> mem.io.bundle
|
||||
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
|
||||
|
||||
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
|
||||
mem2wb.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
|
||||
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
|
||||
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
|
||||
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
|
||||
wb.io.instruction_address := mem2wb.io.output_instruction_address
|
||||
wb.io.alu_result := mem2wb.io.output_alu_result
|
||||
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
|
||||
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
|
||||
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
|
||||
|
||||
forwarding.io.rs1_id := id.io.regs_reg1_read_address
|
||||
forwarding.io.rs2_id := id.io.regs_reg2_read_address
|
||||
forwarding.io.rs1_ex := id2ex.io.output_regs_reg1_read_address
|
||||
forwarding.io.rs2_ex := id2ex.io.output_regs_reg2_read_address
|
||||
forwarding.io.rd_mem := ex2mem.io.output_regs_write_address
|
||||
forwarding.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
|
||||
forwarding.io.rd_wb := mem2wb.io.output_regs_write_address
|
||||
forwarding.io.reg_write_enable_wb := mem2wb.io.output_regs_write_enable
|
||||
|
||||
clint.io.instruction_address_if := inst_fetch.io.instruction_address
|
||||
clint.io.instruction_id := if2id.io.output_instruction
|
||||
clint.io.jump_flag := id.io.clint_jump_flag
|
||||
clint.io.jump_address := id.io.clint_jump_address
|
||||
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
|
||||
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
|
||||
|
||||
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
|
||||
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
|
||||
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
|
||||
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
|
||||
}
|
||||
62
lab3/朱梓涵24325356/core/fivestage_final/Control.scala
Normal file
62
lab3/朱梓涵24325356/core/fivestage_final/Control.scala
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
class Control extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag = Input(Bool())
|
||||
val jump_instruction_id = Input(Bool())
|
||||
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val memory_read_enable_ex = Input(Bool())
|
||||
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val memory_read_enable_mem = Input(Bool())
|
||||
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
|
||||
val if2id_flush = Output(Bool())
|
||||
val id2ex_flush = Output(Bool())
|
||||
val pc_stall = Output(Bool())
|
||||
val if2id_stall = Output(Bool())
|
||||
})
|
||||
|
||||
|
||||
// Lab3(Final)
|
||||
val stall = Wire(Bool())
|
||||
|
||||
val load_use_hazard = io.memory_read_enable_ex && io.rd_ex =/= 0.U &&
|
||||
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
|
||||
|
||||
val id_jump_needs_ex_alu = io.jump_instruction_id && io.rd_ex =/= 0.U &&
|
||||
!io.memory_read_enable_ex &&
|
||||
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
|
||||
|
||||
val id_jump_needs_mem_load = io.jump_instruction_id && io.memory_read_enable_mem && io.rd_mem =/= 0.U &&
|
||||
(io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
|
||||
|
||||
|
||||
stall := load_use_hazard || id_jump_needs_ex_alu || id_jump_needs_mem_load
|
||||
|
||||
|
||||
val flush = io.jump_flag && !stall
|
||||
io.pc_stall := stall
|
||||
io.if2id_stall := stall
|
||||
io.if2id_flush := flush
|
||||
|
||||
io.id2ex_flush := stall
|
||||
// Lab3(Final) End
|
||||
}
|
||||
108
lab3/朱梓涵24325356/core/fivestage_final/EX2MEM.scala
Normal file
108
lab3/朱梓涵24325356/core/fivestage_final/EX2MEM.scala
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class EX2MEM extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val funct3 = Input(UInt(3.W))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_funct3 = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val funct3 = Module(new PipelineRegister(3))
|
||||
funct3.io.in := io.funct3
|
||||
funct3.io.stall := stall
|
||||
funct3.io.flush := flush
|
||||
io.output_funct3 := funct3.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
93
lab3/朱梓涵24325356/core/fivestage_final/Execute.scala
Normal file
93
lab3/朱梓涵24325356/core/fivestage_final/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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{ALU, ALUControl}
|
||||
|
||||
|
||||
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_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_mem = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_wb = Input(UInt(Parameters.DataWidth))
|
||||
val reg1_forward = Input(UInt(2.W))
|
||||
val reg2_forward = Input(UInt(2.W))
|
||||
|
||||
val mem_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val csr_write_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val uimm = io.instruction(19, 15)
|
||||
|
||||
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
|
||||
|
||||
val reg1_data = MuxLookup(
|
||||
io.reg1_forward,
|
||||
io.reg1_data,
|
||||
IndexedSeq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
alu.io.op1 := Mux(
|
||||
io.aluop1_source === ALUOp1Source.InstructionAddress,
|
||||
io.instruction_address,
|
||||
reg1_data
|
||||
)
|
||||
|
||||
val reg2_data = MuxLookup(
|
||||
io.reg2_forward,
|
||||
io.reg2_data,
|
||||
IndexedSeq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
alu.io.op2 := Mux(
|
||||
io.aluop2_source === ALUOp2Source.Immediate,
|
||||
io.immediate,
|
||||
reg2_data
|
||||
)
|
||||
io.mem_alu_result := alu.io.result
|
||||
io.mem_reg2_data := reg2_data
|
||||
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
|
||||
InstructionsTypeCSR.csrrw -> reg1_data,
|
||||
InstructionsTypeCSR.csrrc -> io.csr_read_data.&((~reg1_data).asUInt),
|
||||
InstructionsTypeCSR.csrrs -> io.csr_read_data.|(reg1_data),
|
||||
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
|
||||
InstructionsTypeCSR.csrrci -> io.csr_read_data.&((~Cat(0.U(27.W), uimm)).asUInt),
|
||||
InstructionsTypeCSR.csrrsi -> io.csr_read_data.|(Cat(0.U(27.W), uimm)),
|
||||
))
|
||||
}
|
||||
67
lab3/朱梓涵24325356/core/fivestage_final/Forwarding.scala
Normal file
67
lab3/朱梓涵24325356/core/fivestage_final/Forwarding.scala
Normal file
@@ -0,0 +1,67 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
object ForwardingType {
|
||||
val NoForward = 0.U(2.W)
|
||||
val ForwardFromMEM = 1.U(2.W)
|
||||
val ForwardFromWB = 2.U(2.W)
|
||||
}
|
||||
|
||||
class Forwarding extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_mem = Input(Bool())
|
||||
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_wb = Input(Bool())
|
||||
|
||||
val reg1_forward_id = Output(UInt(2.W))
|
||||
val reg2_forward_id = Output(UInt(2.W))
|
||||
val reg1_forward_ex = Output(UInt(2.W))
|
||||
val reg2_forward_ex = Output(UInt(2.W))
|
||||
})
|
||||
|
||||
// Lab3(Final)
|
||||
val ex_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_ex)
|
||||
val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex)
|
||||
val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex)
|
||||
val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex)
|
||||
|
||||
io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
|
||||
Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
|
||||
io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
|
||||
Mux(ex_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
|
||||
val id_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id)
|
||||
val id_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_id)
|
||||
|
||||
val id_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs1 && (io.rd_wb === io.rs1_id)
|
||||
val id_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs2 && (io.rd_wb === io.rs2_id)
|
||||
io.reg1_forward_id := Mux(id_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
|
||||
Mux(id_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
|
||||
io.reg2_forward_id := Mux(id_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
|
||||
Mux(id_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
|
||||
|
||||
// Lab3(Final) End
|
||||
}
|
||||
|
||||
|
||||
|
||||
163
lab3/朱梓涵24325356/core/fivestage_final/ID2EX.scala
Normal file
163
lab3/朱梓涵24325356/core/fivestage_final/ID2EX.scala
Normal file
@@ -0,0 +1,163 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class ID2EX extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
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_write_enable = Input(Bool())
|
||||
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_reg1_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val output_aluop1_source = Output(UInt(1.W))
|
||||
val output_aluop2_source = Output(UInt(1.W))
|
||||
val output_csr_write_enable = Output(Bool())
|
||||
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val stall = false.B
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg1_read_address.io.in := io.regs_reg1_read_address
|
||||
regs_reg1_read_address.io.stall := stall
|
||||
regs_reg1_read_address.io.flush := io.flush
|
||||
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
|
||||
|
||||
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg2_read_address.io.in := io.regs_reg2_read_address
|
||||
regs_reg2_read_address.io.stall := stall
|
||||
regs_reg2_read_address.io.flush := io.flush
|
||||
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := io.flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := io.flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := io.flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val reg1_data = Module(new PipelineRegister())
|
||||
reg1_data.io.in := io.reg1_data
|
||||
reg1_data.io.stall := stall
|
||||
reg1_data.io.flush := io.flush
|
||||
io.output_reg1_data := reg1_data.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := io.flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val immediate = Module(new PipelineRegister())
|
||||
immediate.io.in := io.immediate
|
||||
immediate.io.stall := stall
|
||||
immediate.io.flush := io.flush
|
||||
io.output_immediate := immediate.io.out
|
||||
|
||||
val aluop1_source = Module(new PipelineRegister(1))
|
||||
aluop1_source.io.in := io.aluop1_source
|
||||
aluop1_source.io.stall := stall
|
||||
aluop1_source.io.flush := io.flush
|
||||
io.output_aluop1_source := aluop1_source.io.out
|
||||
|
||||
val aluop2_source = Module(new PipelineRegister(1))
|
||||
aluop2_source.io.in := io.aluop2_source
|
||||
aluop2_source.io.stall := stall
|
||||
aluop2_source.io.flush := io.flush
|
||||
io.output_aluop2_source := aluop2_source.io.out
|
||||
|
||||
val csr_write_enable = Module(new PipelineRegister(1))
|
||||
csr_write_enable.io.in := io.csr_write_enable
|
||||
csr_write_enable.io.stall := stall
|
||||
csr_write_enable.io.flush := io.flush
|
||||
io.output_csr_write_enable := csr_write_enable.io.out
|
||||
|
||||
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
|
||||
csr_address.io.in := io.csr_address
|
||||
csr_address.io.stall := stall
|
||||
csr_address.io.flush := io.flush
|
||||
io.output_csr_address := csr_address.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := io.flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := io.flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := io.flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
51
lab3/朱梓涵24325356/core/fivestage_final/IF2ID.scala
Normal file
51
lab3/朱梓涵24325356/core/fivestage_final/IF2ID.scala
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class IF2ID extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall = Input(Bool())
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
|
||||
})
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := io.stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := io.stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
|
||||
interrupt_flag.io.in := io.interrupt_flag
|
||||
interrupt_flag.io.stall := io.stall
|
||||
interrupt_flag.io.flush := io.flush
|
||||
io.output_interrupt_flag := interrupt_flag.io.out
|
||||
}
|
||||
274
lab3/朱梓涵24325356/core/fivestage_final/InstructionDecode.scala
Normal file
274
lab3/朱梓涵24325356/core/fivestage_final/InstructionDecode.scala
Normal file
@@ -0,0 +1,274 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
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 instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val reg1_data = Input(UInt(Parameters.DataWidth))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_mem = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_wb = Input(UInt(Parameters.DataWidth))
|
||||
val reg1_forward = Input(UInt(2.W))
|
||||
val reg2_forward = Input(UInt(2.W))
|
||||
val interrupt_assert = Input(Bool())
|
||||
val interrupt_handler_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
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 ex_memory_read_enable = Output(Bool())
|
||||
val ex_memory_write_enable = Output(Bool())
|
||||
val ex_reg_write_source = Output(UInt(2.W))
|
||||
val ex_reg_write_enable = Output(Bool())
|
||||
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val ex_csr_write_enable = Output(Bool())
|
||||
val ctrl_jump_instruction = Output(Bool())
|
||||
val clint_jump_flag = Output(Bool())
|
||||
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
})
|
||||
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)
|
||||
|
||||
// Lab3(Final) ID rs
|
||||
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
|
||||
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
|
||||
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
|
||||
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
|
||||
// Lab3(Final) ID rs End
|
||||
io.ex_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_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.ex_memory_read_enable := opcode === InstructionTypes.L
|
||||
io.ex_memory_write_enable := opcode === InstructionTypes.S
|
||||
io.ex_reg_write_source := MuxLookup(
|
||||
opcode,
|
||||
RegWriteSource.ALUResult,
|
||||
IndexedSeq(
|
||||
InstructionTypes.L -> RegWriteSource.Memory,
|
||||
Instructions.csr -> RegWriteSource.CSR,
|
||||
Instructions.jal -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.jalr -> RegWriteSource.NextInstructionAddress
|
||||
)
|
||||
)
|
||||
// Lab3(Final) ID rd
|
||||
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
|
||||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
|
||||
opcode === Instructions.jalr || opcode === Instructions.csr
|
||||
io.ex_reg_write_enable := rd_used
|
||||
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
|
||||
// Lab3(Final) ID rd End
|
||||
io.ex_csr_address := io.instruction(31, 20)
|
||||
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
|
||||
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
|
||||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
|
||||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
|
||||
)
|
||||
|
||||
// Lab3(Final)
|
||||
|
||||
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
|
||||
Seq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
|
||||
Seq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
val is_jump_instruction = opcode === Instructions.jal || opcode === Instructions.jalr || opcode === InstructionTypes.B
|
||||
io.ctrl_jump_instruction := is_jump_instruction
|
||||
val jump_condition_met =
|
||||
(opcode === Instructions.jal) ||
|
||||
(opcode === Instructions.jalr) ||
|
||||
(opcode === InstructionTypes.B) && MuxLookup(
|
||||
funct3,
|
||||
false.B,
|
||||
IndexedSeq(
|
||||
InstructionsTypeB.beq -> (reg1_data === reg2_data),
|
||||
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
|
||||
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
|
||||
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
|
||||
InstructionsTypeB.bltu -> (reg1_data < reg2_data),
|
||||
InstructionsTypeB.bgeu -> (reg1_data >= reg2_data)
|
||||
)
|
||||
)
|
||||
val jump_address = Mux(
|
||||
opcode === Instructions.jalr,
|
||||
(reg1_data.asSInt + io.ex_immediate.asSInt).asUInt,
|
||||
(io.instruction_address.asSInt + io.ex_immediate.asSInt).asUInt
|
||||
) & (~1.U(Parameters.DataWidth)).asUInt // Ensure address is even
|
||||
io.clint_jump_flag := jump_condition_met
|
||||
io.clint_jump_address := jump_address
|
||||
io.if_jump_flag := jump_condition_met || io.interrupt_assert
|
||||
io.if_jump_address := Mux(
|
||||
io.interrupt_assert,
|
||||
io.interrupt_handler_address,
|
||||
jump_address
|
||||
)
|
||||
// Lab3(Final) End
|
||||
}
|
||||
48
lab3/朱梓涵24325356/core/fivestage_final/InstructionFetch.scala
Normal file
48
lab3/朱梓涵24325356/core/fivestage_final/InstructionFetch.scala
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxCase
|
||||
import riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall_flag_ctrl = Input(Bool())
|
||||
val jump_flag_id = Input(Bool())
|
||||
val jump_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
val rom_instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val id_instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
pc := MuxCase(
|
||||
pc + 4.U,
|
||||
IndexedSeq(
|
||||
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
|
||||
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
|
||||
)
|
||||
)
|
||||
|
||||
io.instruction_address := pc
|
||||
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
|
||||
}
|
||||
83
lab3/朱梓涵24325356/core/fivestage_final/MEM2WB.scala
Normal file
83
lab3/朱梓涵24325356/core/fivestage_final/MEM2WB.scala
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class MEM2WB extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val memory_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_data = Module(new PipelineRegister())
|
||||
memory_read_data.io.in := io.memory_read_data
|
||||
memory_read_data.io.stall := stall
|
||||
memory_read_data.io.flush := flush
|
||||
io.output_memory_read_data := memory_read_data.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
109
lab3/朱梓涵24325356/core/fivestage_final/MemoryAccess.scala
Normal file
109
lab3/朱梓涵24325356/core/fivestage_final/MemoryAccess.scala
Normal file
@@ -0,0 +1,109 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
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 regs_write_source = Input(UInt(2.W))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val forward_data = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
|
||||
io.bundle.write_enable := io.memory_write_enable
|
||||
io.bundle.write_data := 0.U
|
||||
io.bundle.address := io.alu_result
|
||||
io.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.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.bundle.write_data := io.reg2_data
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(io.funct3 === InstructionsTypeS.sb) {
|
||||
io.bundle.write_strobe(mem_address_index) := true.B
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
|
||||
}.otherwise {
|
||||
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
|
||||
io.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.forward_data := Mux(io.regs_write_source === RegWriteSource.CSR, io.csr_read_data, io.alu_result)
|
||||
}
|
||||
40
lab3/朱梓涵24325356/core/fivestage_final/WriteBack.scala
Normal file
40
lab3/朱梓涵24325356/core/fivestage_final/WriteBack.scala
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.fivestage_final
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
103
lab3/朱梓涵24325356/core/fivestage_forward/CLINT.scala
Normal file
103
lab3/朱梓涵24325356/core/fivestage_forward/CLINT.scala
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxLookup
|
||||
import riscv.Parameters
|
||||
|
||||
object InterruptStatus {
|
||||
val None = 0x0.U(8.W)
|
||||
val Timer0 = 0x1.U(8.W)
|
||||
val Ret = 0xFF.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 {
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val jump_flag = Input(Bool())
|
||||
val jump_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
|
||||
val ex_interrupt_assert = Output(Bool())
|
||||
|
||||
val csr_bundle = new CSRDirectAccessBundle
|
||||
})
|
||||
val interrupt_enable = io.csr_bundle.mstatus(3)
|
||||
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
|
||||
val instruction_address = Mux(
|
||||
io.jump_flag,
|
||||
io.jump_address,
|
||||
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
|
||||
)
|
||||
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
|
||||
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
|
||||
|
||||
when(io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := MuxLookup(
|
||||
io.instruction_ex,
|
||||
10.U,
|
||||
IndexedSeq(
|
||||
InstructionsEnv.ecall -> 11.U,
|
||||
InstructionsEnv.ebreak -> 3.U,
|
||||
)
|
||||
)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.instruction_ex === InstructionsRet.mret) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mepc
|
||||
}.otherwise {
|
||||
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := false.B
|
||||
io.ex_interrupt_assert := false.B
|
||||
io.ex_interrupt_handler_address := 0.U
|
||||
}
|
||||
}
|
||||
158
lab3/朱梓涵24325356/core/fivestage_forward/CPU.scala
Normal file
158
lab3/朱梓涵24325356/core/fivestage_forward/CPU.scala
Normal file
@@ -0,0 +1,158 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{CPUBundle, CSR, RegisterFile}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val ctrl = Module(new Control)
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val if2id = Module(new IF2ID)
|
||||
val id = Module(new InstructionDecode)
|
||||
val id2ex = Module(new ID2EX)
|
||||
val ex = Module(new Execute)
|
||||
val ex2mem = Module(new EX2MEM)
|
||||
val mem = Module(new MemoryAccess)
|
||||
val mem2wb = Module(new MEM2WB)
|
||||
val wb = Module(new WriteBack)
|
||||
val forwarding = Module(new Forwarding)
|
||||
val clint = Module(new CLINT)
|
||||
val csr_regs = Module(new CSR)
|
||||
|
||||
ctrl.io.jump_flag := ex.io.if_jump_flag
|
||||
ctrl.io.rs1_id := id.io.regs_reg1_read_address
|
||||
ctrl.io.rs2_id := id.io.regs_reg2_read_address
|
||||
ctrl.io.memory_read_enable_ex := id2ex.io.output_memory_read_enable
|
||||
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
|
||||
|
||||
regs.io.write_enable := mem2wb.io.output_regs_write_enable
|
||||
regs.io.write_address := mem2wb.io.output_regs_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
|
||||
|
||||
regs.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := regs.io.debug_read_data
|
||||
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
|
||||
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
|
||||
inst_fetch.io.jump_address_id := ex.io.if_jump_address
|
||||
inst_fetch.io.rom_instruction := io.instruction
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
|
||||
if2id.io.stall := ctrl.io.if2id_stall
|
||||
if2id.io.flush := ctrl.io.if2id_flush
|
||||
if2id.io.instruction := inst_fetch.io.id_instruction
|
||||
if2id.io.instruction_address := inst_fetch.io.instruction_address
|
||||
if2id.io.interrupt_flag := io.interrupt_flag
|
||||
|
||||
id.io.instruction := if2id.io.output_instruction
|
||||
|
||||
id2ex.io.flush := ctrl.io.id2ex_flush
|
||||
id2ex.io.instruction := if2id.io.output_instruction
|
||||
id2ex.io.instruction_address := if2id.io.output_instruction_address
|
||||
id2ex.io.reg1_data := regs.io.read_data1
|
||||
id2ex.io.reg2_data := regs.io.read_data2
|
||||
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
|
||||
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
|
||||
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
|
||||
id2ex.io.regs_write_address := id.io.ex_reg_write_address
|
||||
id2ex.io.regs_write_source := id.io.ex_reg_write_source
|
||||
id2ex.io.immediate := id.io.ex_immediate
|
||||
id2ex.io.aluop1_source := id.io.ex_aluop1_source
|
||||
id2ex.io.aluop2_source := id.io.ex_aluop2_source
|
||||
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
|
||||
id2ex.io.csr_address := id.io.ex_csr_address
|
||||
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
|
||||
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
|
||||
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
|
||||
|
||||
ex.io.instruction := id2ex.io.output_instruction
|
||||
ex.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex.io.reg1_data := id2ex.io.output_reg1_data
|
||||
ex.io.reg2_data := id2ex.io.output_reg2_data
|
||||
ex.io.immediate_id := id2ex.io.output_immediate
|
||||
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
|
||||
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
|
||||
ex.io.csr_read_data_id := id2ex.io.output_csr_read_data
|
||||
ex.io.forward_from_mem := mem.io.forward_data
|
||||
ex.io.forward_from_wb := wb.io.regs_write_data
|
||||
ex.io.reg1_forward := forwarding.io.reg1_forward_ex
|
||||
ex.io.reg2_forward := forwarding.io.reg2_forward_ex
|
||||
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
|
||||
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
|
||||
|
||||
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
|
||||
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
|
||||
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
|
||||
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
|
||||
ex2mem.io.reg2_data := ex.io.mem_reg2_data
|
||||
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
|
||||
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
|
||||
ex2mem.io.alu_result := ex.io.mem_alu_result
|
||||
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
|
||||
|
||||
mem.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem.io.reg2_data := ex2mem.io.output_reg2_data
|
||||
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
|
||||
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
|
||||
mem.io.funct3 := ex2mem.io.output_funct3
|
||||
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
io.memory_bundle <> mem.io.bundle
|
||||
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
|
||||
|
||||
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
|
||||
mem2wb.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
|
||||
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
|
||||
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
|
||||
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
|
||||
wb.io.instruction_address := mem2wb.io.output_instruction_address
|
||||
wb.io.alu_result := mem2wb.io.output_alu_result
|
||||
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
|
||||
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
|
||||
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
|
||||
|
||||
forwarding.io.rs1_ex := id2ex.io.output_regs_reg1_read_address
|
||||
forwarding.io.rs2_ex := id2ex.io.output_regs_reg2_read_address
|
||||
forwarding.io.rd_mem := ex2mem.io.output_regs_write_address
|
||||
forwarding.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
|
||||
forwarding.io.rd_wb := mem2wb.io.output_regs_write_address
|
||||
forwarding.io.reg_write_enable_wb := mem2wb.io.output_regs_write_enable
|
||||
|
||||
clint.io.instruction_address_if := inst_fetch.io.instruction_address
|
||||
clint.io.instruction_address_id := if2id.io.output_instruction_address
|
||||
clint.io.instruction_ex := id2ex.io.output_instruction
|
||||
clint.io.jump_flag := ex.io.clint_jump_flag
|
||||
clint.io.jump_address := ex.io.clint_jump_address
|
||||
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
|
||||
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
|
||||
|
||||
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
|
||||
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
|
||||
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
|
||||
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
|
||||
}
|
||||
44
lab3/朱梓涵24325356/core/fivestage_forward/Control.scala
Normal file
44
lab3/朱梓涵24325356/core/fivestage_forward/Control.scala
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
class Control extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag = Input(Bool())
|
||||
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val memory_read_enable_ex = Input(Bool())
|
||||
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
|
||||
val if2id_flush = Output(Bool())
|
||||
val id2ex_flush = Output(Bool())
|
||||
val pc_stall = Output(Bool())
|
||||
val if2id_stall = Output(Bool())
|
||||
})
|
||||
|
||||
// Lab3(Forward)
|
||||
val load_use_hazard = io.memory_read_enable_ex &&
|
||||
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id) &&
|
||||
io.rd_ex =/= 0.U
|
||||
val flush = io.jump_flag
|
||||
io.pc_stall := load_use_hazard && !flush
|
||||
io.if2id_stall := load_use_hazard && !flush
|
||||
io.if2id_flush := flush
|
||||
io.id2ex_flush := flush || load_use_hazard
|
||||
// Lab3(Forward) End
|
||||
}
|
||||
108
lab3/朱梓涵24325356/core/fivestage_forward/EX2MEM.scala
Normal file
108
lab3/朱梓涵24325356/core/fivestage_forward/EX2MEM.scala
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class EX2MEM extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val funct3 = Input(UInt(3.W))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_funct3 = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val funct3 = Module(new PipelineRegister(3))
|
||||
funct3.io.in := io.funct3
|
||||
funct3.io.stall := stall
|
||||
funct3.io.flush := flush
|
||||
io.output_funct3 := funct3.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
121
lab3/朱梓涵24325356/core/fivestage_forward/Execute.scala
Normal file
121
lab3/朱梓涵24325356/core/fivestage_forward/Execute.scala
Normal file
@@ -0,0 +1,121 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{ALU, ALUControl}
|
||||
|
||||
|
||||
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_id = Input(UInt(Parameters.DataWidth))
|
||||
val aluop1_source_id = Input(UInt(1.W))
|
||||
val aluop2_source_id = Input(UInt(1.W))
|
||||
val csr_read_data_id = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_mem = Input(UInt(Parameters.DataWidth))
|
||||
val forward_from_wb = Input(UInt(Parameters.DataWidth))
|
||||
val reg1_forward = Input(UInt(2.W))
|
||||
val reg2_forward = Input(UInt(2.W))
|
||||
val interrupt_assert_clint = Input(Bool())
|
||||
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val mem_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val csr_write_data = Output(UInt(Parameters.DataWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
val clint_jump_flag = Output(Bool())
|
||||
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val uimm = io.instruction(19, 15)
|
||||
|
||||
// ALU compute
|
||||
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
|
||||
|
||||
// Lab3(Forward)
|
||||
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
|
||||
Seq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
|
||||
Seq(
|
||||
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
|
||||
ForwardingType.ForwardFromWB -> io.forward_from_wb
|
||||
)
|
||||
)
|
||||
// Lab3(Forward) End
|
||||
|
||||
alu.io.op1 := Mux(
|
||||
io.aluop1_source_id === ALUOp1Source.InstructionAddress,
|
||||
io.instruction_address,
|
||||
reg1_data
|
||||
)
|
||||
alu.io.op2 := Mux(
|
||||
io.aluop2_source_id === ALUOp2Source.Immediate,
|
||||
io.immediate_id,
|
||||
reg2_data
|
||||
)
|
||||
io.mem_alu_result := alu.io.result
|
||||
io.mem_reg2_data := reg2_data
|
||||
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
|
||||
InstructionsTypeCSR.csrrw -> reg1_data,
|
||||
InstructionsTypeCSR.csrrc -> io.csr_read_data_id.&((~reg1_data).asUInt),
|
||||
InstructionsTypeCSR.csrrs -> io.csr_read_data_id.|(reg1_data),
|
||||
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
|
||||
InstructionsTypeCSR.csrrci -> io.csr_read_data_id.&((~Cat(0.U(27.W), uimm)).asUInt),
|
||||
InstructionsTypeCSR.csrrsi -> io.csr_read_data_id.|(Cat(0.U(27.W), uimm)),
|
||||
))
|
||||
|
||||
// jump and interrupt
|
||||
val instruction_jump_flag = (opcode === Instructions.jal) ||
|
||||
(opcode === Instructions.jalr) ||
|
||||
(opcode === InstructionTypes.B) && MuxLookup(
|
||||
funct3,
|
||||
false.B,
|
||||
IndexedSeq(
|
||||
InstructionsTypeB.beq -> (reg1_data === reg2_data),
|
||||
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
|
||||
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
|
||||
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
|
||||
InstructionsTypeB.bltu -> (reg1_data.asUInt < reg2_data.asUInt),
|
||||
InstructionsTypeB.bgeu -> (reg1_data.asUInt >= reg2_data.asUInt)
|
||||
)
|
||||
)
|
||||
io.clint_jump_flag := instruction_jump_flag
|
||||
io.clint_jump_address := alu.io.result
|
||||
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
|
||||
io.if_jump_address := Mux(io.interrupt_assert_clint,
|
||||
io.interrupt_handler_address_clint,
|
||||
alu.io.result
|
||||
)
|
||||
}
|
||||
56
lab3/朱梓涵24325356/core/fivestage_forward/Forwarding.scala
Normal file
56
lab3/朱梓涵24325356/core/fivestage_forward/Forwarding.scala
Normal file
@@ -0,0 +1,56 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
object ForwardingType {
|
||||
val NoForward = 0.U(2.W)
|
||||
val ForwardFromMEM = 1.U(2.W)
|
||||
val ForwardFromWB = 2.U(2.W)
|
||||
}
|
||||
|
||||
class Forwarding extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_mem = Input(Bool())
|
||||
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_wb = Input(Bool())
|
||||
|
||||
// Forwarding Type
|
||||
val reg1_forward_ex = Output(UInt(2.W))
|
||||
val reg2_forward_ex = Output(UInt(2.W))
|
||||
})
|
||||
|
||||
// Lab3(Forward)
|
||||
// io.reg1_forward_ex := 0.U
|
||||
// io.reg2_forward_ex := 0.U
|
||||
io.reg1_forward_ex := ForwardingType.NoForward
|
||||
io.reg2_forward_ex := ForwardingType.NoForward
|
||||
when(io.reg_write_enable_mem && io.rd_mem =/= 0.U && io.rd_mem === io.rs1_ex) {
|
||||
io.reg1_forward_ex := ForwardingType.ForwardFromMEM
|
||||
}.elsewhen(io.reg_write_enable_wb && io.rd_wb =/= 0.U && io.rd_wb === io.rs1_ex) {
|
||||
io.reg1_forward_ex := ForwardingType.ForwardFromWB
|
||||
}
|
||||
when(io.reg_write_enable_mem && io.rd_mem =/= 0.U && io.rd_mem === io.rs2_ex) {
|
||||
io.reg2_forward_ex := ForwardingType.ForwardFromMEM
|
||||
}.elsewhen(io.reg_write_enable_wb && io.rd_wb =/= 0.U && io.rd_wb === io.rs2_ex) {
|
||||
io.reg2_forward_ex := ForwardingType.ForwardFromWB
|
||||
}
|
||||
// Lab3(Forward) End
|
||||
}
|
||||
164
lab3/朱梓涵24325356/core/fivestage_forward/ID2EX.scala
Normal file
164
lab3/朱梓涵24325356/core/fivestage_forward/ID2EX.scala
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class ID2EX extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
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_write_enable = Input(Bool())
|
||||
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_reg1_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val output_aluop1_source = Output(UInt(1.W))
|
||||
val output_aluop2_source = Output(UInt(1.W))
|
||||
val output_csr_write_enable = Output(Bool())
|
||||
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg1_read_address.io.in := io.regs_reg1_read_address
|
||||
regs_reg1_read_address.io.stall := stall
|
||||
regs_reg1_read_address.io.flush := io.flush
|
||||
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
|
||||
|
||||
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg2_read_address.io.in := io.regs_reg2_read_address
|
||||
regs_reg2_read_address.io.stall := stall
|
||||
regs_reg2_read_address.io.flush := io.flush
|
||||
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := io.flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := io.flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := io.flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val reg1_data = Module(new PipelineRegister())
|
||||
reg1_data.io.in := io.reg1_data
|
||||
reg1_data.io.stall := stall
|
||||
reg1_data.io.flush := io.flush
|
||||
io.output_reg1_data := reg1_data.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := io.flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val immediate = Module(new PipelineRegister())
|
||||
immediate.io.in := io.immediate
|
||||
immediate.io.stall := stall
|
||||
immediate.io.flush := io.flush
|
||||
io.output_immediate := immediate.io.out
|
||||
|
||||
val aluop1_source = Module(new PipelineRegister(1))
|
||||
aluop1_source.io.in := io.aluop1_source
|
||||
aluop1_source.io.stall := stall
|
||||
aluop1_source.io.flush := io.flush
|
||||
io.output_aluop1_source := aluop1_source.io.out
|
||||
|
||||
val aluop2_source = Module(new PipelineRegister(1))
|
||||
aluop2_source.io.in := io.aluop2_source
|
||||
aluop2_source.io.stall := stall
|
||||
aluop2_source.io.flush := io.flush
|
||||
io.output_aluop2_source := aluop2_source.io.out
|
||||
|
||||
val csr_write_enable = Module(new PipelineRegister(1))
|
||||
csr_write_enable.io.in := io.csr_write_enable
|
||||
csr_write_enable.io.stall := stall
|
||||
csr_write_enable.io.flush := io.flush
|
||||
io.output_csr_write_enable := csr_write_enable.io.out
|
||||
|
||||
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
|
||||
csr_address.io.in := io.csr_address
|
||||
csr_address.io.stall := stall
|
||||
csr_address.io.flush := io.flush
|
||||
io.output_csr_address := csr_address.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := io.flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := io.flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := io.flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
51
lab3/朱梓涵24325356/core/fivestage_forward/IF2ID.scala
Normal file
51
lab3/朱梓涵24325356/core/fivestage_forward/IF2ID.scala
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class IF2ID extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall = Input(Bool())
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
|
||||
})
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := io.stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := io.stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
|
||||
interrupt_flag.io.in := io.interrupt_flag
|
||||
interrupt_flag.io.stall := io.stall
|
||||
interrupt_flag.io.flush := io.flush
|
||||
io.output_interrupt_flag := interrupt_flag.io.out
|
||||
}
|
||||
218
lab3/朱梓涵24325356/core/fivestage_forward/InstructionDecode.scala
Normal file
218
lab3/朱梓涵24325356/core/fivestage_forward/InstructionDecode.scala
Normal file
@@ -0,0 +1,218 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
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(Bool())
|
||||
val ex_aluop2_source = Output(Bool())
|
||||
val ex_memory_read_enable = Output(Bool())
|
||||
val ex_memory_write_enable = Output(Bool())
|
||||
val ex_reg_write_source = Output(UInt(2.W))
|
||||
val ex_reg_write_enable = Output(Bool())
|
||||
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val ex_csr_write_enable = Output(Bool())
|
||||
})
|
||||
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)
|
||||
|
||||
// Lab3(Forward) ID rs
|
||||
// io.regs_reg1_read_address := rs1
|
||||
// io.regs_reg2_read_address := rs2
|
||||
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
|
||||
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
|
||||
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
|
||||
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
|
||||
// Lab3(Forward) ID rs End
|
||||
io.ex_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_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.ex_memory_read_enable := opcode === InstructionTypes.L
|
||||
io.ex_memory_write_enable := opcode === InstructionTypes.S
|
||||
io.ex_reg_write_source := MuxLookup(
|
||||
opcode,
|
||||
RegWriteSource.ALUResult,
|
||||
IndexedSeq(
|
||||
InstructionTypes.L -> RegWriteSource.Memory,
|
||||
Instructions.csr -> RegWriteSource.CSR,
|
||||
Instructions.jal -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.jalr -> RegWriteSource.NextInstructionAddress
|
||||
)
|
||||
)
|
||||
// Lab3(Forward) ID rd
|
||||
// io.ex_reg_write_enable := false.B
|
||||
// io.ex_reg_write_address := rd
|
||||
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
|
||||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
|
||||
opcode === Instructions.jalr || opcode === Instructions.csr
|
||||
io.ex_reg_write_enable := rd_used
|
||||
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
|
||||
// Lab3(Forward) ID rd End
|
||||
io.ex_csr_address := io.instruction(31, 20)
|
||||
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
|
||||
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
|
||||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
|
||||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxCase
|
||||
import riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall_flag_ctrl = Input(Bool())
|
||||
val jump_flag_id = Input(Bool())
|
||||
val jump_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
val rom_instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val id_instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
pc := MuxCase(
|
||||
pc + 4.U,
|
||||
IndexedSeq(
|
||||
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
|
||||
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
|
||||
)
|
||||
)
|
||||
|
||||
io.instruction_address := pc
|
||||
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
|
||||
}
|
||||
83
lab3/朱梓涵24325356/core/fivestage_forward/MEM2WB.scala
Normal file
83
lab3/朱梓涵24325356/core/fivestage_forward/MEM2WB.scala
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class MEM2WB extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val memory_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_data = Module(new PipelineRegister())
|
||||
memory_read_data.io.in := io.memory_read_data
|
||||
memory_read_data.io.stall := stall
|
||||
memory_read_data.io.flush := flush
|
||||
io.output_memory_read_data := memory_read_data.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
109
lab3/朱梓涵24325356/core/fivestage_forward/MemoryAccess.scala
Normal file
109
lab3/朱梓涵24325356/core/fivestage_forward/MemoryAccess.scala
Normal file
@@ -0,0 +1,109 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
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 regs_write_source = Input(UInt(2.W))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val forward_data = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
|
||||
io.bundle.write_enable := io.memory_write_enable
|
||||
io.bundle.write_data := 0.U
|
||||
io.bundle.address := io.alu_result
|
||||
io.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.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.bundle.write_data := io.reg2_data
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(io.funct3 === InstructionsTypeS.sb) {
|
||||
io.bundle.write_strobe(mem_address_index) := true.B
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
|
||||
}.otherwise {
|
||||
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
|
||||
io.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.forward_data := Mux(io.regs_write_source === RegWriteSource.CSR, io.csr_read_data, io.alu_result)
|
||||
}
|
||||
40
lab3/朱梓涵24325356/core/fivestage_forward/WriteBack.scala
Normal file
40
lab3/朱梓涵24325356/core/fivestage_forward/WriteBack.scala
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.fivestage_forward
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
103
lab3/朱梓涵24325356/core/fivestage_stall/CLINT.scala
Normal file
103
lab3/朱梓涵24325356/core/fivestage_stall/CLINT.scala
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxLookup
|
||||
import riscv.Parameters
|
||||
|
||||
object InterruptStatus {
|
||||
val None = 0x0.U(8.W)
|
||||
val Timer0 = 0x1.U(8.W)
|
||||
val Ret = 0xFF.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 {
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val jump_flag = Input(Bool())
|
||||
val jump_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
|
||||
val ex_interrupt_assert = Output(Bool())
|
||||
|
||||
val csr_bundle = new CSRDirectAccessBundle
|
||||
})
|
||||
val interrupt_enable = io.csr_bundle.mstatus(3)
|
||||
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
|
||||
val instruction_address = Mux(
|
||||
io.jump_flag,
|
||||
io.jump_address,
|
||||
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
|
||||
)
|
||||
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
|
||||
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
|
||||
|
||||
when(io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := MuxLookup(
|
||||
io.instruction_ex,
|
||||
10.U,
|
||||
IndexedSeq(
|
||||
InstructionsEnv.ecall -> 11.U,
|
||||
InstructionsEnv.ebreak -> 3.U,
|
||||
)
|
||||
)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
|
||||
}.elsewhen(io.instruction_ex === InstructionsRet.mret) {
|
||||
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := true.B
|
||||
io.ex_interrupt_assert := true.B
|
||||
io.ex_interrupt_handler_address := io.csr_bundle.mepc
|
||||
}.otherwise {
|
||||
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
|
||||
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
|
||||
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
|
||||
io.csr_bundle.direct_write_enable := false.B
|
||||
io.ex_interrupt_assert := false.B
|
||||
io.ex_interrupt_handler_address := 0.U
|
||||
}
|
||||
}
|
||||
148
lab3/朱梓涵24325356/core/fivestage_stall/CPU.scala
Normal file
148
lab3/朱梓涵24325356/core/fivestage_stall/CPU.scala
Normal file
@@ -0,0 +1,148 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{CPUBundle, CSR, RegisterFile}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val ctrl = Module(new Control)
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val if2id = Module(new IF2ID)
|
||||
val id = Module(new InstructionDecode)
|
||||
val id2ex = Module(new ID2EX)
|
||||
val ex = Module(new Execute)
|
||||
val ex2mem = Module(new EX2MEM)
|
||||
val mem = Module(new MemoryAccess)
|
||||
val mem2wb = Module(new MEM2WB)
|
||||
val wb = Module(new WriteBack)
|
||||
val clint = Module(new CLINT)
|
||||
val csr_regs = Module(new CSR)
|
||||
|
||||
ctrl.io.jump_flag := ex.io.if_jump_flag
|
||||
ctrl.io.rs1_id := id.io.regs_reg1_read_address
|
||||
ctrl.io.rs2_id := id.io.regs_reg2_read_address
|
||||
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
|
||||
ctrl.io.reg_write_enable_ex := id2ex.io.output_regs_write_enable
|
||||
ctrl.io.rd_mem := ex2mem.io.output_regs_write_address
|
||||
ctrl.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
|
||||
|
||||
regs.io.write_enable := mem2wb.io.output_regs_write_enable
|
||||
regs.io.write_address := mem2wb.io.output_regs_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
|
||||
|
||||
regs.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := regs.io.debug_read_data
|
||||
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
|
||||
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
|
||||
inst_fetch.io.jump_address_id := ex.io.if_jump_address
|
||||
inst_fetch.io.rom_instruction := io.instruction
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
|
||||
if2id.io.stall := ctrl.io.if2id_stall
|
||||
if2id.io.flush := ctrl.io.if2id_flush
|
||||
if2id.io.instruction := inst_fetch.io.id_instruction
|
||||
if2id.io.instruction_address := inst_fetch.io.instruction_address
|
||||
if2id.io.interrupt_flag := io.interrupt_flag
|
||||
|
||||
id.io.instruction := if2id.io.output_instruction
|
||||
|
||||
id2ex.io.flush := ctrl.io.id2ex_flush
|
||||
id2ex.io.instruction := if2id.io.output_instruction
|
||||
id2ex.io.instruction_address := if2id.io.output_instruction_address
|
||||
id2ex.io.reg1_data := regs.io.read_data1
|
||||
id2ex.io.reg2_data := regs.io.read_data2
|
||||
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
|
||||
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
|
||||
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
|
||||
id2ex.io.regs_write_address := id.io.ex_reg_write_address
|
||||
id2ex.io.regs_write_source := id.io.ex_reg_write_source
|
||||
id2ex.io.immediate := id.io.ex_immediate
|
||||
id2ex.io.aluop1_source := id.io.ex_aluop1_source
|
||||
id2ex.io.aluop2_source := id.io.ex_aluop2_source
|
||||
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
|
||||
id2ex.io.csr_address := id.io.ex_csr_address
|
||||
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
|
||||
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
|
||||
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
|
||||
|
||||
ex.io.instruction := id2ex.io.output_instruction
|
||||
ex.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex.io.reg1_data := id2ex.io.output_reg1_data
|
||||
ex.io.reg2_data := id2ex.io.output_reg2_data
|
||||
ex.io.immediate_id := id2ex.io.output_immediate
|
||||
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
|
||||
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
|
||||
ex.io.csr_read_data_id := id2ex.io.output_csr_read_data
|
||||
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
|
||||
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
|
||||
|
||||
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
|
||||
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
|
||||
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
|
||||
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
|
||||
ex2mem.io.reg2_data := ex.io.mem_reg2_data
|
||||
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
|
||||
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
|
||||
ex2mem.io.alu_result := ex.io.mem_alu_result
|
||||
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
|
||||
|
||||
mem.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem.io.reg2_data := ex2mem.io.output_reg2_data
|
||||
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
|
||||
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
|
||||
mem.io.funct3 := ex2mem.io.output_funct3
|
||||
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
io.memory_bundle <> mem.io.bundle
|
||||
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
|
||||
|
||||
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
|
||||
mem2wb.io.alu_result := ex2mem.io.output_alu_result
|
||||
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
|
||||
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
|
||||
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
|
||||
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
|
||||
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
|
||||
|
||||
wb.io.instruction_address := mem2wb.io.output_instruction_address
|
||||
wb.io.alu_result := mem2wb.io.output_alu_result
|
||||
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
|
||||
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
|
||||
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
|
||||
|
||||
clint.io.instruction_address_if := inst_fetch.io.instruction_address
|
||||
clint.io.instruction_address_id := if2id.io.output_instruction_address
|
||||
clint.io.instruction_ex := id2ex.io.output_instruction
|
||||
clint.io.jump_flag := ex.io.clint_jump_flag
|
||||
clint.io.jump_address := ex.io.clint_jump_address
|
||||
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
|
||||
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
|
||||
|
||||
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
|
||||
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
|
||||
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
|
||||
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
|
||||
}
|
||||
46
lab3/朱梓涵24325356/core/fivestage_stall/Control.scala
Normal file
46
lab3/朱梓涵24325356/core/fivestage_stall/Control.scala
Normal file
@@ -0,0 +1,46 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
class Control extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag = Input(Bool())
|
||||
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_ex = Input(Bool())
|
||||
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val reg_write_enable_mem = Input(Bool())
|
||||
|
||||
val if2id_flush = Output(Bool())
|
||||
val id2ex_flush = Output(Bool())
|
||||
val pc_stall = Output(Bool())
|
||||
val if2id_stall = Output(Bool())
|
||||
})
|
||||
|
||||
// Lab3(Stall)
|
||||
val hazard_from_ex = io.reg_write_enable_ex && io.rd_ex =/= 0.U && (io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
|
||||
val hazard_from_mem = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
|
||||
val stall = hazard_from_ex || hazard_from_mem
|
||||
val flush = io.jump_flag
|
||||
io.pc_stall := stall && !flush
|
||||
io.if2id_stall := stall && !flush
|
||||
io.if2id_flush := flush
|
||||
io.id2ex_flush := flush || stall
|
||||
// Lab3(Stall) End
|
||||
}
|
||||
108
lab3/朱梓涵24325356/core/fivestage_stall/EX2MEM.scala
Normal file
108
lab3/朱梓涵24325356/core/fivestage_stall/EX2MEM.scala
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class EX2MEM extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val funct3 = Input(UInt(3.W))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_funct3 = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val funct3 = Module(new PipelineRegister(3))
|
||||
funct3.io.in := io.funct3
|
||||
funct3.io.stall := stall
|
||||
funct3.io.flush := flush
|
||||
io.output_funct3 := funct3.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
101
lab3/朱梓涵24325356/core/fivestage_stall/Execute.scala
Normal file
101
lab3/朱梓涵24325356/core/fivestage_stall/Execute.scala
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{ALU, ALUControl}
|
||||
|
||||
|
||||
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_id = Input(UInt(Parameters.DataWidth))
|
||||
val aluop1_source_id = Input(UInt(1.W))
|
||||
val aluop2_source_id = Input(UInt(1.W))
|
||||
val csr_read_data_id = Input(UInt(Parameters.DataWidth))
|
||||
val interrupt_assert_clint = Input(Bool())
|
||||
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val mem_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val csr_write_data = Output(UInt(Parameters.DataWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
val clint_jump_flag = Output(Bool())
|
||||
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val uimm = io.instruction(19, 15)
|
||||
|
||||
// ALU compute
|
||||
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_id === ALUOp1Source.InstructionAddress,
|
||||
io.instruction_address,
|
||||
io.reg1_data
|
||||
)
|
||||
alu.io.op2 := Mux(
|
||||
io.aluop2_source_id === ALUOp2Source.Immediate,
|
||||
io.immediate_id,
|
||||
io.reg2_data
|
||||
)
|
||||
io.mem_alu_result := alu.io.result
|
||||
io.mem_reg2_data := io.reg2_data
|
||||
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
|
||||
InstructionsTypeCSR.csrrw -> io.reg1_data,
|
||||
InstructionsTypeCSR.csrrc -> io.csr_read_data_id.&((~io.reg1_data).asUInt),
|
||||
InstructionsTypeCSR.csrrs -> io.csr_read_data_id.|(io.reg1_data),
|
||||
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
|
||||
InstructionsTypeCSR.csrrci -> io.csr_read_data_id.&((~Cat(0.U(27.W), uimm)).asUInt),
|
||||
InstructionsTypeCSR.csrrsi -> io.csr_read_data_id.|(Cat(0.U(27.W), uimm)),
|
||||
))
|
||||
|
||||
// jump and interrupt
|
||||
val instruction_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.clint_jump_flag := instruction_jump_flag
|
||||
io.clint_jump_address := alu.io.result
|
||||
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
|
||||
io.if_jump_address := Mux(io.interrupt_assert_clint,
|
||||
io.interrupt_handler_address_clint,
|
||||
alu.io.result
|
||||
)
|
||||
}
|
||||
164
lab3/朱梓涵24325356/core/fivestage_stall/ID2EX.scala
Normal file
164
lab3/朱梓涵24325356/core/fivestage_stall/ID2EX.scala
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class ID2EX extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
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_write_enable = Input(Bool())
|
||||
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_reg1_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val output_aluop1_source = Output(UInt(1.W))
|
||||
val output_aluop2_source = Output(UInt(1.W))
|
||||
val output_csr_write_enable = Output(Bool())
|
||||
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg1_read_address.io.in := io.regs_reg1_read_address
|
||||
regs_reg1_read_address.io.stall := stall
|
||||
regs_reg1_read_address.io.flush := io.flush
|
||||
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
|
||||
|
||||
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_reg2_read_address.io.in := io.regs_reg2_read_address
|
||||
regs_reg2_read_address.io.stall := stall
|
||||
regs_reg2_read_address.io.flush := io.flush
|
||||
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := io.flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := io.flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := io.flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val reg1_data = Module(new PipelineRegister())
|
||||
reg1_data.io.in := io.reg1_data
|
||||
reg1_data.io.stall := stall
|
||||
reg1_data.io.flush := io.flush
|
||||
io.output_reg1_data := reg1_data.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := io.flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val immediate = Module(new PipelineRegister())
|
||||
immediate.io.in := io.immediate
|
||||
immediate.io.stall := stall
|
||||
immediate.io.flush := io.flush
|
||||
io.output_immediate := immediate.io.out
|
||||
|
||||
val aluop1_source = Module(new PipelineRegister(1))
|
||||
aluop1_source.io.in := io.aluop1_source
|
||||
aluop1_source.io.stall := stall
|
||||
aluop1_source.io.flush := io.flush
|
||||
io.output_aluop1_source := aluop1_source.io.out
|
||||
|
||||
val aluop2_source = Module(new PipelineRegister(1))
|
||||
aluop2_source.io.in := io.aluop2_source
|
||||
aluop2_source.io.stall := stall
|
||||
aluop2_source.io.flush := io.flush
|
||||
io.output_aluop2_source := aluop2_source.io.out
|
||||
|
||||
val csr_write_enable = Module(new PipelineRegister(1))
|
||||
csr_write_enable.io.in := io.csr_write_enable
|
||||
csr_write_enable.io.stall := stall
|
||||
csr_write_enable.io.flush := io.flush
|
||||
io.output_csr_write_enable := csr_write_enable.io.out
|
||||
|
||||
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
|
||||
csr_address.io.in := io.csr_address
|
||||
csr_address.io.stall := stall
|
||||
csr_address.io.flush := io.flush
|
||||
io.output_csr_address := csr_address.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := io.flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := io.flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := io.flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
51
lab3/朱梓涵24325356/core/fivestage_stall/IF2ID.scala
Normal file
51
lab3/朱梓涵24325356/core/fivestage_stall/IF2ID.scala
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class IF2ID extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall = Input(Bool())
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
|
||||
})
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := io.stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := io.stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
|
||||
interrupt_flag.io.in := io.interrupt_flag
|
||||
interrupt_flag.io.stall := io.stall
|
||||
interrupt_flag.io.flush := io.flush
|
||||
io.output_interrupt_flag := interrupt_flag.io.out
|
||||
}
|
||||
214
lab3/朱梓涵24325356/core/fivestage_stall/InstructionDecode.scala
Normal file
214
lab3/朱梓涵24325356/core/fivestage_stall/InstructionDecode.scala
Normal file
@@ -0,0 +1,214 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
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(Bool())
|
||||
val ex_aluop2_source = Output(Bool())
|
||||
val ex_memory_read_enable = Output(Bool())
|
||||
val ex_memory_write_enable = Output(Bool())
|
||||
val ex_reg_write_source = Output(UInt(2.W))
|
||||
val ex_reg_write_enable = Output(Bool())
|
||||
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val ex_csr_write_enable = Output(Bool())
|
||||
})
|
||||
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)
|
||||
|
||||
// Lab3(Stall) ID rs
|
||||
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
|
||||
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
|
||||
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
|
||||
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
|
||||
// Lab3(Stall) ID rs End
|
||||
io.ex_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_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.ex_memory_read_enable := opcode === InstructionTypes.L
|
||||
io.ex_memory_write_enable := opcode === InstructionTypes.S
|
||||
io.ex_reg_write_source := MuxLookup(
|
||||
opcode,
|
||||
RegWriteSource.ALUResult,
|
||||
IndexedSeq(
|
||||
InstructionTypes.L -> RegWriteSource.Memory,
|
||||
Instructions.csr -> RegWriteSource.CSR,
|
||||
Instructions.jal -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.jalr -> RegWriteSource.NextInstructionAddress
|
||||
)
|
||||
)
|
||||
// Lab3(Stall) ID rd
|
||||
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
|
||||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
|
||||
opcode === Instructions.jalr || opcode === Instructions.csr
|
||||
io.ex_reg_write_enable := rd_used
|
||||
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
|
||||
// Lab3(Stall) ID rd End
|
||||
io.ex_csr_address := io.instruction(31, 20)
|
||||
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
|
||||
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
|
||||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
|
||||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
|
||||
)
|
||||
}
|
||||
48
lab3/朱梓涵24325356/core/fivestage_stall/InstructionFetch.scala
Normal file
48
lab3/朱梓涵24325356/core/fivestage_stall/InstructionFetch.scala
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxCase
|
||||
import riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val stall_flag_ctrl = Input(Bool())
|
||||
val jump_flag_id = Input(Bool())
|
||||
val jump_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
val rom_instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val id_instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
pc := MuxCase(
|
||||
pc + 4.U,
|
||||
IndexedSeq(
|
||||
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
|
||||
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
|
||||
)
|
||||
)
|
||||
|
||||
io.instruction_address := pc
|
||||
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
|
||||
}
|
||||
83
lab3/朱梓涵24325356/core/fivestage_stall/MEM2WB.scala
Normal file
83
lab3/朱梓涵24325356/core/fivestage_stall/MEM2WB.scala
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class MEM2WB extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val memory_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val stall = false.B
|
||||
val flush = false.B
|
||||
|
||||
val alu_result = Module(new PipelineRegister())
|
||||
alu_result.io.in := io.alu_result
|
||||
alu_result.io.stall := stall
|
||||
alu_result.io.flush := flush
|
||||
io.output_alu_result := alu_result.io.out
|
||||
|
||||
val memory_read_data = Module(new PipelineRegister())
|
||||
memory_read_data.io.in := io.memory_read_data
|
||||
memory_read_data.io.stall := stall
|
||||
memory_read_data.io.flush := flush
|
||||
io.output_memory_read_data := memory_read_data.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
106
lab3/朱梓涵24325356/core/fivestage_stall/MemoryAccess.scala
Normal file
106
lab3/朱梓涵24325356/core/fivestage_stall/MemoryAccess.scala
Normal file
@@ -0,0 +1,106 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
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 regs_write_source = Input(UInt(2.W))
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
|
||||
io.bundle.write_enable := io.memory_write_enable
|
||||
io.bundle.write_data := 0.U
|
||||
io.bundle.address := io.alu_result
|
||||
io.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.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.bundle.write_data := io.reg2_data
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(io.funct3 === InstructionsTypeS.sb) {
|
||||
io.bundle.write_strobe(mem_address_index) := true.B
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
|
||||
}.otherwise {
|
||||
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
|
||||
io.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.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.bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
lab3/朱梓涵24325356/core/fivestage_stall/WriteBack.scala
Normal file
40
lab3/朱梓涵24325356/core/fivestage_stall/WriteBack.scala
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.fivestage_stall
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
88
lab3/朱梓涵24325356/core/threestage/CLINT.scala
Normal file
88
lab3/朱梓涵24325356/core/threestage/CLINT.scala
Normal file
@@ -0,0 +1,88 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxLookup
|
||||
import riscv.Parameters
|
||||
|
||||
object InterruptStatus {
|
||||
val None = 0x0.U(8.W)
|
||||
val Timer0 = 0x1.U(8.W)
|
||||
val Ret = 0xFF.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 {
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val jump_flag = Input(Bool())
|
||||
val jump_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
|
||||
val ex_interrupt_assert = Output(Bool())
|
||||
|
||||
val csr_bundle = new CSRDirectAccessBundle
|
||||
})
|
||||
val interrupt_enable = io.csr_bundle.mstatus(3)
|
||||
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
|
||||
val instruction_address = Mux(
|
||||
io.jump_flag,
|
||||
io.jump_address,
|
||||
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
|
||||
)
|
||||
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
|
||||
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
|
||||
val exception = io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak
|
||||
val interrupt = io.interrupt_flag =/= InterruptStatus.None && interrupt_enable
|
||||
val mret = io.instruction_ex === InstructionsRet.mret
|
||||
val interrupt_assert = exception || interrupt || mret
|
||||
|
||||
io.csr_bundle.mstatus_write_data := Mux(mret, mstatus_recover_interrupt, mstatus_disable_interrupt)
|
||||
io.csr_bundle.mepc_write_data := instruction_address
|
||||
io.csr_bundle.mcause_write_data := Mux(
|
||||
exception,
|
||||
MuxLookup(
|
||||
io.instruction_ex,
|
||||
10.U,
|
||||
IndexedSeq(
|
||||
InstructionsEnv.ecall -> 11.U,
|
||||
InstructionsEnv.ebreak -> 3.U,
|
||||
)
|
||||
),
|
||||
Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
|
||||
)
|
||||
io.csr_bundle.direct_write_enable := interrupt_assert
|
||||
io.ex_interrupt_assert := interrupt_assert
|
||||
io.ex_interrupt_handler_address := Mux(mret, io.csr_bundle.mepc, io.csr_bundle.mtvec)
|
||||
}
|
||||
107
lab3/朱梓涵24325356/core/threestage/CPU.scala
Normal file
107
lab3/朱梓涵24325356/core/threestage/CPU.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.threestage
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{CPUBundle, CSR, RegisterFile}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val ctrl = Module(new Control)
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val if2id = Module(new IF2ID)
|
||||
val id = Module(new InstructionDecode)
|
||||
val id2ex = Module(new ID2EX)
|
||||
val ex = Module(new Execute)
|
||||
val clint = Module(new CLINT)
|
||||
val csr_regs = Module(new CSR)
|
||||
|
||||
// Lab3(ThreeStage)
|
||||
// if2id.io.flush := false.B
|
||||
// id2ex.io.flush := false.B
|
||||
ctrl.io.jump_flag_ex := ex.io.if_jump_flag
|
||||
if2id.io.flush := ctrl.io.if2id_flush
|
||||
id2ex.io.flush := ctrl.io.id2ex_flush
|
||||
// Lab3(ThreeStage) End
|
||||
|
||||
regs.io.write_enable := id2ex.io.output_regs_write_enable
|
||||
regs.io.write_address := id2ex.io.output_regs_write_address
|
||||
regs.io.write_data := ex.io.regs_write_data
|
||||
regs.io.read_address1 := id.io.regs_reg1_read_address
|
||||
regs.io.read_address2 := id.io.regs_reg2_read_address
|
||||
regs.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := regs.io.debug_read_data
|
||||
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
inst_fetch.io.jump_flag_ex := ex.io.if_jump_flag
|
||||
inst_fetch.io.jump_address_ex := ex.io.if_jump_address
|
||||
inst_fetch.io.rom_instruction := io.instruction
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
|
||||
if2id.io.instruction := inst_fetch.io.id_instruction
|
||||
if2id.io.instruction_address := inst_fetch.io.instruction_address
|
||||
if2id.io.interrupt_flag := io.interrupt_flag
|
||||
|
||||
id.io.instruction := if2id.io.output_instruction
|
||||
|
||||
id2ex.io.instruction := if2id.io.output_instruction
|
||||
id2ex.io.instruction_address := if2id.io.output_instruction_address
|
||||
id2ex.io.reg1_data := regs.io.read_data1
|
||||
id2ex.io.reg2_data := regs.io.read_data2
|
||||
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
|
||||
id2ex.io.regs_write_address := id.io.ex_reg_write_address
|
||||
id2ex.io.regs_write_source := id.io.ex_reg_write_source
|
||||
id2ex.io.immediate := id.io.ex_immediate
|
||||
id2ex.io.aluop1_source := id.io.ex_aluop1_source
|
||||
id2ex.io.aluop2_source := id.io.ex_aluop2_source
|
||||
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
|
||||
id2ex.io.csr_address := id.io.ex_csr_address
|
||||
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
|
||||
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
|
||||
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
|
||||
|
||||
ex.io.instruction := id2ex.io.output_instruction
|
||||
ex.io.instruction_address := id2ex.io.output_instruction_address
|
||||
ex.io.reg1_data := id2ex.io.output_reg1_data
|
||||
ex.io.reg2_data := id2ex.io.output_reg2_data
|
||||
ex.io.csr_read_data := id2ex.io.output_csr_read_data
|
||||
ex.io.immediate_id := id2ex.io.output_immediate
|
||||
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
|
||||
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
|
||||
ex.io.memory_read_enable_id := id2ex.io.output_memory_read_enable
|
||||
ex.io.memory_write_enable_id := id2ex.io.output_memory_write_enable
|
||||
ex.io.regs_write_source_id := id2ex.io.output_regs_write_source
|
||||
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
|
||||
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
|
||||
io.device_select := ex.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
io.memory_bundle <> ex.io.memory_bundle
|
||||
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## ex.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
|
||||
|
||||
clint.io.instruction_address_if := inst_fetch.io.instruction_address
|
||||
clint.io.instruction_address_id := if2id.io.output_instruction_address
|
||||
clint.io.instruction_ex := id2ex.io.output_instruction
|
||||
clint.io.jump_flag := ex.io.clint_jump_flag
|
||||
clint.io.jump_address := ex.io.clint_jump_address
|
||||
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
|
||||
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
|
||||
|
||||
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
|
||||
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
|
||||
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
|
||||
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
|
||||
}
|
||||
30
lab3/朱梓涵24325356/core/threestage/Control.scala
Normal file
30
lab3/朱梓涵24325356/core/threestage/Control.scala
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
|
||||
class Control extends Module {
|
||||
// Lab3(ThreeStage)
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag_ex = Input(Bool())
|
||||
val if2id_flush = Output(Bool())
|
||||
val id2ex_flush = Output(Bool())
|
||||
})
|
||||
val flush = io.jump_flag_ex
|
||||
io.if2id_flush := flush
|
||||
io.id2ex_flush := flush
|
||||
// Lab3(ThreeStage) End
|
||||
}
|
||||
191
lab3/朱梓涵24325356/core/threestage/Execute.scala
Normal file
191
lab3/朱梓涵24325356/core/threestage/Execute.scala
Normal file
@@ -0,0 +1,191 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import peripheral.RAMBundle
|
||||
import riscv.Parameters
|
||||
import riscv.core.{ALU, ALUControl}
|
||||
|
||||
|
||||
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 csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val immediate_id = Input(UInt(Parameters.DataWidth))
|
||||
val aluop1_source_id = Input(UInt(1.W))
|
||||
val aluop2_source_id = Input(UInt(1.W))
|
||||
val memory_read_enable_id = Input(Bool())
|
||||
val memory_write_enable_id = Input(Bool())
|
||||
val regs_write_source_id = Input(UInt(2.W))
|
||||
val interrupt_assert_clint = Input(Bool())
|
||||
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
|
||||
val csr_write_data = Output(UInt(Parameters.DataWidth))
|
||||
val regs_write_data = Output(UInt(Parameters.DataWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
val clint_jump_flag = Output(Bool())
|
||||
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val uimm = io.instruction(19, 15)
|
||||
|
||||
// ALU compute
|
||||
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_id === ALUOp1Source.InstructionAddress,
|
||||
io.instruction_address,
|
||||
io.reg1_data
|
||||
)
|
||||
alu.io.op2 := Mux(
|
||||
io.aluop2_source_id === ALUOp2Source.Immediate,
|
||||
io.immediate_id,
|
||||
io.reg2_data
|
||||
)
|
||||
io.csr_write_data := MuxLookup(
|
||||
funct3,
|
||||
0.U,
|
||||
IndexedSeq(
|
||||
InstructionsTypeCSR.csrrw -> io.reg1_data,
|
||||
InstructionsTypeCSR.csrrc -> (io.csr_read_data & (~io.reg1_data).asUInt),
|
||||
InstructionsTypeCSR.csrrs -> (io.csr_read_data | io.reg1_data),
|
||||
InstructionsTypeCSR.csrrwi -> (0.U(27.W) ## uimm),
|
||||
InstructionsTypeCSR.csrrci -> (io.csr_read_data & (~(0.U(27.W) ## uimm)).asUInt),
|
||||
InstructionsTypeCSR.csrrsi -> (io.csr_read_data | 0.U(27.W) ## uimm),
|
||||
)
|
||||
)
|
||||
|
||||
// memory access
|
||||
val mem_address_index = alu.io.result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
val mem_read_data = Wire(UInt(Parameters.DataWidth))
|
||||
io.memory_bundle.write_enable := io.memory_write_enable_id
|
||||
io.memory_bundle.write_data := 0.U
|
||||
io.memory_bundle.address := alu.io.result
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
mem_read_data := 0.U
|
||||
|
||||
when(io.memory_read_enable_id) {
|
||||
val data = io.memory_bundle.read_data
|
||||
mem_read_data := MuxLookup(
|
||||
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_id) {
|
||||
io.memory_bundle.write_data := io.reg2_data
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(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(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(funct3 === InstructionsTypeS.sw) {
|
||||
for (i <- 0 until Parameters.WordSize) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write back
|
||||
io.regs_write_data := MuxLookup(
|
||||
io.regs_write_source_id,
|
||||
alu.io.result,
|
||||
IndexedSeq(
|
||||
RegWriteSource.Memory -> mem_read_data,
|
||||
RegWriteSource.CSR -> io.csr_read_data,
|
||||
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
|
||||
)
|
||||
)
|
||||
|
||||
// jump and interrupt
|
||||
val instruction_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.clint_jump_flag := instruction_jump_flag
|
||||
io.clint_jump_address := alu.io.result
|
||||
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
|
||||
io.if_jump_address := Mux(io.interrupt_assert_clint,
|
||||
io.interrupt_handler_address_clint,
|
||||
alu.io.result
|
||||
)
|
||||
}
|
||||
148
lab3/朱梓涵24325356/core/threestage/ID2EX.scala
Normal file
148
lab3/朱梓涵24325356/core/threestage/ID2EX.scala
Normal file
@@ -0,0 +1,148 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class ID2EX extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val regs_write_enable = Input(Bool())
|
||||
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
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_write_enable = Input(Bool())
|
||||
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val csr_read_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_regs_write_enable = Output(Bool())
|
||||
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val output_regs_write_source = Output(UInt(2.W))
|
||||
val output_reg1_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_reg2_data = Output(UInt(Parameters.DataWidth))
|
||||
val output_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val output_aluop1_source = Output(UInt(1.W))
|
||||
val output_aluop2_source = Output(UInt(1.W))
|
||||
val output_csr_write_enable = Output(Bool())
|
||||
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val output_memory_read_enable = Output(Bool())
|
||||
val output_memory_write_enable = Output(Bool())
|
||||
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val regs_write_enable = Module(new PipelineRegister(1))
|
||||
regs_write_enable.io.in := io.regs_write_enable
|
||||
regs_write_enable.io.stall := stall
|
||||
regs_write_enable.io.flush := io.flush
|
||||
io.output_regs_write_enable := regs_write_enable.io.out
|
||||
|
||||
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
|
||||
regs_write_address.io.in := io.regs_write_address
|
||||
regs_write_address.io.stall := stall
|
||||
regs_write_address.io.flush := io.flush
|
||||
io.output_regs_write_address := regs_write_address.io.out
|
||||
|
||||
val regs_write_source = Module(new PipelineRegister(2))
|
||||
regs_write_source.io.in := io.regs_write_source
|
||||
regs_write_source.io.stall := stall
|
||||
regs_write_source.io.flush := io.flush
|
||||
io.output_regs_write_source := regs_write_source.io.out
|
||||
|
||||
val reg1_data = Module(new PipelineRegister())
|
||||
reg1_data.io.in := io.reg1_data
|
||||
reg1_data.io.stall := stall
|
||||
reg1_data.io.flush := io.flush
|
||||
io.output_reg1_data := reg1_data.io.out
|
||||
|
||||
val reg2_data = Module(new PipelineRegister())
|
||||
reg2_data.io.in := io.reg2_data
|
||||
reg2_data.io.stall := stall
|
||||
reg2_data.io.flush := io.flush
|
||||
io.output_reg2_data := reg2_data.io.out
|
||||
|
||||
val immediate = Module(new PipelineRegister())
|
||||
immediate.io.in := io.immediate
|
||||
immediate.io.stall := stall
|
||||
immediate.io.flush := io.flush
|
||||
io.output_immediate := immediate.io.out
|
||||
|
||||
val aluop1_source = Module(new PipelineRegister(1))
|
||||
aluop1_source.io.in := io.aluop1_source
|
||||
aluop1_source.io.stall := stall
|
||||
aluop1_source.io.flush := io.flush
|
||||
io.output_aluop1_source := aluop1_source.io.out
|
||||
|
||||
val aluop2_source = Module(new PipelineRegister(1))
|
||||
aluop2_source.io.in := io.aluop2_source
|
||||
aluop2_source.io.stall := stall
|
||||
aluop2_source.io.flush := io.flush
|
||||
io.output_aluop2_source := aluop2_source.io.out
|
||||
|
||||
val csr_write_enable = Module(new PipelineRegister(1))
|
||||
csr_write_enable.io.in := io.csr_write_enable
|
||||
csr_write_enable.io.stall := stall
|
||||
csr_write_enable.io.flush := io.flush
|
||||
io.output_csr_write_enable := csr_write_enable.io.out
|
||||
|
||||
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
|
||||
csr_address.io.in := io.csr_address
|
||||
csr_address.io.stall := stall
|
||||
csr_address.io.flush := io.flush
|
||||
io.output_csr_address := csr_address.io.out
|
||||
|
||||
val memory_read_enable = Module(new PipelineRegister(1))
|
||||
memory_read_enable.io.in := io.memory_read_enable
|
||||
memory_read_enable.io.stall := stall
|
||||
memory_read_enable.io.flush := io.flush
|
||||
io.output_memory_read_enable := memory_read_enable.io.out
|
||||
|
||||
val memory_write_enable = Module(new PipelineRegister(1))
|
||||
memory_write_enable.io.in := io.memory_write_enable
|
||||
memory_write_enable.io.stall := stall
|
||||
memory_write_enable.io.flush := io.flush
|
||||
io.output_memory_write_enable := memory_write_enable.io.out
|
||||
|
||||
val csr_read_data = Module(new PipelineRegister())
|
||||
csr_read_data.io.in := io.csr_read_data
|
||||
csr_read_data.io.stall := stall
|
||||
csr_read_data.io.flush := io.flush
|
||||
io.output_csr_read_data := csr_read_data.io.out
|
||||
}
|
||||
52
lab3/朱梓涵24325356/core/threestage/IF2ID.scala
Normal file
52
lab3/朱梓涵24325356/core/threestage/IF2ID.scala
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
import riscv.core.PipelineRegister
|
||||
|
||||
class IF2ID extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Input(Bool())
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
|
||||
|
||||
val output_instruction = Output(UInt(Parameters.DataWidth))
|
||||
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
|
||||
})
|
||||
|
||||
val stall = false.B
|
||||
|
||||
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
|
||||
instruction.io.in := io.instruction
|
||||
instruction.io.stall := stall
|
||||
instruction.io.flush := io.flush
|
||||
io.output_instruction := instruction.io.out
|
||||
|
||||
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
|
||||
instruction_address.io.in := io.instruction_address
|
||||
instruction_address.io.stall := stall
|
||||
instruction_address.io.flush := io.flush
|
||||
io.output_instruction_address := instruction_address.io.out
|
||||
|
||||
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
|
||||
interrupt_flag.io.in := io.interrupt_flag
|
||||
interrupt_flag.io.stall := stall
|
||||
interrupt_flag.io.flush := io.flush
|
||||
io.output_interrupt_flag := interrupt_flag.io.out
|
||||
}
|
||||
207
lab3/朱梓涵24325356/core/threestage/InstructionDecode.scala
Normal file
207
lab3/朱梓涵24325356/core/threestage/InstructionDecode.scala
Normal file
@@ -0,0 +1,207 @@
|
||||
// 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.threestage
|
||||
|
||||
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(Bool())
|
||||
val ex_aluop2_source = Output(Bool())
|
||||
val ex_memory_read_enable = Output(Bool())
|
||||
val ex_memory_write_enable = Output(Bool())
|
||||
val ex_reg_write_source = Output(UInt(2.W))
|
||||
val ex_reg_write_enable = Output(Bool())
|
||||
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
|
||||
val ex_csr_write_enable = Output(Bool())
|
||||
})
|
||||
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
|
||||
io.ex_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_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.ex_memory_read_enable := opcode === InstructionTypes.L
|
||||
io.ex_memory_write_enable := opcode === InstructionTypes.S
|
||||
io.ex_reg_write_source := MuxLookup(
|
||||
opcode,
|
||||
RegWriteSource.ALUResult,
|
||||
IndexedSeq(
|
||||
InstructionTypes.L -> RegWriteSource.Memory,
|
||||
Instructions.csr -> RegWriteSource.CSR,
|
||||
Instructions.jal -> RegWriteSource.NextInstructionAddress,
|
||||
Instructions.jalr -> RegWriteSource.NextInstructionAddress
|
||||
)
|
||||
)
|
||||
io.ex_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.ex_reg_write_address := rd
|
||||
io.ex_csr_address := io.instruction(31, 20)
|
||||
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
|
||||
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
|
||||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
|
||||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
|
||||
)
|
||||
}
|
||||
47
lab3/朱梓涵24325356/core/threestage/InstructionFetch.scala
Normal file
47
lab3/朱梓涵24325356/core/threestage/InstructionFetch.scala
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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.threestage
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.MuxCase
|
||||
import riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag_ex = Input(Bool())
|
||||
val jump_address_ex = Input(UInt(Parameters.AddrWidth))
|
||||
val rom_instruction = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val id_instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
pc := MuxCase(
|
||||
pc,
|
||||
IndexedSeq(
|
||||
io.jump_flag_ex -> io.jump_address_ex,
|
||||
io.instruction_valid -> (pc + 4.U)
|
||||
)
|
||||
)
|
||||
|
||||
io.instruction_address := pc
|
||||
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
|
||||
}
|
||||
Reference in New Issue
Block a user