diff --git a/src/main/scala/CPU.scala b/src/main/scala/CPU.scala index 1e10ff7..de251b5 100644 --- a/src/main/scala/CPU.scala +++ b/src/main/scala/CPU.scala @@ -21,14 +21,14 @@ class CPU extends MultiIOModule { /** 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 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 EX = Module(new Execute) val MEM = Module(new MemoryFetch) // val WB = Module(new Execute) (You may not need this one?) @@ -54,4 +54,28 @@ class CPU extends MultiIOModule { /** TODO: Your code here */ + + IFBarrier.PCin := IF.io.PC + IFBarrier.instructionIn := IF.io.instruction + + ID.io.instruction := IFBarrier.instructionOut + ID.io.pc := IFBarrier.PCout + + IDBarrier.op1in := ID.io.op1 + IDBarrier.op2in := ID.io.op2 + IDBarrier.ALUopIn := ID.io.ALUOp + IDBarrier.writeEnableIn := ID.io.writeEnableOut + IDBarrier.writeAddrIn := ID.io.writeAddrOut + + EX.io.op1 := IDBarrier.op1out + EX.io.op2 := IDBarrier.op2out + EX.io.ALUOp := IDBarrier.ALUopOut + + EXBarrier.writeEnableIn := IDBarrier.writeEnableOut + EXBarrier.writeAddrIn := IDBarrier.writeAddrOut + EXBarrier.writeDataIn := EX.io.ALUResult.asUInt() + + ID.io.writeData := EXBarrier.writeDataOut + ID.io.writeEnableIn := EXBarrier.writeEnableOut + ID.io.writeAddrIn := EXBarrier.writeAddrOut } diff --git a/src/main/scala/Decoder.scala b/src/main/scala/Decoder.scala index c1d5273..8330017 100644 --- a/src/main/scala/Decoder.scala +++ b/src/main/scala/Decoder.scala @@ -46,18 +46,28 @@ class Decoder() extends Module { */ val opcodeMap: Array[(BitPat, List[UInt])] = Array( - // signal regWrite, memRead, memWrite, branch, jump, branchType, Op1Select, Op2Select, ImmSelect, ALUOp - LW -> List(Y, Y, N, N, N, branchType.DC, rs1, imm, ITYPE, ALUOps.ADD), + // signal regWrite, memRead, memWrite, branch, jump, branchType, Op1Select, Op2Select, ImmSelect, ALUOp + ADD -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.ADD ), + SUB -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SUB ), + AND -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.AND ), + OR -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.OR ), + XOR -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.XOR ), + SLT -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SLT ), + SLTU -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SLTU), + SRA -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SRA ), + SRL -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SRL ), + SLL -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SLL ), - SW -> List(N, N, Y, N, N, branchType.DC, rs1, imm, STYPE, ALUOps.ADD), - - ADD -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.ADD), - SUB -> List(Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SUB), - - /** - TODO: Fill in the blanks - */ - ) + ADDI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.ADD ), + ANDI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.AND ), + ORI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.OR ), + XORI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.XOR ), + SLTI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.SLT ), + SLTIU -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.ITYPE, ALUOps.SLTU), + SRAI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.SHORT_ITYPE, ALUOps.SRA ), + SRLI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.SHORT_ITYPE, ALUOps.SRL ), + SLLI -> List(Y, N, N, N, N, branchType.DC, rs1, imm, ImmFormat.SHORT_ITYPE, ALUOps.SLL ), + ) val NOP = List(N, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.DC) diff --git a/src/main/scala/EX.scala b/src/main/scala/EX.scala new file mode 100644 index 0000000..3f69167 --- /dev/null +++ b/src/main/scala/EX.scala @@ -0,0 +1,23 @@ +package FiveStage +import Chisel.MuxLookup +import chisel3._ +import chisel3.util.{BitPat, MuxCase} +import chisel3.experimental.MultiIOModule + + +class Execute extends MultiIOModule { + val io = IO( + new Bundle { + val op1 = Input(SInt(32.W)) + val op2 = Input(SInt(32.W)) + val ALUOp = Input(UInt(4.W)) + val ALUResult = Output(SInt(32.W)) + } + ) + + val ALUOpsMap = Array ( + ALUOps.ADD -> (io.op1 + io.op2) + ) + + io.ALUResult := MuxLookup(io.ALUOp, 0.S(32.W), ALUOpsMap) +} \ No newline at end of file diff --git a/src/main/scala/EXBarrier.scala b/src/main/scala/EXBarrier.scala new file mode 100644 index 0000000..6ccffd1 --- /dev/null +++ b/src/main/scala/EXBarrier.scala @@ -0,0 +1,29 @@ +package FiveStage + +import chisel3._ +import chisel3.experimental.MultiIOModule + +class EXBarrier extends MultiIOModule { + val io = IO( + new Bundle { + val writeDataIn = Input(UInt(32.W)) + val writeDataOut = Output(UInt(32.W)) + val writeAddrIn = Input(UInt(5.W)) + val writeAddrOut = Output(UInt(5.W)) + val writeEnableIn = Input(Bool()) + val writeEnableOut = Output(Bool()) + }) + + val writeData = RegInit(UInt(32.W), 0.U) + writeData := io.writeDataIn + io.writeDataOut := writeData + + val writeAddr = RegInit(UInt(5.W), 0.U) + writeAddr := io.writeAddrIn + io.writeAddrOut := writeAddr + + val writeEnable = RegInit(Bool(), false.B) + writeEnable := io.writeEnableIn + io.writeEnableOut := writeEnable +} + diff --git a/src/main/scala/ID.scala b/src/main/scala/ID.scala index e6df740..213153a 100644 --- a/src/main/scala/ID.scala +++ b/src/main/scala/ID.scala @@ -1,6 +1,6 @@ package FiveStage import chisel3._ -import chisel3.util.{ BitPat, MuxCase } +import chisel3.util.{BitPat, MuxCase, MuxLookup} import chisel3.experimental.MultiIOModule @@ -18,32 +18,56 @@ class InstructionDecode extends MultiIOModule { val io = IO( new Bundle { - /** - * TODO: Your code here. - */ + val instruction = Input(new Instruction) + val pc = Input(UInt(32.W)) + val op1 = Output(SInt(32.W)) + val op2 = Output(SInt(32.W)) + val ALUOp = Output(UInt(4.W)) + val writeAddrIn = Input(UInt(5.W)) + val writeAddrOut = Output(UInt(5.W)) + val writeEnableIn = Input(Bool()) + val writeEnableOut = Output(Bool()) + val writeData = Input(UInt(32.W)) } ) val registers = Module(new Registers) val decoder = Module(new Decoder).io - - /** - * Setup. You should not change this code - */ registers.testHarness.setup := testHarness.registerSetup testHarness.registerPeek := registers.io.readData1 testHarness.testUpdates := registers.testHarness.testUpdates + registers.io.readAddress1 := io.instruction.registerRs1 + registers.io.readAddress2 := io.instruction.registerRs2 + registers.io.writeEnable := io.writeEnableIn + registers.io.writeAddress := io.writeAddrIn + registers.io.writeData := io.writeData - /** - * TODO: Your code here. - */ - registers.io.readAddress1 := 0.U - registers.io.readAddress2 := 0.U - registers.io.writeEnable := false.B - registers.io.writeAddress := 0.U - registers.io.writeData := 0.U + decoder.instruction := io.instruction - decoder.instruction := 0.U.asTypeOf(new Instruction) + val select1Map = Array( + Op1Select.rs1 -> registers.io.readData1.asSInt(), + Op1Select.PC -> io.pc.asSInt(), + ) + io.op1 := MuxLookup(decoder.op1Select, 0.S(32.W), select1Map) + + val select2ImmMap = Array( + ImmFormat.ITYPE -> decoder.instruction.immediateIType, + ImmFormat.STYPE -> decoder.instruction.immediateSType, + ImmFormat.BTYPE -> decoder.instruction.immediateBType, + ImmFormat.UTYPE -> decoder.instruction.immediateUType, + ImmFormat.JTYPE -> decoder.instruction.immediateJType, + ImmFormat.SHAMT -> decoder.instruction.immediateZType, + ImmFormat.SHORT_ITYPE -> decoder.instruction.immediateShortIType, + ) + val select2Map = Array( + Op2Select.imm -> MuxLookup(decoder.immType, 0.S(32.W), select2ImmMap), + Op2Select.rs2 -> registers.io.readData2.asSInt(), + ) + io.op2 := MuxLookup(decoder.op2Select, 0.S(32.W), select2Map) + + io.ALUOp := decoder.ALUop + io.writeAddrOut := decoder.instruction.registerRd + io.writeEnableOut := decoder.controlSignals.regWrite } diff --git a/src/main/scala/IDBarrier.scala b/src/main/scala/IDBarrier.scala new file mode 100644 index 0000000..1d2d0f7 --- /dev/null +++ b/src/main/scala/IDBarrier.scala @@ -0,0 +1,40 @@ +package FiveStage + +import chisel3._ +import chisel3.experimental.MultiIOModule + +class IDBarrier extends MultiIOModule { + val io = IO( + new Bundle { + val op1in = Input(SInt(32.W)) + val op1out = Output(SInt(32.W)) + val op2in = Input(SInt(32.W)) + val op2out = Output(SInt(32.W)) + val ALUopIn = Input(UInt(4.W)) + val ALUopOut = Output(UInt(4.W)) + val writeAddrIn = Input(UInt(5.W)) + val writeAddrOut = Output(UInt(5.W)) + val writeEnableIn = Input(Bool()) + val writeEnableOut = Output(Bool()) + }) + + val op1 = RegInit(SInt(32.W), 0.S) + op1 := io.op1in + io.op1out := op1 + + val op2 = RegInit(SInt(32.W), 0.S) + op2 := io.op2in + io.op2out := op2 + + val ALUop = RegInit(UInt(4.W), 0.U) + ALUop := io.ALUopIn + io.ALUopOut := ALUop + + val writeAddr = RegInit(UInt(5.W), 0.U) + writeAddr := io.writeAddrIn + io.writeAddrOut := writeAddr + + val writeEnable = RegInit(Bool(), false.B) + writeEnable := io.writeEnableIn + io.writeEnableOut := writeEnable +} diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index b4bb4ab..1659efd 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -23,7 +23,8 @@ class InstructionFetch extends MultiIOModule { */ val io = IO( new Bundle { - val PC = Output(UInt()) + val PC = Output(UInt(32.W)) + val instruction = Output(new Instruction) }) val IMEM = Module(new IMEM) @@ -44,12 +45,11 @@ class InstructionFetch extends MultiIOModule { */ io.PC := PC IMEM.io.instructionAddress := PC - - // PC := PC + 4.U + PC := PC + 4.U val instruction = Wire(new Instruction) instruction := IMEM.io.instruction.asTypeOf(new Instruction) - + io.instruction := instruction /** * Setup. You should not change this code. diff --git a/src/main/scala/IFBarrier.scala b/src/main/scala/IFBarrier.scala new file mode 100644 index 0000000..0523874 --- /dev/null +++ b/src/main/scala/IFBarrier.scala @@ -0,0 +1,20 @@ +package FiveStage + +import chisel3._ +import chisel3.experimental.MultiIOModule + +class IFBarrier extends MultiIOModule { + val io = IO( + new Bundle { + val PCin = Input(UInt(32.W)) + val PCout = Output(UInt(32.W)) + val instructionIn = Input(new Instruction) + val instructionOut = Output(new Instruction) + }) + + val PC = RegInit(UInt(32.W), 0.U) + PC := io.PCin + io.PCout := PC + + io.instructionOut := io.instructionIn +} diff --git a/src/main/scala/ToplevelSignals.scala b/src/main/scala/ToplevelSignals.scala index d80cfb2..06d1cd2 100644 --- a/src/main/scala/ToplevelSignals.scala +++ b/src/main/scala/ToplevelSignals.scala @@ -15,12 +15,13 @@ class Instruction extends Bundle(){ def funct7 = instruction(31, 25) def funct6 = instruction(26, 31) - def immediateIType = instruction(31, 20).asSInt - def immediateSType = Cat(instruction(31, 25), instruction(11,7)).asSInt - def immediateBType = Cat(instruction(31), instruction(7), instruction(30, 25), instruction(11, 8), 0.U(1.W)).asSInt - def immediateUType = Cat(instruction(31, 12), 0.U(12.W)).asSInt - def immediateJType = Cat(instruction(31), instruction(19, 12), instruction(20), instruction(30, 25), instruction(24, 21), 0.U(1.W)).asSInt - def immediateZType = instruction(19, 15).zext + def immediateIType = instruction(31, 20).asSInt + def immediateSType = Cat(instruction(31, 25), instruction(11,7)).asSInt + def immediateBType = Cat(instruction(31), instruction(7), instruction(30, 25), instruction(11, 8), 0.U(1.W)).asSInt + def immediateUType = Cat(instruction(31, 12), 0.U(12.W)).asSInt + def immediateJType = Cat(instruction(31), instruction(19, 12), instruction(20), instruction(30, 25), instruction(24, 21), 0.U(1.W)).asSInt + def immediateZType = instruction(19, 15).zext + def immediateShortIType = instruction(24, 20).asSInt def bubble(): Instruction = { val bubbled = Wire(new Instruction) @@ -102,6 +103,7 @@ object ImmFormat { val UTYPE = 3.asUInt(3.W) val JTYPE = 4.asUInt(3.W) val SHAMT = 5.asUInt(3.W) + val SHORT_ITYPE = 6.asUInt(3.W) val DC = 0.asUInt(3.W) }