未验证 提交 72951335 编写于 作者: L Li Qianruo 提交者: GitHub

Trigger Implementation for Debug Mode (#1170)

* Untested Trigger Implementation
Co-authored-by: NWilliam Wang <zeweiwang@outlook.com>
Co-authored-by: NLingrui98 <goulingrui19s@ict.ac.cn>
Co-authored-by: Nrvcoresjw <shangjiawei@rvcore.com>
上级 954e08f6
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
* Copyright (c) 2020-2021 Peng Cheng Laboratory
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mu lan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/
package utils
import chisel3._
import chisel3.util._
object TriggerCmp {
def apply(actual: UInt, tdata: UInt, matchType: UInt, enable: Bool) = {
val equal = actual === tdata
val greater = actual >= tdata
val less = actual <= tdata
val res = MuxLookup(matchType, false.B,
Array(0.U -> equal,
2.U -> greater,
3.U -> less))
res && enable
}
}
object ChainCheck {
def TimingCheck(prevTiming: Bool, thisTiming: Bool, chain: Bool) = !((prevTiming ^ thisTiming) && chain)
def HitCheck(prevHit: Bool, chain: Bool) = prevHit || !chain
}
......@@ -111,6 +111,7 @@ class CtrlFlow(implicit p: Parameters) extends XSBundle {
val pc = UInt(VAddrBits.W)
val foldpc = UInt(MemPredPCWidth.W)
val exceptionVec = ExceptionVec()
val trigger = new TriggerCf
val intrVec = Vec(12, Bool())
val pd = new PreDecodeInfo
val pred_taken = Bool()
......@@ -131,6 +132,7 @@ class CtrlFlow(implicit p: Parameters) extends XSBundle {
val replayInst = Bool()
}
class FPUCtrlSignals(implicit p: Parameters) extends XSBundle {
val isAddSub = Bool() // swap23
val typeTagIn = UInt(1.W)
......@@ -287,6 +289,7 @@ class DebugBundle(implicit p: Parameters) extends XSBundle {
val isMMIO = Bool()
val isPerfCnt = Bool()
val paddr = UInt(PAddrBits.W)
val vaddr = UInt(VAddrBits.W)
}
class ExuInput(implicit p: Parameters) extends XSBundle {
......@@ -462,6 +465,10 @@ class CustomCSRCtrlIO(implicit p: Parameters) extends XSBundle {
// distribute csr write signal
val distribute_csr = new DistributedCSRIO()
val frontend_trigger = new FrontendTdataDistributeIO()
val mem_trigger = new MemTdataDistributeIO()
val trigger_enable = Output(Vec(10, Bool()))
}
class DistributedCSRIO(implicit p: Parameters) extends XSBundle {
......@@ -490,4 +497,33 @@ class DistributedCSRUpdateReq(implicit p: Parameters) extends XSBundle {
}
println("Distributed CSR update req registered for " + src_description)
}
}
\ No newline at end of file
}
class TriggerCf (implicit p: Parameters) extends XSBundle {
val triggerHitVec = Vec(10, Bool())
val triggerTiming = Vec(10, Bool())
val triggerChainVec = Vec(5, Bool())
}
class FrontendTdataDistributeIO(implicit p: Parameters) extends XSBundle {
val t = Valid(new Bundle {
val addr = Output(UInt(2.W))
val tdata = new MatchTriggerIO
})
}
class MemTdataDistributeIO(implicit p: Parameters) extends XSBundle {
val t = Valid(new Bundle {
val addr = Output(UInt(3.W))
val tdata = new MatchTriggerIO
})
}
class MatchTriggerIO(implicit p: Parameters) extends XSBundle {
val matchType = Output(UInt(2.W))
val select = Output(Bool())
val timing = Output(Bool())
val action = Output(Bool())
val chain = Output(Bool())
val tdata2 = Output(UInt(64.W))
}
......@@ -118,8 +118,8 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
atomicsUnit.io.out.ready := ldOut0.ready
loadUnits.head.io.ldout.ready := ldOut0.ready
val exeWbReqs = ldOut0 +: loadUnits.tail.map(_.io.ldout)
io.writeback <> exeWbReqs ++ VecInit(storeUnits.map(_.io.stout)) ++ VecInit(stdExeUnits.map(_.io.out))
val ldExeWbReqs = ldOut0 +: loadUnits.tail.map(_.io.ldout)
io.writeback <> ldExeWbReqs ++ VecInit(storeUnits.map(_.io.stout)) ++ VecInit(stdExeUnits.map(_.io.out))
io.otherFastWakeup := DontCare
io.otherFastWakeup.take(2).zip(loadUnits.map(_.io.fastUop)).foreach{case(a,b)=> a := b}
......@@ -189,6 +189,17 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
p.req := d
require(p.req.bits.size.getWidth == d.bits.size.getWidth)
}
val tdata = Reg(Vec(6, new MatchTriggerIO))
val tEnable = RegInit(VecInit(Seq.fill(6)(false.B)))
val en = io.csrCtrl.trigger_enable
tEnable := VecInit(en(2), en (3), en(7), en(4), en(5), en(9))
when(io.csrCtrl.mem_trigger.t.valid) {
tdata(io.csrCtrl.mem_trigger.t.bits.addr) := io.csrCtrl.mem_trigger.t.bits.tdata
}
val lTriggerMapping = Map(0 -> 4, 1 -> 5, 2 -> 9)
val sTriggerMapping = Map(0 -> 2, 1 -> 3, 2 -> 7)
val lChainMapping = Map(0 -> 2)
val sChainMapping = Map(0 -> 1)
// LoadUnit
for (i <- 0 until exuParameters.LduCnt) {
......@@ -225,10 +236,35 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
lsq.io.ldout(i) <> loadUnits(i).io.lsq.ldout
lsq.io.loadDataForwarded(i) <> loadUnits(i).io.lsq.loadDataForwarded
// update waittable
// TODO: read pc
// update mem dependency predictor
io.memPredUpdate(i) := DontCare
lsq.io.needReplayFromRS(i) <> loadUnits(i).io.lsq.needReplayFromRS
// Trigger Regs
// addr: 0-2 for store, 3-5 for load
// TODO: load trigger, a total of 3
for (j <- 0 until 10) {
io.writeback(i).bits.uop.cf.trigger.triggerHitVec(j) := false.B
io.writeback(i).bits.uop.cf.trigger.triggerTiming(j) := false.B
if (lChainMapping.contains(j)) io.writeback(i).bits.uop.cf.trigger.triggerChainVec(j) := false.B
}
when(ldExeWbReqs(i).fire()){
// load data, we need to delay cmp for 1 cycle for better timing
// ldExeWbReqs(i).bits.data
// TriggerCmp(ldExeWbReqs(i).bits.data, DontCare, DontCare, DontCare)
// load vaddr
// ldExeWbReqs(i).bits.debug.vaddr
// TriggerCmp(ldExeWbReqs(i).bits.debug.vaddr, DontCare, DontCare, DontCare)
for (j <- 0 until 3) {
val hit = Mux(tdata(j+3).select, TriggerCmp(ldExeWbReqs(i).bits.data, tdata(j+3).tdata2, tdata(j+3).matchType, tEnable(j+3)),
TriggerCmp(ldExeWbReqs(i).bits.debug.vaddr, tdata(j+3).tdata2, tdata(j+3).matchType, tEnable(j+3)))
io.writeback(i).bits.uop.cf.trigger.triggerHitVec(lTriggerMapping(j)) := hit
io.writeback(i).bits.uop.cf.trigger.triggerTiming(lTriggerMapping(j)) := hit && tdata(j+3).timing
if (lChainMapping.contains(j)) io.writeback(i).bits.uop.cf.trigger.triggerChainVec(lChainMapping(j)) := hit && tdata(j+3).chain
}
}
}
// StoreUnit
......@@ -266,6 +302,44 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
io.stOut(i).valid := stu.io.stout.valid
io.stOut(i).bits := stu.io.stout.bits
stu.io.stout.ready := true.B
// TODO: debug trigger
// store vaddr
when(io.stOut(i).fire()){
io.stOut(i).bits.debug.vaddr
// TriggerCmp(io.stOut(i).bits.debug.vaddr, DontCare, DontCare, DontCare)
for (j <- 0 until 10) {
io.stOut(i).bits.uop.cf.trigger.triggerHitVec(j) := false.B
io.stOut(i).bits.uop.cf.trigger.triggerTiming(j) := false.B
if (sChainMapping.contains(j)) io.stOut(i).bits.uop.cf.trigger.triggerChainVec(j) := false.B
}
for (j <- 0 until 3) {
when(!tdata(j).select) {
val hit = TriggerCmp(io.stOut(i).bits.data, tdata(j).tdata2, tdata(j).matchType, tEnable(j))
io.stOut(i).bits.uop.cf.trigger.triggerHitVec(sTriggerMapping(j)) := hit
io.stOut(i).bits.uop.cf.trigger.triggerTiming(sTriggerMapping(j)) := hit && tdata(j + 3).timing
if (sChainMapping.contains(j)) io.stOut(i).bits.uop.cf.trigger.triggerChainVec(sChainMapping(j)) := hit && tdata(j + 3).chain
}
}
}
// store data
when(lsq.io.storeDataIn(i).fire()){
lsq.io.storeDataIn(i).bits.data(XLEN-1, 0)
for (j <- 0 until 10) {
lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerHitVec(j) := false.B
lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerTiming(j) := false.B
if (sChainMapping.contains(j)) lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerChainVec(j) := false.B
}
// TriggerCmp(lsq.io.storeDataIn(i).bits.data(XLEN-1, 0), DontCare, DontCare, DontCare)
for (j <- 0 until 3) {
when(tdata(j).select) {
val hit = TriggerCmp(lsq.io.storeDataIn(i).bits.data, tdata(j).tdata2, tdata(j).matchType, tEnable(j))
lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerHitVec(sTriggerMapping(j)) := hit
lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerTiming(sTriggerMapping(j)) := hit && tdata(j + 3).timing
if (sChainMapping.contains(j)) lsq.io.storeDataIn(i).bits.uop.cf.trigger.triggerChainVec(sChainMapping(j)) := hit && tdata(j + 3).chain
}
}
}
}
// mmio store writeback will use store writeback port 0
......
......@@ -45,11 +45,10 @@ trait HasExceptionNO {
def loadPageFault = 13
def storePageFault = 15
def singleStep = 14
// def singleStep = 14
val ExcPriority = Seq(
breakPoint, // TODO: different BP has different priority
singleStep,
instrPageFault,
instrAccessFault,
illegalInstr,
......@@ -125,6 +124,28 @@ trait HasExceptionNO {
partialSelect(vec, allPossibleSet, dontCareBits, falseBits)
}
// Trigger Tdata1 bundles
trait HasTriggerConst {
def I_Trigger = 0.U
def S_Trigger = 1.U
def L_Trigger = 2.U
def GenESL(triggerType: UInt) = Cat((triggerType === I_Trigger), (triggerType === I_Trigger), (triggerType === I_Trigger))
}
class TdataBundle extends Bundle {
val hit = Bool()
val select = Bool()
val timing = Bool()
// val size = UInt(4.W) // hardwire to 0
val action = Bool()
val chain = Bool()
val matchType = UInt(2.W)
val m = Bool()
val s = Bool()
val u = Bool()
val data = UInt(64.W) // tdata2
}
class FpuCsrIO extends Bundle {
val fflags = Output(Valid(UInt(5.W)))
val isIllegal = Output(Bool())
......@@ -198,7 +219,7 @@ class CSRFileIO(implicit p: Parameters) extends XSBundle {
val distributedUpdate = Flipped(new DistributedCSRUpdateReq)
}
class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPMethod with PMAMethod
class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPMethod with PMAMethod with HasTriggerConst
{
val csrio = IO(new CSRFileIO)
......@@ -314,6 +335,100 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
}
csrio.singleStep := dcsrData.step
// Trigger CSRs
val tdata1_function = Map(
0.U -> (true, I_Trigger), 1.U -> (false, I_Trigger),
2.U -> (true, S_Trigger), 3.U -> (false, S_Trigger),
4.U -> (true, L_Trigger), 5.U -> (false, L_Trigger),
6.U -> (true, I_Trigger), 7.U -> (false, S_Trigger),
8.U -> (true, I_Trigger), 9.U -> (false, L_Trigger)
).withDefaultValue((false, I_Trigger))
val tdata1Phy = RegInit(VecInit(List.fill(10) {0.U(64.W).asTypeOf(new TdataBundle)}))
val tdata2Phy = Reg(Vec(10, UInt(64.W)))
val tselectPhy = RegInit(0.U(4.W))
val tDummy = WireInit(0.U(64.W))
val tControlPhy = RegInit(0.U(64.W))
def ReadTdata1(rdata: UInt) = {
val tdata1 = tdata1Phy(tselectPhy)
Cat(
2.U(4.W), // type, hardwired
0.U(1.W), // dmode, hardwired
0.U(6.W), // maskmax, hardwired to 0 because we don not support
1.U(2.W), // sizehi, hardwired
tdata1.hit,
tdata1.select, // select
tdata1.timing,
0.U(2.W), // sizelo
0.U(3.W), tdata1.action, // action, 0 is breakpoint 1 is enter debug
tdata1.chain,
0.U(2.W), tdata1.matchType,
tdata1.m, false.B, tdata1.s, tdata1.u,
GenESL(tdata1_function(tselectPhy)._2)
)
}
def WriteTdata1(wdata: UInt) = {
val tdata1_new = WireInit(tdata1Phy(tselectPhy))
tdata1_new.hit := wdata(20)
tdata1_new.select := wdata(19)
tdata1_new.timing := wdata(18)
tdata1_new.action := wdata(12)
tdata1_new.chain := tdata1_function(tselectPhy)._1.B && wdata(11)
when(wdata(10, 7) === 0.U || wdata(10, 7) === 2.U || wdata(10, 7) === 3.U) {tdata1_new.matchType := wdata(8, 7)}
tdata1_new.m := wdata(6)
tdata1_new.s := wdata(4)
tdata1_new.u := wdata(3)
tdata1Phy(tselectPhy) := tdata1_new
0.U
}
def ReadTselect(rdata: UInt) = Cat(0.U(60.W), tselectPhy)
def WriteTselect(wdata: UInt) = {
when (wdata <= 10.U){
tselectPhy := wdata(3, 0)
}
0.U
}
def ReadTdata2(tdata: UInt) = tdata2Phy(tselectPhy)
def WriteTdata2(wdata: UInt) = {
tdata2Phy(tselectPhy) := wdata
0.U
}
def ReadTinfo(tdata: UInt) = 2.U(XLEN.W)
val tcontrolWriteMask = ZeroExt(GenMask(3) | GenMask(7), XLEN)
def GenTdataDistribute(tdata1: TdataBundle, tdata2: UInt): MatchTriggerIO = {
val res = Wire(new MatchTriggerIO)
res.matchType := tdata1.matchType
res.select := tdata1.select
res.timing := tdata1.timing
res.action := tdata1.action
res.chain := tdata1.chain
res.tdata2 := tdata2
res
}
csrio.customCtrl.frontend_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U, Seq(
0.U -> 0.U,
1.U -> 1.U,
6.U -> 2.U,
8.U -> 3.U
))
csrio.customCtrl.mem_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U, Seq(
2.U -> 0.U,
3.U -> 1.U,
4.U -> 2.U,
5.U -> 3.U,
7.U -> 4.U,
9.U -> 5.U
))
csrio.customCtrl.frontend_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy), tdata2Phy(tselectPhy))
csrio.customCtrl.mem_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy), tdata2Phy(tselectPhy))
// Machine-Level CSRs
val mtvec = RegInit(UInt(XLEN.W), 0.U)
......@@ -642,6 +757,13 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
MaskedRegMap(Mtval, mtval),
MaskedRegMap(Mip, mip.asUInt, 0.U(XLEN.W), MaskedRegMap.Unwritable),
//--- Trigger ---
MaskedRegMap(Tselect, tDummy, WritableMask, WriteTselect, WritableMask, ReadTselect),
MaskedRegMap(Tdata1, tDummy, WritableMask, WriteTdata1, WritableMask, ReadTdata1),
MaskedRegMap(Tdata2, tDummy, WritableMask, WriteTdata2, WritableMask, ReadTdata2),
MaskedRegMap(Tinfo, tDummy, 0.U(XLEN.W), MaskedRegMap.Unwritable, WritableMask, ReadTinfo),
MaskedRegMap(Tcontrol, tControlPhy, tcontrolWriteMask),
//--- Debug Mode ---
MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
MaskedRegMap(Dpc, dpc),
......@@ -763,7 +885,9 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
// general CSR wen check
val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
val dcsrPermitted = dcsrPermissionCheck(addr, false.B, debugMode)
val triggerPermitted = triggerPermissionCheck(addr, true.B, debugMode) // todo dmode
val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) && dcsrPermitted && triggerPermitted
val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted
......@@ -806,6 +930,15 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
}
csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
// Trigger Ctrl
csrio.customCtrl.trigger_enable := tdata1Phy.map{tdata1 => tdata1.m && priviledgeMode === ModeM ||
tdata1.s && priviledgeMode === ModeS || tdata1.u && priviledgeMode === ModeU
}
csrio.customCtrl.frontend_trigger.t.valid := RegNext(wen && addr === Tdata1.U && tdata1_function(tselectPhy)._2 === I_Trigger)
csrio.customCtrl.mem_trigger.t.valid := RegNext(wen && addr === Tdata1.U && tdata1_function(tselectPhy)._2 =/= I_Trigger)
// CSR inst decode
val isEbreak = addr === privEbreak && func === CSROpType.jmp
val isEcall = addr === privEcall && func === CSROpType.jmp
......@@ -944,15 +1077,17 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException
val hasSingleStep = csrio.exception.bits.uop.cf.exceptionVec(singleStep) && raiseException
val hasSingleStep = csrio.exception.bits.uop.ctrl.singleStep && raiseException
val hasTriggerHit = csrio.exception.bits.uop.cf.trigger.triggerHitVec.orR && raiseException
val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
val regularExceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
val exceptionNO = Mux(hasSingleStep || hasTriggerHit, 3.U, regularExceptionNO)
val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
val raiseExceptionIntr = csrio.exception.valid
val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep
val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep || hasTriggerHit // todo
val ebreakEnterParkLoop = debugMode && raiseExceptionIntr // exception in debug mode (except ebrk) changes cmderr. how ???
XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
......
......@@ -174,6 +174,14 @@ trait HasCSRConst {
val Mhpmevent31 = 0x33F
// Debug/Trace Registers (shared with Debug Mode) (not implemented)
// Trigger Registers
val Tselect = 0x7A0
val Tdata1 = 0x7A1
val Tdata2 = 0x7A2
val Tinfo = 0x7A4
val Tcontrol = 0x7A5
// Debug Mode Registers
val Dcsr = 0x7B0
val Dpc = 0x7B1
......@@ -239,4 +247,15 @@ trait HasCSRConst {
val index = UIntToOH(addr & 31.U)
Mux(mode === ModeM, true.B, Mux(mode === ModeS, (index & mmask) =/= 0.U, (index & mmask & smask) =/= 0.U))
}
def dcsrPermissionCheck(addr: UInt, mModeCanWrite: UInt, debug: Bool): Bool = {
// debug mode write only regs
val isDebugReg = addr(11, 4) === "h7b".U
Mux(!mModeCanWrite && isDebugReg, debug, true.B)
}
def triggerPermissionCheck(addr: UInt, mModeCanWrite: UInt, debug: Bool): Bool = {
val isTriggerReg = addr(11, 4) === "h7a".U
Mux(!mModeCanWrite && isTriggerReg, debug, true.B)
}
}
......@@ -163,10 +163,23 @@ class RobExceptionInfo(implicit p: Parameters) extends XSBundle {
val replayInst = Bool() // redirect to that inst itself
val singleStep = Bool()
val crossPageIPFFix = Bool()
val trigger = new TriggerCf
// make sure chains are fired at same timing
def trigger_vec_fix = VecInit(trigger.triggerHitVec.zipWithIndex.map{ case (hit, i) =>
def chain = trigger.triggerChainVec(i / 2)
if (i % 2 == 0)
Mux(chain, (trigger.triggerHitVec(i ) && trigger.triggerHitVec(i + 1)), trigger.triggerHitVec(i))
else
Mux(chain, (trigger.triggerHitVec(i ) && trigger.triggerHitVec(i - 1)), trigger.triggerHitVec(i))
})
def trigger_before = trigger_vec_fix.zip(trigger.triggerTiming).map{ case (hit, timing) => hit && !timing}.reduce(_ | _)
def trigger_after = trigger_vec_fix.zip(trigger.triggerTiming).map{ case (hit, timing) => hit && timing}.reduce(_ | _)
def has_exception = exceptionVec.asUInt.orR || flushPipe || singleStep || replayInst
def has_exception = exceptionVec.asUInt.orR || flushPipe || singleStep || replayInst || trigger_vec_fix.asUInt.orR
// only exceptions are allowed to writeback when enqueue
def can_writeback = exceptionVec.asUInt.orR || singleStep
def can_writeback = exceptionVec.asUInt.orR || singleStep || trigger_before
}
class ExceptionGen(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper {
......@@ -226,6 +239,7 @@ class ExceptionGen(implicit p: Parameters) extends XSModule with HasCircularQueu
current.bits.flushPipe := s1_out_bits.flushPipe || current.bits.flushPipe
current.bits.replayInst := s1_out_bits.replayInst || current.bits.replayInst
current.bits.singleStep := s1_out_bits.singleStep || current.bits.singleStep
// current.bits.trigger := (s1_out_bits.trigger.asUInt | current.bits.trigger.asUInt).asTypeOf(new TriggerCf)
}
}
}.elsewhen (s1_out_valid && !s1_flush) {
......@@ -422,11 +436,14 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
val intrBitSetReg = RegNext(io.csr.intrBitSet)
val intrEnable = intrBitSetReg && !hasNoSpecExec && !CommitType.isLoadStore(deqDispatchData.commitType)
val deqHasExceptionOrFlush = exceptionDataRead.valid && exceptionDataRead.bits.robIdx === deqPtr
val triggerBefore = deqHasExceptionOrFlush && exceptionDataRead.bits.trigger_before
val triggerAfter = deqHasExceptionOrFlush && exceptionDataRead.bits.trigger_after && !exceptionDataRead.bits.trigger_before
val deqHasException = deqHasExceptionOrFlush && exceptionDataRead.bits.exceptionVec.asUInt.orR
val deqHasFlushPipe = deqHasExceptionOrFlush && exceptionDataRead.bits.flushPipe
val deqHasReplayInst = deqHasExceptionOrFlush && exceptionDataRead.bits.replayInst
val exceptionEnable = writebacked(deqPtr.value) && deqHasException
val isFlushPipe = writebacked(deqPtr.value) && (deqHasFlushPipe || deqHasReplayInst)
val exceptionEnable = writebacked(deqPtr.value) && deqHasException// && triggerBefore
val isFlushPipe = writebacked(deqPtr.value) && (deqHasFlushPipe || deqHasReplayInst || triggerAfter)
// io.flushOut will trigger redirect at the next cycle.
// Block any redirect or commit at the next cycle.
......@@ -452,6 +469,7 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
io.exception.bits.uop.ctrl.singleStep := RegEnable(exceptionDataRead.bits.singleStep, exceptionHappen)
io.exception.bits.uop.cf.crossPageIPFFix := RegEnable(exceptionDataRead.bits.crossPageIPFFix, exceptionHappen)
io.exception.bits.isInterrupt := RegEnable(intrEnable, exceptionHappen)
io.exception.bits.uop.cf.trigger.triggerHitVec := RegEnable(exceptionDataRead.bits.trigger_vec_fix, exceptionHappen)
XSDebug(io.flushOut.valid,
p"generate redirect: pc 0x${Hexadecimal(io.exception.bits.uop.cf.pc)} intr $intrEnable " +
......@@ -756,6 +774,7 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
assert(exceptionGen.io.enq(i).bits.replayInst === false.B)
exceptionGen.io.enq(i).bits.singleStep := io.enq.req(i).bits.ctrl.singleStep
exceptionGen.io.enq(i).bits.crossPageIPFFix := io.enq.req(i).bits.cf.crossPageIPFFix
exceptionGen.io.enq(i).bits.trigger := io.enq.req(i).bits.cf.trigger
}
// TODO: don't hard code these idxes
......@@ -789,6 +808,7 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
exceptionGen.io.wb(index).bits.replayInst := io.exeWbResults(wb_index).bits.uop.ctrl.replayInst
exceptionGen.io.wb(index).bits.singleStep := false.B
exceptionGen.io.wb(index).bits.crossPageIPFFix := false.B
exceptionGen.io.wb(index).bits.trigger := io.exeWbResults(wb_index).bits.uop.cf.trigger
}
// 4 fmac + 2 fmisc + 1 i2f
......
......@@ -68,6 +68,12 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
val pfevent = Module(new PFEvent)
val tlbCsr = RegNext(io.tlbCsr)
pfevent.io.distribute_csr := io.csrCtrl.distribute_csr
// trigger
ifu.io.frontendTrigger := io.csrCtrl.frontend_trigger
val triggerEn = io.csrCtrl.trigger_enable
ifu.io.csrTriggerEnable := VecInit(triggerEn(0), triggerEn(1), triggerEn(6), triggerEn(8))
// pmp
val pmp = Module(new PMP())
val pmp_check = VecInit(Seq.fill(2)(Module(new PMPChecker(3, sameCycle = true)).io))
......
......@@ -93,6 +93,7 @@ class FetchToIBuffer(implicit p: Parameters) extends XSBundle {
val ipf = Vec(PredictWidth, Bool())
val acf = Vec(PredictWidth, Bool())
val crossPageIPFFix = Vec(PredictWidth, Bool())
val triggered = Vec(PredictWidth, new TriggerCf)
}
// class BitWiseUInt(val width: Int, val init: UInt) extends Module {
......
......@@ -71,6 +71,8 @@ class NewIFUIO(implicit p: Parameters) extends XSBundle {
val req = Valid(new PMPReqBundle())
val resp = Flipped(new PMPRespBundle())
})
val frontendTrigger = Flipped(new FrontendTdataDistributeIO)
val csrTriggerEnable = Input(Vec(4, Bool()))
val rob_commits = Flipped(Vec(CommitWidth, Valid(new RobCommitInfo)))
}
......@@ -95,6 +97,9 @@ class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
val instValid = Bool()
val lastHalfMatch = Bool()
val oversize = Bool()
val mmio = Bool()
val frontendTrigger = new FrontendTdataDistributeIO
val csrTriggerEnable = Vec(4, Bool())
}
class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
......@@ -628,6 +633,9 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
preDecoderIn.lastHalfMatch := f3_lastHalfMatch
preDecoderIn.pageFault := f3_except_pf
preDecoderIn.accessFault := f3_except_af
preDecoderIn.mmio := f3_mmio
preDecoderIn.frontendTrigger := io.frontendTrigger
preDecoderIn.csrTriggerEnable := io.csrTriggerEnable
// TODO: What if next packet does not match?
......@@ -652,6 +660,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
io.toIbuffer.bits.ipf := preDecoderOut.pageFault
io.toIbuffer.bits.acf := preDecoderOut.accessFault
io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF
io.toIbuffer.bits.triggered := preDecoderOut.triggered
//Write back to Ftq
val f3_cache_fetch = f3_valid && !(f2_fire && !f2_flush)
......
......@@ -49,6 +49,7 @@ class Ibuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrH
val ipf = Bool()
val acf = Bool()
val crossPageIPFFix = Bool()
val triggered = new TriggerCf
}
for(out <- io.out) {
......@@ -97,6 +98,11 @@ class Ibuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrH
inWire.ipf := io.in.bits.ipf(i)
inWire.acf := io.in.bits.acf(i)
inWire.crossPageIPFFix := io.in.bits.crossPageIPFFix(i)
inWire.triggered := io.in.bits.triggered(i)
for(k<-0 until 10){
inWire.triggered.triggerHitVec(k) := false.B
}
ibuf.io.waddr(i) := tail_vec(offset(i)).value
ibuf.io.wdata(i) := inWire
......@@ -131,6 +137,7 @@ class Ibuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrH
io.out(i).bits.loadWaitStrict := DontCare
io.out(i).bits.ssid := DontCare
io.out(i).bits.replayInst := false.B
io.out(i).bits.trigger := outWire.triggered
}
val next_head_vec = VecInit(head_vec.map(_ + numDeq))
ibuf.io.raddr := VecInit(next_head_vec.map(_.value))
......
......@@ -97,6 +97,7 @@ class PreDecodeResp(implicit p: Parameters) extends XSBundle with HasPdConst {
val pageFault = Vec(PredictWidth, Bool())
val accessFault = Vec(PredictWidth, Bool())
val crossPageIPF = Vec(PredictWidth, Bool())
val triggered = Vec(PredictWidth, new TriggerCf)
}
class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
......@@ -137,6 +138,17 @@ class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
val nextLinePC = align(pcStart, 64) + 64.U
// Frontend Triggers
val tdata = Reg(Vec(4, new MatchTriggerIO))
when(io.in.frontendTrigger.t.valid) {
tdata(io.in.frontendTrigger.t.bits.addr) := io.in.frontendTrigger.t.bits.tdata
}
io.out.triggered.map{i => i := 0.U.asTypeOf(new TriggerCf)}
val triggerEnable = RegInit(VecInit(Seq.fill(4)(false.B))) // From CSR, controlled by priv mode, etc.
triggerEnable := io.in.csrTriggerEnable
val triggerMapping = Map(0 -> 0, 1 -> 1, 2 -> 6, 3 -> 8)
val chainMapping = Map(0 -> 0, 2 -> 3, 3 -> 4)
for (i <- 0 until PredictWidth) {
//TODO: Terrible timing for pc comparing
val isNextLine = (io.out.pc(i) > nextLinePC)
......@@ -169,6 +181,17 @@ class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
io.out.pd(i).isRet := isRet
io.out.pc(i) := currentPC
io.out.crossPageIPF(i) := (io.out.pc(i) === align(realEndPC, 64) - 2.U) && !pageFault(0) && pageFault(1) && !currentIsRVC
// io.out.triggered(i) := TriggerCmp(Mux(currentIsRVC, inst(15,0), inst), tInstData, matchType, triggerEnable) && TriggerCmp(currentPC, tPcData, matchType, triggerEnable)
io.out.triggered(i).triggerTiming := VecInit(Seq.fill(10)(false.B))
io.out.triggered(i).triggerHitVec := VecInit(Seq.fill(10)(false.B))
io.out.triggered(i).triggerChainVec := VecInit(Seq.fill(5)(false.B))
for (j <- 0 until 4) {
val hit = Mux(tdata(j).select, TriggerCmp(Mux(currentIsRVC, inst(15, 0), inst), tdata(j).tdata2, tdata(j).matchType, triggerEnable(j)),
TriggerCmp(currentPC, tdata(j).tdata2, tdata(j).matchType, triggerEnable(j)))
io.out.triggered(i).triggerHitVec(triggerMapping(j)) := hit
io.out.triggered(i).triggerTiming(triggerMapping(j)) := hit && tdata(j).timing
if(chainMapping.contains(j)) io.out.triggered(i).triggerChainVec(chainMapping(j)) := hit && tdata(j).chain
}
io.out.pageFault(i) := hasPageFault || io.out.crossPageIPF(i)
io.out.accessFault(i) := hasAccessFault
......
......@@ -106,7 +106,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule
// val data = Reg(Vec(LoadQueueSize, new LsRobEntry))
val dataModule = Module(new LoadQueueData(LoadQueueSize, wbNumRead = LoadPipelineWidth, wbNumWrite = LoadPipelineWidth))
dataModule.io := DontCare
val vaddrModule = Module(new SyncDataModuleTemplate(UInt(VAddrBits.W), LoadQueueSize, numRead = 1, numWrite = LoadPipelineWidth))
val vaddrModule = Module(new SyncDataModuleTemplate(UInt(VAddrBits.W), LoadQueueSize, numRead = 3, numWrite = LoadPipelineWidth))
vaddrModule.io := DontCare
val allocated = RegInit(VecInit(List.fill(LoadQueueSize)(false.B))) // lq entry has been allocated
val datavalid = RegInit(VecInit(List.fill(LoadQueueSize)(false.B))) // data is valid
......@@ -331,6 +331,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule
io.ldout(i).bits.debug.isMMIO := debug_mmio(loadWbSel(i))
io.ldout(i).bits.debug.isPerfCnt := false.B
io.ldout(i).bits.debug.paddr := debug_paddr(loadWbSel(i))
io.ldout(i).bits.debug.vaddr := vaddrModule.io.rdata(i+1)
io.ldout(i).bits.fflags := DontCare
io.ldout(i).valid := loadWbSelV(i)
......@@ -709,6 +710,12 @@ class LoadQueue(implicit p: Parameters) extends XSModule
vaddrModule.io.raddr(0) := (deqPtrExt + commitCount).value
io.exceptionAddr.vaddr := vaddrModule.io.rdata(0)
// Read vaddr for debug trigger
(0 until LoadPipelineWidth).map(i => {
vaddrModule.io.raddr(i+1) := loadWbSel(i)
})
// misprediction recovery / exception redirect
// invalidate lq term using robIdx
val needCancel = Wire(Vec(LoadQueueSize, Bool()))
......
......@@ -466,6 +466,7 @@ class StoreQueue(implicit p: Parameters) extends XSModule with HasDCacheParamete
io.mmioStout.bits.debug.paddr := DontCare
io.mmioStout.bits.debug.isPerfCnt := false.B
io.mmioStout.bits.fflags := DontCare
io.mmioStout.bits.debug.vaddr := DontCare
// Remove MMIO inst from store queue after MMIO request is being sent
// That inst will be traced by uncache state machine
when (io.mmioStout.fire()) {
......
......@@ -553,6 +553,7 @@ class LoadUnit(implicit p: Parameters) extends XSModule with HasLoadHelper {
hitLoadOut.bits.debug.isMMIO := load_s2.io.out.bits.mmio
hitLoadOut.bits.debug.isPerfCnt := false.B
hitLoadOut.bits.debug.paddr := load_s2.io.out.bits.paddr
hitLoadOut.bits.debug.vaddr := load_s2.io.out.bits.vaddr
hitLoadOut.bits.fflags := DontCare
load_s2.io.out.ready := true.B
......
......@@ -180,7 +180,8 @@ class StoreUnit_S3(implicit p: Parameters) extends XSModule {
io.stout.bits.redirectValid := false.B
io.stout.bits.redirect := DontCare
io.stout.bits.debug.isMMIO := io.in.bits.mmio
io.stout.bits.debug.paddr := DontCare
io.stout.bits.debug.paddr := io.in.bits.paddr
io.stout.bits.debug.vaddr := io.in.bits.vaddr
io.stout.bits.debug.isPerfCnt := false.B
io.stout.bits.fflags := DontCare
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册