Skip to content

Commit

Permalink
Integrate the mem unit into exu
Browse files Browse the repository at this point in the history
  • Loading branch information
Bohan Hu committed Oct 24, 2020
1 parent edacc84 commit 287f414
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 139 deletions.
129 changes: 82 additions & 47 deletions src/main/scala/core/exu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,58 @@ import common.OpConstants._

class Exe2Mem extends Bundle {
val aluResult = UInt(64.W)
val RdNum = UInt(5.W)
val R2val = UInt(64.W) // For L/S
val WBSel = UInt(2.W)
val RFWen = Bool()
val isMemOp = Bool()
val MemOp = UInt(2.W)
val MemType = UInt(3.W)
val CSRCmd = UInt(3.W)
val isFence = Bool()
val exceInfo = new ExceptionInfo
val RdNum = UInt(5.W)
val R2val = UInt(64.W) // For L/S
val WBSel = UInt(2.W)
val RFWen = Bool()
val isMemOp = Bool()
val MemOp = UInt(2.W)
val MemType = UInt(3.W)
val CSRCmd = UInt(3.W)
val isFence = Bool()
val exceInfo = new ExceptionInfo
}

class Exe2Commit extends Bundle {
// Excution Result
val arithResult = UInt(64.W)
val memResult = UInt(64.W)
// Write back info
val RdNum = UInt(5.W)
val WBSel = UInt(2.W)
val RFWen = Bool()
// CSR
val CSRCmd = UInt(3.W)
// Flush the pipeline and TLBs
val isFence = Bool()
// Cause Exceptions or not?
val exceInfo = new ExceptionInfo
}

class BranchRedir extends Bundle {
val TargetPC = UInt(64.W)
val redir = Bool()
}

class EXUIO extends Bundle {
val instBundleIn = Input(new InstBundle)
// val wbInfoMem = Input()
// val wbInfowb = Input()
val decode2Exe = Input(new Decode2Exe)
val exe2Mem = Output(new Exe2Mem)
val exe2IF = Output(new BranchRedir)
val pauseReq = Output(Bool())
val exe2Commit = Output(new Exe2Commit)
val instBundleOut = Output(new InstBundle)
val mem2dmem = new MEM2dmem
val toclint = Flipped(new MEMCLINT)
}

class EXU extends Module {
val io = IO(new EXUIO)
io.exe2Mem.exceInfo := io.decode2Exe.exceInfo
val alu = Module(new ALU_top)
// Todo: Deal with the bypass condition
// TODO: Deal with the bypass condition
val op1 = io.decode2Exe.Op1
val op2 = io.decode2Exe.Op2
val rs2 = io.decode2Exe.R2val

alu.io.srcA := io.decode2Exe.Op1
alu.io.srcB := io.decode2Exe.Op2
alu.io.aluOP := io.decode2Exe.ALUOp
alu.io.isWordOp := io.decode2Exe.isWordOp

val mulu = Module(new Multiplier)
mulu.io.opA := io.decode2Exe.Op1
mulu.io.opB := io.decode2Exe.Op2
mulu.io.mduOp := io.decode2Exe.ALUOp
mulu.io.opValid := io.decode2Exe.FUType === FU_MUL && io.instBundleIn.instValid

val divu = Module(new Divider)
divu.io.opA := io.decode2Exe.Op1
divu.io.opB := io.decode2Exe.Op2
divu.io.mduOp := io.decode2Exe.ALUOp
divu.io.opValid := io.decode2Exe.FUType === FU_DIV && io.instBundleIn.instValid
io.pauseReq := divu.io.divBusy || mulu.io.mulBusy

// Pass through
io.exe2Mem.aluResult := Mux(io.decode2Exe.FUType === FU_MUL, mulu.io.wbResult,
Mux(io.decode2Exe.FUType === FU_DIV, divu.io.wbResult, alu.io.out))
io.exe2Mem.RdNum := io.decode2Exe.RdNum
io.exe2Mem.R2val := io.decode2Exe.R2val
io.exe2Mem.WBSel := io.decode2Exe.WBSel
io.exe2Mem.RFWen := io.decode2Exe.RFWen
io.exe2Mem.isMemOp := io.decode2Exe.isMemOp
io.exe2Mem.MemOp := io.decode2Exe.MemOp
io.exe2Mem.MemType := io.decode2Exe.MemType
io.exe2Mem.CSRCmd := io.decode2Exe.CSRCmd
io.exe2Mem.isFence := io.decode2Exe.isFence
// Branch Unit
val branchTakenCond = Array(
BR_N -> false.B,
BR_J -> true.B,
Expand All @@ -83,7 +70,55 @@ class EXU extends Module {
BR_LTU -> (op1 < rs2)
)
io.exe2IF.redir := MuxLookup(io.decode2Exe.BrType, false.B, branchTakenCond) & io.instBundleIn.instValid
io.exe2IF.TargetPC := Mux(io.decode2Exe.BrType === BR_JR, alu.io.out, io.instBundleIn.inst_pc + io.decode2Exe.Op2)
io.exe2IF.TargetPC := Mux(io.decode2Exe.BrType === BR_JR, op1 + op2, io.instBundleIn.inst_pc + op2)

// Arith Instruction
val alu = Module(new ALU_top)
alu.io.srcA := op1
alu.io.srcB := op2
alu.io.aluOP := io.decode2Exe.ALUOp
alu.io.isWordOp := io.decode2Exe.isWordOp

// Multiply instruction
val mulu = Module(new Multiplier)
mulu.io.opA := op1
mulu.io.opB := op2
mulu.io.mduOp := io.decode2Exe.ALUOp
mulu.io.opValid := io.decode2Exe.FUType === FU_MUL && io.instBundleIn.instValid

// Division instruction
val divu = Module(new Divider)
divu.io.opA := op1
divu.io.opB := op2
divu.io.mduOp := io.decode2Exe.ALUOp
divu.io.opValid := io.decode2Exe.FUType === FU_DIV && io.instBundleIn.instValid

io.exe2Commit.arithResult := Mux(io.decode2Exe.FUType === FU_ALU, alu.io.out,
Mux(io.decode2Exe.FUType === FU_MUL, mulu.io.wbResult, divu.io.wbResult))

// Load / Store instruction
// Can be exceptions
val mem = Module(new MEM)
io.toclint := mem.io.toclint
io.mem2dmem := mem.io.mem2dmem
mem.io.isMemOp := io.decode2Exe.isMemOp
mem.io.MemOp := io.decode2Exe.MemOp
mem.io.baseAddr := op1
mem.io.imm := op2
mem.io.R2Val := io.decode2Exe.R2val
mem.io.exceInfoIn := io.decode2Exe.exceInfo
io.exe2Commit.memResult := mem.io.memResult

io.pauseReq := divu.io.divBusy || mulu.io.mulBusy || mem.io.pauseReq
io.exe2Commit.exceInfo := mem.io.exceInfoOut

// Pass through
io.exe2Commit.RdNum := io.decode2Exe.RdNum
io.exe2Commit.WBSel := io.decode2Exe.WBSel
io.exe2Commit.RFWen := io.decode2Exe.RFWen
io.exe2Commit.CSRCmd := io.decode2Exe.CSRCmd
io.exe2Commit.isFence := io.decode2Exe.isFence

io.instBundleOut := io.instBundleIn
io.instBundleOut.instValid := (~io.pauseReq) & io.instBundleIn.instValid
}
Expand Down
137 changes: 68 additions & 69 deletions src/main/scala/core/mem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,38 @@ import chisel3.util._
class Mem2Wb extends Bundle {
val aluResult = UInt(64.W)
val memResult = UInt(64.W)
val RdNum = UInt(5.W)
val WBSel = UInt(2.W)
val RFWen = Bool()
val CSRCmd = UInt(3.W)
val isFence = Bool()
val exceInfo = new ExceptionInfo
val RdNum = UInt(5.W)
val WBSel = UInt(2.W)
val RFWen = Bool()
val CSRCmd = UInt(3.W)
val isFence = Bool()
val exceInfo = new ExceptionInfo
}

class MEM2dmem extends Bundle {
val memRreq = Output(Bool())
val memAddr = Output(UInt(64.W))
val memRdata = Input(UInt(64.W))
val memRreq = Output(Bool())
val memAddr = Output(UInt(64.W))
val memRdata = Input(UInt(64.W))
val memRvalid = Input(Bool())
val memWdata = Output(UInt(64.W))
val memWmask = Output(UInt(64.W))
val memWen = Output(Bool())
val memWdata = Output(UInt(64.W))
val memWmask = Output(UInt(64.W))
val memWen = Output(Bool())
}

class MEMIO extends Bundle {
val instBundleIn = Input(new InstBundle)
val exe2Mem = Input(new Exe2Mem)
val mem2Wb = Output(new Mem2Wb)
val instBundleOut = Output(new InstBundle)
val isMemOp = Input(Bool())
val MemOp = Input(UInt(2.W))
val MemType = Input(UInt(3.W))
val baseAddr = Input(UInt(64.W))
val imm = Input(UInt(64.W))
val R2Val = Input(UInt(64.W))
val exceInfoIn = Input(new ExceptionInfo)
val exceInfoOut = Output(new ExceptionInfo)
val memResult = Output(UInt(64.W))
val pauseReq = Output(Bool())
// Will be passed directly by exu to outside
val mem2dmem = new MEM2dmem
val pauseReq = Output(Bool())
val toclint = Flipped(new MEMCLINT)
val toclint = Flipped(new MEMCLINT)
}

object MMIO {
Expand All @@ -46,7 +52,7 @@ object MMIO {
(0x40001000L, 0x8L), // vga ctrl
(0x40000000L, 0x1000L), // flash
(0x40002000L, 0x1000L), // dummy sdcard
(0x42000000L, 0x1000L), // DiffTestCtrl
(0x42000000L, 0x1000L), // DiffTestCtrl
(0x40004000L, 0x1000L), // meipGen
(0x40003000L, 0x1000L), // dma

Expand Down Expand Up @@ -123,27 +129,42 @@ object DataTypesUtils {
class MEM extends Module {
val io = IO(new MEMIO)
val memWrite = Wire(Bool())
val accessVAddr = io.baseAddr + io.imm
val accessPAddr = accessVAddr - 0x80000000L.U // TODO: Handle the Translation
val isMMIO = MMIO.inMMIORange(accessVAddr)
// TODO:
val readClint = io.exe2Mem.aluResult >= 0x38000000L.U && io.exe2Mem.aluResult <= 0x00010000L.U + 0x38000000L.U
io.mem2Wb.exceInfo := io.exe2Mem.exceInfo
io.toclint.wen := io.exe2Mem.aluResult >= 0x38000000L.U && io.exe2Mem.aluResult <= 0x00010000L.U + 0x38000000L.U && memWrite
io.toclint.data := io.exe2Mem.R2val
io.toclint.addr := io.exe2Mem.aluResult
val readClint = accessVAddr >= 0x38000000L.U && accessVAddr <= 0x00010000L.U + 0x38000000L.U
io.exceInfoOut := io.exceInfoIn
io.toclint.wen := accessVAddr >= 0x38000000L.U && accessVAddr <= 0x00010000L.U + 0x38000000L.U && memWrite
io.toclint.data := io.R2Val
io.toclint.addr := accessVAddr
// TODO Ends
val isMMIO = MMIO.inMMIORange(io.exe2Mem.aluResult)
val memRdata = Mux(readClint, io.toclint.rdata, io.mem2dmem.memRdata)
val accessVAddr = io.exe2Mem.aluResult // TODO
val address = io.exe2Mem.aluResult - 0x80000000L.U
val signExt = io.exe2Mem.MemType === SZ_B || io.exe2Mem.MemType === SZ_H || io.exe2Mem.MemType === SZ_W
val memRead = io.exe2Mem.isMemOp & io.exe2Mem.MemOp === MEM_READ & !isMMIO & !io.exe2Mem.exceInfo.valid
val signExt = io.MemType === SZ_B || io.MemType === SZ_H || io.MemType === SZ_W

// LR/SC Handler
val isLR = WireInit(false.B)
val isSC = WireInit(false.B)
val reservationSet = Reg(UInt(64.W))
val reservationValid = RegInit(false.B)
when(isLR) { // Update the reservation set
reservationValid := true.B
reservationSet := accessVAddr
}.elsewhen(isSC){
reservationValid := false.B
}

// No prior Exception happens, and the op type is read, notice the signal is for dmem
val memRead = io.isMemOp & io.MemOp === MEM_READ & !isMMIO & !io.exceInfoIn.valid

io.mem2dmem.memRreq := memRead
val memPending = !io.mem2dmem.memRvalid & memRead
when(memRead) {
// printf("memRAddr = 0x%x, memRdata = 0x%x\n", io.exe2Mem.aluResult, memRdata)
}
io.pauseReq := memPending
memWrite := io.exe2Mem.isMemOp & io.exe2Mem.MemOp === MEM_WRITE & !io.exe2Mem.exceInfo.valid
val dataSize = MuxLookup(io.exe2Mem.MemType, 8.U,
memWrite := io.isMemOp & io.MemOp === MEM_WRITE & !io.exceInfoIn.valid
val dataSize = MuxLookup(io.MemType, 8.U,
Array(
SZ_D -> 8.U,
SZ_W -> 4.U,
Expand All @@ -156,58 +177,36 @@ class MEM extends Module {
)
val memRdataRaw = MuxLookup(dataSize, memRdata, // Including Word Select
Array( // Byte, Addressed by addr[2:0]
1.U -> memRdata.asTypeOf(DataTypesUtils.Bytes)(address(2, 0)),
2.U -> memRdata.asTypeOf(DataTypesUtils.HalfWords)(address(2, 1)),
4.U -> memRdata.asTypeOf(DataTypesUtils.Words)(address(2)),
1.U -> memRdata.asTypeOf(DataTypesUtils.Bytes)(accessVAddr(2, 0)),
2.U -> memRdata.asTypeOf(DataTypesUtils.HalfWords)(accessVAddr(2, 1)),
4.U -> memRdata.asTypeOf(DataTypesUtils.Words)(accessVAddr(2)),
8.U -> memRdata
)
)
val memRdataRawExt = MuxLookup(dataSize, memRdata, // Including Word Select
Array( // Byte, Addressed by addr[2:0]
1.U -> memRdata.asTypeOf(DataTypesUtils.Bytes)(address(2, 0)),
2.U -> memRdata.asTypeOf(DataTypesUtils.HalfWords)(address(2, 1)),
4.U -> memRdata.asTypeOf(DataTypesUtils.Words)(address(2)),
1.U -> memRdata.asTypeOf(DataTypesUtils.Bytes)(accessVAddr(2, 0)),
2.U -> memRdata.asTypeOf(DataTypesUtils.HalfWords)(accessVAddr(2, 1)),
4.U -> memRdata.asTypeOf(DataTypesUtils.Words)(accessVAddr(2)),
8.U -> memRdata
).map( kw => { kw._1 -> signExt64(kw._2) }
)
)
io.mem2Wb.aluResult := io.exe2Mem.aluResult // Mem Address
io.mem2dmem.memAddr := address
io.mem2dmem.memWdata := DataTypesUtils.WDataGen(dataSize, address, io.exe2Mem.R2val)
io.mem2dmem.memWmask := DataTypesUtils.Byte2BitMask(DataTypesUtils.ByteMaskGen(dataSize, address))
io.mem2dmem.memWen := io.instBundleIn.instValid & io.exe2Mem.isMemOp & io.exe2Mem.MemOp === MEM_WRITE & !isMMIO
io.mem2Wb.memResult := Mux(signExt, memRdataRawExt, memRdataRaw)
when(memPending) {
io.instBundleOut := io.instBundleIn
io.instBundleOut.instValid := false.B
} otherwise {
io.instBundleOut := io.instBundleIn
}
io.mem2Wb.WBSel := io.exe2Mem.WBSel
io.mem2Wb.RFWen := io.exe2Mem.RFWen
io.mem2Wb.CSRCmd := io.exe2Mem.CSRCmd
io.mem2Wb.isFence := io.exe2Mem.isFence
io.mem2Wb.RdNum := io.exe2Mem.RdNum
// passthrough

io.mem2dmem.memAddr := accessPAddr
io.mem2dmem.memWdata := DataTypesUtils.WDataGen(dataSize, accessVAddr, io.R2Val)
io.mem2dmem.memWmask := DataTypesUtils.Byte2BitMask(DataTypesUtils.ByteMaskGen(dataSize, accessVAddr))
io.mem2dmem.memWen := memWrite
io.memResult := Mux(signExt, memRdataRawExt, memRdataRaw)
io.pauseReq := memPending

// Fake UART
when(isMMIO & memWrite & 0x40600000L.U <= io.exe2Mem.aluResult & (0x40600000L+10L).U >= io.exe2Mem.aluResult) {
printf("%c", io.exe2Mem.R2val(7,0))
when(isMMIO & memWrite & 0x40600000L.U <= accessVAddr & (0x40600000L+10L).U >= accessVAddr) {
printf("%c", io.R2Val(7,0))
}
// MMIO Flag
BoringUtils.addSource(RegNext(io.exe2Mem.isMemOp & isMMIO), "difftestIsMMIO")
BoringUtils.addSource(RegNext(io.isMemOp & isMMIO), "difftestIsMMIO")

// LR/SC Handler
val isLR = WireInit(false.B)
val isSC = WireInit(false.B)
val reservationSet = Reg(UInt(64.W))
val reservationValid = RegInit(false.B)
when(isLR) { // Update the reservation set
reservationValid := true.B
reservationSet := accessVAddr
}.elsewhen(isSC){
reservationValid := false.B
}
// LSU
// IDLE -> ReqPADDR -> OP -> IDLE
val scWillSuccess = reservationValid && reservationSet === accessVAddr
Expand Down
Loading

0 comments on commit 287f414

Please sign in to comment.