Quellcode durchsuchen

Working forwarding, with load freeze

sindre-ex2
Sindre Stephansen vor 6 Jahren
Ursprung
Commit
04b1daf58f
5 geänderte Dateien mit 150 neuen und 51 gelöschten Zeilen
  1. +60
    -29
      src/main/scala/Barriers.scala
  2. +83
    -11
      src/main/scala/CPU.scala
  3. +4
    -8
      src/main/scala/IF.scala
  4. +2
    -2
      src/test/resources/tests/basic/load.s
  5. +1
    -1
      src/test/scala/chiselTestRunner.scala

+ 60
- 29
src/main/scala/Barriers.scala Datei anzeigen

@@ -4,42 +4,60 @@ import chisel3._
import chisel3.experimental.MultiIOModule


object BarrierReg {
def apply[T <: Data](in: T)(implicit freeze: Bool): Data = {
val reg = RegNext(in)
val old = RegNext(reg)
class Barrier[B <: Bundle](b: B) extends MultiIOModule {
implicit val freeze = IO(Input(Bool()))
implicit val clear = IO(Input(Bool()))
val in = IO(Input(b))
val out = IO(Output(b))

def default() {
out := barrier(in)
}

when (freeze) {
reg := old
def barrier[T <: Data](in: T, delay: Boolean = true): Data = {
val clearVal = in match {
case i: Instruction => Instruction.NOP
case _ => 0.U.asTypeOf(in)
}

reg
}
}
val t = chiselTypeOf(in)
val data = WireInit(t, Mux(clear, clearVal, in))
val out = Wire(t)

val reg = RegNext(data)

class Barrier[B <: Bundle](b: B) extends MultiIOModule {
implicit val freeze = IO(Input(Bool()))
val in = IO(Input(b))
val out = IO(Output(b))
if (delay) {
when (freeze) {
reg := reg
}

out := BarrierReg(in)
out := reg
} else {
out := Mux(RegNext(freeze), reg, data)
}

out
}
}


class IFBundle extends Bundle {
val PC = UInt()
val PC = UInt(32.W)
val next = UInt(32.W)
val instruction = new Instruction
}


class IFBarrier extends Barrier(new IFBundle) {
out.instruction := in.instruction
out.PC := BarrierReg(in.PC)
out.instruction := barrier(in.instruction, false)
out.PC := barrier(in.PC)
out.next := Mux(freeze, RegNext(in.next), in.next)
}


class IDBundle extends IFBundle {
class IDBundle extends Bundle {
val PC = UInt(32.W)
val instruction = new Instruction
val controlSignals = new ControlSignals
val branchType = UInt(3.W)
val reg1 = UInt(32.W)
@@ -49,10 +67,12 @@ class IDBundle extends IFBundle {
}


class IDBarrier extends Barrier(new IDBundle) {}
class IDBarrier extends Barrier(new IDBundle) { default() }


class EXBundle extends IFBundle {
class EXBundle extends Bundle {
val PC = UInt(32.W)
val instruction = new Instruction
val controlSignals = new ControlSignals
val reg2 = UInt(32.W)
val result = UInt(32.W)
@@ -60,20 +80,31 @@ class EXBundle extends IFBundle {
}


class EXBarrier extends Barrier(new EXBundle) {}
class EXBarrier extends Barrier(new EXBundle) { default() }


class MEMBundle extends IFBundle {
class MEMBundle extends Bundle {
val PC = UInt(32.W)
val instruction = new Instruction
val controlSignals = new ControlSignals
val result = UInt(32.W)
val dataOut = UInt(32.W)
val result = UInt(32.W)
val dataOut = UInt(32.W)
}


class MEMBarrier extends Barrier(new MEMBundle) {
out.PC := BarrierReg(in.PC)
out.instruction := BarrierReg(in.instruction)
out.controlSignals := BarrierReg(in.controlSignals)
out.result := BarrierReg(in.result)
out.dataOut := in.dataOut
out.PC := barrier(in.PC)
out.instruction := barrier(in.instruction)
out.controlSignals := barrier(in.controlSignals)
out.result := barrier(in.result)
out.dataOut := barrier(in.dataOut, false)
}

class WBBundle extends Bundle {
val PC = UInt(32.W)
val instruction = new Instruction
val controlSignals = new ControlSignals
val writeback = UInt(32.W)
}

class WBBarrier extends Barrier(new WBBundle) { default() }

+ 83
- 11
src/main/scala/CPU.scala Datei anzeigen

@@ -26,6 +26,7 @@ class CPU extends MultiIOModule {
val IDBarrier = Module(new IDBarrier)
val EXBarrier = Module(new EXBarrier)
val MEMBarrier = Module(new MEMBarrier)
val WBBarrier = Module(new WBBarrier)

val ID = Module(new InstructionDecode)
val IF = Module(new InstructionFetch)
@@ -62,9 +63,22 @@ class CPU extends MultiIOModule {
IDBarrier.freeze := freeze
EXBarrier.freeze := freeze
MEMBarrier.freeze := freeze
WBBarrier.freeze := freeze

val clear = Wire(Bool())
clear := false.B
IFBarrier.clear := clear
IDBarrier.clear := clear
EXBarrier.clear := clear
MEMBarrier.clear := clear
WBBarrier.clear := clear

// The value that is written back to the register
val writeback = Wire(UInt(32.W))

// Stage 1
IFBarrier.in := IF.io
IF.io.addr := IFBarrier.out.next

// Stage 2
ID.io.instruction := IFBarrier.out.instruction
@@ -82,17 +96,61 @@ class CPU extends MultiIOModule {
val exToRs2 = IDBarrier.out.instruction.registerRs2 === EXBarrier.out.instruction.registerRd
val memToRs1 = IDBarrier.out.instruction.registerRs1 === MEMBarrier.out.instruction.registerRd
val memToRs2 = IDBarrier.out.instruction.registerRs2 === MEMBarrier.out.instruction.registerRd
val ldToRs1 = exToRs1 && EXBarrier.out.controlSignals.memRead
val ldToRs2 = exToRs2 && EXBarrier.out.controlSignals.memRead
val wbToRs1 = IDBarrier.out.instruction.registerRs1 === WBBarrier.out.instruction.registerRd
val wbToRs2 = IDBarrier.out.instruction.registerRs2 === WBBarrier.out.instruction.registerRd
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
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
EXBarrier.clear := true.B
state := LOAD_FREEZE
}

val rs1 = Mux(exToRs1, EXBarrier.out.result, Mux(memToRs1, MEMBarrier.out.result, IDBarrier.out.reg1))
val rs2 = Mux(exToRs2, EXBarrier.out.result, Mux(memToRs2, MEMBarrier.out.result, IDBarrier.out.reg2))
//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(IF.io.PC)}: Reg write: ${MEMBarrier.out.controlSignals.regWrite}, ExToR1: $exToRs1, MEMToR1: $memToRs1, wbToR1: $wbToRs1, R1: $rs1, EX: ${EXBarrier.out.result}, MEM: ${MEMBarrier.out.dataOut}, 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
@@ -114,8 +172,9 @@ class CPU extends MultiIOModule {
MEM.io.writeEnable := EXBarrier.out.controlSignals.memWrite
MEM.io.dataAddress := EXBarrier.out.result

IF.io.jumpEnable := EXBarrier.out.branch
IF.io.jumpAddr := EXBarrier.out.result
when (EXBarrier.out.branch) {
//IF.io.addr := EXBarrier.out.result
}

MEMBarrier.in.PC := EXBarrier.out.PC
MEMBarrier.in.instruction := EXBarrier.out.instruction
@@ -124,15 +183,28 @@ class CPU extends MultiIOModule {
MEMBarrier.in.dataOut := MEM.io.dataOut

// Stage 5
ID.io.writeEnable := MEMBarrier.out.controlSignals.regWrite
ID.io.writeAddr := MEMBarrier.out.instruction.registerRd
ID.io.writeData := MEMBarrier.out.result
when (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
}

WBBarrier.in.PC := MEMBarrier.out.PC
WBBarrier.in.instruction := MEMBarrier.out.instruction
WBBarrier.in.controlSignals := MEMBarrier.out.controlSignals
WBBarrier.in.writeback := writeback

writeback := MEMBarrier.out.result

when (MEMBarrier.out.controlSignals.memToReg) {
ID.io.writeData := MEMBarrier.out.dataOut
writeback := MEMBarrier.out.dataOut
}

when (MEMBarrier.out.controlSignals.jump) {
ID.io.writeData := MEMBarrier.out.PC + 4.U
writeback := MEMBarrier.out.PC + 4.U
}
}

+ 4
- 8
src/main/scala/IF.scala Datei anzeigen

@@ -17,9 +17,9 @@ class InstructionFetch extends MultiIOModule {
new Bundle {
val PC = Output(UInt())
val instruction = Output(new Instruction)
val next = Output(UInt(32.W))

val jumpEnable = Input(Bool())
val jumpAddr = Input(UInt(32.W))
val addr = Input(UInt(32.W))
})

val IMEM = Module(new IMEM)
@@ -33,16 +33,12 @@ class InstructionFetch extends MultiIOModule {
testHarness.PC := IMEM.testHarness.requestedAddress


val addr = Mux(io.jumpEnable, io.jumpAddr, PC + 4.U)
when (io.jumpEnable) {
//printf(p"Jump to ${Hexadecimal(addr)}\n")
}

IMEM.io.instructionAddress := PC

PC := addr
PC := io.addr

io.PC := PC
io.next := PC + 4.U
io.instruction := IMEM.io.instruction.asTypeOf(new Instruction)




+ 2
- 2
src/test/resources/tests/basic/load.s Datei anzeigen

@@ -1,8 +1,8 @@
main:
addi x1, zero, 4
addi x2, zero, 4
addi x3, zero, 4
addi x4, zero, 4
addi x3, zero, 4
addi x4, zero, 4
lw x3, 0(x3)
nop
nop


+ 1
- 1
src/test/scala/chiselTestRunner.scala Datei anzeigen

@@ -142,7 +142,7 @@ private class ChiselTestRunner (

// After finishing, let the circuit run until all updates can be committed.
private def flush: List[CircuitTrace] =
(0 to 3).map(_ => stepOne).reverse.toList
(0 to 5).map(_ => stepOne).reverse.toList

/**
* Run the entire shebang


Laden…
Abbrechen
Speichern