From 11e61e54b39f93b8af8acf710bad86dbb91f9c07 Mon Sep 17 00:00:00 2001 From: Sindre Stephansen Date: Sun, 24 Nov 2019 16:52:45 +0100 Subject: [PATCH] Move forwarding logic to separate module --- src/main/scala/CPU.scala | 103 +++++---------------------------- src/main/scala/Forwarder.scala | 68 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 87 deletions(-) create mode 100644 src/main/scala/Forwarder.scala diff --git a/src/main/scala/CPU.scala b/src/main/scala/CPU.scala index 0f2e647..b459e13 100644 --- a/src/main/scala/CPU.scala +++ b/src/main/scala/CPU.scala @@ -1,9 +1,6 @@ package FiveStage import chisel3._ -import chisel3.core.Input -import chisel3.util.ShiftRegister -import chisel3.experimental.MultiIOModule import chisel3.experimental._ @@ -32,7 +29,6 @@ class CPU extends MultiIOModule { val IF = Module(new InstructionFetch) val EX = Module(new Execute) val MEM = Module(new MemoryFetch) - // val WB = Module(new Execute) (You may not need this one?) /** * Setup. You should not change this code @@ -73,8 +69,14 @@ class CPU extends MultiIOModule { MEMBarrier.clear := clear WBBarrier.clear := clear - // The value that is written back to the register val writeback = Wire(UInt(32.W)) + val forwarder = Module(new Forwarder).io + forwarder.IF := IFBarrier.out + forwarder.ID := IDBarrier.out + forwarder.EX := EXBarrier.out + forwarder.MEM := MEMBarrier.out + forwarder.WB := WBBarrier.out + forwarder.writeback := writeback // Stage 1 IFBarrier.in := IF.io @@ -92,24 +94,10 @@ class CPU extends MultiIOModule { IDBarrier.in.ALUop := ID.io.ALUop // Stage 3 - val exToRs1 = IDBarrier.out.instruction.registerRs1 === EXBarrier.out.instruction.registerRd && EXBarrier.out.controlSignals.regWrite - val exToRs2 = IDBarrier.out.instruction.registerRs2 === EXBarrier.out.instruction.registerRd && EXBarrier.out.controlSignals.regWrite - val memToRs1 = IDBarrier.out.instruction.registerRs1 === MEMBarrier.out.instruction.registerRd && MEMBarrier.out.controlSignals.regWrite - val memToRs2 = IDBarrier.out.instruction.registerRs2 === MEMBarrier.out.instruction.registerRd && MEMBarrier.out.controlSignals.regWrite - val wbToRs1 = IDBarrier.out.instruction.registerRs1 === WBBarrier.out.instruction.registerRd && WBBarrier.out.controlSignals.regWrite - val wbToRs2 = IDBarrier.out.instruction.registerRs2 === WBBarrier.out.instruction.registerRd && WBBarrier.out.controlSignals.regWrite - val ldToRs1 = exToRs1 && EXBarrier.out.controlSignals.memToReg - val ldToRs2 = exToRs2 && EXBarrier.out.controlSignals.memToReg - - //printf(p"0x${Hexadecimal(IF.io.PC)}: EX in: ${IDBarrier.out.instruction.registerRs1}, MEM out: ${MEMBarrier.out.instruction.registerRd}\n") - - when ((ldToRs1 || ldToRs2) && state =/= LOAD_FREEZE) { - //printf(p"0x${Hexadecimal(IF.io.PC)}: Load freeze\n") - // Freeze all barriers (repeating the instruction) until the value is loaded from memory + when (forwarder.loadFreeze && state =/= LOAD_FREEZE) { + // Freeze the IF and ID barriers, repeating the instruction. + // EX is cleared, so the instruction isn't computed and written twice. freeze := true.B - - // The MEM and WB carry out their instructions, but MEM is cleared so it doesn't repeat - // the instruction. This carries through to WB next cycle. MEMBarrier.freeze := false.B WBBarrier.freeze := false.B EXBarrier.freeze := false.B @@ -117,48 +105,11 @@ class CPU extends MultiIOModule { state := LOAD_FREEZE } - //printf(p"0x${Hexadecimal(IF.io.PC)}: freeze: $freeze, exR1: ${IDBarrier.out.instruction.registerRs1}, rd: ${IF.io.instruction.registerRd}, IF: ${IFBarrier.out.instruction.opcode}, ID: ${IDBarrier.out.instruction.opcode}, EX: ${EXBarrier.out.instruction.opcode}, MEM: ${MEMBarrier.out.instruction.opcode}, WB: ${WBBarrier.out.instruction.opcode}\n") - - //printf(p"0x${Hexadecimal(IF.io.PC)}: next: 0x${Hexadecimal(IFBarrier.out.next)}, IF: 0x${Hexadecimal(IFBarrier.out.PC)}, ID: 0x${Hexadecimal(IDBarrier.out.PC)}, EX: 0x${Hexadecimal(EXBarrier.out.PC)}, MEM: 0x${Hexadecimal(MEMBarrier.out.PC)}, WB: 0x${Hexadecimal(WBBarrier.out.PC)}, freeze: $freeze\n") - - val rs1 = Wire(UInt(32.W)) - when (ldToRs1) { - rs1 := MEMBarrier.out.dataOut - }.elsewhen (exToRs1) { - rs1 := EXBarrier.out.result - }.elsewhen (memToRs1) { - rs1 := writeback - }.elsewhen (wbToRs1) { - rs1 := WBBarrier.out.writeback - }.otherwise { - rs1 := IDBarrier.out.reg1 - } - - val rs2 = Wire(UInt(32.W)) - when (ldToRs2) { - rs2 := MEMBarrier.out.dataOut - }.elsewhen (exToRs2) { - rs2 := EXBarrier.out.result - }.elsewhen (memToRs2) { - rs2 := writeback - }.elsewhen (wbToRs2) { - rs2 := WBBarrier.out.writeback - }.otherwise { - rs2 := IDBarrier.out.reg2 - } - - //printf(p"0x${Hexadecimal(IFBarrier.out.PC)}: next: ${Hexadecimal(IF.io.addr)} freeze: $freeze, ID imm: ${IDBarrier.out.imm}, ID PC: ${IDBarrier.out.PC}, EX result: ${EXBarrier.out.result}\n") - - //printf(p"0x${Hexadecimal(IF.io.PC)}: Reg write: ${MEMBarrier.out.controlSignals.regWrite}, ExToR1: $exToRs1, MEMToR1: $memToRs1, wbToR1: $wbToRs1, R1: $rs1, EX: ${EXBarrier.out.result}, MEM: $writeback, WB: ${WBBarrier.out.writeback}}\n") - - //printf(p"0x${Hexadecimal(IF.io.PC)}: Next: 0x${Hexadecimal(IFBarrier.out.next)}, freeze: $freeze, IF: ${IFBarrier.out.instruction}, ID: ${IDBarrier.out.instruction}, EX: ${EXBarrier.out.instruction}, MEM: ${MEMBarrier.out.instruction}\n") - - EX.io.PC := IDBarrier.out.PC EX.io.controlSignals := IDBarrier.out.controlSignals EX.io.branchType := IDBarrier.out.branchType - EX.io.reg1 := rs1 - EX.io.reg2 := rs2 + EX.io.reg1 := forwarder.exRs1 + EX.io.reg2 := forwarder.exRs2 EX.io.imm := IDBarrier.out.imm EX.io.ALUop := IDBarrier.out.ALUop @@ -170,22 +121,7 @@ class CPU extends MultiIOModule { EXBarrier.in.branch := EX.io.branch // Stage 4 - val memToMem = EXBarrier.out.instruction.registerRs2 === MEMBarrier.out.instruction.registerRd && EXBarrier.out.controlSignals.memWrite - val wbToMem = EXBarrier.out.instruction.registerRs2 === WBBarrier.out.instruction.registerRd && EXBarrier.out.controlSignals.memWrite - - val memWriteData = Wire(UInt(32.W)) - - when (memToMem) { - memWriteData := writeback - }.elsewhen (wbToMem) { - memWriteData := WBBarrier.out.writeback - }.otherwise { - memWriteData := EXBarrier.out.reg2 - } - - //printf(p"0x${Hexadecimal(IF.io.PC)}: Reg write: ${MEMBarrier.out.controlSignals.regWrite}, ExToR2: $exToRs2, MEMToR2: $memToRs2, wbToR2: $wbToRs2, R2: $rs2, EX: ${EXBarrier.out.result}, MEM: $writeback, WB: ${WBBarrier.out.writeback}}\n") - - MEM.io.dataIn := memWriteData + MEM.io.dataIn := forwarder.memWrite MEM.io.writeEnable := EXBarrier.out.controlSignals.memWrite MEM.io.dataAddress := EXBarrier.out.result @@ -199,20 +135,13 @@ class CPU extends MultiIOModule { // Stage 5 when (EXBarrier.out.branch) { IF.io.addr := EXBarrier.out.result - //printf(p"Jumping to ${EXBarrier.out.result}\n") IDBarrier.clear := true.B EXBarrier.clear := true.B } - when (false.B && freeze) { - ID.io.writeEnable := false.B - ID.io.writeAddr := 0.U - ID.io.writeData := 0.U - }.otherwise { - ID.io.writeEnable := MEMBarrier.out.controlSignals.regWrite - ID.io.writeAddr := MEMBarrier.out.instruction.registerRd - ID.io.writeData := writeback - } + ID.io.writeEnable := MEMBarrier.out.controlSignals.regWrite + ID.io.writeAddr := MEMBarrier.out.instruction.registerRd + ID.io.writeData := writeback WBBarrier.in.PC := MEMBarrier.out.PC WBBarrier.in.instruction := MEMBarrier.out.instruction diff --git a/src/main/scala/Forwarder.scala b/src/main/scala/Forwarder.scala new file mode 100644 index 0000000..cbb09ce --- /dev/null +++ b/src/main/scala/Forwarder.scala @@ -0,0 +1,68 @@ +package FiveStage + +import chisel3._ + + +class Forwarder extends Module { + val io = IO(new Bundle { + val IF = Input(new IFBundle) + val ID = Input(new IDBundle) + val EX = Input(new EXBundle) + val MEM = Input(new MEMBundle) + val WB = Input(new WBBundle) + val writeback = Input(UInt(32.W)) + + val exRs1 = Output(UInt(32.W)) + val exRs2 = Output(UInt(32.W)) + val memWrite = Output(UInt(32.W)) + val loadFreeze = Output(Bool()) + }) + + val exToRs1 = io.ID.instruction.registerRs1 === io.EX.instruction.registerRd && io.EX.controlSignals.regWrite + val exToRs2 = io.ID.instruction.registerRs2 === io.EX.instruction.registerRd && io.EX.controlSignals.regWrite + val memToRs1 = io.ID.instruction.registerRs1 === io.MEM.instruction.registerRd && io.MEM.controlSignals.regWrite + val memToRs2 = io.ID.instruction.registerRs2 === io.MEM.instruction.registerRd && io.MEM.controlSignals.regWrite + val wbToRs1 = io.ID.instruction.registerRs1 === io.WB.instruction.registerRd && io.WB.controlSignals.regWrite + val wbToRs2 = io.ID.instruction.registerRs2 === io.WB.instruction.registerRd && io.WB.controlSignals.regWrite + val ldToRs1 = exToRs1 && io.EX.controlSignals.memToReg + val ldToRs2 = exToRs2 && io.EX.controlSignals.memToReg + + io.loadFreeze := (ldToRs1 || ldToRs2) + + // Choose which forwarded values to use for Rs1 and Rs2 + when (ldToRs1) { + io.exRs1 := io.MEM.dataOut + }.elsewhen (exToRs1) { + io.exRs1 := io.EX.result + }.elsewhen (memToRs1) { + io.exRs1 := io.writeback + }.elsewhen (wbToRs1) { + io.exRs1 := io.WB.writeback + }.otherwise { + io.exRs1 := io.ID.reg1 + } + + when (ldToRs2) { + io.exRs2 := io.MEM.dataOut + }.elsewhen (exToRs2) { + io.exRs2 := io.EX.result + }.elsewhen (memToRs2) { + io.exRs2 := io.writeback + }.elsewhen (wbToRs2) { + io.exRs2 := io.WB.writeback + }.otherwise { + io.exRs2 := io.ID.reg2 + } + + // If a value read from MEM is used as the address in the next instruction, forward it + val memToMem = io.EX.instruction.registerRs2 === io.MEM.instruction.registerRd && io.EX.controlSignals.memWrite + val wbToMem = io.EX.instruction.registerRs2 === io.WB.instruction.registerRd && io.EX.controlSignals.memWrite + + when (memToMem) { + io.memWrite := io.writeback + }.elsewhen (wbToMem) { + io.memWrite := io.WB.writeback + }.otherwise { + io.memWrite := io.EX.reg2 + } +}