Explorar el Código

Move forwarding logic to separate module

sindre-ex2
Sindre Stephansen hace 6 años
padre
commit
11e61e54b3
Se han modificado 2 ficheros con 84 adiciones y 87 borrados
  1. +16
    -87
      src/main/scala/CPU.scala
  2. +68
    -0
      src/main/scala/Forwarder.scala

+ 16
- 87
src/main/scala/CPU.scala Ver fichero

@@ -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


+ 68
- 0
src/main/scala/Forwarder.scala Ver fichero

@@ -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
}
}

Cargando…
Cancelar
Guardar