提交 42f6b542 编写于 作者: Fa_wang's avatar Fa_wang

Merge branch 'dev-bpu-rvc' into dev-predecode

......@@ -50,7 +50,7 @@ $(SIM_TOP_V): $(SCALA_FILE) $(TEST_FILE)
ifeq ($(REMOTE),localhost)
mill chiselModule.test.runMain $(SIMTOP) -X verilog -td $(@D) --output-file $(@F) $(SIM_ARGS)
else
ssh $(REMOTE) "cd $(REMOTE_PRJ_HOME) && mill chiselModule.test.runMain $(SIMTOP) -X verilog -td $(@D) --output-file $(@F) $(SIM_ARGS)"
ssh -tt $(REMOTE) "cd $(REMOTE_PRJ_HOME) && mill chiselModule.test.runMain $(SIMTOP) -X verilog -td $(@D) --output-file $(@F) $(SIM_ARGS)"
endif
......@@ -98,7 +98,7 @@ $(REF_SO):
$(EMU): $(EMU_MK) $(EMU_DEPS) $(EMU_HEADERS) $(REF_SO)
CPPFLAGS=-DREF_SO=\\\"$(REF_SO)\\\" $(MAKE) VM_PARALLEL_BUILDS=1 -C $(dir $(EMU_MK)) -f $(abspath $(EMU_MK))
SEED = -s $(shell shuf -i 1-10000 -n 1)
SEED ?= $(shell shuf -i 1-10000 -n 1)
# log will only be printed when (B<=GTimer<=E) && (L < loglevel)
......@@ -108,9 +108,9 @@ E ?= -1
emu: $(EMU)
ifeq ($(REMOTE),localhost)
@$(EMU) -i $(IMAGE) $(SEED) -b $(B) -e $(E)
@$(EMU) -i $(IMAGE) -s $(SEED) -b $(B) -e $(E)
else
ssh $(REMOTE) "cd $(REMOTE_PRJ_HOME) && $(EMU) -i $(REMOTE_PREFIX)/$(realpath $(IMAGE)) $(SEED) -b $(B) -e $(E)"
ssh -tt $(REMOTE) "cd $(REMOTE_PRJ_HOME) && $(EMU) -i $(REMOTE_PREFIX)/$(realpath $(IMAGE)) -s $(SEED) -b $(B) -e $(E)"
endif
cache:
......
此差异已折叠。
......@@ -13,14 +13,14 @@ EMU_ARGS = B=$(B) E=$(E) V=$(V)
# ------------------------------------------------------------------
cpu:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=dummy $(EMU_ARGS) run
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=dummy $(EMU_ARGS) run
# ------------------------------------------------------------------
# run different test sets
# ------------------------------------------------------------------
cputest:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(EMU_ARGS) run 2>&1 | tee > cpu.log
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(EMU_ARGS) run 2 > cpu.log
cat cpu.log | grep different
cat cpu.log | grep IPC
......@@ -28,32 +28,32 @@ cputest:
# $(MAKE) -C $(AM_HOME)/tests/bputest $(ARCH) run 2>&1 | tee > bpu.log
# cat bpu.log | grep different
bputest:
$(MAKE) -C $(AM_HOME)/tests/bputest $(ARCH) run 2>&1 | tee > bpu.log
$(MAKE) -C $(AM_HOME)/tests/bputest $(ARCH) run 2 > bpu.log
cat bpu.log | grep Mbp
amtest:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(SINGLETEST) run 2>&1 | tee > test.log
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(SINGLETEST) run 2 > test.log
cat test.log | grep different
cat test.log | grep ISU > isu.log
microbench:
$(MAKE) -C $(AM_HOME)/apps/microbench $(ARCH) mainargs=test run 2>&1 | tee > microbench.log
$(MAKE) -C $(AM_HOME)/apps/microbench $(ARCH) $(EMU_ARGS) mainargs=test run 2 > microbench.log
cat microbench.log | grep IPC
microbench_train:
$(MAKE) -C $(AM_HOME)/apps/microbench $(ARCH) mainargs=train run 2>&1 | tee > microbench.log
$(MAKE) -C $(AM_HOME)/apps/microbench $(ARCH) $(EMU_ARGS) mainargs=train run 2 > microbench.log
cat microbench.log | grep IPC
coremark:
$(MAKE) -C $(AM_HOME)/apps/coremark $(ARCH) mainargs=test run 2>&1 | tee > coremark.log
$(MAKE) -C $(AM_HOME)/apps/coremark $(ARCH) $(EMU_ARGS) mainargs=test run 2 > coremark.log
cat coremark.log | grep IPC
dhrystone:
$(MAKE) -C $(AM_HOME)/apps/dhrystone $(ARCH) mainargs=test run 2>&1 | tee > dhrystone.log
$(MAKE) -C $(AM_HOME)/apps/dhrystone $(ARCH) $(EMU_ARGS) mainargs=test run 2 > dhrystone.log
cat dhrystone.log | grep IPC
xj:
$(MAKE) -C $(NANOS_HOME) $(ARCH) run
$(MAKE) -C $(NANOS_HOME) $(ARCH) $(EMU_ARGS) run
xjnemu:
$(MAKE) -C $(NANOS_HOME) ARCH=riscv64-nemu run
......@@ -74,7 +74,7 @@ xv6-debug:
$(MAKE) -C $(XV6_HOME) noop 2>&1 | tee > xv6.log
linux:
$(MAKE) -C $(BBL_LINUX_HOME) noop
$(MAKE) -C $(BBL_LINUX_HOME) $(EMU_ARGS) noop
# ------------------------------------------------------------------
# get disassembled test src
# ------------------------------------------------------------------
......
mymap = {}
last = ""
with open("../build/XSSimTop.v", "r") as f:
line = f.readline()
cnt = 0
while(line):
if "module " in line:
if last!="" :
mymap[last] = cnt
last = line[6:-2]
cnt = 1
else:
cnt = cnt + 1
line = f.readline()
mymap[last] = cnt
for k,v in mymap.items():
print(k, v)
\ No newline at end of file
/**************************************************************************************
* Copyright (c) 2020 Institute of Computing Technology, CAS
* Copyright (c) 2020 University of Chinese Academy of Sciences
*
* NutShell is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan 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 bus.simplebus
import chisel3._
......@@ -11,7 +27,7 @@ class SimpleBusCrossbar1toN(addressSpace: List[(Long, Long)]) extends Module {
val out = Vec(addressSpace.length, new SimpleBusUC)
})
val s_idle :: s_resp :: Nil = Enum(2)
val s_idle :: s_resp :: s_error :: Nil = Enum(3)
val state = RegInit(s_idle)
// select the output channel according to the address
......@@ -22,8 +38,10 @@ class SimpleBusCrossbar1toN(addressSpace: List[(Long, Long)]) extends Module {
val outSel = io.out(outSelIdx)
val outSelIdxResp = RegEnable(outSelIdx, outSel.req.fire() && (state === s_idle))
val outSelResp = io.out(outSelIdxResp)
val reqInvalidAddr = io.in.req.valid && !outSelVec.asUInt.orR
assert(!io.in.req.valid || outSelVec.asUInt.orR, "address decode error, bad addr = 0x%x\n", addr)
when(!(!io.in.req.valid || outSelVec.asUInt.orR) || !(!(io.in.req.valid && outSelVec.asUInt.andR))){printf("[ERROR] bad addr %x, time %d\n", addr, GTimer())}
// assert(!io.in.req.valid || outSelVec.asUInt.orR, "address decode error, bad addr = 0x%x\n", addr)
assert(!(io.in.req.valid && outSelVec.asUInt.andR), "address decode error, bad addr = 0x%x\n", addr)
// bind out.req channel
......@@ -34,14 +52,19 @@ class SimpleBusCrossbar1toN(addressSpace: List[(Long, Long)]) extends Module {
}}
switch (state) {
is (s_idle) { when (outSel.req.fire()) { state := s_resp } }
is (s_idle) {
when (outSel.req.fire()) { state := s_resp }
when (reqInvalidAddr) { state := s_error }
}
is (s_resp) { when (outSelResp.resp.fire()) { state := s_idle } }
is (s_error) { when(io.in.resp.fire()){ state := s_idle } }
}
io.in.resp.valid := outSelResp.resp.fire()
io.in.resp.valid := outSelResp.resp.fire() || state === s_error
io.in.resp.bits <> outSelResp.resp.bits
// io.in.resp.bits.exc.get := state === s_error
outSelResp.resp.ready := io.in.resp.ready
io.in.req.ready := outSel.req.ready
io.in.req.ready := outSel.req.ready || reqInvalidAddr
Debug() {
when (state === s_idle && io.in.req.valid) {
......
......@@ -63,7 +63,7 @@ class XSSoc(implicit val p: XSConfig) extends Module with HasSoCParameter {
xsCore.io.imem.coh.req.bits := DontCare
val addrSpace = List(
(0x40000000L, 0x08000000L), // external devices
(0x40000000L, 0x40000000L), // external devices
(0x38000000L, 0x00010000L) // CLINT
)
val mmioXbar = Module(new SimpleBusCrossbar1toN(addrSpace))
......
......@@ -28,6 +28,9 @@ object XSLog {
if(generateLog){
when (cond && logEnable) {
printf((if (prefix) commonInfo else p"") + pable)
if (debugLevel >= XSLogLevel.ERROR) {
assert(false.B)
}
}
}
}
......
......@@ -11,12 +11,12 @@ class FetchPacket extends XSBundle {
val instrs = Vec(FetchWidth, UInt(32.W))
val mask = UInt((FetchWidth*2).W)
val pc = UInt(VAddrBits.W) // the pc of first inst in the fetch group
val pnpc = Vec(FetchWidth, UInt(VAddrBits.W))
val hist = Vec(FetchWidth, UInt(HistoryLength.W))
val pnpc = Vec(FetchWidth*2, UInt(VAddrBits.W))
val hist = Vec(FetchWidth*2, UInt(HistoryLength.W))
// val btbVictimWay = UInt(log2Up(BtbWays).W)
val predCtr = Vec(FetchWidth, UInt(2.W))
val btbHitWay = Bool()
val tageMeta = Vec(FetchWidth, (new TageMeta))
val predCtr = Vec(FetchWidth*2, UInt(2.W))
val btbHit = Vec(FetchWidth*2, Bool())
val tageMeta = Vec(FetchWidth*2, (new TageMeta))
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
}
......@@ -47,20 +47,20 @@ class BranchPrediction extends XSBundle {
val redirect = Bool()
// mask off all the instrs after the first redirect instr
val instrValid = Vec(FetchWidth, Bool())
val instrValid = Vec(FetchWidth*2, Bool())
// target of the first redirect instr in a fetch package
val target = UInt(VAddrBits.W)
val lateJump = Bool()
// save these info in brq!
// global history of each valid(or uncancelled) instruction, excluding branch's own prediction result
val hist = Vec(FetchWidth, UInt(HistoryLength.W))
val hist = Vec(FetchWidth*2, UInt(HistoryLength.W))
// victim way when updating btb
// val btbVictimWay = UInt(log2Up(BtbWays).W)
// 2-bit saturated counter
val predCtr = Vec(FetchWidth, UInt(2.W))
val btbHitWay = Bool()
val predCtr = Vec(FetchWidth*2, UInt(2.W))
val btbHit = Vec(FetchWidth*2, Bool())
// tage meta info
val tageMeta = Vec(FetchWidth, (new TageMeta))
val tageMeta = Vec(FetchWidth*2, (new TageMeta))
// ras checkpoint, only used in Stage3
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
......@@ -68,9 +68,10 @@ class BranchPrediction extends XSBundle {
// Save predecode info in icache
class Predecode extends XSBundle {
val mask = UInt(FetchWidth.W)
val fuTypes = Vec(FetchWidth, FuType())
val fuOpTypes = Vec(FetchWidth, FuOpType())
val mask = UInt((FetchWidth*2).W)
val isRVC = Vec(FetchWidth*2, Bool())
val fuTypes = Vec(FetchWidth*2, FuType())
val fuOpTypes = Vec(FetchWidth*2, FuOpType())
}
// Dequeue DecodeWidth insts from Ibuffer
......@@ -82,7 +83,7 @@ class CtrlFlow extends XSBundle {
val hist = UInt(HistoryLength.W)
// val btbVictimWay = UInt(log2Up(BtbWays).W)
val btbPredCtr = UInt(2.W)
val btbHitWay = Bool()
val btbHit = Bool()
val tageMeta = new TageMeta
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
......@@ -128,15 +129,16 @@ class Redirect extends XSBundle {
val target = UInt(VAddrBits.W)
val brTarget = UInt(VAddrBits.W)
val brTag = new BrqPtr
val _type = UInt(2.W)
val btbType = UInt(2.W)
val isRVC = Bool()
//val isCall = Bool()
val taken = Bool()
val hist = UInt(HistoryLength.W)
val tageMeta = new TageMeta
val fetchIdx = UInt(log2Up(FetchWidth).W)
val fetchIdx = UInt(log2Up(FetchWidth*2).W)
// val btbVictimWay = UInt(log2Up(BtbWays).W)
val btbPredCtr = UInt(2.W)
val btbHitWay = Bool()
val btbHit = Bool()
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
val isException = Bool()
......@@ -179,7 +181,8 @@ class ExuIO extends XSBundle {
val in = Flipped(DecoupledIO(new ExuInput))
val redirect = Flipped(ValidIO(new Redirect))
val out = DecoupledIO(new ExuOutput)
// for csr
val exception = Flipped(ValidIO(new MicroOp))
// for Lsu
val dmem = new SimpleBusUC
val scommit = Input(UInt(3.W))
......@@ -195,5 +198,5 @@ class FrontendToBackendIO extends XSBundle {
val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
// from backend
val redirectInfo = Input(new RedirectInfo)
val commits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit))) // update branch pred
val inOrderBrInfo = Input(new RedirectInfo)
}
......@@ -31,6 +31,7 @@ trait HasXSParameter {
val PredictWidth = FetchWidth * 2
val EnableBPU = true
val EnableBPD = false // enable backing predictor(like Tage) in BPUStage3
val EnableRAS = true
val HistoryLength = 64
val BtbSize = 256
// val BtbWays = 4
......@@ -50,7 +51,7 @@ trait HasXSParameter {
val PhyRegIdxWidth = log2Up(NRPhyRegs)
val NRReadPorts = 14
val NRWritePorts = 8
val RoqSize = 32
val RoqSize = 128
val InnerRoqIdxWidth = log2Up(RoqSize)
val RoqIdxWidth = InnerRoqIdxWidth + 1
val IntDqDeqWidth = 4
......
......@@ -38,6 +38,7 @@ class Backend(implicit val p: XSConfig) extends XSModule
// val fmiscDivSqrtExeUnits = Array.tabulate(exuParameters.FmiscDivSqrtCnt)(_ => Module(new FmiscDivSqrt))
val lsuExeUnits = Array.tabulate(exuParameters.StuCnt)(_ => Module(new LsExeUnit))
val exeUnits = jmpExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits ++ lsuExeUnits)
exeUnits.foreach(_.io.exception := DontCare)
exeUnits.foreach(_.io.dmem := DontCare)
exeUnits.foreach(_.io.scommit := DontCare)
......@@ -121,12 +122,15 @@ class Backend(implicit val p: XSConfig) extends XSModule
lsuExeUnits.foreach(_.io.dmem <> io.dmem)
lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit)
jmpExeUnit.io.exception.valid := roq.io.redirect.valid
jmpExeUnit.io.exception.bits := roq.io.exception
io.frontend.redirectInfo <> redirectInfo
io.frontend.commits <> roq.io.commits
io.frontend.inOrderBrInfo <> brq.io.inOrderBrInfo
decode.io.in <> io.frontend.cfVec
brq.io.roqRedirect <> roq.io.redirect
brq.io.bcommit := roq.io.bcommit
brq.io.enqReqs <> decode.io.toBrq
for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) {
x.bits := y.io.out.bits
......
......@@ -4,7 +4,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import chisel3.util.experimental.BoringUtils
import chisel3.ExcitingUtils._
class BrqPtr extends XSBundle {
......@@ -63,6 +63,10 @@ class BrqIO extends XSBundle{
val out = ValidIO(new ExuOutput)
// misprediction, flush pipeline
val redirect = Output(Valid(new Redirect))
// commit cnt of branch instr
val bcommit = Input(UInt(BrTagWidth.W))
// in order dequeue to train bpd
val inOrderBrInfo = Output(new RedirectInfo)
}
class Brq extends XSModule {
......@@ -87,6 +91,7 @@ class Brq extends XSModule {
val isIdle = Bool()
}
val brCommitCnt = RegInit(0.U(BrTagWidth.W))
val brQueue = Reg(Vec(BrqSize, new BrqEntry))
val stateQueue = RegInit(VecInit(Seq.fill(BrqSize)(s_idle)))
......@@ -117,10 +122,17 @@ class Brq extends XSModule {
}
val commitIsHead = commitIdx===headIdx
val deqValid = !stateQueue(headIdx).isIdle && commitIsHead
val deqValid = !stateQueue(headIdx).isIdle && commitIsHead && brCommitCnt=/=0.U
val commitValid = stateQueue(commitIdx).isWb
val commitEntry = brQueue(commitIdx)
brCommitCnt := brCommitCnt + io.bcommit - deqValid
XSDebug(p"brCommitCnt:$brCommitCnt\n")
assert(brCommitCnt+io.bcommit >= deqValid)
io.inOrderBrInfo.valid := deqValid
io.inOrderBrInfo.misPred := commitEntry.misPred
io.inOrderBrInfo.redirect := commitEntry.exuOut.redirect
XSDebug(p"headIdx:$headIdx commitIdx:$commitIdx\n")
XSDebug(p"headPtr:$headPtr tailPtr:$tailPtr\n")
......@@ -142,7 +154,7 @@ class Brq extends XSModule {
)
headPtr := headPtrNext
io.redirect.valid := commitValid && commitEntry.misPred
io.redirect.valid := commitValid && commitEntry.misPred && !io.roqRedirect.valid
io.redirect.bits := commitEntry.exuOut.redirect
io.out.valid := commitValid
io.out.bits := commitEntry.exuOut
......@@ -194,6 +206,7 @@ class Brq extends XSModule {
stateQueue.foreach(_ := s_idle)
headPtr := BrqPtr(false.B, 0.U)
tailPtr := BrqPtr(false.B, 0.U)
brCommitCnt := 0.U
}.elsewhen(io.redirect.valid){
// misprediction
stateQueue.zipWithIndex.foreach({case(s, i) =>
......@@ -224,28 +237,37 @@ class Brq extends XSModule {
XSInfo(debug_roq_redirect, "roq redirect, flush brq\n")
XSInfo(debug_brq_redirect, p"brq redirect, target:${Hexadecimal(io.redirect.bits.target)}\n")
val mbpInstr = io.out.fire()
val mbpRight = io.out.fire() && !commitEntry.misPred
val mbpWrong = io.out.fire() && commitEntry.misPred
val mbpBRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.B
val mbpBWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.B
val mbpJRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.J
val mbpJWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.J
val mbpIRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.I
val mbpIWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.I
val mbpRRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.R
val mbpRWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.R
val fire = io.out.fire()
val predRight = fire && !commitEntry.misPred
val predWrong = fire && commitEntry.misPred
val isBType = commitEntry.exuOut.redirect.btbType===BTBtype.B
val isJType = commitEntry.exuOut.redirect.btbType===BTBtype.J
val isIType = commitEntry.exuOut.redirect.btbType===BTBtype.I
val isRType = commitEntry.exuOut.redirect.btbType===BTBtype.R
val mbpInstr = fire
val mbpRight = predRight
val mbpWrong = predWrong
val mbpBRight = predRight && isBType
val mbpBWrong = predWrong && isBType
val mbpJRight = predRight && isJType
val mbpJWrong = predWrong && isJType
val mbpIRight = predRight && isIType
val mbpIWrong = predWrong && isIType
val mbpRRight = predRight && isRType
val mbpRWrong = predWrong && isRType
if(EnableBPU){
BoringUtils.addSource(mbpInstr, "MbpInstr")
BoringUtils.addSource(mbpRight, "MbpRight")
BoringUtils.addSource(mbpWrong, "MbpWrong")
BoringUtils.addSource(mbpBRight, "MbpBRight")
BoringUtils.addSource(mbpBWrong, "MbpBWrong")
BoringUtils.addSource(mbpJRight, "MbpJRight")
BoringUtils.addSource(mbpJWrong, "MbpJWrong")
BoringUtils.addSource(mbpIRight, "MbpIRight")
BoringUtils.addSource(mbpIWrong, "MbpIWrong")
BoringUtils.addSource(mbpRRight, "MbpRRight")
BoringUtils.addSource(mbpRWrong, "MbpRWrong")
ExcitingUtils.addSource(mbpInstr, "perfCntCondMbpInstr", Perf)
ExcitingUtils.addSource(mbpRight, "perfCntCondMbpRight", Perf)
ExcitingUtils.addSource(mbpWrong, "perfCntCondMbpWrong", Perf)
ExcitingUtils.addSource(mbpBRight, "perfCntCondMbpBRight", Perf)
ExcitingUtils.addSource(mbpBWrong, "perfCntCondMbpBWrong", Perf)
ExcitingUtils.addSource(mbpJRight, "perfCntCondMbpJRight", Perf)
ExcitingUtils.addSource(mbpJWrong, "perfCntCondMbpJWrong", Perf)
ExcitingUtils.addSource(mbpIRight, "perfCntCondMbpIRight", Perf)
ExcitingUtils.addSource(mbpIWrong, "perfCntCondMbpIWrong", Perf)
ExcitingUtils.addSource(mbpRRight, "perfCntCondMbpRRight", Perf)
ExcitingUtils.addSource(mbpRWrong, "perfCntCondMbpRWrong", Perf)
}
}
......@@ -52,6 +52,7 @@ object Instructions extends HasInstrType with HasXSParameter {
RVIInstr.table ++
XSTrap.table ++
RVZicsrInstr.table ++
RVZifenceiInstr.table ++
Privileged.table ++
RVFInstr.table ++
RVDInstr.table ++
......@@ -60,7 +61,7 @@ object Instructions extends HasInstrType with HasXSParameter {
// (if (HasFPU) RVFInstr.table ++ RVDInstr.table else Nil) ++
// Privileged.table ++
// RVAInstr.table ++
// RVZicsrInstr.table ++ RVZifenceiInstr.table
// RVZicsrInstr.table
}
object CInstructions extends HasInstrType with HasXSParameter {
......
......@@ -19,7 +19,6 @@ class Decoder extends XSModule with HasInstrType {
io.out := DontCare // FIXME: remove me!!!
io.out.cf := io.in
val hasIntr = Wire(Bool())
val instr: UInt = io.in.instr
val decodeList = ListLookup(instr, Instructions.DecodeDefault, Instructions.DecodeTable)
val instrType :: fuType :: fuOpType :: Nil = decodeList
......@@ -27,7 +26,11 @@ class Decoder extends XSModule with HasInstrType {
// todo: remove this when fetch stage can decide if an instr is br/jmp
io.out.cf.isBr := (instrType === InstrB ||
(fuOpType === JumpOpType.jal && instrType === InstrJ && fuType === FuType.jmp) ||
(fuOpType === JumpOpType.jalr && instrType === InstrI && fuType === FuType.jmp))
(fuOpType === JumpOpType.jalr && instrType === InstrI && fuType === FuType.jmp) ||
(fuOpType === CSROpType.jmp && instrType === InstrI && fuType === FuType.csr))
// val isRVC = instr(1, 0) =/= "b11".U
// val rvcImmType :: rvcSrc1Type :: rvcSrc2Type :: rvcDestType :: Nil =
// ListLookup(instr, CInstructions.DecodeDefault, CInstructions.CExtraDecodeTable)
io.out.ctrl.fuOpType := fuOpType
io.out.ctrl.fuType := fuType
......@@ -83,17 +86,11 @@ class Decoder extends XSModule with HasInstrType {
io.out.ctrl.src1Type := Mux(instr(6,0) === "b0110111".U, SrcType.reg, src1Type)
io.out.ctrl.src2Type := src2Type
//FIXME: move it to ROB
val intrVec = WireInit(0.U(12.W))
// BoringUtils.addSink(intrVec, "intrVecIDU")
io.out.cf.intrVec.zip(intrVec.asBools).map{ case(x, y) => x := y }
hasIntr := intrVec.orR
val vmEnable = WireInit(false.B)
BoringUtils.addSink(vmEnable, "DTLBENABLE")
io.out.cf.exceptionVec.map(_ := false.B)
io.out.cf.exceptionVec(illegalInstr) := (instrType === InstrN && !hasIntr)
io.out.cf.exceptionVec(illegalInstr) := instrType === InstrN
io.out.cf.exceptionVec(instrPageFault) := io.in.exceptionVec(instrPageFault)
io.out.cf.exceptionVec(instrAccessFault) := io.in.pc(VAddrBits - 1, PAddrBits).orR && !vmEnable
......
......@@ -3,12 +3,16 @@ package xiangshan.backend.decode.isa
import chisel3._
import chisel3.util._
import xiangshan.FuType
import xiangshan.backend.ALUOpType
import xiangshan.backend.decode._
import xiangshan.backend.decode.isa.RV64IInstr.InstrI
object RVZifenceiInstr extends HasInstrType {
def FENCEI = BitPat("b000000000000_00000_001_00000_0001111")
// fixme: add rvzifencei inst
val table = Array()
val table = Array(
FENCEI -> List(InstrI, FuType.alu, ALUOpType.add)
)
}
......@@ -99,7 +99,7 @@ class Dispatch1 extends XSModule{
"roq handshake not continuous %d", i.U)
}
io.fromRename(i).ready := all_recv
XSDebug("v:%d r:%d pc 0x%x of type %b is in %d-th slot\n",
XSDebug(io.fromRename(i).valid, "v:%d r:%d pc 0x%x of type %b is in %d-th slot\n",
io.fromRename(i).valid, io.fromRename(i).ready, io.fromRename(i).bits.cf.pc, io.fromRename(i).bits.ctrl.fuType, i.U)
}
}
......@@ -112,7 +112,6 @@ class Dispatch2(exuCfg: Array[ExuConfig]) extends XSModule{
enq.bits.src3State := io.fpPregRdy(startIndex + 2.U)
}
else {
// TODO: load store with fp
val startIndex = 8.U// regfileRPGen.io.lsIQRfSrc(0)
enq.valid := !instIdxes(i)(2) && io.fromLsDq(instIdxes(i)(1, 0)).valid
enq.bits := io.fromLsDq(instIdxes(i)(1, 0)).bits
......@@ -165,7 +164,6 @@ class Dispatch2(exuCfg: Array[ExuConfig]) extends XSModule{
io.fromLsDq(i).bits.cf.pc, i.U)
}
// TODO: store needs data from FpRegfile
val intExuIndexReg = Reg(Vec(exuParameters.IntExuCnt, UInt(log2Ceil(NRReadPorts).W)))
val fpExuIndexReg = Reg(Vec(exuParameters.FpExuCnt, UInt(log2Ceil(NRReadPorts).W)))
val lsExuIndexReg = Reg(Vec(exuParameters.LduCnt + exuParameters.StuCnt, UInt(log2Ceil(NRReadPorts).W)))
......
......@@ -87,11 +87,4 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int, name: String) extends X
}
head := (head + num_deq) % size.U
head_direction := ((Cat(0.U(1.W), head) + num_deq) >= size.U).asUInt() ^ head_direction
XSDebug(num_deq > 0.U, name + ": num_deq = %d, head = (%d -> %d)\n",
num_deq, head, (head + num_deq) % size.U)
XSDebug(num_enq > 0.U, name + ": num_enq = %d, tail = (%d -> %d)\n",
num_enq, tail, (tail + num_enq) % size.U)
XSDebug(valid_entries > 0.U, name + ": valid_entries = %d, head = (%d, %d), tail = (%d, %d), \n",
valid_entries, head_direction, head, tail_direction, tail)
}
......@@ -62,14 +62,15 @@ class AluExeUnit extends Exu(Exu.aluExeUnitCfg) {
io.out.bits.redirect.target := Mux(!taken && isBranch, pcLatchSlot, target)
io.out.bits.redirect.brTarget := target
io.out.bits.redirect.brTag := uop.brTag
io.out.bits.redirect._type := "b00".U
io.out.bits.redirect.btbType := "b00".U
io.out.bits.redirect.isRVC := isRVC
io.out.bits.redirect.taken := isBranch && taken
io.out.bits.redirect.hist := uop.cf.hist
io.out.bits.redirect.tageMeta := uop.cf.tageMeta
io.out.bits.redirect.fetchIdx := uop.cf.fetchOffset >> 2.U //TODO: consider RVC
io.out.bits.redirect.fetchIdx := uop.cf.fetchOffset >> 1.U //TODO: consider RVC
// io.out.bits.redirect.btbVictimWay := uop.cf.btbVictimWay
io.out.bits.redirect.btbPredCtr := uop.cf.btbPredCtr
io.out.bits.redirect.btbHitWay := uop.cf.btbHitWay
io.out.bits.redirect.btbHit := uop.cf.btbHit
io.out.bits.redirect.rasSp := uop.cf.rasSp
io.out.bits.redirect.rasTopCtr := uop.cf.rasTopCtr
io.out.bits.redirect.isException := DontCare // false.B
......
......@@ -11,6 +11,7 @@ class JmpExeUnit(implicit val p: XSConfig) extends Exu(Exu.jmpExeUnitCfg) {
val jmp = Module(new Jump)
jmp.io.out.ready := io.out.ready
jmp.io.exception <> DontCare
jmp.io.dmem <> DontCare
jmp.io.scommit := DontCare
jmp.io.redirect := io.redirect
......@@ -18,6 +19,7 @@ class JmpExeUnit(implicit val p: XSConfig) extends Exu(Exu.jmpExeUnitCfg) {
val csr = Module(new CSR)
csr.io.cfIn := io.in.bits.uop.cf
csr.io.fpu_csr := DontCare
csr.io.exception <> io.exception
csr.io.instrValid := DontCare
csr.io.imemMMU := DontCare
csr.io.dmemMMU := DontCare
......@@ -32,6 +34,7 @@ class JmpExeUnit(implicit val p: XSConfig) extends Exu(Exu.jmpExeUnitCfg) {
val csrExuOut = Wire(new ExuOutput)
csrExuOut.uop := io.in.bits.uop
csrExuOut.uop.cf := csr.io.cfOut
csrExuOut.data := csrOut
csrExuOut.redirectValid := csr.io.redirectValid
csrExuOut.redirect.brTag := io.in.bits.uop.brTag
......@@ -43,13 +46,14 @@ class JmpExeUnit(implicit val p: XSConfig) extends Exu(Exu.jmpExeUnitCfg) {
val uop = io.in.bits.uop
csrExuOut.redirect.pc := uop.cf.pc
csrExuOut.redirect.brTarget := DontCare // DontCare
csrExuOut.redirect._type := LookupTree(uop.ctrl.fuOpType, RV32I_BRUInstr.bruFuncTobtbTypeTable)
csrExuOut.redirect.btbType := LookupTree(uop.ctrl.fuOpType, RV32I_BRUInstr.bruFuncTobtbTypeTable)
csrExuOut.redirect.isRVC := uop.cf.isRVC
csrExuOut.redirect.taken := false.B
csrExuOut.redirect.hist := uop.cf.hist
csrExuOut.redirect.tageMeta := uop.cf.tageMeta
csrExuOut.redirect.fetchIdx := uop.cf.fetchOffset >> 2.U //TODO: consider RVC
csrExuOut.redirect.fetchIdx := uop.cf.fetchOffset >> 1.U //TODO: consider RVC
csrExuOut.redirect.btbPredCtr := uop.cf.btbPredCtr
csrExuOut.redirect.btbHitWay := uop.cf.btbHitWay
csrExuOut.redirect.btbHit := uop.cf.btbHit
csrExuOut.redirect.rasSp := uop.cf.rasSp
csrExuOut.redirect.rasTopCtr := uop.cf.rasTopCtr
......
......@@ -48,7 +48,7 @@ class LsExeUnit extends Exu(Exu.lsuExeUnitCfg){
Mux(retiringStore, stqData(stqTail).src3, src3In),
Mux(retiringStore, stqData(stqTail).func, funcIn)
)
assert(!(retiringStore && !stqValid(stqTail)))
// assert(!(retiringStore && !stqValid(stqTail)))
def genWmask(addr: UInt, sizeEncode: UInt): UInt = {
LookupTree(sizeEncode, List(
......@@ -149,7 +149,7 @@ class LsExeUnit extends Exu(Exu.lsuExeUnitCfg){
){
retiringStore := true.B
}
when(state === s_partialLoad && retiringStore){
when(dmem.resp.fire() && retiringStore){
retiringStore := false.B
}
......@@ -184,7 +184,7 @@ class LsExeUnit extends Exu(Exu.lsuExeUnitCfg){
val expRedirect = io.redirect.valid && io.redirect.bits.isException
val brRedirect = io.redirect.valid && !io.redirect.bits.isException
for(i <- 0 until 8){
when((i.U >= stqCommited) && (expRedirect || brRedirect && stqData(stqPtr(i)).brTag.needBrFlush(io.redirect.bits.brTag) && stqValid(stqPtr(i)))){
when((i.U >= stqCommited && i.U < stqHead) && (expRedirect || brRedirect && stqData(stqPtr(i)).brTag.needBrFlush(io.redirect.bits.brTag) && stqValid(stqPtr(i)))){
stqValid(stqPtr(i)) := false.B
}
XSDebug("sptrtable: id %d ptr %d valid %d\n", i.U, stqPtr(i), stqValid(stqPtr(i)))
......
......@@ -18,6 +18,7 @@ class MulDivExeUnit extends Exu(Exu.mulDivExeUnitCfg){
val div = Module(new DivExeUnit)
for(x <- Seq(mul.io, div.io)){
x.exception <> DontCare
x.scommit <> DontCare
x.dmem <> DontCare
x.in.bits := io.in.bits
......
package xiangshan.backend.fu
import chisel3._
import chisel3.ExcitingUtils.ConnectionType
import chisel3.util._
import chisel3.util.experimental.BoringUtils
import fpu.Fflags
......@@ -163,10 +164,13 @@ class CSRIO extends FunctionUnitIO {
val redirect = Output(new Redirect)
val redirectValid = Output(Bool())
val fpu_csr = Flipped(new FpuCsrIO)
val cfOut = Output(new CtrlFlow)
// from rob
val exception = Flipped(ValidIO(new MicroOp))
// for exception check
val instrValid = Input(Bool())
// for differential testing
val intrNO = Output(UInt(XLEN.W))
// val intrNO = Output(UInt(XLEN.W))
val imemMMU = Flipped(new MMUIO)
val dmemMMU = Flipped(new MMUIO)
val wenFix = Output(Bool())
......@@ -175,6 +179,8 @@ class CSRIO extends FunctionUnitIO {
class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRConst{
val io = IO(new CSRIO)
io.cfOut := io.cfIn
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
this.valid := valid
......@@ -381,12 +387,11 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
val priviledgeMode = RegInit(UInt(2.W), ModeM)
// perfcnt
// TODO: deal with perfCnt
val hasPerfCnt = false
val hasPerfCnt = !p.FPGAPlatform
val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3
val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
val perfCntsLoMapping = (0 until nrPerfCnts).map { case i => MaskedRegMap(0xb00 + i, perfCnts(i)) }
val perfCntsHiMapping = (0 until nrPerfCnts).map { case i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)) }
val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i)))
val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)))
// CSR reg map
val mapping = Map(
......@@ -510,12 +515,9 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
val isSret = addr === privSret && func === CSROpType.jmp
val isUret = addr === privUret && func === CSROpType.jmp
Debug(false){
when(wen){
printf("[CSR] csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
printf("[MST] time %d pc %x mstatus %x mideleg %x medeleg %x mode %x\n", GTimer(), io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
}
}
XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// MMU Permission Check
......@@ -550,19 +552,19 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
io.imemMMU.status_mxr := DontCare
io.dmemMMU.status_mxr := mstatusStruct.mxr.asBool
val hasInstrPageFault = io.cfIn.exceptionVec(instrPageFault) && valid
val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid
val hasLoadPageFault = io.dmemMMU.loadPF
val hasStorePageFault = io.dmemMMU.storePF
val hasStoreAddrMisaligned = io.cfIn.exceptionVec(storeAddrMisaligned)
val hasLoadAddrMisaligned = io.cfIn.exceptionVec(loadAddrMisaligned)
val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned)
val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned)
when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
val tval = Mux(
hasInstrPageFault,
Mux(
io.cfIn.crossPageIPFFix,
SignExt(io.cfIn.pc + 2.U, XLEN),
SignExt(io.cfIn.pc, XLEN)
io.exception.bits.cf.crossPageIPFFix,
SignExt(io.exception.bits.cf.pc + 2.U, XLEN),
SignExt(io.exception.bits.cf.pc, XLEN)
),
SignExt(io.dmemMMU.addr, XLEN)
)
......@@ -591,12 +593,11 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
val intrVecEnable = Wire(Vec(12, Bool()))
intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
// BoringUtils.addSource(intrVec, "intrVecIDU")
// val intrNO = PriorityEncoder(intrVec)
val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(io.cfIn.intrVec(i), i.U, sum))
// val intrNO = PriorityEncoder(io.cfIn.intrVec)
val raiseIntr = io.cfIn.intrVec.asUInt.orR
val intrBitSet = intrVec.orR()
ExcitingUtils.addSource(intrBitSet, "intrBitSetIDU")
val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
val raiseIntr = intrBitSet && io.exception.valid
XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO)
val mtip = WireInit(false.B)
val meip = WireInit(false.B)
......@@ -606,8 +607,6 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
mipWire.e.m := meip
// exceptions
// TODO: merge iduExceptionVec, csrExceptionVec as raiseExceptionVec
val csrExceptionVec = Wire(Vec(16, Bool()))
csrExceptionVec.map(_ := false.B)
csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
......@@ -618,64 +617,38 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
csrExceptionVec(loadPageFault) := hasLoadPageFault
csrExceptionVec(storePageFault) := hasStorePageFault
val iduExceptionVec = io.cfIn.exceptionVec
val raiseExceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
val raiseException = raiseExceptionVec.orR
val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
io.wenFix := raiseException
val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
io.wenFix := DontCare
val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt()
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)
io.intrNO := Mux(raiseIntr, causeNO, 0.U)
val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
val raiseExceptionIntr = (raiseException || raiseIntr) && io.instrValid
val raiseExceptionIntr = io.exception.valid
val retTarget = Wire(UInt(VAddrBits.W))
val trapTarget = Wire(UInt(VAddrBits.W))
ExcitingUtils.addSource(trapTarget, "trapTarget")
io.redirect := DontCare
io.redirectValid := (valid && func === CSROpType.jmp) || raiseExceptionIntr || resetSatp
io.redirectValid := (valid && func === CSROpType.jmp && !isEcall) || resetSatp
//TODO: use pred pc instead pc+4
io.redirect.target := Mux(
resetSatp,
io.cfIn.pc+4.U,
Mux(
raiseExceptionIntr,
trapTarget,
retTarget
)
)
io.redirect.target := Mux(resetSatp, io.cfIn.pc+4.U, retTarget)
XSDebug(
io.redirectValid,
"redirect to %x, pc=%x\n",
io.redirect.target,
io.cfIn.pc
)
XSDebug(io.redirectValid, "redirect to %x, pc=%x\n", io.redirect.target, io.cfIn.pc)
// Debug(){
// when(raiseExceptionIntr){
// printf("[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
// printf("[MST] time %d pc %x mstatus %x mideleg %x medeleg %x mode %x\n", GTimer(), io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// }
// when(io.redirect.valid){
// printf("[CSR] redirect to %x\n", io.redirect.target)
// }
// }
XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.exception.bits.cf.pc, intrNO, io.exception.bits.cf.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode)
// Debug(false){
// when(raiseExceptionIntr){
// printf("[CSR] raiseExceptionIntr!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
// printf("[MST] time %d pc %x mstatus %x mideleg %x medeleg %x mode %x\n", GTimer(), io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// }
XSDebug(io.redirectValid, "redirect to %x\n", io.redirect.target)
// when(valid && isMret){
// printf("[CSR] Mret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
// printf("[MST] time %d pc %x mstatus %x mideleg %x medeleg %x mode %x\n", GTimer(), io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// }
XSDebug(valid && isMret, "Mret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
XSDebug(valid && isMret, "[MST] pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// when(valid && isSret){
// printf("[CSR] Sret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
// printf("[MST] time %d pc %x mstatus %x mideleg %x medeleg %x mode %x\n", GTimer(), io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
// }
//printf("[CSR] Red(%d, %x) raiseExcepIntr:%d valid:%d instrValid:%x \n", io.redirect.valid, io.redirect.target, raiseExceptionIntr, valid, io.instrValid)
// }
XSDebug(valid && isSret, "Sret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
XSDebug(valid && isSret, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
XSDebug(io.redirectValid, "Redirect %x raiseExcepIntr:%d valid:%d instrValid:%x \n", io.redirect.target, raiseExceptionIntr, valid, io.instrValid)
// Branch control
......@@ -687,7 +660,6 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
ret := isMret || isSret || isUret
trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
retTarget := DontCare
// TODO redirect target
// val illegalEret = TODO
when (valid && isMret) {
......@@ -733,7 +705,7 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
when (delegS) {
scause := causeNO
sepc := SignExt(io.cfIn.pc, XLEN)
sepc := SignExt(io.exception.bits.cf.pc, XLEN)
mstatusNew.spp := priviledgeMode
mstatusNew.pie.s := mstatusOld.ie.s
mstatusNew.ie.s := false.B
......@@ -743,7 +715,7 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
// trapTarget := stvec(VAddrBits-1. 0)
}.otherwise {
mcause := causeNO
mepc := SignExt(io.cfIn.pc, XLEN)
mepc := SignExt(io.exception.bits.cf.pc, XLEN)
mstatusNew.mpp := priviledgeMode
mstatusNew.pie.m := mstatusOld.ie.m
mstatusNew.ie.m := false.B
......@@ -764,91 +736,86 @@ class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRCons
io.in.ready := true.B
io.out.valid := valid
// Debug(false) {
// printf("[CSR2] Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", io.redirect.valid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
// }
//
// Debug(false) {
// when(raiseExceptionIntr && delegS ) {
// printf("[CSR2] Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", io.redirect.valid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
// printf("[CSR3] sepc is writen!!! pc:%x time:%d\n", io.cfIn.pc, GTimer())
// }
// }
XSDebug(io.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
XSDebug(raiseExceptionIntr && delegS, "Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
io.redirectValid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc)
// perfcnt
val perfCntList = Map(
"Mcycle" -> (0xb00, "perfCntCondMcycle" ),
"Minstret" -> (0xb02, "perfCntCondMinstret" ),
"MimemStall" -> (0xb03, "perfCntCondMimemStall" ),
"MaluInstr" -> (0xb04, "perfCntCondMaluInstr" ),
"MbruInstr" -> (0xb05, "perfCntCondMbruInstr" ),
"MlsuInstr" -> (0xb06, "perfCntCondMlsuInstr" ),
"MmduInstr" -> (0xb07, "perfCntCondMmduInstr" ),
"McsrInstr" -> (0xb08, "perfCntCondMcsrInstr" ),
"MloadInstr" -> (0xb09, "perfCntCondMloadInstr" ),
"MloadStall" -> (0xb0a, "perfCntCondMloadStall" ),
"MstoreStall" -> (0xb0b, "perfCntCondMstoreStall"),
"MmmioInstr" -> (0xb0c, "perfCntCondMmmioInstr" ),
"MicacheHit" -> (0xb0d, "perfCntCondMicacheHit" ),
"MdcacheHit" -> (0xb0e, "perfCntCondMdcacheHit" ),
"MmulInstr" -> (0xb0f, "perfCntCondMmulInstr" ),
"MifuFlush" -> (0xb10, "perfCntCondMifuFlush" ),
"MrawStall" -> (0xb11, "perfCntCondMrawStall" ),
"MexuBusy" -> (0xb12, "perfCntCondMexuBusy" ),
"MbpBRight" -> (0xb13, "MbpBRight" ),
"MbpBWrong" -> (0xb14, "MbpBWrong" ),
"MbpJRight" -> (0xb15, "MbpJRight" ),
"MbpJWrong" -> (0xb16, "MbpJWrong" ),
"MbpIRight" -> (0xb17, "MbpIRight" ),
"MbpIWrong" -> (0xb18, "MbpIWrong" ),
"MbpRRight" -> (0xb19, "MbpRRight" ),
"MbpRWrong" -> (0xb1a, "MbpRWrong" ),
"Custom1" -> (0xb1b, "Custom1" ),
"Custom2" -> (0xb1c, "Custom2" ),
"Custom3" -> (0xb1d, "Custom3" ),
"Custom4" -> (0xb1e, "Custom4" ),
"Custom5" -> (0xb1f, "Custom5" ),
"Custom6" -> (0xb20, "Custom6" ),
"Custom7" -> (0xb21, "Custom7" ),
"Custom8" -> (0xb22, "Custom8" ),
"Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
// "Mcycle" -> (0xb00, "perfCntCondMcycle" ),
// "Minstret" -> (0xb02, "perfCntCondMinstret" ),
"MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ),
"MbpRight" -> (0xb04, "perfCntCondMbpRight" ),
"MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ),
"MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ),
"MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ),
"MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ),
"MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ),
"MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ),
"MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ),
"MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ),
"MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" )
// "Custom1" -> (0xb1b, "Custom1" ),
// "Custom2" -> (0xb1c, "Custom2" ),
// "Custom3" -> (0xb1d, "Custom3" ),
// "Custom4" -> (0xb1e, "Custom4" ),
// "Custom5" -> (0xb1f, "Custom5" ),
// "Custom6" -> (0xb20, "Custom6" ),
// "Custom7" -> (0xb21, "Custom7" ),
// "Custom8" -> (0xb22, "Custom8" ),
// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
)
val perfCntCond = List.fill(0x80)(WireInit(false.B))
(perfCnts zip perfCntCond).map { case (c, e) => { when (e) { c := c + 1.U } } }
BoringUtils.addSource(WireInit(true.B), "perfCntCondMcycle")
perfCntList.map { case (name, (addr, boringId)) => {
BoringUtils.addSink(perfCntCond(addr & 0x7f), boringId)
if (!hasPerfCnt) {
// do not enable perfcnts except for Mcycle and Minstret
if (addr != perfCntList("Mcycle")._1 && addr != perfCntList("Minstret")._1) {
perfCntCond(addr & 0x7f) := false.B
(perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
perfCntList.foreach {
case (_, (address, boringId)) =>
if(hasPerfCnt){
ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
}
}
}}
// if (!hasPerfCnt) {
// // do not enable perfcnts except for Mcycle and Minstret
// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
// perfCntCond(address & 0x7f) := false.B
// }
// }
}
val nooptrap = WireInit(false.B)
BoringUtils.addSink(nooptrap, "nooptrap")
val xstrap = WireInit(false.B)
BoringUtils.addSink(xstrap, "XSTRAP")
def readWithScala(addr: Int): UInt = mapping(addr)._1
if (!p.FPGAPlatform) {
// display all perfcnt when nooptrap is executed
// when (nooptrap) {
// printf("======== PerfCnt =========\n")
// perfCntList.toSeq.sortBy(_._2._1).map { case (name, (addr, boringId)) =>
// printf("%d <- " + name + "\n", readWithScala(addr)) }
// }
when (xstrap) {
printf("======== PerfCnt =========\n")
perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
printf("%d <- " + str + "\n", readWithScala(address))
}
}
// for differential testing
BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode")
BoringUtils.addSource(RegNext(mstatus), "difftestMstatus")
BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus")
BoringUtils.addSource(RegNext(mepc), "difftestMepc")
BoringUtils.addSource(RegNext(sepc), "difftestSepc")
BoringUtils.addSource(RegNext(mcause), "difftestMcause")
BoringUtils.addSource(RegNext(scause), "difftestScause")
// BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode")
// BoringUtils.addSource(RegNext(mstatus), "difftestMstatus")
// BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus")
// BoringUtils.addSource(RegNext(mepc), "difftestMepc")
// BoringUtils.addSource(RegNext(sepc), "difftestSepc")
// BoringUtils.addSource(RegNext(mcause), "difftestMcause")
// BoringUtils.addSource(RegNext(scause), "difftestScause")
BoringUtils.addSource(priviledgeMode, "difftestMode")
BoringUtils.addSource(mstatus, "difftestMstatus")
BoringUtils.addSource(mstatus & sstatusRmask, "difftestSstatus")
BoringUtils.addSource(mepc, "difftestMepc")
BoringUtils.addSource(sepc, "difftestSepc")
BoringUtils.addSource(mcause, "difftestMcause")
BoringUtils.addSource(scause, "difftestScause")
} else {
// BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt")
}
......
......@@ -25,13 +25,14 @@ class Jump extends FunctionUnit(jmpCfg){
io.out.bits.redirect.target := target
io.out.bits.redirect.brTarget := target // DontCare
io.out.bits.redirect.brTag := uop.brTag
io.out.bits.redirect._type := LookupTree(func, RV32I_BRUInstr.bruFuncTobtbTypeTable)
io.out.bits.redirect.btbType := LookupTree(func, RV32I_BRUInstr.bruFuncTobtbTypeTable)
io.out.bits.redirect.isRVC := isRVC
io.out.bits.redirect.taken := true.B
io.out.bits.redirect.hist := uop.cf.hist
io.out.bits.redirect.tageMeta := uop.cf.tageMeta
io.out.bits.redirect.fetchIdx := uop.cf.fetchOffset >> 2.U //TODO: consider RVC
io.out.bits.redirect.fetchIdx := uop.cf.fetchOffset >> 1.U //TODO: consider RVC
io.out.bits.redirect.btbPredCtr := uop.cf.btbPredCtr
io.out.bits.redirect.btbHitWay := uop.cf.btbHitWay
io.out.bits.redirect.btbHit := uop.cf.btbHit
io.out.bits.redirect.rasSp := uop.cf.rasSp
io.out.bits.redirect.rasTopCtr := uop.cf.rasTopCtr
io.out.bits.redirect.isException := false.B
......
......@@ -48,7 +48,7 @@ trait HasPipelineReg { this: ArrayMultiplier =>
}
for(i <- 1 to latency){
when(flushVec(i) || rdyVec(i) && !validVec(i-1)){
when(flushVec(i-1) || rdyVec(i) && !validVec(i-1)){
validVec(i) := false.B
}.elsewhen(rdyVec(i-1) && validVec(i-1) && !flushVec(i-1)){
validVec(i) := validVec(i-1)
......
......@@ -99,7 +99,7 @@ class FreeList extends XSModule with HasFreeListConsts {
headPtr := Mux(io.redirect.valid, // mispredict or exception happen
Mux(io.redirect.bits.isException,
tailPtr,
FreeListPtr(!tailPtr.flag, tailPtr.value),
checkPoints(io.redirect.bits.brTag.value)
),
headPtrNext
......
......@@ -29,7 +29,7 @@ class Rename extends XSModule {
def printRenameInfo(in: DecoupledIO[CfCtrl], out: DecoupledIO[MicroOp]) = {
XSInfo(
debug_norm,
debug_norm && in.valid && in.ready,
p"pc:${Hexadecimal(in.bits.cf.pc)} in v:${in.valid} in rdy:${in.ready} " +
p"lsrc1:${in.bits.ctrl.lsrc1} -> psrc1:${out.bits.psrc1} " +
p"lsrc2:${in.bits.ctrl.lsrc2} -> psrc2:${out.bits.psrc2} " +
......
......@@ -14,19 +14,19 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
val roqIdxs = Output(Vec(RenameWidth, UInt(RoqIdxWidth.W)))
val redirect = Output(Valid(new Redirect))
val exception = Output(new MicroOp)
// exu + brq
val exeWbResults = Vec(exuParameters.ExuCnt + 1, Flipped(ValidIO(new ExuOutput)))
val commits = Vec(CommitWidth, Valid(new RoqCommit))
val scommit = Output(UInt(3.W))
val bcommit = Output(UInt(BrTagWidth.W))
})
val numWbPorts = io.exeWbResults.length
val microOp = Mem(RoqSize, new MicroOp)
// val brMask = Reg(Vec(RoqSize, UInt(BrqSize.W)))
val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
val writebacked = Reg(Vec(RoqSize, Bool()))
val redirect = Reg(Vec(RoqSize, new Redirect))
val exuData = Reg(Vec(RoqSize, UInt(XLEN.W)))//for debug
val exuDebug = Reg(Vec(RoqSize, new DebugBundle))//for debug
......@@ -48,7 +48,6 @@ class Roq(implicit val p: XSConfig) extends XSModule {
// Dispatch
val csrEnRoq = io.dp1Req.map(i => i.bits.ctrl.fuType === FuType.csr)
val hasCsr = RegInit(false.B)
XSError(!(hasCsr && state =/= s_idle), "CSR block should only happen in s_idle\n")
when(ringBufferEmpty){ hasCsr:= false.B }
val validDispatch = VecInit((0 until RenameWidth).map(io.dp1Req(_).valid)).asUInt
XSDebug("(ready, valid): ")
......@@ -80,6 +79,7 @@ class Roq(implicit val p: XSConfig) extends XSModule {
for(i <- 0 until numWbPorts){
when(io.exeWbResults(i).fire()){
writebacked(io.exeWbResults(i).bits.uop.roqIdx) := true.B
microOp(io.exeWbResults(i).bits.uop.roqIdx).cf.exceptionVec := io.exeWbResults(i).bits.uop.cf.exceptionVec
exuData(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.data
exuDebug(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.debug
XSInfo(io.exeWbResults(i).valid, "writebacked pc 0x%x wen %d data 0x%x ldst %d pdst %d skip %x\n",
......@@ -93,6 +93,21 @@ class Roq(implicit val p: XSConfig) extends XSModule {
}
}
// roq redirect only used for exception
val intrBitSet = WireInit(false.B)
ExcitingUtils.addSink(intrBitSet, "intrBitSetIDU")
val trapTarget = WireInit(0.U(VAddrBits.W))
ExcitingUtils.addSink(trapTarget, "trapTarget")
val intrEnable = intrBitSet && (state === s_idle) && !ringBufferEmpty && !hasCsr
val exceptionEnable = Cat(microOp(ringBufferTail).cf.exceptionVec).orR() && (state === s_idle) && !ringBufferEmpty
val isEcall = microOp(ringBufferTail).cf.exceptionVec(ecallM) || microOp(ringBufferTail).cf.exceptionVec(ecallS) || microOp(ringBufferTail).cf.exceptionVec(ecallU)
io.redirect := DontCare
io.redirect.valid := intrEnable || exceptionEnable
io.redirect.bits.isException := true.B
io.redirect.bits.target := trapTarget
io.exception := microOp(ringBufferTail)
XSDebug(io.redirect.valid, "generate exception: pc 0x%x target 0x%x exceptionVec %b\n", io.exception.cf.pc, trapTarget, Cat(microOp(ringBufferTail).cf.exceptionVec))
// Commit uop to Rename
val shouldWalkVec = Wire(Vec(CommitWidth, Bool()))
shouldWalkVec(0) := ringBufferWalkExtended =/= ringBufferWalkTarget
......@@ -108,20 +123,22 @@ class Roq(implicit val p: XSConfig) extends XSModule {
io.commits(i) := DontCare
switch(state){
is(s_idle){
val ringBufferIndex = ringBufferTail + i.U
val hasException = Cat(microOp(ringBufferIndex).cf.exceptionVec).orR() || intrEnable
val canCommit = if(i!=0) io.commits(i-1).valid else true.B
io.commits(i).valid := valid(ringBufferTail+i.U) && writebacked(ringBufferTail+i.U) && canCommit
io.commits(i).bits.uop := microOp(ringBufferTail+i.U)
when(io.commits(i).valid){valid(ringBufferTail+i.U) := false.B}
io.commits(i).valid := valid(ringBufferIndex) && writebacked(ringBufferIndex) && canCommit && !hasException
io.commits(i).bits.uop := microOp(ringBufferIndex)
when(io.commits(i).valid){valid(ringBufferIndex) := false.B}
XSInfo(io.commits(i).valid,
"retired pc %x wen %d ldst %d data %x\n",
microOp(ringBufferTail+i.U).cf.pc,
microOp(ringBufferTail+i.U).ctrl.rfWen,
microOp(ringBufferTail+i.U).ctrl.ldest,
exuData(ringBufferTail+i.U)
microOp(ringBufferIndex).cf.pc,
microOp(ringBufferIndex).ctrl.rfWen,
microOp(ringBufferIndex).ctrl.ldest,
exuData(ringBufferIndex)
)
XSInfo(io.commits(i).valid && exuDebug(ringBufferTail+i.U).isMMIO,
XSInfo(io.commits(i).valid && exuDebug(ringBufferIndex).isMMIO,
"difftest skiped pc0x%x\n",
microOp(ringBufferTail+i.U).cf.pc
microOp(ringBufferIndex).cf.pc
)
}
......@@ -169,13 +186,21 @@ class Roq(implicit val p: XSConfig) extends XSModule {
ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
}
val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
// commit store to lsu
val validScommit = WireInit(VecInit((0 until CommitWidth).map(i => state === s_idle && io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.fuType === FuType.stu && microOp(ringBufferTail+i.U).ctrl.fuOpType(3)))) //FIXIT
io.scommit := PopCount(validScommit.asUInt)
val validBcommit = WireInit(VecInit(
(0 until CommitWidth).map(
i => state === s_idle &&
io.commits(i).valid &&
microOp(ringBufferTail+i.U).cf.isBr
)
))
io.bcommit := PopCount(validBcommit)
// when redirect, walk back roq entries
when(io.brqRedirect.valid){
state := s_walk
......@@ -192,9 +217,14 @@ class Roq(implicit val p: XSConfig) extends XSModule {
XSDebug("roq full, switched to s_extrawalk. needExtraSpaceForMPR: %b\n", needExtraSpaceForMPR.asUInt)
}
// roq redirect only used for exception
io.redirect := DontCare //TODO
io.redirect.valid := false.B //TODO
// when exception occurs, cancels all
when (io.redirect.valid) {
ringBufferHeadExtended := 0.U
ringBufferTailExtended := 0.U
for (i <- 0 until RoqSize) {
valid(i) := false.B
}
}
// debug info
XSDebug("head %d:%d tail %d:%d\n", ringBufferHeadExtended(InnerRoqIdxWidth), ringBufferHead, ringBufferTailExtended(InnerRoqIdxWidth), ringBufferTail)
......@@ -242,18 +272,23 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
val trapPC = PriorityMux(wpc.zip(trapVec).map(x => x._2 ->x._1))
val difftestIntrNO = WireInit(0.U(XLEN.W))
ExcitingUtils.addSink(difftestIntrNO, "difftestIntrNOfromCSR")
XSDebug(difftestIntrNO =/= 0.U, "difftest intrNO set %x\n", difftestIntrNO)
val retireCounterFix = Mux(io.redirect.valid, 1.U, retireCounter)
val retirePCFix = Mux(io.redirect.valid, microOp(ringBufferTail).cf.pc, microOp(firstValidCommit).cf.pc)
val retireInstFix = Mux(io.redirect.valid, microOp(ringBufferTail).cf.instr, microOp(firstValidCommit).cf.instr)
if(!p.FPGAPlatform){
BoringUtils.addSource(RegNext(retireCounter), "difftestCommit")
BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.pc), "difftestThisPC")//first valid PC
BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.instr), "difftestThisINST")//first valid inst
BoringUtils.addSource(RegNext(retireCounterFix), "difftestCommit")
BoringUtils.addSource(RegNext(retirePCFix), "difftestThisPC")//first valid PC
BoringUtils.addSource(RegNext(retireInstFix), "difftestThisINST")//first valid inst
BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
BoringUtils.addSource(RegNext(wpc), "difftestWpc")
BoringUtils.addSource(RegNext(wdata), "difftestWdata")
BoringUtils.addSource(RegNext(wdst), "difftestWdst")
BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
//TODO: skip insts that commited in the same cycle ahead of exception
BoringUtils.addSource(RegNext(difftestIntrNO), "difftestIntrNO")
class Monitor extends BlackBox {
val io = IO(new Bundle {
......@@ -276,9 +311,8 @@ class Roq(implicit val p: XSConfig) extends XSModule {
debugMonitor.io.cycleCnt := GTimer()
debugMonitor.io.instrCnt := instrCnt
// BPU temp Perf Cnt
if(EnableBPU){
BoringUtils.addSource(hitTrap, "XSTRAP_BPU")
BoringUtils.addSource(hitTrap, "XSTRAP")
}
}
}
......@@ -34,11 +34,14 @@ class TempPreDecoder extends XSModule {
for (i <- 0 until FetchWidth) {
tempPreDecoders(i).io.in <> DontCare
tempPreDecoders(i).io.in.instr <> io.in(i)
io.out.fuTypes(i) := tempPreDecoders(i).io.out.ctrl.fuType
io.out.fuOpTypes(i) := tempPreDecoders(i).io.out.ctrl.fuOpType
io.out.fuTypes(2*i) := tempPreDecoders(i).io.out.ctrl.fuType
io.out.fuTypes(2*i+1) := tempPreDecoders(i).io.out.ctrl.fuType
io.out.fuOpTypes(2*i) := tempPreDecoders(i).io.out.ctrl.fuOpType
io.out.fuOpTypes(2*i+1) := tempPreDecoders(i).io.out.ctrl.fuOpType
}
io.out.mask := DontCare
io.out.isRVC := DontCare
}
......
......@@ -27,7 +27,7 @@ class FakeBPU extends XSModule{
val redirectInfo = Input(new RedirectInfo)
val in = new Bundle { val pc = Flipped(Valid(UInt(VAddrBits.W))) }
val btbOut = ValidIO(new BranchPrediction)
val tageOut = ValidIO(new BranchPrediction)
val tageOut = Decoupled(new BranchPrediction)
val predecode = Flipped(ValidIO(new Predecode))
})
......@@ -54,26 +54,20 @@ class IFU extends XSModule with HasIFUConst
val if1_pc = RegInit(resetVector.U(VAddrBits.W))
//next
val if2_ready = WireInit(false.B)
val if2_snpc = snpc(if1_pc) //TODO: this is ugly
val if2_snpc = snpc(if1_pc) //TODO: calculate snpc according to mask of current fetch packet
val needflush = WireInit(false.B)
// when an RVI instruction is predicted as taken and it crosses over two fetch packets,
// IFU should not take this branch but fetch the latter half of the instruction sequentially,
// and take the jump target in the next fetch cycle
val if2_lateJumpLatch = WireInit(false.B)
val if2_lateJumpTarget = RegInit(0.U(VAddrBits.W))
val if4_lateJumpLatch = WireInit(false.B)
val if4_lateJumpTarget = RegInit(0.U(VAddrBits.W))
//pipe fire
val if1_fire = if1_valid && if2_ready
val if1_fire = if1_valid && if2_ready || needflush
val if1_pcUpdate = if1_fire || needflush
when(RegNext(reset.asBool) && !reset.asBool){
//when((GTimer() === 501.U)){ //TODO:this is ugly
XSDebug("RESET....\n")
if1_npc := resetVector.U(VAddrBits.W)
} .otherwise{
if1_npc := if2_snpc
}
when(if1_pcUpdate)
{
if1_pc := if1_npc
}
bpu.io.in.pc.valid := if1_fire
bpu.io.in.pc.bits := if1_npc
bpu.io.redirectInfo := io.redirectInfo
......@@ -90,8 +84,15 @@ class IFU extends XSModule with HasIFUConst
val if2_valid = RegEnable(next=if1_valid,init=false.B,enable=if1_fire)
val if2_pc = if1_pc
val if2_btb_taken = bpu.io.btbOut.valid && bpu.io.btbOut.bits.redirect
val if2_btb_insMask = bpu.io.btbOut.bits.instrValid
val if2_btb_target = bpu.io.btbOut.bits.target
val if2_btb_lateJump = WireInit(false.B)
val if2_btb_insMask = Mux(if2_btb_taken, bpu.io.btbOut.bits.instrValid.asUInt, Fill(FetchWidth*2, 1.U(1.W))) // TODO: FIX THIS
val if2_btb_target = Mux(if2_btb_lateJump, if2_snpc, bpu.io.btbOut.bits.target)
if2_lateJumpLatch := BoolStopWatch(if2_btb_lateJump, if1_fire, startHighPriority = true)
// since late jump target should be taken after the latter half of late jump instr is fetched, we need to latch this target
when (if2_btb_lateJump) {
if2_lateJumpTarget := bpu.io.btbOut.bits.target
}
//next
val if3_ready = WireInit(false.B)
......@@ -103,11 +104,29 @@ class IFU extends XSModule with HasIFUConst
io.icacheReq.valid := if2_valid
io.icacheReq.bits.addr := if2_pc
when(if2_valid && if2_btb_taken)
when(RegNext(reset.asBool) && !reset.asBool){
//when((GTimer() === 501.U)){ //TODO:this is ugly
XSDebug("RESET....\n")
if1_npc := resetVector.U(VAddrBits.W)
}.elsewhen (if2_fire) {
if1_npc := Mux(if4_lateJumpLatch, if4_lateJumpTarget, Mux(if2_lateJumpLatch, if2_lateJumpTarget, if2_snpc))
}.otherwise {
if1_npc := if1_pc
}
when(if1_pcUpdate)
{
if1_pc := if1_npc
}
// when if2 fire and if2 redirects, update npc
when(if2_fire && if2_btb_taken)
{
if1_npc := if2_btb_target
}
bpu.io.in.pc.valid := if1_fire && !if2_btb_lateJump
XSDebug("[IF2]if2_valid:%d || if2_pc:0x%x || if3_ready:%d ",if2_valid,if2_pc,if3_ready)
XSDebug(false,if2_fire,"------IF2->fire!!!")
XSDebug(false,true.B,"\n")
......@@ -119,10 +138,11 @@ class IFU extends XSModule with HasIFUConst
//local
val if3_valid = RegEnable(next=if2_valid,init=false.B,enable=if2_fire)
val if3_pc = RegEnable(if2_pc,if2_fire)
val if3_npc = RegEnable(if1_npc,if2_fire)
val if3_btb_target = RegEnable(if2_btb_target,if2_fire)
val if3_btb_taken = RegEnable(if2_btb_taken,if2_fire)
val if3_btb_insMask = RegEnable(if2_btb_insMask, if2_fire)
val if3_npc = RegEnable(if1_npc, if2_fire)
val if3_btb_target = RegEnable(Mux(if2_lateJumpLatch, if2_lateJumpTarget, Mux(if2_btb_lateJump, bpu.io.btbOut.bits.target, if2_btb_target)), if2_fire)
val if3_btb_taken = RegEnable(Mux(if2_lateJumpLatch, true.B, if2_btb_taken), if2_fire)
val if3_btb_insMask = RegEnable(Mux(if2_lateJumpLatch, 1.U((FetchWidth*2).W), if2_btb_insMask), if2_fire)
val if3_btb_lateJump = RegEnable(if2_btb_lateJump, if2_fire)
//next
val if4_ready = WireInit(false.B)
......@@ -133,6 +153,8 @@ class IFU extends XSModule with HasIFUConst
XSDebug("[IF3]if3_valid:%d || if3_pc:0x%x if3_npc:0x%x || if4_ready:%d ",if3_valid,if3_pc,if3_npc,if4_ready)
XSDebug("[IF3]if3_btb_taken:%d if3_btb_insMask:%b if3_btb_lateJump:%d if3_btb_target:0x%x\n",
if3_btb_taken, if3_btb_insMask, if3_btb_lateJump, if3_btb_target)
XSDebug(false,if3_fire,"------IF3->fire!!!")
XSDebug(false,true.B,"\n")
......@@ -147,27 +169,31 @@ class IFU extends XSModule with HasIFUConst
val if4_btb_target = RegEnable(if3_btb_target,if3_fire)
val if4_btb_taken = RegEnable(if3_btb_taken,if3_fire)
val if4_btb_insMask = RegEnable(if3_btb_insMask, if3_fire)
val if4_tage_target = bpu.io.tageOut.bits.target
val if4_btb_lateJump = RegEnable(if3_btb_lateJump, if3_fire)
val if4_tage_taken = bpu.io.tageOut.valid && bpu.io.tageOut.bits.redirect
val if4_tage_lateJump = if4_tage_taken && bpu.io.tageOut.bits.lateJump && !io.redirectInfo.flush()
val if4_tage_insMask = bpu.io.tageOut.bits.instrValid
val if4_btb_missPre = WireInit(false.B)
val if4_snpc = if4_pc + (PopCount(if4_tage_insMask) << 1.U)
val if4_tage_target = Mux(if4_tage_lateJump, if4_snpc, bpu.io.tageOut.bits.target)
if2_btb_lateJump := if2_btb_taken && bpu.io.btbOut.bits.lateJump && !io.redirectInfo.flush() && !if4_tage_taken
if4_lateJumpLatch := BoolStopWatch(if4_tage_lateJump, if1_fire, startHighPriority = true)
when (if4_tage_lateJump) {
if4_lateJumpTarget := bpu.io.tageOut.bits.target
}
bpu.io.in.pc.valid := if1_fire && !if2_btb_lateJump && !if4_tage_lateJump
XSDebug("[IF4]if4_valid:%d || if4_pc:0x%x if4_npc:0x%x\n",if4_valid,if4_pc,if4_npc)
XSDebug("[IF4-TAGE-out]if4_tage_taken:%d || if4_btb_insMask:%b || if4_tage_target:0x%x \n",if4_tage_taken,if4_tage_insMask.asUInt,if4_tage_target)
XSDebug("[IF4] if4_btb_taken:%d if4_btb_lateJump:%d if4_btb_insMask:%b if4_btb_target:0x%x\n",if4_btb_taken, if4_btb_lateJump, if4_btb_insMask.asUInt, if4_btb_target)
XSDebug("[IF4-TAGE-out]if4_tage_taken:%d if4_tage_lateJump:%d if4_tage_insMask:%b if4_tage_target:0x%x\n",if4_tage_taken,if4_tage_lateJump,if4_tage_insMask.asUInt,if4_tage_target)
XSDebug("[IF4-ICACHE-RESP]icacheResp.valid:%d icacheResp.ready:%d\n",io.icacheResp.valid,io.icacheResp.ready)
when(io.icacheResp.fire() && if4_tage_taken &&if4_valid)
{
if1_npc := if4_tage_target
}
//redirect: tage result differ btb
if4_btb_missPre := (if4_tage_taken ^ if4_btb_taken) || (if4_tage_taken && if4_btb_taken && (if4_tage_target =/= if4_btb_target))
if(EnableBPD){
when(!if4_tage_taken && if4_btb_taken && if4_valid){
if1_npc := if4_pc + (PopCount(io.fetchPacket.bits.mask) >> 2.U)
}
}
//redirect: miss predict
when(io.redirectInfo.flush()){
......@@ -177,8 +203,9 @@ class IFU extends XSModule with HasIFUConst
//flush pipline
if(EnableBPD){needflush := (if4_valid && if4_btb_missPre) || io.redirectInfo.flush() }
else {needflush := io.redirectInfo.flush()}
// if(EnableBPD){needflush := (if4_valid && if4_tage_taken) || io.redirectInfo.flush() }
// else {needflush := io.redirectInfo.flush()}
needflush := (if4_valid && if4_tage_taken && io.icacheResp.fire()) || io.redirectInfo.flush()
when(needflush){
if3_valid := false.B
if4_valid := false.B
......@@ -191,43 +218,61 @@ class IFU extends XSModule with HasIFUConst
if4_ready := io.fetchPacket.ready && (io.icacheResp.valid || !if4_valid) && (GTimer() > 500.U)
io.fetchPacket.valid := if4_valid && !io.redirectInfo.flush()
io.fetchPacket.bits.instrs := io.icacheResp.bits.icacheOut
/*
if(EnableBPU){
io.fetchPacket.bits.mask := Mux(if4_tage_taken,(Fill(FetchWidth*2, 1.U(1.W)) & Reverse(Cat(if4_tage_insMask.map(i => Fill(2, i.asUInt))).asUInt)),
Mux(if4_btb_taken, Fill(FetchWidth*2, 1.U(1.W)) & Reverse(Cat(if4_btb_insMask.map(i => Fill(2, i.asUInt))).asUInt),
Fill(FetchWidth*2, 1.U(1.W)))
io.fetchPacket.bits.mask := Mux(if4_tage_taken, Fill(FetchWidth*2, 1.U(1.W)) & if4_tage_insMask.asUInt,
Mux(if4_btb_taken, Fill(FetchWidth*2, 1.U(1.W)) & if4_btb_insMask.asUInt,
Fill(FetchWidth*2, 1.U(1.W)))
)
}
else{
io.fetchPacket.bits.mask := Fill(FetchWidth*2, 1.U(1.W)) //TODO : consider cross cacheline fetch
}
}
*/
io.fetchPacket.bits.mask := Mux(if4_lateJumpLatch, 1.U((FetchWidth*2).W),
Mux(if4_tage_taken, Fill(FetchWidth*2, 1.U(1.W)) & if4_tage_insMask.asUInt,
Fill(FetchWidth*2, 1.U(1.W)) & if4_btb_insMask.asUInt))
io.fetchPacket.bits.pc := if4_pc
XSDebug(io.fetchPacket.fire,"[IFU-Out-FetchPacket] starPC:0x%x GroupPC:0x%xn\n",if4_pc.asUInt,groupPC(if4_pc).asUInt)
XSDebug(io.fetchPacket.fire,"[IFU-Out-FetchPacket] instrmask %b\n",io.fetchPacket.bits.mask.asUInt)
for(i <- 0 until FetchWidth){
//io.fetchPacket.bits.pnpc(i) := if1_npc
when (if4_btb_taken && !if4_tage_taken && i.U === OHToUInt(HighestBit(if4_btb_insMask.asUInt, FetchWidth))) {
if(EnableBPD){io.fetchPacket.bits.pnpc(i) := if4_pc + ((i + 1).U << 2.U) } //tage not taken use snpc
else{io.fetchPacket.bits.pnpc(i) := if4_btb_target}//use fetch PC
}.elsewhen (if4_tage_taken && i.U === OHToUInt(HighestBit(if4_tage_insMask.asUInt, FetchWidth))) {
io.fetchPacket.bits.pnpc(i) := if1_npc
for(i <- 0 until (FetchWidth*2)) {
when (if4_btb_taken && !if4_tage_taken && i.U === OHToUInt(HighestBit(if4_btb_insMask.asUInt, FetchWidth*2))) {
io.fetchPacket.bits.pnpc(i) := if4_btb_target
if (i != 0) {
when (!io.icacheResp.bits.predecode.isRVC(i) && !if4_btb_lateJump) {
io.fetchPacket.bits.pnpc(i-1) := if4_btb_target
}
}
}.elsewhen (if4_tage_taken && i.U === OHToUInt(HighestBit(if4_tage_insMask.asUInt, FetchWidth*2))) {
io.fetchPacket.bits.pnpc(i) := Mux(if4_tage_lateJump, bpu.io.tageOut.bits.target, if4_tage_target)
if (i != 0) {
when (!io.icacheResp.bits.predecode.isRVC(i) && !if4_tage_lateJump) {
io.fetchPacket.bits.pnpc(i-1) := if4_tage_target
}
}
}.otherwise {
io.fetchPacket.bits.pnpc(i) := if4_pc + ((i + 1).U << 2.U) //use fetch PC
io.fetchPacket.bits.pnpc(i) := if4_pc + (i.U << 1.U) + Mux(io.icacheResp.bits.predecode.isRVC(i), 2.U, 4.U)
}
XSDebug(io.fetchPacket.fire,"[IFU-Out-FetchPacket] instruction %x pnpc:0x%x\n",io.fetchPacket.bits.instrs(i).asUInt,io.fetchPacket.bits.pnpc(i).asUInt)
}
XSDebug(io.fetchPacket.fire,"[IFU-Out-FetchPacket] instruction %x pnpc:0x%x\n",
Mux((i.U)(0), io.fetchPacket.bits.instrs(i>>1)(31,16), io.fetchPacket.bits.instrs(i>>1)(15,0)),
io.fetchPacket.bits.pnpc(i))
}
io.fetchPacket.bits.hist := bpu.io.tageOut.bits.hist
// io.fetchPacket.bits.btbVictimWay := bpu.io.tageOut.bits.btbVictimWay
io.fetchPacket.bits.predCtr := bpu.io.tageOut.bits.predCtr
io.fetchPacket.bits.btbHitWay := bpu.io.tageOut.bits.btbHitWay
io.fetchPacket.bits.btbHit := bpu.io.tageOut.bits.btbHit
io.fetchPacket.bits.tageMeta := bpu.io.tageOut.bits.tageMeta
io.fetchPacket.bits.rasSp := bpu.io.tageOut.bits.rasSp
io.fetchPacket.bits.rasTopCtr := bpu.io.tageOut.bits.rasTopCtr
bpu.io.tageOut.ready := io.fetchPacket.ready
//to BPU
bpu.io.predecode.valid := io.icacheResp.fire() && if4_valid
bpu.io.predecode.bits <> io.icacheResp.bits.predecode
bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) //TODO: consider RVC && consider cross cacheline fetch
//TODO: consider RVC && consider cross cacheline fetch
bpu.io.predecode.bits.mask := Fill(FetchWidth*2, 1.U(1.W))
bpu.io.predecode.bits.isRVC := 0.U.asTypeOf(Vec(FetchWidth*2, Bool()))
bpu.io.redirectInfo := io.redirectInfo
io.icacheResp.ready := io.fetchPacket.ready && (GTimer() > 500.U)
......
......@@ -13,6 +13,19 @@ class Ibuffer extends XSModule {
val out = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
})
class IBufEntry extends XSBundle {
val inst = UInt(16.W)
val pc = UInt(VAddrBits.W)
val pnpc = UInt(VAddrBits.W)
val fetchOffset = UInt((log2Up(FetchWidth * 4)).W)
val hist = UInt(HistoryLength.W)
val btbPredCtr = UInt(2.W)
val btbHit = Bool()
val tageMeta = new TageMeta
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
}
// ignore
for(i <- 0 until DecodeWidth) {
io.out(i).bits.exceptionVec := DontCare
......@@ -26,17 +39,7 @@ class Ibuffer extends XSModule {
// (0 until 16).map(i => mask(i.U) := (io.in.bits.pc(4,1) <= i.U))
// ibuf define
val ibuf = Reg(Vec(IBufSize*2, UInt(16.W)))
val ibuf_pc = Reg(Vec(IBufSize*2, UInt(VAddrBits.W)))
val ibuf_pnpc = Reg(Vec(IBufSize*2, UInt(VAddrBits.W)))
val ibuf_fetchOffset = Reg(Vec(IBufSize*2, UInt(log2Up(FetchWidth*4).W)))
val ibuf_hist = Reg(Vec(IBufSize*2, UInt(HistoryLength.W)))
// val ibuf_btbVictimWay = Reg(Vec(IBufSize*2, UInt(log2Up(BtbWays).W)))
val ibuf_btbPredCtr = Reg(Vec(IBufSize*2, UInt(2.W)))
val ibuf_btbHitWay = Reg(Vec(IBufSize*2, Bool()))
val ibuf_tageMeta = Reg(Vec(IBufSize*2, (new TageMeta)))
val ibuf_rasSp = Reg(Vec(IBufSize*2, UInt(log2Up(RasSize).W)))
val ibuf_rasTopCtr = Reg(Vec(IBufSize*2, UInt(8.W)))
val ibuf = Mem(IBufSize*2, new IBufEntry)
val ibuf_valid = RegInit(VecInit(Seq.fill(IBufSize*2)(false.B)))
val head_ptr = RegInit(0.U(log2Up(IBufSize*2).W))
val tail_ptr = RegInit(0.U(log2Up(IBufSize*2).W))
......@@ -53,66 +56,71 @@ class Ibuffer extends XSModule {
// enque
when(enqValid) {
var enq_idx = 0.U(log2Up(FetchWidth*2+1).W)
var enq_idx = WireInit(tail_ptr)
for(i <- 0 until FetchWidth*2) {
when(io.in.bits.mask(i)) {
ibuf(tail_ptr + enq_idx) := Mux(i.U(0), io.in.bits.instrs(i>>1)(31,16), io.in.bits.instrs(i>>1)(15,0))
ibuf_pc(tail_ptr + enq_idx) := io.in.bits.pc + (enq_idx<<1).asUInt
ibuf_pnpc(tail_ptr + enq_idx) := io.in.bits.pnpc(i>>1)
ibuf_fetchOffset(tail_ptr + enq_idx) := (enq_idx << 1).asUInt
ibuf_hist(tail_ptr + enq_idx) := io.in.bits.hist(i>>1)
// ibuf_btbVictimWay(tail_ptr + enq_idx) := io.in.bits.btbVictimWay
ibuf_btbPredCtr(tail_ptr + enq_idx) := io.in.bits.predCtr(i>>1)
ibuf_btbHitWay(tail_ptr + enq_idx) := io.in.bits.btbHitWay
ibuf_tageMeta(tail_ptr + enq_idx) := io.in.bits.tageMeta(i>>1)
ibuf_rasSp(tail_ptr + enq_idx) := io.in.bits.rasSp
ibuf_rasTopCtr(tail_ptr + enq_idx) := io.in.bits.rasTopCtr
ibuf_valid(tail_ptr + enq_idx) := true.B
ibuf(enq_idx).inst := Mux(i.U(0), io.in.bits.instrs(i>>1)(31,16), io.in.bits.instrs(i>>1)(15,0))
ibuf(enq_idx).pc := io.in.bits.pc + ((enq_idx - tail_ptr)<<1).asUInt
ibuf(enq_idx).pnpc := io.in.bits.pnpc(i)
ibuf(enq_idx).fetchOffset := ((enq_idx - tail_ptr) << 1).asUInt
ibuf(enq_idx).hist := io.in.bits.hist(i)
// ibuf(enq_idx).btbVictimWay := io.in.bits.btbVictimWay
ibuf(enq_idx).btbPredCtr := io.in.bits.predCtr(i)
ibuf(enq_idx).btbHit := io.in.bits.btbHit(i)
ibuf(enq_idx).tageMeta := io.in.bits.tageMeta(i)
ibuf(enq_idx).rasSp := io.in.bits.rasSp
ibuf(enq_idx).rasTopCtr := io.in.bits.rasTopCtr
ibuf_valid(enq_idx) := true.B
XSDebug("Enq: i:%d idx:%d mask:%b instr:%x pc:%x fetchOffset=%d\n",
i.U, enq_idx, io.in.bits.mask(i), Mux(i.U(0), io.in.bits.instrs(i>>1)(31,16), io.in.bits.instrs(i>>1)(15,0)), io.in.bits.pc + ((enq_idx - tail_ptr)<<1).asUInt, ((enq_idx - tail_ptr) << 1).asUInt)
}
// XSDebug(!(i.U)(0), "Enq: i:%d Idx:%d mask:%b instr:%x pc:%x pnpc:%x\n",
// (i/2).U, enq_idx, io.in.bits.mask(i), io.in.bits.instrs(i/2), io.in.bits.pc + ((enq_idx - tail_ptr)<<1).asUInt, io.in.bits.pnpc(i/2))
enq_idx = enq_idx + io.in.bits.mask(i)
}
tail_ptr := tail_ptr + enq_idx
tail_ptr := enq_idx
last_enq := true.B
}
// deque
when(deqValid) {
var deq_idx = 0.U(log2Up(DecodeWidth*2+1).W)
var deq_idx = WireInit(head_ptr)
for(i <- 0 until DecodeWidth) {
io.out(i).valid := ibuf_valid(head_ptr + deq_idx) // FIXME: need fix me when support RVC
when(ibuf_valid(head_ptr + deq_idx)) {
when(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) {
io.out(i).valid := ibuf_valid(deq_idx) // FIXME: need fix me when support RVC
when(ibuf_valid(deq_idx)) {
when(ibuf(deq_idx).inst(1,0) =/= "b11".U) {
// is RVC
io.out(i).bits.instr := Cat(0.U(16.W), ibuf(head_ptr + deq_idx))
io.out(i).bits.pc := ibuf_pc(head_ptr + deq_idx)
io.out(i).bits.pnpc := ibuf_pnpc(head_ptr + deq_idx)
io.out(i).bits.fetchOffset := ibuf_fetchOffset(head_ptr + deq_idx)
io.out(i).bits.hist := ibuf_hist(head_ptr + deq_idx)
// io.out(i).bits.btbVictimWay := ibuf_btbVictimWay(head_ptr + deq_idx)
io.out(i).bits.btbPredCtr := ibuf_btbPredCtr(head_ptr + deq_idx)
io.out(i).bits.btbHitWay := ibuf_btbHitWay(head_ptr + deq_idx)
io.out(i).bits.tageMeta := ibuf_tageMeta(head_ptr + deq_idx)
io.out(i).bits.rasSp := ibuf_rasSp(head_ptr + deq_idx)
io.out(i).bits.rasTopCtr := ibuf_rasTopCtr(head_ptr + deq_idx)
io.out(i).bits.instr := Cat(0.U(16.W), ibuf(deq_idx).inst)
io.out(i).bits.pc := ibuf(deq_idx).pc
io.out(i).bits.pnpc := ibuf(deq_idx).pnpc
io.out(i).bits.fetchOffset := ibuf(deq_idx).fetchOffset
io.out(i).bits.hist := ibuf(deq_idx).hist
// io.out(i).bits.btbVictimWay := ibuf(deq_idx).btbVictimWay
io.out(i).bits.btbPredCtr := ibuf(deq_idx).btbPredCtr
io.out(i).bits.btbHit := ibuf(deq_idx).btbHit
io.out(i).bits.tageMeta := ibuf(deq_idx).tageMeta
io.out(i).bits.rasSp := ibuf(deq_idx).rasSp
io.out(i).bits.rasTopCtr := ibuf(deq_idx).rasTopCtr
io.out(i).bits.isRVC := true.B
ibuf_valid(head_ptr + deq_idx) := !io.out(i).fire
}.elsewhen(ibuf_valid(head_ptr + deq_idx + 1.U)) {
ibuf_valid(deq_idx) := !io.out(i).fire
}.elsewhen(ibuf_valid(deq_idx + 1.U)) {
// isn't RVC
io.out(i).bits.instr := Cat(ibuf(head_ptr + deq_idx+1.U), ibuf(head_ptr + deq_idx))
io.out(i).bits.pc := ibuf_pc(head_ptr + deq_idx)
io.out(i).bits.pnpc := ibuf_pnpc(head_ptr + deq_idx)
io.out(i).bits.fetchOffset := ibuf_fetchOffset(head_ptr + deq_idx)
io.out(i).bits.hist := ibuf_hist(head_ptr + deq_idx)
// io.out(i).bits.btbVictimWay := ibuf_btbVictimWay(head_ptr + deq_idx)
io.out(i).bits.btbPredCtr := ibuf_btbPredCtr(head_ptr + deq_idx)
io.out(i).bits.btbHitWay := ibuf_btbHitWay(head_ptr + deq_idx)
io.out(i).bits.tageMeta := ibuf_tageMeta(head_ptr + deq_idx)
io.out(i).bits.rasSp := ibuf_rasSp(head_ptr + deq_idx)
io.out(i).bits.rasTopCtr := ibuf_rasTopCtr(head_ptr + deq_idx)
io.out(i).bits.instr := Cat(ibuf(deq_idx+1.U).inst, ibuf(deq_idx).inst)
io.out(i).bits.pc := ibuf(deq_idx).pc
io.out(i).bits.pnpc := ibuf(deq_idx).pnpc
io.out(i).bits.fetchOffset := ibuf(deq_idx).fetchOffset
io.out(i).bits.hist := ibuf(deq_idx).hist
// io.out(i).bits.btbVictimWay := ibuf(deq_idx).btbVictimWay
io.out(i).bits.btbPredCtr := ibuf(deq_idx).btbPredCtr
io.out(i).bits.btbHit := ibuf(deq_idx).btbHit
io.out(i).bits.tageMeta := ibuf(deq_idx).tageMeta
io.out(i).bits.rasSp := ibuf(deq_idx).rasSp
io.out(i).bits.rasTopCtr := ibuf(deq_idx).rasTopCtr
io.out(i).bits.isRVC := false.B
ibuf_valid(head_ptr + deq_idx) := !io.out(i).fire
ibuf_valid(head_ptr + deq_idx+1.U) := !io.out(i).fire
ibuf_valid(deq_idx) := !io.out(i).fire
ibuf_valid(deq_idx+1.U) := !io.out(i).fire
}.otherwise {
// half inst keep in buffer
io.out(i).bits.instr := 0.U(32.W)
......@@ -122,7 +130,7 @@ class Ibuffer extends XSModule {
io.out(i).bits.hist := 0.U(HistoryLength.W)
// io.out(i).bits.btbVictimWay := 0.U(log2Up(BtbWays).W)
io.out(i).bits.btbPredCtr := 0.U(2.W)
io.out(i).bits.btbHitWay := false.B
io.out(i).bits.btbHit := false.B
io.out(i).bits.tageMeta := 0.U.asTypeOf(new TageMeta)
io.out(i).bits.rasSp := 0.U(log2Up(RasSize))
io.out(i).bits.rasTopCtr := 0.U(8.W)
......@@ -130,31 +138,32 @@ class Ibuffer extends XSModule {
io.out(i).valid := false.B
}
}.otherwise {
io.out(i).bits.instr := Cat(ibuf(head_ptr + (i<<1).U + 1.U), ibuf(head_ptr + (i<<1).U))
io.out(i).bits.pc := ibuf_pc(head_ptr + (i<<1).U)
io.out(i).bits.pnpc := ibuf_pnpc(head_ptr + (i<<1).U)
io.out(i).bits.fetchOffset := ibuf_fetchOffset(head_ptr + (i<<1).U)
io.out(i).bits.hist := ibuf_hist(head_ptr + (i<<1).U)
// io.out(i).bits.btbVictimWay := ibuf_btbVictimWay(head_ptr + (i<<1).U)
io.out(i).bits.btbPredCtr := ibuf_btbPredCtr(head_ptr + (i<<1).U)
io.out(i).bits.btbHitWay := ibuf_btbHitWay(head_ptr + (i<<1).U)
io.out(i).bits.tageMeta := ibuf_tageMeta(head_ptr + (i<<1).U)
io.out(i).bits.rasSp := ibuf_rasSp(head_ptr + (i<<1).U)
io.out(i).bits.rasTopCtr := ibuf_rasTopCtr(head_ptr + (i<<1).U)
io.out(i).bits.instr := Cat(ibuf(head_ptr + (i<<1).U + 1.U).inst, ibuf(head_ptr + (i<<1).U).inst)
io.out(i).bits.pc := ibuf(head_ptr + (i<<1).U).pc
io.out(i).bits.pnpc := ibuf(head_ptr + (i<<1).U).pnpc
io.out(i).bits.fetchOffset := ibuf(head_ptr + (i<<1).U).fetchOffset
io.out(i).bits.hist := ibuf(head_ptr + (i<<1).U).hist
// io.out(i).bits.btbVictimWay := ibuf(head_ptr + (i<<1).U).btbVictimWay
io.out(i).bits.btbPredCtr := ibuf(head_ptr + (i<<1).U).btbPredCtr
io.out(i).bits.btbHit := ibuf(head_ptr + (i<<1).U).btbHit
io.out(i).bits.tageMeta := ibuf(head_ptr + (i<<1).U).tageMeta
io.out(i).bits.rasSp := ibuf(head_ptr + (i<<1).U).rasSp
io.out(i).bits.rasTopCtr := ibuf(head_ptr + (i<<1).U).rasTopCtr
io.out(i).bits.isRVC := false.B
}
XSDebug(deqValid, p"Deq: i:${i.U} valid:${ibuf_valid(deq_idx)} idx=${Decimal(deq_idx)} ${Decimal(deq_idx + 1.U)} instr:${Hexadecimal(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)} v=${io.out(i).valid} r=${io.out(i).ready}\n")
// When can't deque, deq_idx+0
// when RVC deque, deq_idx+1
// when not RVC deque, deq_idx+2
// when only have half inst, keep it in buffer
deq_idx = deq_idx + PriorityMux(Seq(
!(io.out(i).ready && ibuf_valid(head_ptr + deq_idx)) -> 0.U,
(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) -> 1.U,
ibuf_valid(head_ptr + deq_idx + 1.U) -> 2.U
!(io.out(i).ready && ibuf_valid(deq_idx)) -> 0.U,
(ibuf(deq_idx).inst(1,0) =/= "b11".U) -> 1.U,
ibuf_valid(deq_idx + 1.U) -> 2.U
))
}
head_ptr := head_ptr + deq_idx
head_ptr := deq_idx
last_enq := false.B
}.otherwise {
......@@ -166,7 +175,7 @@ class Ibuffer extends XSModule {
io.out(i).bits.hist := 0.U(HistoryLength.W)
// io.out(i).bits.btbVictimWay := 0.U(log2Up(BtbWays).W)
io.out(i).bits.btbPredCtr := 0.U(2.W)
io.out(i).bits.btbHitWay := false.B
io.out(i).bits.btbHit := false.B
io.out(i).bits.tageMeta := 0.U.asTypeOf(new TageMeta)
io.out(i).bits.rasSp := 0.U(log2Up(RasSize))
io.out(i).bits.rasTopCtr := 0.U(8.W)
......@@ -189,16 +198,16 @@ class Ibuffer extends XSModule {
}
//Debug Info
XSDebug(enqValid, "Enque:\n")
for(i <- 0 until FetchWidth) {
XSDebug(enqValid, p"${Binary(io.in.bits.instrs(i))}\n")
}
// XSDebug(enqValid, "Enque:\n")
// for(i <- 0 until FetchWidth) {
// XSDebug(enqValid, p"${Binary(io.in.bits.instrs(i))}\n")
// }
XSInfo(io.flush, "Flush signal received, clear buffer\n")
XSDebug(deqValid, "Deque:\n")
for(i <- 0 until DecodeWidth) {
XSDebug(deqValid, p"${Binary(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)} v=${io.out(i).valid} r=${io.out(i).ready}\n")
}
XSDebug(enqValid, p"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n")
// XSDebug(deqValid, "Deque:\n")
// for(i <- 0 until DecodeWidth) {
// XSDebug(deqValid, p"${Binary(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)} v=${io.out(i).valid} r=${io.out(i).ready}\n")
// }
XSDebug(p"head_ptr=$head_ptr tail_ptr=$tail_ptr\n")
// XSInfo(full, "Queue is full\n")
}
......@@ -109,9 +109,9 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
val (hashed_idx, tag) = compute_tag_and_hash(io.req.bits.pc >> (2 + log2Ceil(FetchWidth)), io.req.bits.hist)
val hi_us = List.fill(BankWidth)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=true, holdRead=true, singlePort=false)))
val lo_us = List.fill(BankWidth)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=true, holdRead=true, singlePort=false)))
val table = List.fill(BankWidth)(Module(new SRAMTemplate(new TageEntry, set=nRows, shouldReset=true, holdRead=true, singlePort=false)))
val hi_us = List.fill(BankWidth)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
val lo_us = List.fill(BankWidth)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
val table = List.fill(BankWidth)(Module(new SRAMTemplate(new TageEntry, set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
val hi_us_r = Wire(Vec(BankWidth, Bool()))
val lo_us_r = Wire(Vec(BankWidth, Bool()))
......@@ -133,9 +133,9 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
lo_us_r(b) := lo_us(b).io.r.resp.data(0)
table_r(b) := table(b).io.r.resp.data(0)
io.resp(b).valid := table_r(b).valid && table_r(b).tag === tag // Missing reset logic
io.resp(b).bits.ctr := table_r(b).ctr
io.resp(b).bits.u := Cat(hi_us_r(b),lo_us_r(b))
// io.resp(b).valid := table_r(b).valid && table_r(b).tag === tag // Missing reset logic
// io.resp(b).bits.ctr := table_r(b).ctr
// io.resp(b).bits.u := Cat(hi_us_r(b),lo_us_r(b))
}
)
......@@ -262,8 +262,8 @@ class Tage extends TageModule {
val updateMeta = io.redirectInfo.redirect.tageMeta
//val updateMisPred = UIntToOH(io.redirectInfo.redirect.fetchIdx) &
// Fill(FetchWidth, (io.redirectInfo.misPred && io.redirectInfo.redirect._type === BTBtype.B).asUInt)
val updateMisPred = io.redirectInfo.misPred && io.redirectInfo.redirect._type === BTBtype.B
// Fill(FetchWidth, (io.redirectInfo.misPred && io.redirectInfo.redirect.btbType === BTBtype.B).asUInt)
val updateMisPred = io.redirectInfo.misPred && io.redirectInfo.redirect.btbType === BTBtype.B
val updateMask = WireInit(0.U.asTypeOf(Vec(TageNTables, Vec(BankWidth, Bool()))))
val updateUMask = WireInit(0.U.asTypeOf(Vec(TageNTables, Vec(BankWidth, Bool()))))
......@@ -317,8 +317,8 @@ class Tage extends TageModule {
io.meta(w).allocate.bits := allocEntry
val isUpdateTaken = io.redirectInfo.valid && io.redirectInfo.redirect.fetchIdx === w.U &&
io.redirectInfo.redirect.taken && io.redirectInfo.redirect._type === BTBtype.B
when (io.redirectInfo.redirect._type === BTBtype.B && io.redirectInfo.valid && io.redirectInfo.redirect.fetchIdx === w.U) {
io.redirectInfo.redirect.taken && io.redirectInfo.redirect.btbType === BTBtype.B
when (io.redirectInfo.redirect.btbType === BTBtype.B && io.redirectInfo.valid && io.redirectInfo.redirect.fetchIdx === w.U) {
when (updateMeta.provider.valid) {
val provider = updateMeta.provider.bits
......@@ -374,4 +374,6 @@ class Tage extends TageModule {
io.out.hits := outHits.asUInt
XSDebug(io.req.valid, "req: pc=0x%x, hist=%b\n", io.req.bits.pc, io.req.bits.hist)
}
\ No newline at end of file
......@@ -9,35 +9,33 @@ import chisel3.util.experimental.BoringUtils
import xiangshan.backend.decode.XSTrap
class BTBUpdateBundle extends XSBundle {
// val fetchPC = UInt(VAddrBits.W)
val pc = UInt(VAddrBits.W)
// val fetchIdx = UInt(log2Up(FetchWidth*2).W)
val hit = Bool()
val misPred = Bool()
// val writeWay = UInt(log2Up(BtbWays).W)
val oldCtr = UInt(2.W)
val taken = Bool()
val target = UInt(VAddrBits.W)
val _type = UInt(2.W)
val btbType = UInt(2.W)
val isRVC = Bool()
}
class BTBPred extends XSBundle {
val hit = Bool()
val taken = Bool()
val takenIdx = UInt(log2Up(FetchWidth).W)
val takenIdx = UInt(log2Up(PredictWidth).W)
val target = UInt(VAddrBits.W)
// val writeWay = UInt(log2Up(BtbWays).W)
val notTakens = Vec(FetchWidth, Bool())
val dEntries = Vec(FetchWidth, btbDataEntry())
val hits = Vec(FetchWidth, Bool())
val notTakens = Vec(PredictWidth, Bool())
val dEntries = Vec(PredictWidth, btbDataEntry())
val hits = Vec(PredictWidth, Bool())
// whether an RVI instruction crosses over two fetch packet
val isRVILateJump = Bool()
}
case class btbDataEntry() extends XSBundle {
val target = UInt(VAddrBits.W)
val pred = UInt(2.W) // 2-bit saturated counter as a quick predictor
val _type = UInt(2.W)
val btbType = UInt(2.W)
val isRVC = Bool()
}
......@@ -53,7 +51,7 @@ class BTB extends XSModule {
val in = new Bundle {
val pc = Flipped(Decoupled(UInt(VAddrBits.W)))
val pcLatch = Input(UInt(VAddrBits.W))
val mask = Input(UInt((PredictWidth).W))
val mask = Input(UInt(PredictWidth.W))
}
val redirectValid = Input(Bool())
val flush = Input(Bool())
......@@ -64,10 +62,7 @@ class BTB extends XSModule {
io.in.pc.ready := true.B
val fireLatch = RegNext(io.in.pc.fire())
val nextFire = Wire(Bool())
nextFire := fireLatch
val maskLatch = RegEnable(io.in.mask, io.in.pc.fire())
val btbAddr = new TableAddr(log2Up(BtbSize), BtbBanks)
......@@ -79,8 +74,6 @@ class BTB extends XSModule {
// BTB read requests
val baseBank = btbAddr.getBank(io.in.pc.bits)
// val baseTag = btbAddr.getTag(io.in.pc.bits)
// val isAligned = baseBank === 0.U
// circular shifting
def circularShiftLeft(source: UInt, len: Int, shamt: UInt): UInt = {
val res = Wire(UInt(len.W))
......@@ -110,8 +103,6 @@ class BTB extends XSModule {
}
// // latch pc for 1 cycle latency when reading SRAM
// val pcLatch = RegEnable(io.in.pc.bits, io.in.pc.valid)
// Entries read from SRAM
val metaRead = Wire(Vec(BtbBanks, btbMetaEntry()))
val dataRead = Wire(Vec(BtbBanks, btbDataEntry()))
......@@ -139,27 +130,18 @@ class BTB extends XSModule {
// not taken branches from a valid entry
val notTakenBranches = Wire(Vec(BtbBanks, Bool()))
for (b <- 0 until BtbBanks) {
predTakens(b) := bankHits(b) && (dataRead(b)._type === BTBtype.J || dataRead(b)._type === BTBtype.B && dataRead(b).pred(1).asBool)
notTakenBranches(b) := bankHits(b) && dataRead(b)._type === BTBtype.B && !dataRead(b).pred(1).asBool
predTakens(b) := bankHits(b) && (dataRead(b).btbType === BTBtype.J || dataRead(b).btbType === BTBtype.B && dataRead(b).pred(1).asBool)
notTakenBranches(b) := bankHits(b) && dataRead(b).btbType === BTBtype.B && !dataRead(b).pred(1).asBool
}
// e.g: baseBank == 5 => (5, 6,..., 15, 0, 1, 2, 3, 4)
val bankIdxInOrder = VecInit((0 until BtbBanks).map(b => (baseBankLatch + b.U) % BtbBanks.U))
// Let predTakens(0) be in correspond with the first instruction in fetchPC
// val predUInt = predTakens.asUInt
// val realPreds = Mux(isAlignedLatch, predUInt, Cat(predUInt(BtbBanks-baseBankLatch-1, 0), predUInt(BtbBanks-1, BtbBanks-baseBankLatch))
// val realPredsVec = VecInit((0 until BtbBanks).map(realPreds(_).asBool))
// val ntbUInt = notTakenBranches.asUInt
// val realNtb = Mux(isAlignedLatch, ntbUInt, Cat(ntbUInt(BtbBanks-baseBankLatch-1, 0), ntbUInt(BtbBanks-1, BtbBanks-baseBankLatch))
// val realNtbVec = VecInit((0 until BtbBanks).map(realNtb(_).asBool))
val isTaken = predTakens.reduce(_||_)
// Priority mux which corresponds with inst orders
// BTB only produce one single prediction
val takenTarget = MuxCase(0.U, bankIdxInOrder.map(b => (predTakens(b), dataRead(b).target)))
val takenType = MuxCase(0.U, bankIdxInOrder.map(b => (predTakens(b), dataRead(b)._type)))
val takenType = MuxCase(0.U, bankIdxInOrder.map(b => (predTakens(b), dataRead(b).btbType)))
// Record which inst is predicted taken
val takenIdx = MuxCase(0.U, (0 until BtbBanks).map(b => (predTakens(bankIdxInOrder(b)), b.U)))
......@@ -168,7 +150,7 @@ class BTB extends XSModule {
def satUpdate(old: UInt, len: Int, taken: Bool): UInt = {
val oldSatTaken = old === ((1 << len)-1).U
val oldSatNotTaken = old === 0.U
Mux(oldSatTaken && taken, ((1 << len)-1-1).U,
Mux(oldSatTaken && taken, ((1 << len)-1).U,
Mux(oldSatNotTaken && !taken, 0.U,
Mux(taken, old + 1.U, old - 1.U)))
}
......@@ -187,15 +169,15 @@ class BTB extends XSModule {
val btbDataWrite = Wire(btbDataEntry())
btbDataWrite.target := u.target
btbDataWrite.pred := newCtr
btbDataWrite._type := u._type
btbDataWrite.btbType := u.btbType
btbDataWrite.isRVC := u.isRVC
val isBr = u._type === BTBtype.B
val isJ = u._type === BTBtype.J
val notBrOrJ = u._type =/= BTBtype.B && u._type =/= BTBtype.J
val isBr = u.btbType === BTBtype.B
val isJ = u.btbType === BTBtype.J
val notBrOrJ = u.btbType =/= BTBtype.B && u.btbType =/= BTBtype.J
// Do not update BTB on indirect or return, or correctly predicted J or saturated counters
val noNeedToUpdate = (!u.misPred && (isBr && updateOnSaturated || isJ)) || (u.misPred && notBrOrJ)
val noNeedToUpdate = (!u.misPred && (isBr && updateOnSaturated || isJ)) || notBrOrJ
// do not update on saturated ctrs
val btbWriteValid = io.redirectValid && !noNeedToUpdate
......@@ -209,27 +191,58 @@ class BTB extends XSModule {
btbData(b).io.w.req.bits.data := btbDataWrite
}
io.out.hit := bankHits.reduce(_||_)
// io.out.hit := bankHits.reduce(_||_)
io.out.taken := isTaken
io.out.takenIdx := takenIdx(log2Up(PredictWidth)-1, 1)
io.out.takenIdx := takenIdx
io.out.target := takenTarget
// io.out.writeWay := writeWay
io.out.notTakens := VecInit((0 until BtbBanks by 2).map(b => notTakenBranches(bankIdxInOrder(b))))
io.out.dEntries := VecInit((0 until BtbBanks by 2).map(b => dataRead(bankIdxInOrder(b))))
io.out.hits := VecInit((0 until BtbBanks by 2).map(b => bankHits(bankIdxInOrder(b))))
io.out.notTakens := VecInit((0 until BtbBanks).map(b => notTakenBranches(bankIdxInOrder(b))))
io.out.dEntries := VecInit((0 until BtbBanks).map(b => dataRead(bankIdxInOrder(b))))
io.out.hits := VecInit((0 until BtbBanks).map(b => bankHits(bankIdxInOrder(b))))
io.out.isRVILateJump := io.out.taken && takenIdx === OHToUInt(HighestBit(maskLatch, PredictWidth)) && !dataRead(bankIdxInOrder(takenIdx)).isRVC
// read-after-write bypass
val rawBypassHit = Wire(Vec(BtbBanks, Bool()))
for (b <- 0 until BtbBanks) {
when (b.U === updateBankIdx && realRow(b) === updateRow) { // read and write to the same address
when (realMask(b) && io.in.pc.valid && btbWriteValid) { // both read and write valid
rawBypassHit(b) := true.B
btbMeta(b).io.r.req.valid := false.B
btbData(b).io.r.req.valid := false.B
// metaRead(b) := RegNext(btbMetaWrite)
// dataRead(b) := RegNext(btbDataWrite)
readFire(b) := true.B
XSDebug("raw bypass hits: bank=%d, row=%d, meta: %d %x, data: tgt=%x pred=%b btbType=%b isRVC=%d\n",
b.U, updateRow,
btbMetaWrite.valid, btbMetaWrite.tag,
btbDataWrite.target, btbDataWrite.pred, btbDataWrite.btbType, btbDataWrite.isRVC)
}.otherwise {
rawBypassHit(b) := false.B
}
}.otherwise {
rawBypassHit(b) := false.B
}
when (RegNext(rawBypassHit(b))) {
metaRead(b) := RegNext(btbMetaWrite)
dataRead(b) := RegNext(btbDataWrite)
}
}
XSDebug(io.in.pc.fire(), "[BTB]read: pc=0x%x, baseBank=%d, realMask=%b\n", io.in.pc.bits, baseBank, realMask)
XSDebug(nextFire, "[BTB]read_resp: pc=0x%x, readIdx=%d-------------------------------\n",
XSDebug(io.in.pc.fire(), "read: pc=0x%x, baseBank=%d, realMask=%b\n", io.in.pc.bits, baseBank, realMask)
XSDebug(fireLatch, "read_resp: pc=0x%x, readIdx=%d-------------------------------\n",
io.in.pcLatch, btbAddr.getIdx(io.in.pcLatch))
for (i <- 0 until BtbBanks){
XSDebug(nextFire, "[BTB]read_resp[b=%d][r=%d]: valid=%d, tag=0x%x, target=0x%x, type=%d, ctr=%d\n",
i.U, realRowLatch(i), metaRead(i).valid, metaRead(i).tag, dataRead(i).target, dataRead(i)._type, dataRead(i).pred)
XSDebug(fireLatch, "read_resp[b=%d][r=%d]: valid=%d, tag=0x%x, target=0x%x, type=%d, ctr=%d\n",
i.U, realRowLatch(i), metaRead(i).valid, metaRead(i).tag, dataRead(i).target, dataRead(i).btbType, dataRead(i).pred)
}
XSDebug(nextFire, "[BTB]bankIdxInOrder:")
for (i <- 0 until BtbBanks){ XSDebug(nextFire, "%d ", bankIdxInOrder(i))}
XSDebug(nextFire, "\n")
XSDebug(io.redirectValid, "[BTB]update_req: pc=0x%x, hit=%d, misPred=%d, oldCtr=%d, taken=%d, target=0x%x, _type=%d\n",
u.pc, u.hit, u.misPred, u.oldCtr, u.taken, u.target, u._type)
XSDebug(io.redirectValid, "[BTB]update: noNeedToUpdate=%d, writeValid=%d, bank=%d, row=%d, newCtr=%d\n",
XSDebug("out: taken=%d takenIdx=%d tgt=%x notTakens=%b hits=%b isRVILateJump=%d\n",
io.out.taken, io.out.takenIdx, io.out.target, io.out.notTakens.asUInt, io.out.hits.asUInt, io.out.isRVILateJump)
XSDebug(fireLatch, "bankIdxInOrder:")
for (i <- 0 until BtbBanks){ XSDebug(fireLatch, "%d ", bankIdxInOrder(i))}
XSDebug(fireLatch, "\n")
XSDebug(io.redirectValid, "update_req: pc=0x%x, hit=%d, misPred=%d, oldCtr=%d, taken=%d, target=0x%x, btbType=%d\n",
u.pc, u.hit, u.misPred, u.oldCtr, u.taken, u.target, u.btbType)
XSDebug(io.redirectValid, "update: noNeedToUpdate=%d, writeValid=%d, bank=%d, row=%d, newCtr=%d\n",
noNeedToUpdate, btbWriteValid, updateBankIdx, updateRow, newCtr)
}
\ No newline at end of file
......@@ -12,14 +12,17 @@ class JBTACUpdateBundle extends XSBundle {
val fetchIdx = UInt(log2Up(PredictWidth).W)
val hist = UInt(HistoryLength.W)
val target = UInt(VAddrBits.W)
val _type = UInt(2.W)
val btbType = UInt(2.W)
val misPred = Bool()
val isRVC = Bool()
}
class JBTACPred extends XSBundle {
val hit = Bool()
val target = UInt(VAddrBits.W)
val hitIdx = UInt(log2Up(PredictWidth).W)
val isRVILateJump = Bool()
val isRVC = Bool()
}
class JBTAC extends XSModule {
......@@ -27,6 +30,7 @@ class JBTAC extends XSModule {
val in = new Bundle {
val pc = Flipped(Decoupled(UInt(VAddrBits.W)))
val pcLatch = Input(UInt(VAddrBits.W))
val mask = Input(UInt(PredictWidth.W))
val hist = Input(UInt(HistoryLength.W))
}
val redirectValid = Input(Bool())
......@@ -39,8 +43,6 @@ class JBTAC extends XSModule {
io.in.pc.ready := true.B
val fireLatch = RegNext(io.in.pc.fire())
val nextFire = Wire(Bool())
nextFire := fireLatch
// JBTAC, divided into 8 banks, makes prediction for indirect jump except ret.
val jbtacAddr = new TableAddr(log2Up(JbtacSize), JbtacBanks)
......@@ -50,6 +52,7 @@ class JBTAC extends XSModule {
val tag = UInt(jbtacAddr.tagBits.W + jbtacAddr.idxBits.W)
val target = UInt(VAddrBits.W)
val offset = UInt(log2Up(PredictWidth).W)
val isRVC = Bool()
}
val jbtac = List.fill(JbtacBanks)(Module(new SRAMTemplate(jbtacEntry(), set = JbtacSize / JbtacBanks, shouldReset = true, holdRead = true, singlePort = false)))
......@@ -76,16 +79,19 @@ class JBTAC extends XSModule {
val readBankLatch = jbtacAddr.getBank(histXORAddrLatch)
val readRowLatch = jbtacAddr.getBankIdx(histXORAddrLatch)
val readMaskLatch = RegEnable(io.in.mask, io.in.pc.fire())
val outHit = readEntries(readBankLatch).valid &&
readEntries(readBankLatch).tag === Cat(jbtacAddr.getTag(io.in.pcLatch), jbtacAddr.getIdx(io.in.pcLatch)) &&
!io.flush && readFire(readBankLatch)
!io.flush && RegNext(readFire(readBankLatch)) && readMaskLatch(readEntries(readBankLatch).offset).asBool
io.out.hit := outHit
io.out.hitIdx := readEntries(readBankLatch).offset(log2Up(PredictWidth)-1, 1)
io.out.hitIdx := readEntries(readBankLatch).offset
io.out.target := readEntries(readBankLatch).target
io.out.isRVILateJump := io.out.hit && io.out.hitIdx === OHToUInt(HighestBit(readMaskLatch, PredictWidth)) && !readEntries(readBankLatch).isRVC
io.out.isRVC := readEntries(readBankLatch).isRVC
// 2. update jbtac
// update jbtac
val writeEntry = Wire(jbtacEntry())
// val updateHistXORAddr = updatefetchPC ^ Cat(r.hist, 0.U(2.W))(VAddrBits - 1, 0)
val updateHistXORAddr = io.update.fetchPC ^ Cat(io.update.hist, 0.U(1.W))(VAddrBits - 1, 0)
......@@ -95,10 +101,11 @@ class JBTAC extends XSModule {
writeEntry.target := io.update.target
// writeEntry.offset := updateFetchIdx
writeEntry.offset := io.update.fetchIdx
writeEntry.isRVC := io.update.isRVC
val writeBank = jbtacAddr.getBank(updateHistXORAddr)
val writeRow = jbtacAddr.getBankIdx(updateHistXORAddr)
val writeValid = io.redirectValid && io.update.misPred && io.update._type === BTBtype.I
val writeValid = io.redirectValid && io.update.misPred && io.update.btbType === BTBtype.I
for (b <- 0 until JbtacBanks) {
when (b.U === writeBank) {
jbtac(b).io.w.req.valid := writeValid
......@@ -111,10 +118,34 @@ class JBTAC extends XSModule {
}
}
XSDebug(io.in.pc.fire(), "[JBTAC]read: pc=0x%x, histXORAddr=0x%x, bank=%d, row=%d, hist=%b\n",
// read-after-write bypass
val rawBypassHit = Wire(Vec(JbtacBanks, Bool()))
for (b <- 0 until JbtacBanks) {
when (readBank === writeBank && readRow === writeRow && b.U === readBank) {
when (io.in.pc.fire() && writeValid) {
rawBypassHit(b) := true.B
jbtac(b).io.r.req.valid := false.B
// readEntries(b) := RegNext(writeEntry)
readFire(b) := true.B
XSDebug("raw bypass hits: bank=%d, row=%d, tag=%x, tgt=%x, offet=%d, isRVC=%d\n",
b.U, readRow, writeEntry.tag, writeEntry.target, writeEntry.offset, writeEntry.isRVC)
}.otherwise {
rawBypassHit(b) := false.B
}
}.otherwise {
rawBypassHit(b) := false.B
}
when (RegNext(rawBypassHit(b))) { readEntries(b) := RegNext(writeEntry) }
}
XSDebug(io.in.pc.fire(), "read: pc=0x%x, histXORAddr=0x%x, bank=%d, row=%d, hist=%b\n",
io.in.pc.bits, histXORAddr, readBank, readRow, io.in.hist)
XSDebug(nextFire, "[JBTAC]read_resp: pc=0x%x, bank=%d, row=%d, target=0x%x, offset=%d, hit=%d\n",
XSDebug("out: hit=%d tgt=%x hitIdx=%d iRVILateJump=%d isRVC=%d\n",
io.out.hit, io.out.target, io.out.hitIdx, io.out.isRVILateJump, io.out.isRVC)
XSDebug(fireLatch, "read_resp: pc=0x%x, bank=%d, row=%d, target=0x%x, offset=%d, hit=%d\n",
io.in.pcLatch, readBankLatch, readRowLatch, readEntries(readBankLatch).target, readEntries(readBankLatch).offset, outHit)
XSDebug(io.redirectValid, "[JBTAC]update_req: fetchPC=0x%x, writeValid=%d, hist=%b, bank=%d, row=%d, target=0x%x, offset=%d, type=0x%d\n",
io.update.fetchPC, writeValid, io.update.hist, writeBank, writeRow, io.update.target, io.update.fetchIdx, io.update._type)
XSDebug(io.redirectValid, "update_req: fetchPC=0x%x, writeValid=%d, hist=%b, bank=%d, row=%d, target=0x%x, offset=%d, type=0x%d\n",
io.update.fetchPC, writeValid, io.update.hist, writeBank, writeRow, io.update.target, io.update.fetchIdx, io.update.btbType)
}
\ No newline at end of file
......@@ -90,7 +90,7 @@ static const char *reg_name[DIFFTEST_NR_REG] = {
int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
int skip, int isRVC, uint64_t *wpc, uint64_t *wdata, uint32_t *wdst, int wen, uint64_t intrNO, int priviledgeMode) {
assert(!isRVC && intrNO == 0);
assert(!isRVC);
#define DEBUG_RETIRE_TRACE_SIZE 16
#define DEBUG_WB_TRACE_SIZE 16
......@@ -125,28 +125,29 @@ int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
if (intrNO) {
ref_difftest_raise_intr(intrNO);
ref_difftest_exec(1);//TODO
// ref_difftest_exec(1);//TODO
}
assert(commit > 0 && commit <= 6);
for(int i = 0; i < commit; i++){
pc_wb_queue[wb_pointer] = wpc[i];
wen_wb_queue[wb_pointer] = selectBit(wen, i);
wdst_wb_queue[wb_pointer] = wdst[i];
wdata_wb_queue[wb_pointer] = wdata[i];
wb_pointer = (wb_pointer+1) % DEBUG_WB_TRACE_SIZE;
if(selectBit(skip, i)){
// MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
// printf("SKIP %d\n", i);
// to skip the checking of an instruction, just copy the reg state to reference design
ref_difftest_getregs(&ref_r);
ref_r[DIFFTEST_THIS_PC] += 4; //TODO: RVC
if(selectBit(wen, i)){
ref_r[wdst[i]] = wdata[i];
else {
assert(commit > 0 && commit <= 6);
for(int i = 0; i < commit; i++){
pc_wb_queue[wb_pointer] = wpc[i];
wen_wb_queue[wb_pointer] = selectBit(wen, i);
wdst_wb_queue[wb_pointer] = wdst[i];
wdata_wb_queue[wb_pointer] = wdata[i];
wb_pointer = (wb_pointer+1) % DEBUG_WB_TRACE_SIZE;
if(selectBit(skip, i)){
// MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
// printf("SKIP %d\n", i);
// to skip the checking of an instruction, just copy the reg state to reference design
ref_difftest_getregs(&ref_r);
ref_r[DIFFTEST_THIS_PC] += 4; //TODO: RVC
if(selectBit(wen, i)){
ref_r[wdst[i]] = wdata[i];
}
ref_difftest_setregs(ref_r);
}else{
ref_difftest_exec(1);
}
ref_difftest_setregs(ref_r);
}else{
ref_difftest_exec(1);
}
}
ref_difftest_getregs(&ref_r);
......
......@@ -2,6 +2,8 @@
#include <SDL2/SDL.h>
//#define SHOW_SCREEN
#define SCREEN_PORT 0x100 // Note that this is not the standard
#define SCREEN_MMIO 0x4100
#define SCREEN_H 600
......@@ -20,7 +22,9 @@ extern "C" void put_pixel(uint32_t pixel) {
}
extern "C" void vmem_sync(void) {
#ifndef SHOW_SCREEN
return;
#endif
SDL_UpdateTexture(texture, NULL, vmem, SCREEN_W * sizeof(uint32_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
......@@ -28,7 +32,9 @@ extern "C" void vmem_sync(void) {
}
void init_sdl() {
#ifndef SHOW_SCREEN
return;
#endif
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(SCREEN_W, SCREEN_H, 0, &window, &renderer);
SDL_SetWindowTitle(window, "NOOP");
......
......@@ -7,6 +7,7 @@ import chisel3.experimental.BundleLiterals._
import chisel3.util._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.VerilatorBackendAnnotation
import utils.XSLog
import xiangshan._
import xiangshan.testutils._
import xiangshan.testutils.TestCaseGenerator._
......@@ -19,14 +20,15 @@ class BrqTest extends FlatSpec
with ParallelTestExecution
with HasPartialDecoupledDriver {
it should "" in {
XSLog.generateLog = true
test(new Brq {
AddSinks()
}).withAnnotations(Seq(VerilatorBackendAnnotation)) { c =>
}).withAnnotations(Seq()) { c =>
def genEnqReq(x: => DecoupledIO[CfCtrl], pc: Long) = {
chiselTypeOf(x.bits).Lit(
_.cf.pc -> pc.U
_.cf.pc -> pc.U,
_.cf.pnpc -> (pc+4).U
)
}
......@@ -51,11 +53,17 @@ class BrqTest extends FlatSpec
val misPred = Random.nextInt(10)
println(s"enqTags:$enqTags misPredTag:$misPred")
enqTags = enqTags.take(misPred + 1)
var deqTags = List[Int]()
var commitTags, deqTags = List[Int]()
def checkDeq = {
def checkCommit = {
if (c.io.out.valid.peek().litToBoolean) {
deqTags = deqTags :+ c.io.redirect.bits.brTag.value.peek().litValue().toInt
commitTags = commitTags :+ c.io.redirect.bits.brTag.value.peek().litValue().toInt
println(s"====commited tags:$commitTags====")
}
}
def checkDeq = {
if(c.io.inOrderBrInfo.valid.peek().litToBoolean){
deqTags = deqTags :+ c.io.inOrderBrInfo.redirect.brTag.value.peek().litValue().toInt
println(s"====deq tags:$deqTags====")
}
}
......@@ -73,35 +81,43 @@ class BrqTest extends FlatSpec
wbPort.bits.pokePartial(
genExuWb(wbPort, tag, tagFlag = false, if (tag == misPred) 0xffff else tag * 0x1000 + 4)
)
checkDeq
checkCommit
c.clock.step(1)
wbPort.valid.poke(false.B)
for (i <- 0 until Random.nextInt(3)) {
checkDeq
checkCommit
c.clock.step(1)
}
}
c.io.bcommit.poke((misPred+1).U)
while (deqTags.size != misPred+1) {
checkCommit
checkDeq
c.clock.step(1)
}
c.clock.step(10)
val left = deqTags.takeWhile(x => x!=misPred)
val right = deqTags.dropWhile(x => x!=misPred).drop(1)
val left = commitTags.takeWhile(x => x!=misPred)
val right = commitTags.dropWhile(x => x!=misPred).drop(1)
println(s"deq before mispred: $left")
println(s"deq after mispred: $right")
println(s"commited before mispred: $left")
println(s"commited after mispred: $right")
def isValidDeqSeq(in: Seq[Int]): Boolean = {
def isValidCommitSeq(in: Seq[Int]): Boolean = {
for(i <- 1 until in.size){
if(in(i) == in(i-1)) return false
}
true
}
assert(isValidCommitSeq(left) && isValidCommitSeq(right))
println(s"deq tags: $deqTags")
assert(isValidDeqSeq(left) && isValidDeqSeq(right))
def isValidDeqSeq(in: Seq[Int]): Boolean = {
in.zipWithIndex.map(x => x._1==x._2).reduce(_&&_)
}
assert(isValidDeqSeq(deqTags))
}
}
}
......@@ -18,14 +18,23 @@ object AddSinks {
"perfCntCondMl2cacheReq",
"mtip",
"perfCntCondMdcacheReq",
"meip"
"meip",
"perfCntCondMbpInstr",
"perfCntCondMbpRight",
"perfCntCondMbpWrong",
"perfCntCondMbpBRight",
"perfCntCondMbpBWrong",
"perfCntCondMbpJRight",
"perfCntCondMbpJWrong",
"perfCntCondMbpIRight",
"perfCntCondMbpIWrong",
"perfCntCondMbpRRight",
"perfCntCondMbpRWrong"
)
for (s <- sinks){ BoringUtils.addSink(tmp, s) }
val disp_begin = WireInit(dispBegin.S(64.W).asUInt())
val disp_end = WireInit(dispEnd.S(64.W).asUInt())
BoringUtils.addSource(disp_begin, "DISPLAY_LOG_START")
BoringUtils.addSource(disp_end, "DISPLAY_LOG_END")
val disp_enable = WireInit(dispBegin.S(64.W).asUInt() < dispEnd.S(64.W).asUInt())
BoringUtils.addSource(disp_enable, "DISPLAY_LOG_ENABLE")
}
}
include $(AM_HOME)/Makefile.check
.PHONY: all run clean latest $(ALL)
ALL = $(basename $(notdir $(shell find tests/. -name "*.c")))
all: $(addprefix Makefile., $(ALL))
@echo "" $(ALL)
$(ALL): %: Makefile.%
Makefile.%: tests/%.c latest
@/bin/echo -e "NAME = $*\nSRCS = $<\nLIBS += klib\ninclude $${AM_HOME}/Makefile.app" > $@
-@make -s -f $@ ARCH=$(ARCH) $(MAKECMDGOALS)
-@rm -f Makefile.$*
#cancel rules included by $(AM_HOME)/Makefile.check
image: ;
default $(MAKECMDGOALS): all ;
clean:
rm -rf Makefile.* build/
latest:
\ No newline at end of file
// #include <am.h>
// #include <klib.h>
# define OutLoopNum 20
# define InnerLoopNum 20
int array[OutLoopNum][InnerLoopNum];
void double_loop() {
for (int i = 0; i < OutLoopNum; i++) {
for (int j = 1; j < InnerLoopNum; j++) {
array[i][j] = i + j;
}
}
}
int main () {
double_loop();
return 0;
}
// #include <am.h>
// #include <klib.h>
# define DEPTH 100
int nest(int depth) {
if (depth == 0) return depth;
nest(depth - 1);
return depth;
}
int main () {
nest(DEPTH);
return 0;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册