141 lines
4.8 KiB
Scala
141 lines
4.8 KiB
Scala
package FiveStage
|
|
|
|
import chisel3._
|
|
import chisel3.core.Input
|
|
import chisel3.experimental.MultiIOModule
|
|
import chisel3.experimental._
|
|
|
|
|
|
class CPU extends MultiIOModule {
|
|
|
|
val testHarness = IO(
|
|
new Bundle {
|
|
val setupSignals = Input(new SetupSignals)
|
|
val testReadouts = Output(new TestReadouts)
|
|
val regUpdates = Output(new RegisterUpdates)
|
|
val memUpdates = Output(new MemUpdates)
|
|
val currentPC = Output(UInt(32.W))
|
|
}
|
|
)
|
|
|
|
/**
|
|
You need to create the classes for these yourself
|
|
*/
|
|
val IFBarrier = Module(new IFBarrier).io
|
|
val IDBarrier = Module(new IDBarrier).io
|
|
val EXBarrier = Module(new EXBarrier).io
|
|
val MEMBarrier = Module(new MEMBarrier).io
|
|
|
|
val ID = Module(new InstructionDecode)
|
|
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
|
|
*/
|
|
IF.testHarness.IMEMsetup := testHarness.setupSignals.IMEMsignals
|
|
ID.testHarness.registerSetup := testHarness.setupSignals.registerSignals
|
|
MEM.testHarness.DMEMsetup := testHarness.setupSignals.DMEMsignals
|
|
|
|
testHarness.testReadouts.registerRead := ID.testHarness.registerPeek
|
|
testHarness.testReadouts.DMEMread := MEM.testHarness.DMEMpeek
|
|
|
|
/**
|
|
spying stuff
|
|
*/
|
|
testHarness.regUpdates := ID.testHarness.testUpdates
|
|
testHarness.memUpdates := MEM.testHarness.testUpdates
|
|
testHarness.currentPC := IF.testHarness.PC
|
|
|
|
|
|
/**
|
|
TODO: Your code here
|
|
*/
|
|
def forward(data: UInt, addr: UInt, useForward: Bool, mem: Forwarding, wb: Forwarding, id: Forwarding): UInt = {
|
|
Mux(
|
|
!useForward,
|
|
data,
|
|
Mux(
|
|
mem.valid && mem.writeAddr === addr,
|
|
mem.writeData,
|
|
Mux(
|
|
wb.valid && wb.writeAddr === addr,
|
|
wb.writeData,
|
|
Mux(
|
|
id.valid && id.writeAddr === addr,
|
|
id.writeData,
|
|
data,
|
|
)
|
|
)
|
|
)
|
|
)
|
|
}
|
|
|
|
IFBarrier.PCin := IF.io.PC
|
|
IFBarrier.instructionIn := IF.io.instruction
|
|
|
|
ID.io.instruction := IFBarrier.instructionOut
|
|
ID.io.pc := IFBarrier.PCout
|
|
|
|
IDBarrier.in.op1 := ID.io.op1
|
|
IDBarrier.in.op2 := ID.io.op2
|
|
IDBarrier.in.isOp1RValue := ID.io.isOp1RValue
|
|
IDBarrier.in.isOp2RValue := ID.io.isOp2RValue
|
|
IDBarrier.in.r1Value := ID.io.r1Value
|
|
IDBarrier.in.r2Value := ID.io.r2Value
|
|
IDBarrier.in.r1Address := ID.io.r1Address
|
|
IDBarrier.in.r2Address := ID.io.r2Address
|
|
IDBarrier.in.ALUop := ID.io.ALUOp
|
|
IDBarrier.in.returnAddr := ID.io.returnAddr
|
|
IDBarrier.in.jump := ID.io.jump
|
|
IDBarrier.in.branchType := ID.io.branchType
|
|
IDBarrier.in.writeEnable := ID.io.writeEnableOut
|
|
IDBarrier.in.writeAddr := ID.io.writeAddrOut
|
|
IDBarrier.in.memWrite := ID.io.memWrite
|
|
IDBarrier.in.memRead := ID.io.memRead
|
|
|
|
EX.io.op1 := forward(IDBarrier.out.op1.asUInt(), IDBarrier.out.r1Address, IDBarrier.out.isOp1RValue, mem = MEMBarrier.forwardMem, wb = MEMBarrier.forwardWb, id = MEMBarrier.forwardId).asSInt()
|
|
EX.io.op2 := forward(IDBarrier.out.op2.asUInt(), IDBarrier.out.r2Address, IDBarrier.out.isOp2RValue, mem = MEMBarrier.forwardMem, wb = MEMBarrier.forwardWb, id = MEMBarrier.forwardId).asSInt()
|
|
EX.io.ALUOp := IDBarrier.out.ALUop
|
|
EX.io.branchType := IDBarrier.out.branchType
|
|
EX.io.rs1ValueIn := forward(IDBarrier.out.r1Value, IDBarrier.out.r1Address, true.B, mem = MEMBarrier.forwardMem, wb = MEMBarrier.forwardWb, id = MEMBarrier.forwardId).asSInt()
|
|
EX.io.rs2ValueIn := forward(IDBarrier.out.r2Value, IDBarrier.out.r2Address, true.B, mem = MEMBarrier.forwardMem, wb = MEMBarrier.forwardWb, id = MEMBarrier.forwardId).asSInt()
|
|
|
|
EXBarrier.in.r2Value := EX.io.rs2ValueOut.asUInt()
|
|
EXBarrier.in.ALUResult := EX.io.ALUResult.asUInt()
|
|
EXBarrier.in.branch := EX.io.branch
|
|
EXBarrier.in.jump := IDBarrier.out.jump
|
|
EXBarrier.in.returnAddr := IDBarrier.out.returnAddr
|
|
EXBarrier.in.writeEnable := IDBarrier.out.writeEnable
|
|
EXBarrier.in.writeAddr := IDBarrier.out.writeAddr
|
|
EXBarrier.in.memWrite := IDBarrier.out.memWrite
|
|
EXBarrier.in.memRead := IDBarrier.out.memRead
|
|
|
|
MEM.io.ALUResult := EXBarrier.out.ALUResult
|
|
MEM.io.jump := EXBarrier.out.jump
|
|
MEM.io.returnAddr := EXBarrier.out.returnAddr
|
|
MEM.io.writeMem := EXBarrier.out.memWrite
|
|
MEM.io.readMem := EXBarrier.out.memRead
|
|
MEM.io.writeData := EXBarrier.out.r2Value
|
|
|
|
MEMBarrier.memRead := EXBarrier.out.memRead
|
|
MEMBarrier.in.data := MEM.io.dataOut
|
|
MEMBarrier.in.writeEnable := EXBarrier.out.writeEnable
|
|
MEMBarrier.in.writeAddr := EXBarrier.out.writeAddr
|
|
|
|
// Write back
|
|
ID.io.writeData := MEMBarrier.out.data
|
|
ID.io.writeEnableIn := MEMBarrier.out.writeEnable
|
|
ID.io.writeAddrIn := MEMBarrier.out.writeAddr
|
|
|
|
// Branching
|
|
IF.io.branch := EXBarrier.out.branch
|
|
IF.io.branchAddress := EXBarrier.out.ALUResult
|
|
|
|
// Stall
|
|
IF.io.stall := IDBarrier.stall || ID.io.stall
|
|
IFBarrier.stall := IDBarrier.stall
|
|
}
|