Nuke
This commit is contained in:
commit
932413bb3d
61 changed files with 7249 additions and 0 deletions
57
src/main/scala/CPU.scala
Normal file
57
src/main/scala/CPU.scala
Normal file
|
@ -0,0 +1,57 @@
|
|||
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
|
||||
*/
|
||||
}
|
60
src/main/scala/Const.scala
Normal file
60
src/main/scala/Const.scala
Normal file
|
@ -0,0 +1,60 @@
|
|||
package FiveStage
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.core.Input
|
||||
import chisel3.iotesters.PeekPokeTester
|
||||
|
||||
|
||||
// From RISC-V reference card
|
||||
object ALUOps {
|
||||
|
||||
val ADD = 0.U(4.W)
|
||||
val SUB = 1.U(4.W)
|
||||
val AND = 2.U(4.W)
|
||||
val OR = 3.U(4.W)
|
||||
val XOR = 4.U(4.W)
|
||||
val SLT = 5.U(4.W)
|
||||
val SLL = 6.U(4.W)
|
||||
val SLTU = 7.U(4.W)
|
||||
val SRL = 8.U(4.W)
|
||||
val SRA = 9.U(4.W)
|
||||
val COPY_A = 10.U(4.W)
|
||||
val COPY_B = 11.U(4.W)
|
||||
|
||||
val DC = 15.U(4.W)
|
||||
}
|
||||
|
||||
object lookup {
|
||||
def BEQ = BitPat("b?????????????????000?????1100011")
|
||||
def BNE = BitPat("b?????????????????001?????1100011")
|
||||
def BLT = BitPat("b?????????????????100?????1100011")
|
||||
def BGE = BitPat("b?????????????????101?????1100011")
|
||||
def BLTU = BitPat("b?????????????????110?????1100011")
|
||||
def BGEU = BitPat("b?????????????????111?????1100011")
|
||||
def JALR = BitPat("b?????????????????000?????1100111")
|
||||
def JAL = BitPat("b?????????????????????????1101111")
|
||||
def LUI = BitPat("b?????????????????????????0110111")
|
||||
def AUIPC = BitPat("b?????????????????????????0010111")
|
||||
def ADDI = BitPat("b?????????????????000?????0010011")
|
||||
def SLLI = BitPat("b000000???????????001?????0010011")
|
||||
def SLTI = BitPat("b?????????????????010?????0010011")
|
||||
def SLTIU = BitPat("b?????????????????011?????0010011")
|
||||
def XORI = BitPat("b?????????????????100?????0010011")
|
||||
def SRLI = BitPat("b000000???????????101?????0010011")
|
||||
def SRAI = BitPat("b010000???????????101?????0010011")
|
||||
def ORI = BitPat("b?????????????????110?????0010011")
|
||||
def ANDI = BitPat("b?????????????????111?????0010011")
|
||||
def ADD = BitPat("b0000000??????????000?????0110011")
|
||||
def SUB = BitPat("b0100000??????????000?????0110011")
|
||||
def SLL = BitPat("b0000000??????????001?????0110011")
|
||||
def SLT = BitPat("b0000000??????????010?????0110011")
|
||||
def SLTU = BitPat("b0000000??????????011?????0110011")
|
||||
def XOR = BitPat("b0000000??????????100?????0110011")
|
||||
def SRL = BitPat("b0000000??????????101?????0110011")
|
||||
def SRA = BitPat("b0100000??????????101?????0110011")
|
||||
def OR = BitPat("b0000000??????????110?????0110011")
|
||||
def AND = BitPat("b0000000??????????111?????0110011")
|
||||
def LW = BitPat("b?????????????????010?????0000011")
|
||||
def SW = BitPat("b?????????????????010?????0100011")
|
||||
}
|
54
src/main/scala/DMem.scala
Normal file
54
src/main/scala/DMem.scala
Normal file
|
@ -0,0 +1,54 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
|
||||
/**
|
||||
* This module is already done. Have one on me
|
||||
*/
|
||||
class DMEM extends MultiIOModule {
|
||||
|
||||
|
||||
// Don't touch the test harness
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val setup = Input(new DMEMsetupSignals)
|
||||
val testUpdates = Output(new MemUpdates)
|
||||
})
|
||||
|
||||
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
val writeEnable = Input(Bool())
|
||||
val dataIn = Input(UInt(32.W))
|
||||
val dataAddress = Input(UInt(12.W))
|
||||
|
||||
val dataOut = Output(UInt(32.W))
|
||||
})
|
||||
|
||||
val data = SyncReadMem(4096, UInt(32.W))
|
||||
|
||||
val addressSource = Wire(UInt(32.W))
|
||||
val dataSource = Wire(UInt(32.W))
|
||||
val writeEnableSource = Wire(Bool())
|
||||
|
||||
// For loading data
|
||||
when(testHarness.setup.setup){
|
||||
addressSource := testHarness.setup.dataAddress
|
||||
dataSource := testHarness.setup.dataIn
|
||||
writeEnableSource := testHarness.setup.writeEnable
|
||||
}.otherwise {
|
||||
addressSource := io.dataAddress
|
||||
dataSource := io.dataIn
|
||||
writeEnableSource := io.writeEnable
|
||||
}
|
||||
|
||||
testHarness.testUpdates.writeEnable := writeEnableSource
|
||||
testHarness.testUpdates.writeData := dataSource
|
||||
testHarness.testUpdates.writeAddress := addressSource
|
||||
|
||||
io.dataOut := data(addressSource)
|
||||
when(writeEnableSource){
|
||||
data(addressSource) := dataSource
|
||||
}
|
||||
}
|
82
src/main/scala/Decoder.scala
Normal file
82
src/main/scala/Decoder.scala
Normal file
|
@ -0,0 +1,82 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.util.BitPat
|
||||
import chisel3.util.ListLookup
|
||||
|
||||
|
||||
/**
|
||||
* This module is mostly done, but you will have to fill in the blanks in opcodeMap.
|
||||
* You may want to add more signals to be decoded in this module depending on your
|
||||
* design if you so desire.
|
||||
*
|
||||
* In the "classic" 5 stage decoder signals such as op1select and immType
|
||||
* are not included, however I have added them to my design, and similarily you might
|
||||
* find it useful to add more
|
||||
*/
|
||||
class Decoder() extends Module {
|
||||
|
||||
val io = IO(new Bundle {
|
||||
val instruction = Input(new Instruction)
|
||||
|
||||
val controlSignals = Output(new ControlSignals)
|
||||
val branchType = Output(UInt(3.W))
|
||||
val op1Select = Output(UInt(1.W))
|
||||
val op2Select = Output(UInt(1.W))
|
||||
val immType = Output(UInt(3.W))
|
||||
val ALUop = Output(UInt(4.W))
|
||||
})
|
||||
|
||||
import lookup._
|
||||
import Op1Select._
|
||||
import Op2Select._
|
||||
import branchType._
|
||||
import ImmFormat._
|
||||
|
||||
val N = 0.asUInt(1.W)
|
||||
val Y = 1.asUInt(1.W)
|
||||
|
||||
/**
|
||||
* In scala we sometimes (ab)use the `->` operator to create tuples.
|
||||
* The reason for this is that it serves as convenient sugar to make maps.
|
||||
*
|
||||
* This doesn't matter to you, just fill in the blanks in the style currently
|
||||
* used, I just want to demystify some of the magic.
|
||||
*
|
||||
* `a -> b` == `(a, b)` == `Tuple2(a, b)`
|
||||
*/
|
||||
val opcodeMap: Array[(BitPat, List[UInt])] = Array(
|
||||
|
||||
// signal memToReg, regWrite, memRead, memWrite, branch, jump, branchType, Op1Select, Op2Select, ImmSelect, ALUOp
|
||||
LW -> List(Y, Y, Y, N, N, N, branchType.DC, rs1, imm, ITYPE, ALUOps.ADD),
|
||||
|
||||
SW -> List(N, N, N, Y, N, N, branchType.DC, rs1, imm, STYPE, ALUOps.ADD),
|
||||
|
||||
ADD -> List(N, Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.ADD),
|
||||
SUB -> List(N, Y, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.SUB),
|
||||
|
||||
/**
|
||||
TODO: Fill in the blanks
|
||||
*/
|
||||
)
|
||||
|
||||
|
||||
val NOP = List(N, N, N, N, N, N, branchType.DC, rs1, rs2, ImmFormat.DC, ALUOps.DC)
|
||||
|
||||
val decodedControlSignals = ListLookup(
|
||||
io.instruction.asUInt(),
|
||||
NOP,
|
||||
opcodeMap)
|
||||
|
||||
io.controlSignals.memToReg := decodedControlSignals(0)
|
||||
io.controlSignals.regWrite := decodedControlSignals(1)
|
||||
io.controlSignals.memRead := decodedControlSignals(2)
|
||||
io.controlSignals.memWrite := decodedControlSignals(3)
|
||||
io.controlSignals.branch := decodedControlSignals(4)
|
||||
io.controlSignals.jump := decodedControlSignals(5)
|
||||
|
||||
io.branchType := decodedControlSignals(6)
|
||||
io.op1Select := decodedControlSignals(7)
|
||||
io.op2Select := decodedControlSignals(8)
|
||||
io.immType := decodedControlSignals(9)
|
||||
io.ALUop := decodedControlSignals(10)
|
||||
}
|
49
src/main/scala/ID.scala
Normal file
49
src/main/scala/ID.scala
Normal file
|
@ -0,0 +1,49 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.util.{ BitPat, MuxCase }
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
|
||||
class InstructionDecode extends MultiIOModule {
|
||||
|
||||
// Don't touch the test harness
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val registerSetup = Input(new RegisterSetupSignals)
|
||||
val registerPeek = Output(UInt(32.W))
|
||||
|
||||
val testUpdates = Output(new RegisterUpdates)
|
||||
})
|
||||
|
||||
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
/**
|
||||
* TODO: Your code here.
|
||||
*/
|
||||
}
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
|
||||
/**
|
||||
* 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 := 0.U.asTypeOf(new Instruction)
|
||||
}
|
59
src/main/scala/IF.scala
Normal file
59
src/main/scala/IF.scala
Normal file
|
@ -0,0 +1,59 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
class InstructionFetch extends MultiIOModule {
|
||||
|
||||
// Don't touch
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val IMEMsetup = Input(new IMEMsetupSignals)
|
||||
val PC = Output(UInt())
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Add signals for handling events such as jumps
|
||||
*/
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
val PC = Output(UInt())
|
||||
})
|
||||
|
||||
val IMEM = Module(new IMEM)
|
||||
val PC = RegInit(UInt(32.W), 0.U)
|
||||
|
||||
|
||||
/**
|
||||
* Setup. You should not change this code
|
||||
*/
|
||||
IMEM.testHarness.setupSignals := testHarness.IMEMsetup
|
||||
testHarness.PC := IMEM.testHarness.requestedAddress
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Your code here.
|
||||
*
|
||||
* You should expand on or rewrite the code below.
|
||||
*/
|
||||
io.PC := PC
|
||||
IMEM.io.instructionAddress := PC
|
||||
|
||||
PC := PC + 4.U
|
||||
|
||||
val instruction = Wire(new Instruction)
|
||||
instruction := IMEM.io.instruction.asTypeOf(new Instruction)
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup. You should not change this code
|
||||
*/
|
||||
when(testHarness.IMEMsetup.setup) {
|
||||
PC := 0.U
|
||||
// TODO: You must set the instruction to Instruction.NOP here.
|
||||
// throw new Exception("Just making sure you're seeing the line above")
|
||||
}
|
||||
}
|
52
src/main/scala/IMem.scala
Normal file
52
src/main/scala/IMem.scala
Normal file
|
@ -0,0 +1,52 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
/**
|
||||
* This module is finished and does not need to be modified to complete your fivestage.
|
||||
*
|
||||
* When setup is enabled data is written to the instruction memory.
|
||||
* In normal operation this memory is write only (no self modifying code)
|
||||
*/
|
||||
class IMEM() extends MultiIOModule {
|
||||
|
||||
// Don't touch
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val setupSignals = Input(new IMEMsetupSignals)
|
||||
val requestedAddress = Output(UInt())
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
val instructionAddress = Input(UInt(32.W))
|
||||
val instruction = Output(UInt(32.W))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
SyncReadMem will output the value of the address signal set in the previous cycle.
|
||||
*/
|
||||
val instructions = SyncReadMem(4096, UInt(32.W))
|
||||
|
||||
// The address we want to read at during operation. During setup it acts as a write address
|
||||
// leading to the somewhat uninformative name shown here.
|
||||
val addressSource = Wire(UInt(32.W))
|
||||
|
||||
testHarness.requestedAddress := io.instructionAddress
|
||||
|
||||
when(testHarness.setupSignals.setup){
|
||||
addressSource := testHarness.setupSignals.address
|
||||
}.otherwise {
|
||||
addressSource := io.instructionAddress
|
||||
}
|
||||
|
||||
// For loading data
|
||||
when(testHarness.setupSignals.setup){
|
||||
instructions(addressSource) := testHarness.setupSignals.instruction
|
||||
}
|
||||
|
||||
io.instruction := instructions(addressSource)
|
||||
}
|
41
src/main/scala/MEM.scala
Normal file
41
src/main/scala/MEM.scala
Normal file
|
@ -0,0 +1,41 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
|
||||
class MemoryFetch() extends MultiIOModule {
|
||||
|
||||
|
||||
// Don't touch the test harness
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val DMEMsetup = Input(new DMEMsetupSignals)
|
||||
val DMEMpeek = Output(UInt(32.W))
|
||||
|
||||
val testUpdates = Output(new MemUpdates)
|
||||
})
|
||||
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
})
|
||||
|
||||
|
||||
val DMEM = Module(new DMEM)
|
||||
|
||||
|
||||
/**
|
||||
* Setup. You should not change this code
|
||||
*/
|
||||
DMEM.testHarness.setup := testHarness.DMEMsetup
|
||||
testHarness.DMEMpeek := DMEM.io.dataOut
|
||||
testHarness.testUpdates := DMEM.testHarness.testUpdates
|
||||
|
||||
|
||||
/**
|
||||
* Your code here.
|
||||
*/
|
||||
DMEM.io.dataIn := 0.U
|
||||
DMEM.io.dataAddress := 0.U
|
||||
DMEM.io.writeEnable := false.B
|
||||
}
|
81
src/main/scala/Registers.scala
Normal file
81
src/main/scala/Registers.scala
Normal file
|
@ -0,0 +1,81 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
|
||||
/**
|
||||
* This module is already done. Have one on me
|
||||
*
|
||||
* When a write and read conflicts this might result in stale data.
|
||||
* This caveat must be handled using a bypass.
|
||||
*/
|
||||
class Registers() extends MultiIOModule {
|
||||
|
||||
|
||||
// Don't touch the test harness
|
||||
val testHarness = IO(
|
||||
new Bundle {
|
||||
val setup = Input(new RegisterSetupSignals)
|
||||
val testUpdates = Output(new RegisterUpdates)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// You shouldn't really touch these either
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
val readAddress1 = Input(UInt(5.W))
|
||||
val readAddress2 = Input(UInt(5.W))
|
||||
val writeEnable = Input(Bool())
|
||||
val writeAddress = Input(UInt(5.W))
|
||||
val writeData = Input(UInt(32.W))
|
||||
|
||||
val readData1 = Output(UInt(32.W))
|
||||
val readData2 = Output(UInt(32.W))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Mem creates asynchronous read, synchronous write.
|
||||
* In other words, reading is combinatory.
|
||||
*/
|
||||
val registerFile = Mem(32, UInt(32.W))
|
||||
|
||||
val readAddress1 = Wire(UInt(5.W))
|
||||
val readAddress2 = Wire(UInt(5.W))
|
||||
val writeAddress = Wire(UInt(5.W))
|
||||
val writeData = Wire(UInt(32.W))
|
||||
val writeEnable = Wire(Bool())
|
||||
|
||||
when(testHarness.setup.setup){
|
||||
readAddress1 := testHarness.setup.readAddress
|
||||
readAddress2 := io.readAddress2
|
||||
writeData := testHarness.setup.writeData
|
||||
writeEnable := testHarness.setup.writeEnable
|
||||
writeAddress := testHarness.setup.readAddress
|
||||
}.otherwise{
|
||||
readAddress1 := io.readAddress1
|
||||
readAddress2 := io.readAddress2
|
||||
writeData := io.writeData
|
||||
writeEnable := io.writeEnable
|
||||
writeAddress := io.writeAddress
|
||||
}
|
||||
|
||||
|
||||
testHarness.testUpdates.writeData := writeData
|
||||
testHarness.testUpdates.writeEnable := writeEnable
|
||||
testHarness.testUpdates.writeAddress := writeAddress
|
||||
|
||||
|
||||
when(writeEnable){
|
||||
when(writeAddress =/= 0.U){
|
||||
registerFile(writeAddress) := writeData
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
io.readData1 := 0.U
|
||||
io.readData2 := 0.U
|
||||
when(readAddress1 =/= 0.U){ io.readData1 := registerFile(readAddress1) }
|
||||
when(readAddress2 =/= 0.U){ io.readData2 := registerFile(readAddress2) }
|
||||
}
|
51
src/main/scala/SetupSignals.scala
Normal file
51
src/main/scala/SetupSignals.scala
Normal file
|
@ -0,0 +1,51 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.core.Wire
|
||||
import chisel3.util.{ BitPat, Cat }
|
||||
|
||||
/**
|
||||
* Don't touch these
|
||||
*/
|
||||
class SetupSignals extends Bundle {
|
||||
val IMEMsignals = new IMEMsetupSignals
|
||||
val DMEMsignals = new DMEMsetupSignals
|
||||
val registerSignals = new RegisterSetupSignals
|
||||
}
|
||||
|
||||
class IMEMsetupSignals extends Bundle {
|
||||
val setup = Bool()
|
||||
val address = UInt(32.W)
|
||||
val instruction = UInt(32.W)
|
||||
}
|
||||
|
||||
class DMEMsetupSignals extends Bundle {
|
||||
val setup = Bool()
|
||||
val writeEnable = Bool()
|
||||
val dataIn = UInt(32.W)
|
||||
val dataAddress = UInt(32.W)
|
||||
}
|
||||
|
||||
class RegisterSetupSignals extends Bundle {
|
||||
val setup = Bool()
|
||||
val readAddress = UInt(5.W)
|
||||
val writeEnable = Bool()
|
||||
val writeAddress = UInt(5.W)
|
||||
val writeData = UInt(32.W)
|
||||
}
|
||||
|
||||
class TestReadouts extends Bundle {
|
||||
val registerRead = UInt(32.W)
|
||||
val DMEMread = UInt(32.W)
|
||||
}
|
||||
|
||||
class RegisterUpdates extends Bundle {
|
||||
val writeEnable = Bool()
|
||||
val writeData = UInt(32.W)
|
||||
val writeAddress = UInt(5.W)
|
||||
}
|
||||
|
||||
class MemUpdates extends Bundle {
|
||||
val writeEnable = Bool()
|
||||
val writeData = UInt(32.W)
|
||||
val writeAddress = UInt(32.W)
|
||||
}
|
75
src/main/scala/Tile.scala
Normal file
75
src/main/scala/Tile.scala
Normal file
|
@ -0,0 +1,75 @@
|
|||
package FiveStage
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.core.Input
|
||||
import chisel3.iotesters.PeekPokeTester
|
||||
|
||||
|
||||
/**
|
||||
* The top level module. You do not have to change anything here,
|
||||
* however you are free to route out signals as you see fit for debugging.
|
||||
*/
|
||||
class Tile() extends Module{
|
||||
|
||||
val io = IO(
|
||||
new Bundle {
|
||||
val DMEMWriteData = Input(UInt(32.W))
|
||||
val DMEMAddress = Input(UInt(32.W))
|
||||
val DMEMWriteEnable = Input(Bool())
|
||||
val DMEMReadData = Output(UInt(32.W))
|
||||
|
||||
val regsWriteData = Input(UInt(32.W))
|
||||
val regsAddress = Input(UInt(5.W))
|
||||
val regsWriteEnable = Input(Bool())
|
||||
val regsReadData = Output(UInt(32.W))
|
||||
|
||||
val regsDeviceWriteEnable = Output(Bool())
|
||||
val regsDeviceWriteData = Output(UInt(32.W))
|
||||
val regsDeviceWriteAddress = Output(UInt(5.W))
|
||||
|
||||
val memDeviceWriteEnable = Output(Bool())
|
||||
val memDeviceWriteData = Output(UInt(32.W))
|
||||
val memDeviceWriteAddress = Output(UInt(32.W))
|
||||
|
||||
val IMEMWriteData = Input(UInt(32.W))
|
||||
val IMEMAddress = Input(UInt(32.W))
|
||||
|
||||
val setup = Input(Bool())
|
||||
|
||||
val currentPC = Output(UInt())
|
||||
})
|
||||
|
||||
val CPU = Module(new CPU).testHarness
|
||||
|
||||
CPU.setupSignals.IMEMsignals.address := io.IMEMAddress
|
||||
CPU.setupSignals.IMEMsignals.instruction := io.IMEMWriteData
|
||||
CPU.setupSignals.IMEMsignals.setup := io.setup
|
||||
|
||||
CPU.setupSignals.DMEMsignals.writeEnable := io.DMEMWriteEnable
|
||||
CPU.setupSignals.DMEMsignals.dataAddress := io.DMEMAddress
|
||||
CPU.setupSignals.DMEMsignals.dataIn := io.DMEMWriteData
|
||||
CPU.setupSignals.DMEMsignals.setup := io.setup
|
||||
|
||||
CPU.setupSignals.registerSignals.readAddress := io.regsAddress
|
||||
CPU.setupSignals.registerSignals.writeEnable := io.regsWriteEnable
|
||||
CPU.setupSignals.registerSignals.writeAddress := io.regsAddress
|
||||
CPU.setupSignals.registerSignals.writeData := io.regsWriteData
|
||||
CPU.setupSignals.registerSignals.setup := io.setup
|
||||
|
||||
io.DMEMReadData := CPU.testReadouts.DMEMread
|
||||
io.regsReadData := CPU.testReadouts.registerRead
|
||||
|
||||
io.regsDeviceWriteAddress := CPU.regUpdates.writeAddress
|
||||
io.regsDeviceWriteEnable := CPU.regUpdates.writeEnable
|
||||
io.regsDeviceWriteData := CPU.regUpdates.writeData
|
||||
|
||||
io.memDeviceWriteAddress := CPU.memUpdates.writeAddress
|
||||
io.memDeviceWriteEnable := CPU.memUpdates.writeEnable
|
||||
io.memDeviceWriteData := CPU.memUpdates.writeData
|
||||
|
||||
io.currentPC := CPU.currentPC
|
||||
}
|
||||
|
||||
|
||||
|
105
src/main/scala/ToplevelSignals.scala
Normal file
105
src/main/scala/ToplevelSignals.scala
Normal file
|
@ -0,0 +1,105 @@
|
|||
package FiveStage
|
||||
import chisel3._
|
||||
import chisel3.core.Wire
|
||||
import chisel3.util.{ BitPat, Cat }
|
||||
|
||||
|
||||
class Instruction extends Bundle(){
|
||||
val instruction = UInt(32.W)
|
||||
|
||||
def opcode = instruction(6, 0)
|
||||
def registerRd = instruction(11, 7)
|
||||
def funct3 = instruction(14, 12)
|
||||
def registerRs1 = instruction(19, 15)
|
||||
def registerRs2 = instruction(24, 20)
|
||||
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
|
||||
|
||||
}
|
||||
object Instruction {
|
||||
def bubble(i: Instruction) =
|
||||
i.opcode := BitPat.bitPatToUInt(BitPat("b0010011"))
|
||||
|
||||
def default: Instruction = {
|
||||
val w = Wire(new Instruction)
|
||||
w.instruction := 0.U
|
||||
w
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ControlSignals extends Bundle(){
|
||||
val memToReg = Bool()
|
||||
val regWrite = Bool()
|
||||
val memRead = Bool()
|
||||
val memWrite = Bool()
|
||||
val branch = Bool()
|
||||
val jump = Bool()
|
||||
}
|
||||
|
||||
|
||||
object ControlSignals {
|
||||
def nop: ControlSignals = {
|
||||
val b = Wire(new ControlSignals)
|
||||
b.memToReg := false.B
|
||||
b.regWrite := false.B
|
||||
b.memRead := false.B
|
||||
b.memWrite := false.B
|
||||
b.branch := false.B
|
||||
b.jump := false.B
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object branchType {
|
||||
val beq = 0.asUInt(3.W)
|
||||
val neq = 1.asUInt(3.W)
|
||||
val gte = 2.asUInt(3.W)
|
||||
val lt = 3.asUInt(3.W)
|
||||
val gteu = 4.asUInt(3.W)
|
||||
val ltu = 5.asUInt(3.W)
|
||||
val jump = 6.asUInt(3.W)
|
||||
val DC = 0.asUInt(3.W)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
these take the role of the alu source signal.
|
||||
Used in the decoder.
|
||||
In the solution manual I use these to select signals at the decode stage.
|
||||
You can choose to instead do this in the execute stage, and you may forego
|
||||
using them altogether.
|
||||
*/
|
||||
object Op1Select {
|
||||
val rs1 = 0.asUInt(1.W)
|
||||
val PC = 1.asUInt(1.W)
|
||||
val DC = 0.asUInt(1.W)
|
||||
}
|
||||
|
||||
object Op2Select {
|
||||
val rs2 = 0.asUInt(1.W)
|
||||
val imm = 1.asUInt(1.W)
|
||||
val DC = 0.asUInt(1.W)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Used in the decoder
|
||||
*/
|
||||
object ImmFormat {
|
||||
val ITYPE = 0.asUInt(3.W)
|
||||
val STYPE = 1.asUInt(3.W)
|
||||
val BTYPE = 2.asUInt(3.W)
|
||||
val UTYPE = 3.asUInt(3.W)
|
||||
val JTYPE = 4.asUInt(3.W)
|
||||
val SHAMT = 5.asUInt(3.W)
|
||||
val DC = 0.asUInt(3.W)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue