Initial Chisel core implementation

This commit is contained in:
abnerhexu
2026-06-26 08:20:25 +00:00
commit 502803c37f
47 changed files with 2342 additions and 0 deletions

173
src/main/scala/Core.scala Normal file
View File

@@ -0,0 +1,173 @@
import chisel3._
import chisel3.util._
import _root_.circt.stage.ChiselStage
class Core(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val imem_req_valid = Output(Bool())
val imem_req_bits = Output(UInt(p.xlen.W))
val imem_resp_valid = Input(Bool())
val imem_resp_bits_0 = Input(UInt(32.W))
val imem_resp_bits_1 = Input(UInt(32.W))
val dmem_req_valid = Output(Bool())
val dmem_req_bits_addr = Output(UInt(p.xlen.W))
val dmem_req_bits_data = Output(UInt(p.xlen.W))
val dmem_req_bits_isStore = Output(Bool())
val dmem_req_bits_size = Output(UInt(3.W))
val dmem_resp_valid = Input(Bool())
val dmem_resp_bits = Input(UInt(p.xlen.W))
})
val sFetch :: sExec :: sLoadWait :: Nil = Enum(3)
val state = RegInit(sFetch)
val pc = RegInit(Consts.ResetVector)
val instReg = RegInit(0.U(32.W))
val pcReg = RegInit(Consts.ResetVector)
val regs = RegInit(VecInit(Seq.fill(32)(0.U(p.xlen.W))))
val decoder = Module(new Decoder(p))
decoder.io.pc := pcReg
decoder.io.inst := instReg
val dec = decoder.io.out
val alu = Module(new ALU(p))
val branch = Module(new BranchUnit(p))
val csr = Module(new CSRFile(p))
def regRead(addr: UInt): UInt = Mux(addr === 0.U, 0.U, regs(addr))
def lowLoad(data: UInt, size: UInt, signed: Bool): UInt = {
val b = data(7, 0)
val h = data(15, 0)
val w = data(31, 0)
MuxLookup(size, data)(Seq(
0.U -> Mux(signed, Consts.signExtend(b, 8), b),
1.U -> Mux(signed, Consts.signExtend(h, 16), h),
2.U -> Mux(signed, Consts.signExtend(w, 32), w),
3.U -> data
))
}
val src1 = regRead(dec.rs1)
val src2 = regRead(dec.rs2)
val aluB = Mux(dec.isOpImm || dec.isJalr || dec.isLoad, dec.immI, src2)
alu.io.fn := dec.aluFn
alu.io.a := src1
alu.io.b := aluB
alu.io.isWord := dec.isWord
branch.io.funct3 := dec.funct3
branch.io.a := src1
branch.io.b := src2
csr.io.cmd.valid := state === sExec && dec.isSystem && dec.funct3 =/= 0.U &&
!(dec.funct3(1) && dec.rs1 === 0.U)
csr.io.cmd.addr := instReg(31, 20)
csr.io.cmd.cmd := dec.funct3
csr.io.cmd.rs1 := src1
csr.io.cmd.zimm := dec.rs1
val isEcall = instReg === "h00000073".U
val isEbreak = instReg === "h00100073".U
val isMret = instReg === "h30200073".U
val takeTrap = state === sExec && (isEcall || isEbreak)
csr.io.trap := takeTrap
csr.io.trapPc := pcReg
csr.io.trapCause := Mux(isEbreak, 3.U, 11.U)
val loadAddr = src1 + dec.immI
val storeAddr = src1 + dec.immS
val pendingLoadAddr = Reg(UInt(p.xlen.W))
val pendingLoadRd = Reg(UInt(5.W))
val pendingLoadSize = Reg(UInt(3.W))
val pendingLoadSigned = Reg(Bool())
val isAmo = instReg(6, 0) === "b0101111".U
val amoOp = instReg(31, 27)
val amoLoadLike = isAmo && amoOp === "b00010".U
val amoStoreLike = isAmo && amoOp === "b00011".U
val memReqInExec = state === sExec && (dec.isLoad || dec.isStore)
io.imem_req_valid := state === sFetch
io.imem_req_bits := pc
io.dmem_req_valid := memReqInExec || state === sLoadWait
io.dmem_req_bits_addr := Mux(state === sLoadWait, pendingLoadAddr, Mux(dec.isStore, storeAddr, loadAddr))
io.dmem_req_bits_data := src2
io.dmem_req_bits_isStore := state === sExec && Mux(isAmo, !amoLoadLike, dec.isStore)
io.dmem_req_bits_size := Mux(state === sLoadWait, pendingLoadSize, dec.memWidth)
val branchTarget = pcReg + dec.immB
val jalTarget = pcReg + dec.immJ
val jalrTarget = (src1 + dec.immI) & (~1.U(p.xlen.W))
val branchTaken = dec.isBranch && branch.io.taken
val nextPc = Mux(dec.isJal, jalTarget,
Mux(dec.isJalr, jalrTarget,
Mux(branchTaken, branchTarget, pcReg + 4.U)))
val execWriteData = WireDefault(alu.io.out)
when(dec.isLui) {
execWriteData := dec.immU
}.elsewhen(dec.isAuipc) {
execWriteData := pcReg + dec.immU
}.elsewhen(dec.isJal || dec.isJalr) {
execWriteData := pcReg + 4.U
}.elsewhen(dec.isSystem && dec.funct3 =/= 0.U) {
execWriteData := csr.io.rdata
}
when(state === sFetch) {
when(io.imem_resp_valid) {
instReg := io.imem_resp_bits_0
pcReg := pc
state := sExec
}
}.elsewhen(state === sExec) {
when(takeTrap) {
pc := csr.io.mtvec
state := sFetch
}.elsewhen(isMret) {
pc := csr.io.mepc
state := sFetch
}.elsewhen(dec.isLoad && !amoStoreLike) {
when(io.dmem_resp_valid) {
when(dec.rd =/= 0.U) {
regs(dec.rd) := lowLoad(io.dmem_resp_bits, dec.memWidth, dec.memSigned)
}
pc := pcReg + 4.U
state := sFetch
}.otherwise {
pendingLoadAddr := loadAddr
pendingLoadRd := dec.rd
pendingLoadSize := dec.memWidth
pendingLoadSigned := dec.memSigned
state := sLoadWait
}
}.elsewhen(dec.isStore || amoStoreLike) {
pc := pcReg + 4.U
state := sFetch
}.otherwise {
when(dec.writesRd && dec.rd =/= 0.U) {
regs(dec.rd) := execWriteData
}
pc := nextPc
state := sFetch
}
}.elsewhen(state === sLoadWait) {
when(io.dmem_resp_valid) {
when(pendingLoadRd =/= 0.U) {
regs(pendingLoadRd) := lowLoad(io.dmem_resp_bits, pendingLoadSize, pendingLoadSigned)
}
pc := pcReg + 4.U
state := sFetch
}
}
}
object Core extends App {
ChiselStage.emitSystemVerilogFile(
new Core(),
args = Array("--target-dir", "generated"),
firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info")
)
}

View File

@@ -0,0 +1,18 @@
import chisel3._
import chisel3.util._
class CommitStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val robValid = Input(Bool())
val robEntry = Input(new RobEntry(p))
val commitReady = Output(Bool())
val freeOldPhys = Output(Bool())
val oldPhys = Output(UInt(log2Ceil(p.physRegs).W))
val flush = Output(Bool())
})
io.commitReady := io.robValid
io.freeOldPhys := io.robValid && io.robEntry.oldDest =/= io.robEntry.dest
io.oldPhys := io.robEntry.oldDest
io.flush := io.robValid && (io.robEntry.exception || io.robEntry.branchMispredict)
}

View File

@@ -0,0 +1,76 @@
import chisel3._
import chisel3.util._
class FetchPacket(p: CoreParams = CoreParams()) extends Bundle {
val pc = UInt(p.xlen.W)
val inst = Vec(p.fetchWidth, UInt(32.W))
val predictedTaken = Bool()
val predictedTarget = UInt(p.xlen.W)
}
class BranchUpdate(p: CoreParams = CoreParams()) extends Bundle {
val valid = Bool()
val pc = UInt(p.xlen.W)
val taken = Bool()
val target = UInt(p.xlen.W)
val isCall = Bool()
val isReturn = Bool()
}
class DecodedInst(p: CoreParams = CoreParams()) extends Bundle {
val valid = Bool()
val pc = UInt(p.xlen.W)
val inst = UInt(32.W)
val rs1 = UInt(5.W)
val rs2 = UInt(5.W)
val rd = UInt(5.W)
val funct3 = UInt(3.W)
val funct7 = UInt(7.W)
val immI = UInt(p.xlen.W)
val immS = UInt(p.xlen.W)
val immB = UInt(p.xlen.W)
val immU = UInt(p.xlen.W)
val immJ = UInt(p.xlen.W)
val opClass = UInt(Consts.OpClassWidth.W)
val aluFn = UInt(5.W)
val memWidth = UInt(3.W)
val memSigned = Bool()
val isLoad = Bool()
val isStore = Bool()
val isBranch = Bool()
val isJal = Bool()
val isJalr = Bool()
val isLui = Bool()
val isAuipc = Bool()
val isOpImm = Bool()
val isOp = Bool()
val isWord = Bool()
val isSystem = Bool()
val writesRd = Bool()
val illegal = Bool()
}
class RenamePacket(p: CoreParams = CoreParams()) extends Bundle {
val valid = Bool()
val decoded = new DecodedInst(p)
val prs1 = UInt(log2Ceil(p.physRegs).W)
val prs2 = UInt(log2Ceil(p.physRegs).W)
val prd = UInt(log2Ceil(p.physRegs).W)
val oldPrd = UInt(log2Ceil(p.physRegs).W)
val robIdx = UInt(log2Ceil(p.robEntries).W)
}
class MemRequest(p: CoreParams = CoreParams()) extends Bundle {
val addr = UInt(p.xlen.W)
val data = UInt(p.xlen.W)
val isStore = Bool()
val size = UInt(3.W)
}
class CsrCommand(p: CoreParams = CoreParams()) extends Bundle {
val valid = Bool()
val addr = UInt(12.W)
val cmd = UInt(3.W)
val rs1 = UInt(p.xlen.W)
val zimm = UInt(5.W)
}

View File

@@ -0,0 +1,35 @@
import chisel3._
import chisel3.util._
object Consts {
val ResetVector = "h80000000".U(64.W)
val OpClassWidth = 4
val OP_NONE = 0.U(OpClassWidth.W)
val OP_ALU = 1.U(OpClassWidth.W)
val OP_BRANCH = 2.U(OpClassWidth.W)
val OP_LOAD = 3.U(OpClassWidth.W)
val OP_STORE = 4.U(OpClassWidth.W)
val OP_SYSTEM = 5.U(OpClassWidth.W)
val OP_FP = 6.U(OpClassWidth.W)
val ALU_ADD = 0.U(5.W)
val ALU_SUB = 1.U(5.W)
val ALU_SLL = 2.U(5.W)
val ALU_SLT = 3.U(5.W)
val ALU_SLTU = 4.U(5.W)
val ALU_XOR = 5.U(5.W)
val ALU_SRL = 6.U(5.W)
val ALU_SRA = 7.U(5.W)
val ALU_OR = 8.U(5.W)
val ALU_AND = 9.U(5.W)
val ALU_MUL = 10.U(5.W)
val ALU_DIV = 11.U(5.W)
val ALU_DIVU = 12.U(5.W)
val ALU_REM = 13.U(5.W)
val ALU_REMU = 14.U(5.W)
val ALU_COPY_B = 15.U(5.W)
def signExtend(value: UInt, from: Int, to: Int = 64): UInt =
Cat(Fill(to - from, value(from - 1)), value(from - 1, 0))
}

View File

@@ -0,0 +1,28 @@
case class CoreParams(
xlen: Int = 64,
fetchWidth: Int = 2,
issueWidth: Int = 2,
archRegs: Int = 32,
physRegs: Int = 64,
robEntries: Int = 64,
intRsEntries: Int = 16,
lsuRsEntries: Int = 12,
fpRsEntries: Int = 16,
loadQueueEntries: Int = 16,
storeQueueEntries: Int = 16,
btbEntries: Int = 512,
rasEntries: Int = 16,
ghrBits: Int = 12,
iCacheBytes: Int = 32 * 1024,
iCacheWays: Int = 4,
dCacheBytes: Int = 32 * 1024,
dCacheWays: Int = 8,
cacheLineBytes: Int = 64,
itlbEntries: Int = 32,
dtlbEntries: Int = 32
) {
require(xlen == 64, "this implementation targets RV64")
require(fetchWidth == 2, "frontend is parameterized around dual fetch")
require(issueWidth == 2, "backend structures are parameterized around dual issue")
}

View File

@@ -0,0 +1,99 @@
import chisel3._
import chisel3.util._
class CSRFile(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val cmd = Input(new CsrCommand(p))
val rdata = Output(UInt(p.xlen.W))
val trap = Input(Bool())
val trapPc = Input(UInt(p.xlen.W))
val trapCause = Input(UInt(p.xlen.W))
val satp = Output(UInt(p.xlen.W))
val mtvec = Output(UInt(p.xlen.W))
val mepc = Output(UInt(p.xlen.W))
})
val cycle = RegInit(0.U(p.xlen.W))
val instret = RegInit(0.U(p.xlen.W))
val mstatus = RegInit(0.U(p.xlen.W))
val misa = RegInit("h800000000014112d".U(p.xlen.W))
val mtvecReg = RegInit(0.U(p.xlen.W))
val mepcReg = RegInit(0.U(p.xlen.W))
val mcause = RegInit(0.U(p.xlen.W))
val mtval = RegInit(0.U(p.xlen.W))
val medeleg = RegInit(0.U(p.xlen.W))
val mideleg = RegInit(0.U(p.xlen.W))
val mie = RegInit(0.U(p.xlen.W))
val mip = RegInit(0.U(p.xlen.W))
val sstatus = RegInit(0.U(p.xlen.W))
val stvec = RegInit(0.U(p.xlen.W))
val sepc = RegInit(0.U(p.xlen.W))
val scause = RegInit(0.U(p.xlen.W))
val stval = RegInit(0.U(p.xlen.W))
val sscratch = RegInit(0.U(p.xlen.W))
val satpReg = RegInit(0.U(p.xlen.W))
cycle := cycle + 1.U
io.satp := satpReg
io.mtvec := mtvecReg
io.mepc := mepcReg
val r = WireDefault(0.U(p.xlen.W))
switch(io.cmd.addr) {
is("h300".U) { r := mstatus }
is("h301".U) { r := misa }
is("h302".U) { r := medeleg }
is("h303".U) { r := mideleg }
is("h304".U) { r := mie }
is("h305".U) { r := mtvecReg }
is("h341".U) { r := mepcReg }
is("h342".U) { r := mcause }
is("h343".U) { r := mtval }
is("h344".U) { r := mip }
is("h100".U) { r := sstatus }
is("h105".U) { r := stvec }
is("h140".U) { r := sscratch }
is("h141".U) { r := sepc }
is("h142".U) { r := scause }
is("h143".U) { r := stval }
is("h180".U) { r := satpReg }
is("hf14".U) { r := 0.U }
is("hc00".U) { r := cycle }
is("hc01".U) { r := 0.U }
is("hc02".U) { r := instret }
}
io.rdata := r
val operand = Mux(io.cmd.cmd(2), io.cmd.zimm, io.cmd.rs1)
val next = MuxLookup(io.cmd.cmd(1, 0), r)(Seq(
1.U -> operand,
2.U -> (r | operand),
3.U -> (r & ~operand)
))
when(io.cmd.valid && io.cmd.cmd =/= 0.U) {
switch(io.cmd.addr) {
is("h300".U) { mstatus := next }
is("h302".U) { medeleg := next }
is("h303".U) { mideleg := next }
is("h304".U) { mie := next }
is("h305".U) { mtvecReg := next }
is("h341".U) { mepcReg := next }
is("h342".U) { mcause := next }
is("h343".U) { mtval := next }
is("h344".U) { mip := next }
is("h100".U) { sstatus := next }
is("h105".U) { stvec := next }
is("h140".U) { sscratch := next }
is("h141".U) { sepc := next }
is("h142".U) { scause := next }
is("h143".U) { stval := next }
is("h180".U) { satpReg := next }
}
}
when(io.trap) {
mepcReg := io.trapPc
mcause := io.trapCause
}
}

View File

@@ -0,0 +1,21 @@
import chisel3._
class PrivilegeControl(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val trap = Input(Bool())
val mret = Input(Bool())
val sret = Input(Bool())
val privilege = Output(UInt(2.W))
})
val mode = RegInit(3.U(2.W))
when(io.trap) {
mode := 3.U
}.elsewhen(io.mret) {
mode := 0.U
}.elsewhen(io.sret) {
mode := 0.U
}
io.privilege := mode
}

View File

@@ -0,0 +1,150 @@
import chisel3._
import chisel3.util._
class Decoder(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val pc = Input(UInt(p.xlen.W))
val inst = Input(UInt(32.W))
val out = Output(new DecodedInst(p))
})
val opcode = io.inst(6, 0)
val rd = io.inst(11, 7)
val funct3 = io.inst(14, 12)
val rs1 = io.inst(19, 15)
val rs2 = io.inst(24, 20)
val funct7 = io.inst(31, 25)
val immI = Consts.signExtend(io.inst(31, 20), 12)
val immS = Consts.signExtend(Cat(io.inst(31, 25), io.inst(11, 7)), 12)
val immB = Consts.signExtend(Cat(io.inst(31), io.inst(7), io.inst(30, 25), io.inst(11, 8), 0.U(1.W)), 13)
val immU = Consts.signExtend(Cat(io.inst(31, 12), 0.U(12.W)), 32)
val immJ = Consts.signExtend(Cat(io.inst(31), io.inst(19, 12), io.inst(20), io.inst(30, 21), 0.U(1.W)), 21)
val d = WireDefault(0.U.asTypeOf(new DecodedInst(p)))
d.valid := true.B
d.pc := io.pc
d.inst := io.inst
d.rs1 := rs1
d.rs2 := rs2
d.rd := rd
d.funct3 := funct3
d.funct7 := funct7
d.immI := immI
d.immS := immS
d.immB := immB
d.immU := immU
d.immJ := immJ
d.memWidth := MuxLookup(funct3, 3.U)(Seq(
"b000".U -> 0.U,
"b001".U -> 1.U,
"b010".U -> 2.U,
"b011".U -> 3.U,
"b100".U -> 0.U,
"b101".U -> 1.U,
"b110".U -> 2.U
))
d.memSigned := !funct3(2)
d.illegal := false.B
switch(opcode) {
is("b0110111".U) {
d.isLui := true.B
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_ALU
d.aluFn := Consts.ALU_COPY_B
}
is("b0010111".U) {
d.isAuipc := true.B
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_ALU
d.aluFn := Consts.ALU_ADD
}
is("b1101111".U) {
d.isJal := true.B
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_BRANCH
}
is("b1100111".U) {
d.isJalr := true.B
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_BRANCH
}
is("b1100011".U) {
d.isBranch := true.B
d.opClass := Consts.OP_BRANCH
}
is("b0000011".U) {
d.isLoad := true.B
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_LOAD
}
is("b0100011".U) {
d.isStore := true.B
d.opClass := Consts.OP_STORE
}
is("b0010011".U, "b0011011".U) {
d.isOpImm := true.B
d.isWord := opcode === "b0011011".U
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_ALU
d.aluFn := MuxLookup(funct3, Consts.ALU_ADD)(Seq(
"b000".U -> Consts.ALU_ADD,
"b001".U -> Consts.ALU_SLL,
"b010".U -> Consts.ALU_SLT,
"b011".U -> Consts.ALU_SLTU,
"b100".U -> Consts.ALU_XOR,
"b101".U -> Mux(funct7(5), Consts.ALU_SRA, Consts.ALU_SRL),
"b110".U -> Consts.ALU_OR,
"b111".U -> Consts.ALU_AND
))
}
is("b0110011".U, "b0111011".U) {
d.isOp := true.B
d.isWord := opcode === "b0111011".U
d.writesRd := rd =/= 0.U
d.opClass := Consts.OP_ALU
d.aluFn := Mux(funct7 === "b0000001".U, MuxLookup(funct3, Consts.ALU_MUL)(Seq(
"b000".U -> Consts.ALU_MUL,
"b100".U -> Consts.ALU_DIV,
"b101".U -> Consts.ALU_DIVU,
"b110".U -> Consts.ALU_REM,
"b111".U -> Consts.ALU_REMU
)), MuxLookup(funct3, Consts.ALU_ADD)(Seq(
"b000".U -> Mux(funct7(5), Consts.ALU_SUB, Consts.ALU_ADD),
"b001".U -> Consts.ALU_SLL,
"b010".U -> Consts.ALU_SLT,
"b011".U -> Consts.ALU_SLTU,
"b100".U -> Consts.ALU_XOR,
"b101".U -> Mux(funct7(5), Consts.ALU_SRA, Consts.ALU_SRL),
"b110".U -> Consts.ALU_OR,
"b111".U -> Consts.ALU_AND
)))
}
is("b0001111".U) {
d.opClass := Consts.OP_SYSTEM
}
is("b1110011".U) {
d.isSystem := true.B
d.writesRd := rd =/= 0.U && funct3 =/= 0.U
d.opClass := Consts.OP_SYSTEM
}
is("b0101111".U) {
d.isLoad := true.B
d.isStore := true.B
d.writesRd := rd =/= 0.U
d.memWidth := Mux(funct3 === "b010".U, 2.U, 3.U)
d.opClass := Consts.OP_LOAD
}
}
when(opcode =/= "b0110111".U && opcode =/= "b0010111".U && opcode =/= "b1101111".U &&
opcode =/= "b1100111".U && opcode =/= "b1100011".U && opcode =/= "b0000011".U &&
opcode =/= "b0100011".U && opcode =/= "b0010011".U && opcode =/= "b0011011".U &&
opcode =/= "b0110011".U && opcode =/= "b0111011".U && opcode =/= "b0001111".U &&
opcode =/= "b1110011".U && opcode =/= "b0101111".U) {
d.illegal := true.B
}
io.out := d
}

View File

@@ -0,0 +1,20 @@
import chisel3._
class IDStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val inValid = Input(Bool())
val in = Input(new FetchPacket(p))
val outValid = Output(Vec(p.fetchWidth, Bool()))
val out = Output(Vec(p.fetchWidth, new DecodedInst(p)))
})
val decoders = Seq.fill(p.fetchWidth)(Module(new Decoder(p)))
for (i <- 0 until p.fetchWidth) {
decoders(i).io.pc := io.in.pc + (4 * i).U
decoders(i).io.inst := io.in.inst(i)
io.out(i) := decoders(i).io.out
io.out(i).valid := io.inValid
io.outValid(i) := io.inValid
}
}

View File

@@ -0,0 +1,36 @@
import chisel3._
import chisel3.util._
class ALU(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val fn = Input(UInt(5.W))
val a = Input(UInt(p.xlen.W))
val b = Input(UInt(p.xlen.W))
val isWord = Input(Bool())
val out = Output(UInt(p.xlen.W))
})
val shamt = Mux(io.isWord, io.b(4, 0), io.b(5, 0))
val raw = WireDefault(0.U(p.xlen.W))
switch(io.fn) {
is(Consts.ALU_ADD) { raw := io.a + io.b }
is(Consts.ALU_SUB) { raw := io.a - io.b }
is(Consts.ALU_SLL) { raw := io.a << shamt }
is(Consts.ALU_SLT) { raw := (io.a.asSInt < io.b.asSInt).asUInt }
is(Consts.ALU_SLTU) { raw := io.a < io.b }
is(Consts.ALU_XOR) { raw := io.a ^ io.b }
is(Consts.ALU_SRL) { raw := io.a >> shamt }
is(Consts.ALU_SRA) { raw := (io.a.asSInt >> shamt).asUInt }
is(Consts.ALU_OR) { raw := io.a | io.b }
is(Consts.ALU_AND) { raw := io.a & io.b }
is(Consts.ALU_MUL) { raw := (io.a * io.b)(p.xlen - 1, 0) }
is(Consts.ALU_DIV) { raw := Mux(io.b === 0.U, Fill(p.xlen, 1.U), (io.a.asSInt / io.b.asSInt).asUInt) }
is(Consts.ALU_DIVU) { raw := Mux(io.b === 0.U, Fill(p.xlen, 1.U), io.a / io.b) }
is(Consts.ALU_REM) { raw := Mux(io.b === 0.U, io.a, (io.a.asSInt % io.b.asSInt).asUInt) }
is(Consts.ALU_REMU) { raw := Mux(io.b === 0.U, io.a, io.a % io.b) }
is(Consts.ALU_COPY_B) { raw := io.b }
}
io.out := Mux(io.isWord, Consts.signExtend(raw(31, 0), 32), raw)
}

View File

@@ -0,0 +1,21 @@
import chisel3._
import chisel3.util._
class BranchUnit(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val funct3 = Input(UInt(3.W))
val a = Input(UInt(p.xlen.W))
val b = Input(UInt(p.xlen.W))
val taken = Output(Bool())
})
io.taken := MuxLookup(io.funct3, false.B)(Seq(
"b000".U -> (io.a === io.b),
"b001".U -> (io.a =/= io.b),
"b100".U -> (io.a.asSInt < io.b.asSInt),
"b101".U -> (io.a.asSInt >= io.b.asSInt),
"b110".U -> (io.a < io.b),
"b111".U -> (io.a >= io.b)
))
}

View File

@@ -0,0 +1,14 @@
import chisel3._
import chisel3.util._
class Divider(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val signed = Input(Bool())
val a = Input(UInt(p.xlen.W))
val b = Input(UInt(p.xlen.W))
val quotient = Output(UInt(p.xlen.W))
val remainder = Output(UInt(p.xlen.W))
})
io.quotient := Mux(io.b === 0.U, Fill(p.xlen, 1.U), Mux(io.signed, (io.a.asSInt / io.b.asSInt).asUInt, io.a / io.b))
io.remainder := Mux(io.b === 0.U, io.a, Mux(io.signed, (io.a.asSInt % io.b.asSInt).asUInt, io.a % io.b))
}

View File

@@ -0,0 +1,29 @@
import chisel3._
class ExecStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val inValid = Input(Bool())
val in = Input(new DecodedInst(p))
val src1 = Input(UInt(p.xlen.W))
val src2 = Input(UInt(p.xlen.W))
val outValid = Output(Bool())
val result = Output(UInt(p.xlen.W))
val branchTaken = Output(Bool())
})
val alu = Module(new ALU(p))
val branch = Module(new BranchUnit(p))
alu.io.fn := io.in.aluFn
alu.io.a := io.src1
alu.io.b := io.src2
alu.io.isWord := io.in.isWord
branch.io.funct3 := io.in.funct3
branch.io.a := io.src1
branch.io.b := io.src2
io.outValid := io.inValid
io.result := alu.io.out
io.branchTaken := branch.io.taken
}

View File

@@ -0,0 +1,16 @@
import chisel3._
class FPU(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val inValid = Input(Bool())
val op = Input(UInt(4.W))
val a = Input(UInt(p.xlen.W))
val b = Input(UInt(p.xlen.W))
val outValid = Output(Bool())
val out = Output(UInt(p.xlen.W))
})
io.outValid := io.inValid
io.out := 0.U
}

View File

@@ -0,0 +1,11 @@
import chisel3._
class Multiplier(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(p.xlen.W))
val b = Input(UInt(p.xlen.W))
val out = Output(UInt(p.xlen.W))
})
io.out := (io.a * io.b)(p.xlen - 1, 0)
}

View File

@@ -0,0 +1,32 @@
import chisel3._
import chisel3.util._
class BTB(p: CoreParams = CoreParams()) extends Module {
private val idxBits = log2Ceil(p.btbEntries)
private val tagBits = 20
val io = IO(new Bundle {
val pc = Input(UInt(p.xlen.W))
val hit = Output(Bool())
val target = Output(UInt(p.xlen.W))
val update = Input(new BranchUpdate(p))
})
val valid = RegInit(VecInit(Seq.fill(p.btbEntries)(false.B)))
val tags = Reg(Vec(p.btbEntries, UInt(tagBits.W)))
val targets = Reg(Vec(p.btbEntries, UInt(p.xlen.W)))
val idx = io.pc(idxBits + 1, 2)
val tag = io.pc(idxBits + tagBits + 1, idxBits + 2)
io.hit := valid(idx) && tags(idx) === tag
io.target := targets(idx)
when(io.update.valid && io.update.taken) {
val uidx = io.update.pc(idxBits + 1, 2)
valid(uidx) := true.B
tags(uidx) := io.update.pc(idxBits + tagBits + 1, idxBits + 2)
targets(uidx) := io.update.target
}
}

View File

@@ -0,0 +1,38 @@
import chisel3._
import chisel3.util._
class BranchPredictor(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val pc = Input(UInt(p.xlen.W))
val taken = Output(Bool())
val target = Output(UInt(p.xlen.W))
val update = Input(new BranchUpdate(p))
})
val ghr = RegInit(0.U(p.ghrBits.W))
val pht = RegInit(VecInit(Seq.fill(1 << p.ghrBits)(1.U(2.W))))
val btb = Module(new BTB(p))
val ras = Module(new RAS(p))
val idx = io.pc(p.ghrBits + 1, 2) ^ ghr
btb.io.pc := io.pc
btb.io.update := io.update
ras.io.push := io.update.valid && io.update.isCall
ras.io.pop := io.update.valid && io.update.isReturn
ras.io.pushAddr := io.update.pc + 4.U
io.taken := pht(idx)(1) && btb.io.hit
io.target := Mux(io.update.isReturn && !ras.io.empty, ras.io.top, btb.io.target)
when(io.update.valid) {
val uidx = io.update.pc(p.ghrBits + 1, 2) ^ ghr
when(io.update.taken && pht(uidx) =/= 3.U) {
pht(uidx) := pht(uidx) + 1.U
}.elsewhen(!io.update.taken && pht(uidx) =/= 0.U) {
pht(uidx) := pht(uidx) - 1.U
}
ghr := Cat(ghr(p.ghrBits - 2, 0), io.update.taken)
}
}

View File

@@ -0,0 +1,43 @@
import chisel3._
class Frontend(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val redirectValid = Input(Bool())
val redirectPc = Input(UInt(p.xlen.W))
val imemReqValid = Output(Bool())
val imemReqAddr = Output(UInt(p.xlen.W))
val imemRespValid = Input(Bool())
val imemRespBits = Input(Vec(p.fetchWidth, UInt(32.W)))
val outValid = Output(Bool())
val out = Output(new FetchPacket(p))
val branchUpdate = Input(new BranchUpdate(p))
})
val pc = RegInit(Consts.ResetVector)
val predictor = Module(new BranchPredictor(p))
val itlb = Module(new ITLB(p))
val icache = Module(new ICache(p))
predictor.io.pc := pc
predictor.io.update := io.branchUpdate
itlb.io.vaddr := pc
icache.io.reqValid := true.B
icache.io.reqAddr := itlb.io.paddr
icache.io.memRespValid := io.imemRespValid
icache.io.memRespBits := io.imemRespBits
io.imemReqValid := icache.io.memReqValid
io.imemReqAddr := icache.io.memReqAddr
io.outValid := icache.io.respValid
io.out := icache.io.resp
io.out.predictedTaken := predictor.io.taken
io.out.predictedTarget := predictor.io.target
when(io.redirectValid) {
pc := io.redirectPc
}.elsewhen(icache.io.respValid) {
pc := Mux(predictor.io.taken, predictor.io.target, pc + (4 * p.fetchWidth).U)
}
}

View File

@@ -0,0 +1,23 @@
import chisel3._
class ICache(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val reqValid = Input(Bool())
val reqAddr = Input(UInt(p.xlen.W))
val memReqValid = Output(Bool())
val memReqAddr = Output(UInt(p.xlen.W))
val memRespValid = Input(Bool())
val memRespBits = Input(Vec(p.fetchWidth, UInt(32.W)))
val respValid = Output(Bool())
val resp = Output(new FetchPacket(p))
})
io.memReqValid := io.reqValid
io.memReqAddr := io.reqAddr
io.respValid := io.memRespValid
io.resp.pc := io.reqAddr
io.resp.inst := io.memRespBits
io.resp.predictedTaken := false.B
io.resp.predictedTarget := io.reqAddr + (4 * p.fetchWidth).U
}

View File

@@ -0,0 +1,16 @@
import chisel3._
import chisel3.util._
class ITLB(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val vaddr = Input(UInt(p.xlen.W))
val paddr = Output(UInt(p.xlen.W))
val hit = Output(Bool())
val miss = Output(Bool())
})
io.paddr := io.vaddr
io.hit := true.B
io.miss := false.B
}

View File

@@ -0,0 +1,31 @@
import chisel3._
import chisel3.util._
class RAS(p: CoreParams = CoreParams()) extends Module {
private val ptrBits = log2Ceil(p.rasEntries)
val io = IO(new Bundle {
val push = Input(Bool())
val pop = Input(Bool())
val pushAddr = Input(UInt(p.xlen.W))
val top = Output(UInt(p.xlen.W))
val empty = Output(Bool())
})
val stack = Reg(Vec(p.rasEntries, UInt(p.xlen.W)))
val sp = RegInit(0.U(ptrBits.W))
val count = RegInit(0.U(log2Ceil(p.rasEntries + 1).W))
io.empty := count === 0.U
io.top := stack(Mux(sp === 0.U, (p.rasEntries - 1).U, sp - 1.U))
when(io.push) {
stack(sp) := io.pushAddr
sp := Mux(sp === (p.rasEntries - 1).U, 0.U, sp + 1.U)
when(count =/= p.rasEntries.U) { count := count + 1.U }
}.elsewhen(io.pop && count =/= 0.U) {
sp := Mux(sp === 0.U, (p.rasEntries - 1).U, sp - 1.U)
count := count - 1.U
}
}

View File

@@ -0,0 +1,24 @@
import chisel3._
class IssueQueue(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val enqValid = Input(Bool())
val enq = Input(new RenamePacket(p))
val enqReady = Output(Bool())
val issueValid = Output(Bool())
val issue = Output(new RenamePacket(p))
val issueReady = Input(Bool())
val flush = Input(Bool())
})
val intRs = Module(new ReservationStation(p, p.intRsEntries))
intRs.io.enqValid := io.enqValid
intRs.io.enq := io.enq
intRs.io.issueReady := io.issueReady
intRs.io.flush := io.flush
io.enqReady := intRs.io.enqReady
io.issueValid := intRs.io.issueValid
io.issue := intRs.io.issue
}

View File

@@ -0,0 +1,24 @@
import chisel3._
class IssueStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val inValid = Input(Bool())
val in = Input(new RenamePacket(p))
val inReady = Output(Bool())
val outValid = Output(Bool())
val out = Output(new RenamePacket(p))
val outReady = Input(Bool())
val flush = Input(Bool())
})
val queue = Module(new IssueQueue(p))
queue.io.enqValid := io.inValid
queue.io.enq := io.in
queue.io.issueReady := io.outReady
queue.io.flush := io.flush
io.inReady := queue.io.enqReady
io.outValid := queue.io.issueValid
io.out := queue.io.issue
}

View File

@@ -0,0 +1,24 @@
import chisel3._
import chisel3.util._
class ReservationStation(p: CoreParams = CoreParams(), entries: Int = 16) extends Module {
val io = IO(new Bundle {
val enqValid = Input(Bool())
val enq = Input(new RenamePacket(p))
val enqReady = Output(Bool())
val issueValid = Output(Bool())
val issue = Output(new RenamePacket(p))
val issueReady = Input(Bool())
val flush = Input(Bool())
})
val q = Module(new Queue(new RenamePacket(p), entries, flow = false, pipe = true))
q.io.enq.valid := io.enqValid
q.io.enq.bits := io.enq
q.io.deq.ready := io.issueReady || io.flush
io.enqReady := q.io.enq.ready
io.issueValid := q.io.deq.valid && !io.flush
io.issue := q.io.deq.bits
}

View File

@@ -0,0 +1,20 @@
import chisel3._
class DCache(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val reqValid = Input(Bool())
val req = Input(new MemRequest(p))
val memReqValid = Output(Bool())
val memReq = Output(new MemRequest(p))
val memRespValid = Input(Bool())
val memRespData = Input(UInt(p.xlen.W))
val respValid = Output(Bool())
val respData = Output(UInt(p.xlen.W))
})
io.memReqValid := io.reqValid
io.memReq := io.req
io.respValid := io.memRespValid
io.respData := io.memRespData
}

View File

@@ -0,0 +1,15 @@
import chisel3._
class DTLB(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val vaddr = Input(UInt(p.xlen.W))
val paddr = Output(UInt(p.xlen.W))
val hit = Output(Bool())
val miss = Output(Bool())
})
io.paddr := io.vaddr
io.hit := true.B
io.miss := false.B
}

View File

@@ -0,0 +1,30 @@
import chisel3._
class LSU(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val reqValid = Input(Bool())
val req = Input(new MemRequest(p))
val dmemReqValid = Output(Bool())
val dmemReq = Output(new MemRequest(p))
val dmemRespValid = Input(Bool())
val dmemRespData = Input(UInt(p.xlen.W))
val respValid = Output(Bool())
val respData = Output(UInt(p.xlen.W))
})
val dtlb = Module(new DTLB(p))
val dcache = Module(new DCache(p))
dtlb.io.vaddr := io.req.addr
dcache.io.reqValid := io.reqValid
dcache.io.req := io.req
dcache.io.req.addr := dtlb.io.paddr
dcache.io.memRespValid := io.dmemRespValid
dcache.io.memRespData := io.dmemRespData
io.dmemReqValid := dcache.io.memReqValid
io.dmemReq := dcache.io.memReq
io.respValid := dcache.io.respValid
io.respData := dcache.io.respData
}

View File

@@ -0,0 +1,23 @@
import chisel3._
import chisel3.util._
class LoadQueue(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val enqValid = Input(Bool())
val enqAddr = Input(UInt(p.xlen.W))
val enqReady = Output(Bool())
val complete = Input(Bool())
val flush = Input(Bool())
})
val count = RegInit(0.U(log2Ceil(p.loadQueueEntries + 1).W))
io.enqReady := count =/= p.loadQueueEntries.U
when(io.flush) {
count := 0.U
}.otherwise {
when(io.enqValid && io.enqReady) { count := count + 1.U }
when(io.complete && count =/= 0.U) { count := count - 1.U }
}
}

View File

@@ -0,0 +1,15 @@
import chisel3._
class MMU(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val satp = Input(UInt(p.xlen.W))
val vaddr = Input(UInt(p.xlen.W))
val isStore = Input(Bool())
val paddr = Output(UInt(p.xlen.W))
val pageFault = Output(Bool())
})
io.paddr := io.vaddr
io.pageFault := false.B
}

View File

@@ -0,0 +1,26 @@
import chisel3._
class MemStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val reqValid = Input(Bool())
val req = Input(new MemRequest(p))
val dmemReqValid = Output(Bool())
val dmemReq = Output(new MemRequest(p))
val dmemRespValid = Input(Bool())
val dmemRespData = Input(UInt(p.xlen.W))
val respValid = Output(Bool())
val respData = Output(UInt(p.xlen.W))
})
val lsu = Module(new LSU(p))
lsu.io.reqValid := io.reqValid
lsu.io.req := io.req
lsu.io.dmemRespValid := io.dmemRespValid
lsu.io.dmemRespData := io.dmemRespData
io.dmemReqValid := lsu.io.dmemReqValid
io.dmemReq := lsu.io.dmemReq
io.respValid := lsu.io.respValid
io.respData := lsu.io.respData
}

View File

@@ -0,0 +1,24 @@
import chisel3._
import chisel3.util._
class StoreQueue(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val enqValid = Input(Bool())
val enq = Input(new MemRequest(p))
val enqReady = Output(Bool())
val drainValid = Output(Bool())
val drain = Output(new MemRequest(p))
val drainReady = Input(Bool())
val flush = Input(Bool())
})
val q = Module(new Queue(new MemRequest(p), p.storeQueueEntries))
q.io.enq.valid := io.enqValid && !io.flush
q.io.enq.bits := io.enq
q.io.deq.ready := io.drainReady || io.flush
io.enqReady := q.io.enq.ready
io.drainValid := q.io.deq.valid && !io.flush
io.drain := q.io.deq.bits
}

View File

@@ -0,0 +1,23 @@
import chisel3._
import chisel3.util._
class PhysicalRegFile(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val raddr = Input(Vec(4, UInt(log2Ceil(p.physRegs).W)))
val rdata = Output(Vec(4, UInt(p.xlen.W)))
val wen = Input(Vec(2, Bool()))
val waddr = Input(Vec(2, UInt(log2Ceil(p.physRegs).W)))
val wdata = Input(Vec(2, UInt(p.xlen.W)))
})
val regs = RegInit(VecInit(Seq.fill(p.physRegs)(0.U(p.xlen.W))))
for (i <- 0 until 4) {
io.rdata(i) := Mux(io.raddr(i) === 0.U, 0.U, regs(io.raddr(i)))
}
for (i <- 0 until 2) {
when(io.wen(i) && io.waddr(i) =/= 0.U) {
regs(io.waddr(i)) := io.wdata(i)
}
}
}

View File

@@ -0,0 +1,26 @@
import chisel3._
import chisel3.util._
class FreeList(p: CoreParams = CoreParams()) extends Module {
private val physBits = log2Ceil(p.physRegs)
val io = IO(new Bundle {
val alloc = Input(Bool())
val allocPhys = Output(UInt(physBits.W))
val canAlloc = Output(Bool())
val free = Input(Bool())
val freePhys = Input(UInt(physBits.W))
})
val freeBits = RegInit(VecInit((0 until p.physRegs).map(i => (i >= p.archRegs).B)))
val chosen = PriorityEncoder(freeBits)
io.canAlloc := freeBits.asUInt.orR
io.allocPhys := chosen
when(io.alloc && io.canAlloc) {
freeBits(chosen) := false.B
}
when(io.free && io.freePhys >= p.archRegs.U) {
freeBits(io.freePhys) := true.B
}
}

View File

@@ -0,0 +1,71 @@
import chisel3._
import chisel3.util._
class RobEntry(p: CoreParams = CoreParams()) extends Bundle {
val valid = Bool()
val pc = UInt(p.xlen.W)
val opClass = UInt(Consts.OpClassWidth.W)
val dest = UInt(log2Ceil(p.physRegs).W)
val oldDest = UInt(log2Ceil(p.physRegs).W)
val completed = Bool()
val exception = Bool()
val branchMispredict = Bool()
}
class ROB(p: CoreParams = CoreParams()) extends Module {
private val idxBits = log2Ceil(p.robEntries)
val io = IO(new Bundle {
val allocate = Input(Bool())
val allocatePc = Input(UInt(p.xlen.W))
val allocateClass = Input(UInt(Consts.OpClassWidth.W))
val allocateDest = Input(UInt(log2Ceil(p.physRegs).W))
val allocateOldDest = Input(UInt(log2Ceil(p.physRegs).W))
val allocateIdx = Output(UInt(idxBits.W))
val canAllocate = Output(Bool())
val complete = Input(Bool())
val completeIdx = Input(UInt(idxBits.W))
val commitValid = Output(Bool())
val commit = Output(new RobEntry(p))
val commitReady = Input(Bool())
val flush = Input(Bool())
})
val entries = RegInit(VecInit(Seq.fill(p.robEntries)(0.U.asTypeOf(new RobEntry(p)))))
val head = RegInit(0.U(idxBits.W))
val tail = RegInit(0.U(idxBits.W))
val count = RegInit(0.U(log2Ceil(p.robEntries + 1).W))
io.canAllocate := count =/= p.robEntries.U
io.allocateIdx := tail
io.commit := entries(head)
io.commitValid := count =/= 0.U && entries(head).valid && entries(head).completed
when(io.flush) {
entries.foreach(_.valid := false.B)
head := 0.U
tail := 0.U
count := 0.U
}.otherwise {
when(io.allocate && io.canAllocate) {
entries(tail).valid := true.B
entries(tail).pc := io.allocatePc
entries(tail).opClass := io.allocateClass
entries(tail).dest := io.allocateDest
entries(tail).oldDest := io.allocateOldDest
entries(tail).completed := false.B
entries(tail).exception := false.B
entries(tail).branchMispredict := false.B
tail := tail + 1.U
count := count + 1.U
}
when(io.complete) {
entries(io.completeIdx).completed := true.B
}
when(io.commitValid && io.commitReady) {
entries(head).valid := false.B
head := head + 1.U
count := count - 1.U
}
}
}

View File

@@ -0,0 +1,49 @@
import chisel3._
import chisel3.util._
class RenameStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val inValid = Input(Bool())
val in = Input(new DecodedInst(p))
val outValid = Output(Bool())
val out = Output(new RenamePacket(p))
val commitFree = Input(Bool())
val commitOldPhys = Input(UInt(log2Ceil(p.physRegs).W))
val flush = Input(Bool())
})
val table = Module(new RenameTable(p))
val freeList = Module(new FreeList(p))
val rob = Module(new ROB(p))
table.io.rs1 := io.in.rs1
table.io.rs2 := io.in.rs2
table.io.rd := io.in.rd
table.io.newPhys := freeList.io.allocPhys
table.io.wen := io.inValid && io.in.writesRd && freeList.io.canAlloc && rob.io.canAllocate
table.io.recover := io.flush
freeList.io.alloc := table.io.wen
freeList.io.free := io.commitFree
freeList.io.freePhys := io.commitOldPhys
rob.io.allocate := io.inValid && rob.io.canAllocate && (!io.in.writesRd || freeList.io.canAlloc)
rob.io.allocatePc := io.in.pc
rob.io.allocateClass := io.in.opClass
rob.io.allocateDest := Mux(io.in.writesRd, freeList.io.allocPhys, table.io.oldPrd)
rob.io.allocateOldDest := table.io.oldPrd
rob.io.complete := false.B
rob.io.completeIdx := 0.U
rob.io.commitReady := false.B
rob.io.flush := io.flush
io.outValid := rob.io.allocate
io.out.valid := io.outValid
io.out.decoded := io.in
io.out.prs1 := table.io.prs1
io.out.prs2 := table.io.prs2
io.out.prd := Mux(io.in.writesRd, freeList.io.allocPhys, table.io.oldPrd)
io.out.oldPrd := table.io.oldPrd
io.out.robIdx := rob.io.allocateIdx
}

View File

@@ -0,0 +1,32 @@
import chisel3._
import chisel3.util._
class RenameTable(p: CoreParams = CoreParams()) extends Module {
private val physBits = log2Ceil(p.physRegs)
val io = IO(new Bundle {
val rs1 = Input(UInt(5.W))
val rs2 = Input(UInt(5.W))
val rd = Input(UInt(5.W))
val newPhys = Input(UInt(physBits.W))
val wen = Input(Bool())
val prs1 = Output(UInt(physBits.W))
val prs2 = Output(UInt(physBits.W))
val oldPrd = Output(UInt(physBits.W))
val recover = Input(Bool())
})
val init = VecInit((0 until p.archRegs).map(_.U(physBits.W)))
val speculative = RegInit(init)
val committed = RegInit(init)
io.prs1 := speculative(io.rs1)
io.prs2 := speculative(io.rs2)
io.oldPrd := speculative(io.rd)
when(io.recover) {
speculative := committed
}.elsewhen(io.wen && io.rd =/= 0.U) {
speculative(io.rd) := io.newPhys
}
}

View File

@@ -0,0 +1,18 @@
import chisel3._
import chisel3.util._
class WriteBackStage(p: CoreParams = CoreParams()) extends Module {
val io = IO(new Bundle {
val valid = Input(Bool())
val physDest = Input(UInt(log2Ceil(p.physRegs).W))
val data = Input(UInt(p.xlen.W))
val wen = Output(Bool())
val waddr = Output(UInt(log2Ceil(p.physRegs).W))
val wdata = Output(UInt(p.xlen.W))
})
io.wen := io.valid
io.waddr := io.physDest
io.wdata := io.data
}