提交 308973fd 编写于 作者: W William Wang

Merge branch 'opt-lq-wbsel' of https://github.com/RISCVERS/XiangShan into opt-lq-wbsel

......@@ -23,7 +23,9 @@ int main(int argc, char* argv[]){
fd = tryLock(argv[1]);
if(fd > 0){
getlogin_r(user, BUF_SIZE);
write(fd, user, strlen(user));
int len = strlen(user);
user[len] = '\0';
write(fd, user, len+1);
break;
} else {
// someone is holding the lock...
......
......@@ -182,7 +182,7 @@ class CfiUpdateInfo extends XSBundle {
class CtrlFlow extends XSBundle {
val instr = UInt(32.W)
val pc = UInt(VAddrBits.W)
val exceptionVec = Vec(16, Bool())
val exceptionVec = ExceptionVec()
val intrVec = Vec(12, Bool())
val brUpdate = new CfiUpdateInfo
val crossPageIPFFix = Bool()
......
......@@ -237,4 +237,4 @@ class IntegerBlock
rf.addr := wb.bits.uop.pdest
rf.data := wb.bits.data
}
}
\ No newline at end of file
}
......@@ -458,10 +458,8 @@ class DecodeUnit extends XSModule with DecodeUnitConstants {
cs.ldest := Mux(cs.fpWen || cs.rfWen, ctrl_flow.instr(RD_MSB,RD_LSB), 0.U)
// fill in exception vector
cf_ctrl.cf.exceptionVec.map(_ := false.B)
cf_ctrl.cf.exceptionVec := io.enq.ctrl_flow.exceptionVec
cf_ctrl.cf.exceptionVec(illegalInstr) := cs.selImm === SelImm.INVALID_INSTR
cf_ctrl.cf.exceptionVec(instrPageFault) := io.enq.ctrl_flow.exceptionVec(instrPageFault)
cf_ctrl.cf.exceptionVec(instrAccessFault) := io.enq.ctrl_flow.exceptionVec(instrAccessFault)
// fix frflags
// fflags zero csrrs rd csr
......
......@@ -8,9 +8,10 @@ import utils.{XSDebug, XSError, XSInfo}
import xiangshan.backend.roq.{RoqPtr, RoqEnqIO}
import xiangshan.backend.rename.RenameBypassInfo
import xiangshan.mem.LsqEnqIO
import xiangshan.backend.fu.HasExceptionNO
// read rob and enqueue
class Dispatch1 extends XSModule {
class Dispatch1 extends XSModule with HasExceptionNO {
val io = IO(new Bundle() {
// from rename
val fromRename = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
......@@ -116,6 +117,7 @@ class Dispatch1 extends XSModule {
// thisIsBlocked: this instruction is blocked by itself (based on noSpecExec)
// nextCanOut: next instructions can out (based on blockBackward)
// notBlockedByPrevious: previous instructions can enqueue
val hasException = VecInit(io.fromRename.map(r => selectFrontend(r.bits.cf.exceptionVec).asUInt.orR))
val thisIsBlocked = VecInit((0 until RenameWidth).map(i => {
// for i > 0, when Roq is empty but dispatch1 have valid instructions to enqueue, it's blocked
if (i > 0) isNoSpecExec(i) && (!io.enqRoq.isEmpty || Cat(io.fromRename.take(i).map(_.valid)).orR)
......@@ -156,17 +158,17 @@ class Dispatch1 extends XSModule {
// We use notBlockedByPrevious here.
io.toIntDq.needAlloc(i) := io.fromRename(i).valid && isInt(i)
io.toIntDq.req(i).bits := updatedUop(i)
io.toIntDq.req(i).valid := io.fromRename(i).valid && isInt(i) && thisCanActualOut(i) &&
io.toIntDq.req(i).valid := io.fromRename(i).valid && !hasException(i) && isInt(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
io.toFpDq.needAlloc(i) := io.fromRename(i).valid && isFp(i)
io.toFpDq.req(i).bits := updatedUop(i)
io.toFpDq.req(i).valid := io.fromRename(i).valid && isFp(i) && thisCanActualOut(i) &&
io.toFpDq.req(i).valid := io.fromRename(i).valid && !hasException(i) && isFp(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toLsDq.canAccept
io.toLsDq.needAlloc(i) := io.fromRename(i).valid && isLs(i)
io.toLsDq.req(i).bits := updatedUop(i)
io.toLsDq.req(i).valid := io.fromRename(i).valid && isLs(i) && thisCanActualOut(i) &&
io.toLsDq.req(i).valid := io.fromRename(i).valid && !hasException(i) && isLs(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept
XSDebug(io.toIntDq.req(i).valid, p"pc 0x${Hexadecimal(io.toIntDq.req(i).bits.cf.pc)} int index $i\n")
......
......@@ -88,6 +88,7 @@ class Dispatch2Int extends XSModule {
val src2Ready = VecInit((0 until 4).map(i => io.regRdy(i * 2 + 1)))
enq.bits.src1State := src1Ready(readPortIndex(i))
enq.bits.src2State := src2Ready(readPortIndex(i))
enq.bits.src3State := DontCare
XSInfo(enq.fire(), p"pc 0x${Hexadecimal(enq.bits.cf.pc)} with type ${enq.bits.ctrl.fuType} " +
p"srcState(${enq.bits.src1State} ${enq.bits.src2State}) " +
......
......@@ -83,6 +83,7 @@ class Dispatch2Ls extends XSModule {
enq.bits.src2State := Mux(io.fromDq(indexVec(i)).bits.ctrl.src2Type === SrcType.fp,
io.fpRegRdy(i - exuParameters.LduCnt), io.intRegRdy(readPort(i) + 1))
}
enq.bits.src3State := DontCare
XSInfo(enq.fire(), p"pc 0x${Hexadecimal(enq.bits.cf.pc)} with type ${enq.bits.ctrl.fuType} " +
p"srcState(${enq.bits.src1State} ${enq.bits.src2State}) " +
......
......@@ -120,13 +120,21 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
def writebackArb(in: Seq[DecoupledIO[FuOutput]], out: DecoupledIO[ExuOutput]): Arbiter[FuOutput] = {
if (needArbiter) {
val arb = Module(new Arbiter(new FuOutput(in.head.bits.len), in.size))
arb.io.in <> in
arb.io.out.ready := out.ready
out.bits.data := arb.io.out.bits.data
out.bits.uop := arb.io.out.bits.uop
out.valid := arb.io.out.valid
arb
if(in.size == 1){
in.head.ready := out.ready
out.bits.data := in.head.bits.data
out.bits.uop := in.head.bits.uop
out.valid := in.head.valid
null
} else {
val arb = Module(new Arbiter(new FuOutput(in.head.bits.len), in.size))
arb.io.in <> in
arb.io.out.ready := out.ready
out.bits.data := arb.io.out.bits.data
out.bits.uop := arb.io.out.bits.uop
out.valid := arb.io.out.valid
arb
}
} else {
in.foreach(_.ready := out.ready)
val sel = Mux1H(in.map(x => x.valid -> x))
......
......@@ -14,8 +14,8 @@ class FmiscExeUnit extends Exu(fmiscExeUnitCfg) {
val toFpUnits = Seq(f2f, fdivSqrt)
val toIntUnits = Seq(f2i)
assert(fpArb.io.in.length == toFpUnits.size)
assert(intArb.io.in.length == toIntUnits.size)
assert(toFpUnits.size == 1 || fpArb.io.in.length == toFpUnits.size)
assert(toIntUnits.size == 1 || intArb.io.in.length == toIntUnits.size)
val input = io.fromFp
val isRVF = input.bits.uop.ctrl.isRVF
......
......@@ -56,15 +56,20 @@ class Wb(cfgs: Seq[ExuConfig], numOut: Int, isFp: Boolean) extends XSModule {
mulReq.size
)
val arbiters = for(i <- mulReq.indices) yield {
val other = arbReq(i).getOrElse(Seq())
val arb = Module(new Arbiter(new ExuOutput, 1+other.size))
arb.io.in <> mulReq(i) +: other
for(i <- mulReq.indices) {
val out = io.out(directConnect.size + i)
out.valid := arb.io.out.valid
out.bits := arb.io.out.bits
arb.io.out.ready := true.B
arb
val other = arbReq(i).getOrElse(Seq())
if(other.isEmpty){
out.valid := mulReq(i).valid
out.bits := mulReq(i).bits
mulReq(i).ready := true.B
} else {
val arb = Module(new Arbiter(new ExuOutput, 1+other.size))
arb.io.in <> mulReq(i) +: other
out.valid := arb.io.out.valid
out.bits := arb.io.out.bits
arb.io.out.ready := true.B
}
}
if(portUsed < numOut){
......@@ -78,10 +83,11 @@ class Wb(cfgs: Seq[ExuConfig], numOut: Int, isFp: Boolean) extends XSModule {
}
for(i <- mulReq.indices){
sb.append(s"[ ${cfgs(io.in.indexOf(mulReq(i))).name} ")
val useArb = arbReq(i).nonEmpty
for(req <- arbReq(i).getOrElse(Nil)){
sb.append(s"${cfgs(io.in.indexOf(req)).name} ")
}
sb.append(s"] -> arb -> out #${directConnect.size + i}\n")
sb.append(s"] -> ${if(useArb) "arb ->" else ""} out #${directConnect.size + i}\n")
}
println(sb)
......
......@@ -47,6 +47,62 @@ trait HasExceptionNO {
storeAddrMisaligned,
loadAddrMisaligned
)
val frontendSet = List(
// instrAddrMisaligned,
instrAccessFault,
illegalInstr,
instrPageFault
)
val csrSet = List(
illegalInstr,
breakPoint,
ecallU,
ecallS,
ecallM
)
val loadUnitSet = List(
loadAddrMisaligned,
loadAccessFault,
loadPageFault
)
val storeUnitSet = List(
storeAddrMisaligned,
storeAccessFault,
storePageFault
)
val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct
val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct
def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = {
if (dontCareBits) {
val new_vec = Wire(ExceptionVec())
new_vec := DontCare
select.map(i => new_vec(i) := vec(i))
return new_vec
}
else if (falseBits) {
val new_vec = Wire(ExceptionVec())
new_vec.map(_ := false.B)
select.map(i => new_vec(i) := vec(i))
return new_vec
}
else {
val new_vec = Wire(Vec(select.length, Bool()))
select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) }
return new_vec
}
}
def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, frontendSet, dontCareBits, falseBits)
def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, csrSet, dontCareBits, falseBits)
def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, loadUnitSet, dontCareBits, falseBits)
def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, storeUnitSet, dontCareBits, falseBits)
def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits)
def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
partialSelect(vec, allPossibleSet, dontCareBits, falseBits)
}
class FpuCsrIO extends XSBundle {
......@@ -580,6 +636,17 @@ class CSR extends FunctionUnit with HasCSRConst
io.in.ready := true.B
io.out.valid := valid
val csrExceptionVec = WireInit(cfIn.exceptionVec)
csrExceptionVec(breakPoint) := io.in.valid && isEbreak
csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
// Trigger an illegal instr exception when:
// * unimplemented csr is being read/written
// * csr access is illegal
csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
cfOut.exceptionVec := csrExceptionVec
/**
* Exception and Intr
*/
......@@ -613,25 +680,7 @@ class CSR extends FunctionUnit with HasCSRConst
val hasLoadAccessFault = csrio.exception.bits.cf.exceptionVec(loadAccessFault) && raiseException
val hasStoreAccessFault = csrio.exception.bits.cf.exceptionVec(storeAccessFault) && raiseException
val csrExceptionVec = Wire(Vec(16, Bool()))
csrExceptionVec.map(_ := false.B)
csrExceptionVec(breakPoint) := io.in.valid && isEbreak
csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
// Trigger an illegal instr exception when:
// * unimplemented csr is being read/written
// * csr access is illegal
csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
csrExceptionVec(loadPageFault) := hasLoadPageFault
csrExceptionVec(storePageFault) := hasStorePageFault
csrExceptionVec(loadAccessFault) := hasLoadAccessFault
csrExceptionVec(storeAccessFault) := hasStoreAccessFault
val iduExceptionVec = cfIn.exceptionVec
val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt()
val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec
val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
......
......@@ -501,6 +501,7 @@ class ReservationStationData
val exuInput = io.deq.bits
exuInput := DontCare
exuInput.uop := uop(deq)
exuInput.uop.cf.exceptionVec := 0.U.asTypeOf(ExceptionVec())
val regValues = List.tabulate(srcNum)(i => dataRead(Mux(sel.valid, sel.bits, deq), i))
XSDebug(io.deq.fire(), p"[regValues] " + List.tabulate(srcNum)(idx => p"reg$idx: ${Hexadecimal(regValues(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
exuInput.src1 := regValues(0)
......@@ -542,6 +543,7 @@ class ReservationStationData
bpQueue.io.redirect := io.redirect
io.selectedUop.valid := bpQueue.io.out.valid
io.selectedUop.bits := bpQueue.io.out.bits
io.selectedUop.bits.cf.exceptionVec := 0.U.asTypeOf(ExceptionVec())
XSDebug(io.selectedUop.valid, p"SelUop: pc:0x${Hexadecimal(io.selectedUop.bits.cf.pc)}" +
p" roqIdx:${io.selectedUop.bits.roqIdx} pdest:${io.selectedUop.bits.pdest} " +
......
......@@ -54,12 +54,9 @@ class RoqEnqIO extends XSBundle {
class RoqDispatchData extends RoqCommitInfo {
val crossPageIPFFix = Bool()
val exceptionVec = Vec(16, Bool())
}
class RoqWbData extends XSBundle {
// mostly for exceptions
val exceptionVec = Vec(16, Bool())
val fflags = UInt(5.W)
val flushPipe = Bool()
}
......@@ -70,7 +67,7 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val state = Input(UInt(2.W))
val deq_v = Vec(CommitWidth, Input(Bool()))
val deq_w = Vec(CommitWidth, Input(Bool()))
val deq_exceptionVec = Vec(CommitWidth, Input(UInt(16.W)))
val deq_exceptionVec = Vec(CommitWidth, Input(ExceptionVec()))
val deq_flushPipe = Vec(CommitWidth, Input(Bool()))
// for flush: when exception occurs, reset deqPtrs to range(0, CommitWidth)
val intrBitSetReg = Input(Bool())
......@@ -83,15 +80,16 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val deqPtrVec = RegInit(VecInit((0 until CommitWidth).map(_.U.asTypeOf(new RoqPtr))))
val possibleException = VecInit(io.deq_exceptionVec.map(selectAll(_, false)))
// for exceptions (flushPipe included) and interrupts:
// only consider the first instruction
val intrEnable = io.intrBitSetReg && !io.hasNoSpecExec && !CommitType.isLoadStore(io.commitType)
val exceptionEnable = io.deq_w(0) && (io.deq_exceptionVec(0).orR || io.deq_flushPipe(0))
val exceptionEnable = io.deq_w(0) && (possibleException(0).asUInt.orR || io.deq_flushPipe(0))
val redirectOutValid = io.state === 0.U && io.deq_v(0) && (intrEnable || exceptionEnable)
// for normal commits: only to consider when there're no exceptions
// we don't need to consider whether the first instruction has exceptions since it wil trigger exceptions.
val commitBlocked = VecInit((0 until CommitWidth).map(i => if (i == 0) false.B else io.deq_exceptionVec(i).orR || io.deq_flushPipe(i)))
val commitBlocked = VecInit((0 until CommitWidth).map(i => if (i == 0) false.B else possibleException(i).asUInt.orR || io.deq_flushPipe(i)))
val canCommit = VecInit((0 until CommitWidth).map(i => io.deq_v(i) && io.deq_w(i) && !commitBlocked(i)))
val normalCommitCnt = PriorityEncoder(canCommit.map(c => !c) :+ true.B)
// when io.intrBitSetReg, only one instruction is allowed to commit
......@@ -118,7 +116,7 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val state = Input(UInt(2.W))
val deq_v = Input(Bool())
val deq_w = Input(Bool())
val deq_exceptionVec = Input(UInt(16.W))
val deq_exceptionVec = Input(ExceptionVec())
val deq_flushPipe = Input(Bool())
val intrBitSetReg = Input(Bool())
val hasNoSpecExec = Input(Bool())
......@@ -137,7 +135,7 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
// for exceptions (flushPipe included) and interrupts:
// only consider the first instruction
val intrEnable = io.intrBitSetReg && !io.hasNoSpecExec && !CommitType.isLoadStore(io.commitType)
val exceptionEnable = io.deq_w && (io.deq_exceptionVec.orR || io.deq_flushPipe)
val exceptionEnable = io.deq_w && (selectAll(io.deq_exceptionVec, false).asUInt.orR || io.deq_flushPipe)
val redirectOutValid = io.state === 0.U && io.deq_v && (intrEnable || exceptionEnable)
// enqueue
......@@ -264,28 +262,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val writebackData = Module(new SyncDataModuleTemplate(new RoqWbData, RoqSize, CommitWidth, numWbPorts))
val writebackDataRead = writebackData.io.rdata
def mergeExceptionVec(dpData: RoqDispatchData, wbData: RoqWbData) = {
// these exceptions can be determined before dispatch.
// by default, let all exceptions be determined by dispatch.
// mergeVec(instrAddrMisaligned) := dpData(instrAddrMisaligned)
// mergeVec(instrAccessFault) := dpData(instrAccessFault)
// mergeVec(instrPageFault) := dpData(instrPageFault)
val mergeVec = WireInit(dpData.exceptionVec)
// these exceptions are determined in execution units
mergeVec(illegalInstr) := wbData.exceptionVec(illegalInstr)
mergeVec(breakPoint) := wbData.exceptionVec(breakPoint)
mergeVec(loadAddrMisaligned) := wbData.exceptionVec(loadAddrMisaligned)
mergeVec(loadAccessFault) := wbData.exceptionVec(loadAccessFault)
mergeVec(storeAddrMisaligned) := wbData.exceptionVec(storeAddrMisaligned)
mergeVec(storeAccessFault) := wbData.exceptionVec(storeAccessFault)
mergeVec(ecallU) := wbData.exceptionVec(ecallU)
mergeVec(ecallS) := wbData.exceptionVec(ecallS)
mergeVec(ecallM) := wbData.exceptionVec(ecallM)
mergeVec(loadPageFault) := wbData.exceptionVec(loadPageFault)
mergeVec(storePageFault) := wbData.exceptionVec(storePageFault)
// returns the merged exception vector
mergeVec
}
val exceptionVecWritePortNum = RenameWidth + 1 + 2 + 2 // CSR, 2*load, 2*store
val exceptionData = Module(new SyncDataModuleTemplate(ExceptionVec(), RoqSize, CommitWidth, exceptionVecWritePortNum))
io.roqDeqPtr := deqPtr
......@@ -357,7 +335,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val deqWritebackData = writebackDataRead(0)
val debug_deqUop = debug_microOp(deqPtr.value)
val deqExceptionVec = mergeExceptionVec(deqDispatchData, deqWritebackData)
val deqExceptionVec = exceptionData.io.rdata(0)
// For MMIO instructions, they should not trigger interrupts since they may be sent to lower level before it writes back.
// However, we cannot determine whether a load/store instruction is MMIO.
// Thus, we don't allow load/store instructions to trigger an interrupt.
......@@ -419,7 +397,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.commits.isWalk := state =/= s_idle
val commit_v = Mux(state === s_idle, VecInit(deqPtrVec.map(ptr => valid(ptr.value))), VecInit(walkPtrVec.map(ptr => valid(ptr.value))))
val commit_w = VecInit(deqPtrVec.map(ptr => writebacked(ptr.value)))
val commit_exception = dispatchDataRead.zip(writebackDataRead).map{ case (d, w) => mergeExceptionVec(d, w).asUInt.orR }
val commit_exception = exceptionData.io.rdata.map(_.asUInt.orR)
val commit_block = VecInit((0 until CommitWidth).map(i => !commit_w(i) || commit_exception(i) || writebackDataRead(i).flushPipe))
for (i <- 0 until CommitWidth) {
// defaults: state === s_idle and instructions commit
......@@ -493,7 +471,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
deqPtrGenModule.io.state := state
deqPtrGenModule.io.deq_v := commit_v
deqPtrGenModule.io.deq_w := commit_w
deqPtrGenModule.io.deq_exceptionVec := VecInit(dispatchDataRead.zip(writebackDataRead).map{ case (d, w) => mergeExceptionVec(d, w).asUInt })
deqPtrGenModule.io.deq_exceptionVec := exceptionData.io.rdata
deqPtrGenModule.io.deq_flushPipe := writebackDataRead.map(_.flushPipe)
deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
deqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
......@@ -505,7 +483,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
enqPtrGenModule.io.state := state
enqPtrGenModule.io.deq_v := commit_v(0)
enqPtrGenModule.io.deq_w := commit_w(0)
enqPtrGenModule.io.deq_exceptionVec := deqExceptionVec.asUInt
enqPtrGenModule.io.deq_exceptionVec := deqExceptionVec
enqPtrGenModule.io.deq_flushPipe := writebackDataRead(0).flushPipe
enqPtrGenModule.io.intrBitSetReg := intrBitSetReg
enqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
......@@ -598,7 +576,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// enqueue logic set 6 writebacked to false
for (i <- 0 until RenameWidth) {
when (canEnqueue(i)) {
writebacked(enqPtrVec(i).value) := false.B
writebacked(enqPtrVec(i).value) := selectFrontend(io.enq.req(i).bits.cf.exceptionVec, false).asUInt.orR
}
}
// writeback logic set numWbPorts writebacked to true
......@@ -639,19 +617,41 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
wdata.sqIdx := req.sqIdx
wdata.pc := req.cf.pc
wdata.crossPageIPFFix := req.cf.crossPageIPFFix
wdata.exceptionVec := req.cf.exceptionVec
// wdata.exceptionVec := req.cf.exceptionVec
}
dispatchData.io.raddr := commitReadAddr_next
writebackData.io.wen := io.exeWbResults.map(_.valid)
writebackData.io.waddr := io.exeWbResults.map(_.bits.uop.roqIdx.value)
writebackData.io.wdata.zip(io.exeWbResults.map(_.bits)).map{ case (wdata, wb) =>
wdata.exceptionVec := wb.uop.cf.exceptionVec
wdata.fflags := wb.fflags
wdata.flushPipe := wb.uop.ctrl.flushPipe
}
writebackData.io.raddr := commitReadAddr_next
for (i <- 0 until RenameWidth) {
exceptionData.io.wen(i) := canEnqueue(i)
exceptionData.io.waddr(i) := enqPtrVec(i).value
exceptionData.io.wdata(i) := selectAll(io.enq.req(i).bits.cf.exceptionVec, false, true)
}
def connectWbExc(index: Int, i: Int) = {
exceptionData.io.wen(index) := io.exeWbResults(i).valid
exceptionData.io.waddr(index) := io.exeWbResults(i).bits.uop.roqIdx.value
}
// csr
connectWbExc(RenameWidth, 6)
exceptionData.io.wdata(RenameWidth) := selectCSR(io.exeWbResults(6).bits.uop.cf.exceptionVec)
// load
connectWbExc(RenameWidth+1, 4)
exceptionData.io.wdata(RenameWidth+1) := selectAtomics(io.exeWbResults(4).bits.uop.cf.exceptionVec)
connectWbExc(RenameWidth+2, 5)
exceptionData.io.wdata(RenameWidth+2) := selectAtomics(io.exeWbResults(5).bits.uop.cf.exceptionVec)
// store
connectWbExc(RenameWidth+3, 16)
exceptionData.io.wdata(RenameWidth+3) := selectStore(io.exeWbResults(16).bits.uop.cf.exceptionVec)
connectWbExc(RenameWidth+4, 17)
exceptionData.io.wdata(RenameWidth+4) := selectStore(io.exeWbResults(17).bits.uop.cf.exceptionVec)
exceptionData.io.raddr := VecInit(deqPtrVec_next.map(_.value))
/**
* debug info
......
......@@ -41,7 +41,6 @@ class LsPipelineBundle extends XSBundle {
val miss = Bool()
val tlbMiss = Bool()
val mmio = Bool()
val rollback = Bool()
val forwardMask = Vec(8, Bool())
val forwardData = Vec(8, UInt(8.W))
......
......@@ -10,6 +10,7 @@ import xiangshan.cache.{DCacheLineIO, DCacheWordIO, MemoryOpConstants, TlbReques
import xiangshan.backend.LSUOpType
import xiangshan.mem._
import xiangshan.backend.roq.RoqPtr
import xiangshan.backend.fu.HasExceptionNO
class LqPtr extends CircularQueuePtr(LqPtr.LoadQueueSize) { }
......@@ -58,6 +59,7 @@ class LoadQueue extends XSModule
with HasDCacheParameters
with HasCircularQueuePtrHelper
with HasLoadHelper
with HasExceptionNO
{
val io = IO(new Bundle() {
val enq = new LqEnqIO
......@@ -150,7 +152,7 @@ class LoadQueue extends XSModule
vaddrModule.io.wen(i) := false.B
when(io.loadIn(i).fire()) {
when(io.loadIn(i).bits.miss) {
XSInfo(io.loadIn(i).valid, "load miss write to lq idx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x roll %x exc %x\n",
XSInfo(io.loadIn(i).valid, "load miss write to lq idx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x\n",
io.loadIn(i).bits.uop.lqIdx.asUInt,
io.loadIn(i).bits.uop.cf.pc,
io.loadIn(i).bits.vaddr,
......@@ -159,12 +161,10 @@ class LoadQueue extends XSModule
io.loadIn(i).bits.mask,
io.loadIn(i).bits.forwardData.asUInt,
io.loadIn(i).bits.forwardMask.asUInt,
io.loadIn(i).bits.mmio,
io.loadIn(i).bits.rollback,
io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
io.loadIn(i).bits.mmio
)
}.otherwise {
XSInfo(io.loadIn(i).valid, "load hit write to cbd lqidx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x roll %x exc %x\n",
XSInfo(io.loadIn(i).valid, "load hit write to cbd lqidx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x\n",
io.loadIn(i).bits.uop.lqIdx.asUInt,
io.loadIn(i).bits.uop.cf.pc,
io.loadIn(i).bits.vaddr,
......@@ -173,9 +173,7 @@ class LoadQueue extends XSModule
io.loadIn(i).bits.mask,
io.loadIn(i).bits.forwardData.asUInt,
io.loadIn(i).bits.forwardMask.asUInt,
io.loadIn(i).bits.mmio,
io.loadIn(i).bits.rollback,
io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
io.loadIn(i).bits.mmio
)
}
val loadWbIndex = io.loadIn(i).bits.uop.lqIdx.value
......@@ -187,7 +185,6 @@ class LoadQueue extends XSModule
loadWbData.mask := io.loadIn(i).bits.mask
loadWbData.data := io.loadIn(i).bits.data // fwd data
loadWbData.fwdMask := io.loadIn(i).bits.forwardMask
loadWbData.exception := io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
dataModule.io.wbWrite(i, loadWbIndex, loadWbData)
dataModule.io.wb.wen(i) := true.B
......@@ -196,11 +193,10 @@ class LoadQueue extends XSModule
vaddrModule.io.wen(i) := true.B
debug_mmio(loadWbIndex) := io.loadIn(i).bits.mmio
val dcacheMissed = io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio
miss(loadWbIndex) := dcacheMissed && !io.loadIn(i).bits.uop.cf.exceptionVec.asUInt.orR
// listening(loadWbIndex) := dcacheMissed
pending(loadWbIndex) := io.loadIn(i).bits.mmio && !io.loadIn(i).bits.uop.cf.exceptionVec.asUInt.orR
miss(loadWbIndex) := dcacheMissed
pending(loadWbIndex) := io.loadIn(i).bits.mmio
}
}
......@@ -343,7 +339,7 @@ class LoadQueue extends XSModule
loadWbSelV(i) := true.B
}
})
// Stage 1
// Use indexes generated in cycle 0 to read data
// writeback data to cdb
......@@ -367,10 +363,9 @@ class LoadQueue extends XSModule
val rdataPartialLoad = rdataHelper(seluop, rdataSel)
// writeback missed int/fp load
//
//
// Int load writeback will finish (if not blocked) in one cycle
io.ldout(i).bits.uop := seluop
io.ldout(i).bits.uop.cf.exceptionVec := dataModule.io.wb.rdata(i).exception.asBools
io.ldout(i).bits.uop.lqIdx := loadWbSel(i).asTypeOf(new LqPtr)
io.ldout(i).bits.data := rdataPartialLoad
io.ldout(i).bits.redirectValid := false.B
......
......@@ -15,7 +15,6 @@ class LQDataEntry extends XSBundle {
val paddr = UInt(PAddrBits.W)
val mask = UInt(8.W)
val data = UInt(XLEN.W)
val exception = UInt(16.W) // TODO: opt size
val fwdMask = Vec(8, Bool())
}
......@@ -236,7 +235,6 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
// data module
val paddrModule = Module(new PaddrModule(size, numRead = 3, numWrite = 2))
val maskModule = Module(new MaskModule(size, numRead = 3, numWrite = 2))
val exceptionModule = Module(new AsyncDataModuleTemplate(UInt(16.W), size, numRead = 3, numWrite = 2))
val coredataModule = Module(new CoredataModule(size, numRead = 3, numWrite = 3))
// read data
......@@ -244,26 +242,22 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
(0 until wbNumRead).map(i => {
paddrModule.io.raddr(i) := io.wb.raddr(i)
maskModule.io.raddr(i) := io.wb.raddr(i)
exceptionModule.io.raddr(i) := io.wb.raddr(i)
coredataModule.io.raddr(i) := io.wb.raddr(i)
io.wb.rdata(i).paddr := paddrModule.io.rdata(i)
io.wb.rdata(i).mask := maskModule.io.rdata(i)
io.wb.rdata(i).data := coredataModule.io.rdata(i)
io.wb.rdata(i).exception := exceptionModule.io.rdata(i)
io.wb.rdata(i).fwdMask := DontCare
})
// read port wbNumRead
paddrModule.io.raddr(wbNumRead) := io.uncache.raddr
maskModule.io.raddr(wbNumRead) := io.uncache.raddr
exceptionModule.io.raddr(wbNumRead) := io.uncache.raddr
coredataModule.io.raddr(wbNumRead) := io.uncache.raddr
io.uncache.rdata.paddr := paddrModule.io.rdata(wbNumRead)
io.uncache.rdata.mask := maskModule.io.rdata(wbNumRead)
io.uncache.rdata.data := exceptionModule.io.rdata(wbNumRead)
io.uncache.rdata.exception := coredataModule.io.rdata(wbNumRead)
io.uncache.rdata.data := coredataModule.io.rdata(wbNumRead)
io.uncache.rdata.fwdMask := DontCare
// write data
......@@ -271,19 +265,16 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
(0 until wbNumWrite).map(i => {
paddrModule.io.wen(i) := false.B
maskModule.io.wen(i) := false.B
exceptionModule.io.wen(i) := false.B
coredataModule.io.wen(i) := false.B
coredataModule.io.fwdMaskWen(i) := false.B
coredataModule.io.paddrWen(i) := false.B
paddrModule.io.waddr(i) := io.wb.waddr(i)
maskModule.io.waddr(i) := io.wb.waddr(i)
exceptionModule.io.waddr(i) := io.wb.waddr(i)
coredataModule.io.waddr(i) := io.wb.waddr(i)
paddrModule.io.wdata(i) := io.wb.wdata(i).paddr
maskModule.io.wdata(i) := io.wb.wdata(i).mask
exceptionModule.io.wdata(i) := io.wb.wdata(i).exception
coredataModule.io.wdata(i) := io.wb.wdata(i).data
coredataModule.io.fwdMaskWdata(i) := io.wb.wdata(i).fwdMask.asUInt
coredataModule.io.paddrWdata(i) := io.wb.wdata(i).paddr
......@@ -291,7 +282,6 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
when(io.wb.wen(i)){
paddrModule.io.wen(i) := true.B
maskModule.io.wen(i) := true.B
exceptionModule.io.wen(i) := true.B
coredataModule.io.wen(i) := true.B
coredataModule.io.fwdMaskWen(i) := true.B
coredataModule.io.paddrWen(i) := true.B
......
......@@ -52,8 +52,6 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
dataModule.io := DontCare
val vaddrModule = Module(new AsyncDataModuleTemplate(UInt(VAddrBits.W), StoreQueueSize, numRead = 1, numWrite = StorePipelineWidth))
vaddrModule.io := DontCare
val exceptionModule = Module(new AsyncDataModuleTemplate(UInt(16.W), StoreQueueSize, numRead = StorePipelineWidth, numWrite = StorePipelineWidth))
exceptionModule.io := DontCare
// state & misc
val allocated = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // sq entry has been allocated
......@@ -83,7 +81,6 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
dataModule.io.raddr(i) := deqPtrExt(i).value
}
vaddrModule.io.raddr(0) := io.exceptionAddr.lsIdx.sqIdx.value
exceptionModule.io.raddr(0) := deqPtr // read exception
/**
* Enqueue at dispatch
......@@ -123,14 +120,11 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
for (i <- 0 until StorePipelineWidth) {
dataModule.io.wen(i) := false.B
vaddrModule.io.wen(i) := false.B
exceptionModule.io.wen(i) := false.B
when(io.storeIn(i).fire()) {
when (io.storeIn(i).fire()) {
val stWbIndex = io.storeIn(i).bits.uop.sqIdx.value
val hasException = io.storeIn(i).bits.uop.cf.exceptionVec.asUInt.orR
val hasWritebacked = !io.storeIn(i).bits.mmio || hasException
datavalid(stWbIndex) := hasWritebacked
writebacked(stWbIndex) := hasWritebacked
pending(stWbIndex) := !hasWritebacked // valid mmio require
datavalid(stWbIndex) := !io.storeIn(i).bits.mmio
writebacked(stWbIndex) := !io.storeIn(i).bits.mmio
pending(stWbIndex) := io.storeIn(i).bits.mmio
val storeWbData = Wire(new SQDataEntry)
storeWbData := DontCare
......@@ -145,21 +139,15 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
vaddrModule.io.wdata(i) := io.storeIn(i).bits.vaddr
vaddrModule.io.wen(i) := true.B
exceptionModule.io.waddr(i) := stWbIndex
exceptionModule.io.wdata(i) := io.storeIn(i).bits.uop.cf.exceptionVec.asUInt
exceptionModule.io.wen(i) := true.B
mmio(stWbIndex) := io.storeIn(i).bits.mmio
XSInfo("store write to sq idx %d pc 0x%x vaddr %x paddr %x data %x mmio %x roll %x exc %x\n",
XSInfo("store write to sq idx %d pc 0x%x vaddr %x paddr %x data %x mmio %x\n",
io.storeIn(i).bits.uop.sqIdx.value,
io.storeIn(i).bits.uop.cf.pc,
io.storeIn(i).bits.vaddr,
io.storeIn(i).bits.paddr,
io.storeIn(i).bits.data,
io.storeIn(i).bits.mmio,
io.storeIn(i).bits.rollback,
io.storeIn(i).bits.uop.cf.exceptionVec.asUInt
io.storeIn(i).bits.mmio
)
}
}
......@@ -258,7 +246,6 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
io.mmioStout.valid := allocated(deqPtr) && datavalid(deqPtr) && !writebacked(deqPtr)
io.mmioStout.bits.uop := uop(deqPtr)
io.mmioStout.bits.uop.sqIdx := deqPtrExt(0)
io.mmioStout.bits.uop.cf.exceptionVec := exceptionModule.io.rdata(0).asBools
io.mmioStout.bits.data := dataModuleRead(0).data // dataModuleRead.read(deqPtr)
io.mmioStout.bits.redirectValid := false.B
io.mmioStout.bits.redirect := DontCare
......
......@@ -25,6 +25,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
val s_invalid :: s_tlb :: s_flush_sbuffer_req :: s_flush_sbuffer_resp :: s_cache_req :: s_cache_resp :: s_finish :: Nil = Enum(7)
val state = RegInit(s_invalid)
val in = Reg(new ExuInput())
val exceptionVec = RegInit(0.U.asTypeOf(ExceptionVec()))
val atom_override_xtval = RegInit(false.B)
// paddr after translation
val paddr = Reg(UInt())
......@@ -89,11 +90,11 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
"b10".U -> (in.src1(1,0) === 0.U), //w
"b11".U -> (in.src1(2,0) === 0.U) //d
))
in.uop.cf.exceptionVec(storeAddrMisaligned) := !addrAligned
in.uop.cf.exceptionVec(storePageFault) := io.dtlb.resp.bits.excp.pf.st
in.uop.cf.exceptionVec(loadPageFault) := io.dtlb.resp.bits.excp.pf.ld
in.uop.cf.exceptionVec(storeAccessFault) := io.dtlb.resp.bits.excp.af.st
in.uop.cf.exceptionVec(loadAccessFault) := io.dtlb.resp.bits.excp.af.ld
exceptionVec(storeAddrMisaligned) := !addrAligned
exceptionVec(storePageFault) := io.dtlb.resp.bits.excp.pf.st
exceptionVec(loadPageFault) := io.dtlb.resp.bits.excp.pf.ld
exceptionVec(storeAccessFault) := io.dtlb.resp.bits.excp.af.st
exceptionVec(loadAccessFault) := io.dtlb.resp.bits.excp.af.ld
val exception = !addrAligned ||
io.dtlb.resp.bits.excp.pf.st ||
io.dtlb.resp.bits.excp.pf.ld ||
......@@ -215,6 +216,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
when (state === s_finish) {
io.out.valid := true.B
io.out.bits.uop := in.uop
io.out.bits.uop.cf.exceptionVec := exceptionVec
io.out.bits.uop.diffTestDebugLrScValid := is_lrsc_valid
io.out.bits.data := resp_data
io.out.bits.redirectValid := false.B
......
......@@ -91,7 +91,7 @@ class LoadUnit_S1 extends XSModule {
val s1_uop = io.in.bits.uop
val s1_paddr = io.dtlbResp.bits.paddr
val s1_exception = io.out.bits.uop.cf.exceptionVec.asUInt.orR
val s1_exception = selectLoad(io.out.bits.uop.cf.exceptionVec, false).asUInt.orR
val s1_tlb_miss = io.dtlbResp.bits.miss
val s1_mmio = !s1_tlb_miss && io.dtlbResp.bits.mmio
val s1_mask = io.in.bits.mask
......@@ -148,7 +148,7 @@ class LoadUnit_S2 extends XSModule with HasLoadHelper {
val s2_paddr = io.in.bits.paddr
val s2_tlb_miss = io.in.bits.tlbMiss
val s2_mmio = io.in.bits.mmio
val s2_exception = io.in.bits.uop.cf.exceptionVec.asUInt.orR
val s2_exception = selectLoad(io.in.bits.uop.cf.exceptionVec, false).asUInt.orR
val s2_cache_miss = io.dcacheResp.bits.miss
val s2_cache_replay = io.dcacheResp.bits.replay
......@@ -193,7 +193,9 @@ class LoadUnit_S2 extends XSModule with HasLoadHelper {
// so we do not need to care about flush in load / store unit's out.valid
io.out.bits := io.in.bits
io.out.bits.data := rdataPartialLoad
io.out.bits.miss := s2_cache_miss && !fullForward
// when exception occurs, set it to not miss and let it write back to roq (via int port)
io.out.bits.miss := s2_cache_miss && !fullForward && !s2_exception
io.out.bits.uop.ctrl.fpWen := io.in.bits.uop.ctrl.fpWen && !s2_exception
io.out.bits.mmio := s2_mmio
io.in.ready := io.out.ready || !io.in.valid
......@@ -270,12 +272,14 @@ class LoadUnit extends XSModule with HasLoadHelper {
// Load queue will be updated at s2 for both hit/miss int/fp load
io.lsq.loadIn.valid := load_s2.io.out.valid
io.lsq.loadIn.bits := load_s2.io.out.bits
val s2Valid = load_s2.io.out.valid && (!load_s2.io.out.bits.miss || load_s2.io.out.bits.uop.cf.exceptionVec.asUInt.orR)
// write to rob and writeback bus
val s2_wb_valid = load_s2.io.out.valid && !load_s2.io.out.bits.miss
val refillFpLoad = io.lsq.ldout.bits.uop.ctrl.fpWen
// Int load, if hit, will be writebacked at s2
val intHitLoadOut = Wire(Valid(new ExuOutput))
intHitLoadOut.valid := s2Valid && !load_s2.io.out.bits.uop.ctrl.fpWen
intHitLoadOut.valid := s2_wb_valid && !load_s2.io.out.bits.uop.ctrl.fpWen
intHitLoadOut.bits.uop := load_s2.io.out.bits.uop
intHitLoadOut.bits.data := load_s2.io.out.bits.data
intHitLoadOut.bits.redirectValid := false.B
......@@ -289,10 +293,10 @@ class LoadUnit extends XSModule with HasLoadHelper {
io.ldout.bits := Mux(intHitLoadOut.valid, intHitLoadOut.bits, io.lsq.ldout.bits)
io.ldout.valid := intHitLoadOut.valid || io.lsq.ldout.valid && !refillFpLoad
// Fp load, if hit, will be send to recoder at s2, then it will be recoded & writebacked at s3
val fpHitLoadOut = Wire(Valid(new ExuOutput))
fpHitLoadOut.valid := s2Valid && load_s2.io.out.bits.uop.ctrl.fpWen
fpHitLoadOut.valid := s2_wb_valid && load_s2.io.out.bits.uop.ctrl.fpWen
fpHitLoadOut.bits := intHitLoadOut.bits
val fpLoadOut = Wire(Valid(new ExuOutput))
......
......@@ -90,7 +90,7 @@ class StoreUnit_S1 extends XSModule {
io.lsq.bits.uop.cf.exceptionVec(storeAccessFault) := io.dtlbResp.bits.excp.af.st
// mmio inst with exception will be writebacked immediately
val hasException = io.out.bits.uop.cf.exceptionVec.asUInt.orR
val hasException = selectStore(io.out.bits.uop.cf.exceptionVec, false).asUInt.orR
io.out.valid := io.in.valid && (!io.out.bits.mmio || hasException) && !s1_tlb_miss
io.out.bits := io.lsq.bits
......
......@@ -110,6 +110,10 @@ package object xiangshan {
def isException(level: UInt) = level(1) && level(0)
}
object ExceptionVec {
def apply() = Vec(16, Bool())
}
object PMAMode {
def R = "b1".U << 0 //readable
def W = "b1".U << 1 //writeable
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册