未验证 提交 583a68ce 编写于 作者: 张发旺 提交者: GitHub

Merge branch 'master' into ibuf

......@@ -86,11 +86,14 @@ $(EMU): $(EMU_MK) $(EMU_DEPS) $(EMU_HEADERS) $(REF_SO)
SEED = -s $(shell seq 1 10000 | shuf | head -n 1)
# log will only be printed when (B<=GTimer<=E) && (L < loglevel)
# use 'emu -h' to see more details
B ?= 0
E ?= -1
L ?= ALL
emu: $(EMU)
@$(EMU) -i $(IMAGE) $(SEED) -b $(B) -e $(E)
@$(EMU) -i $(IMAGE) $(SEED) -b $(B) -e $(E) -l $(L)
cache:
$(MAKE) emu IMAGE=Makefile
......
......@@ -2,12 +2,17 @@ ARCH = ARCH=riscv64-noop
NANOS_HOME ?= $(AM_HOME)/../nanos-lite
SINGLETEST = ALL=min3
B ?= 0
E ?= -1
L ?= ALL
EMU_ARGS = B=$(B) E=$(E) L=$(L)
# ------------------------------------------------------------------
# bulid CPU and run dummy test
# ------------------------------------------------------------------
cpu:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=dummy run
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=dummy $(EMU_ARGS) run
# ------------------------------------------------------------------
# run different test sets
......
......@@ -11,7 +11,6 @@ import xiangshan.frontend.Frontend
import xiangshan.utils._
trait HasXSParameter {
val LogLevel = XSLogLevel.ALL
val XLEN = 64
val HasMExtension = true
val HasCExtension = true
......
......@@ -5,7 +5,7 @@ import chisel3.util._
import xiangshan._
import xiangshan.utils._
class DecodeBuffer extends XSModule with NeedImpl {
class DecodeBuffer extends XSModule {
val io = IO(new Bundle() {
val redirect = Flipped(ValidIO(new Redirect))
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
......
......@@ -36,16 +36,16 @@ class DecodeStage extends XSModule {
decoderToBrq(i) := decoders(i).io.out // CfCtrl without bfTag and brMask
// send CfCtrl without brTags and brMasks to brq
io.toBrq(i).valid := io.in(i).valid && io.out(i).ready && decoders(i).io.out.cf.isBr
XSDebug(io.toBrq(i).valid && io.toBrq(i).ready, p"Branch instr detected. Sending it to BRQ.")
XSDebug(io.toBrq(i).valid && !io.toBrq(i).ready, p"Branch instr detected. BRQ full...waiting")
XSDebug(io.in(i).valid && !io.out(i).ready, p"DecBuf full...waiting")
XSDebug(io.toBrq(i).valid && io.toBrq(i).ready, p"Branch instr detected. Sending it to BRQ.\n")
XSDebug(io.toBrq(i).valid && !io.toBrq(i).ready, p"Branch instr detected. BRQ full...waiting\n")
XSDebug(io.in(i).valid && !io.out(i).ready, p"DecBuf full...waiting\n")
decoderToBrq(i).brMask := DontCare
decoderToBrq(i).brTag := DontCare
io.toBrq(i).bits := decoderToBrq(i)
// if brq returns ready, then assert valid and send CfCtrl with bfTag and brMask to DecBuffer
io.out(i).valid := io.toBrq(i).ready && io.in(i).valid
XSDebug(io.out(i).valid && decoders(i).io.out.cf.isBr && io.out(i).ready, p"Sending branch instr to DecBuf")
XSDebug(io.out(i).valid && !decoders(i).io.out.cf.isBr && io.out(i).ready, p"Sending non-branch instr to DecBuf")
XSDebug(io.out(i).valid && decoders(i).io.out.cf.isBr && io.out(i).ready, p"Sending branch instr to DecBuf\n")
XSDebug(io.out(i).valid && !decoders(i).io.out.cf.isBr && io.out(i).ready, p"Sending non-branch instr to DecBuf\n")
decoderToDecBuffer(i) := decoders(i).io.out
decoderToDecBuffer(i).brTag := io.brTags(i)
decoderToDecBuffer(i).brMask := io.brMasks(i)
......
......@@ -3,7 +3,7 @@ package xiangshan.backend.dispatch
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils.{XSDebug, XSInfo}
import xiangshan.utils.{XSDebug, XSInfo, XSWarn}
case class DP1Config
(
......@@ -72,7 +72,6 @@ class Dispatch1 extends XSModule{
for (i <- 0 until RenameWidth) {
uop_nroq(i) := io.fromRename(i).bits
uop_nroq(i).roqIdx := Mux(io.toRoq(i).ready, io.roqIdxs(i), roqIndexReg(i))
XSDebug(io.toRoq(i).fire(), "instruction 0x%x receives nroq %d\n", io.fromRename(i).bits.cf.pc, io.roqIdxs(i))
}
// uop can enqueue when rename.valid and roq.valid
......@@ -93,6 +92,11 @@ class Dispatch1 extends XSModule{
for (i <- 0 until RenameWidth) {
io.toRoq(i).bits <> io.fromRename(i).bits
io.toRoq(i).valid := io.fromRename(i).valid && !roqIndexRegValid(i)
XSDebug(io.toRoq(i).fire(), "instruction 0x%x receives nroq %d\n", io.fromRename(i).bits.cf.pc, io.roqIdxs(i))
if (i > 0) {
XSWarn(io.toRoq(i).fire() && !io.toRoq(i - 1).ready && io.toRoq(i - 1).valid,
"roq handshake not continuous %d", i.U)
}
io.fromRename(i).ready := all_recv
XSDebug(io.fromRename(i).valid, "instruction 0x%x of type %b is in %d-th slot\n",
io.fromRename(i).bits.cf.pc, io.fromRename(i).bits.ctrl.fuType, i.U)
......
......@@ -6,7 +6,7 @@ import xiangshan._
import xiangshan.backend.regfile.RfReadPort
import xiangshan.utils.{XSDebug, XSInfo}
class Dispatch2 extends XSModule with NeedImpl {
class Dispatch2 extends XSModule {
val io = IO(new Bundle() {
// from dispatch queues
val fromIntDq = Flipped(Vec(IntDqDeqWidth, DecoupledIO(new MicroOp)))
......@@ -116,8 +116,8 @@ class Dispatch2 extends XSModule with NeedImpl {
enq.bits.src2State := io.intPregRdy(11)
}
XSInfo(enq.fire(), "instruction 0x%x with type %b enters reservation station %d from %d\n",
enq.bits.cf.pc, enq.bits.ctrl.fuType, i.U, instIdxes(i))
XSInfo(enq.fire(), "instruction 0x%x with type %b srcState(%d %d %d) enters reservation station %d from %d\n",
enq.bits.cf.pc, enq.bits.ctrl.fuType, enq.bits.src1State, enq.bits.src2State, enq.bits.src3State, i.U, instIdxes(i))
}
// responds to dispatch queue
......@@ -221,9 +221,10 @@ class Dispatch2 extends XSModule with NeedImpl {
io.enqIQData(i).bits.src3 := Mux(index_reg(i)(2), 0.U, src3)
XSDebug(io.enqIQData(i).valid,
"instruction 0x%x reads operands from (%d, %d, %x), (%d, %d, %x), (%d, %d, %x)\n",
io.enqIQData(i).bits.uop.cf.pc, src1Type(i), src1Index(i), src1,
src2Type(i), src2Index(i), src2, src3Type(i), src3Index(i), src3)
"instruction 0x%x reads operands from (%d, %d, %d, %x), (%d, %d, %d, %x), (%d, %d, %d, %x)\n",
io.enqIQData(i).bits.uop.cf.pc, src1Type(i), src1Index(i), io.enqIQData(i).bits.uop.psrc1, src1,
src2Type(i), src2Index(i), io.enqIQData(i).bits.uop.psrc2, src2,
src3Type(i), src3Index(i), io.enqIQData(i).bits.uop.psrc3, src3)
}
}
......@@ -108,11 +108,24 @@ trait HasExeUnits{
exeUnits.foreach(_.io.dmem := DontCare)
}
class WriteBackArbMtoN(m: Int, n: Int) extends XSModule with NeedImpl {
class WriteBackArbMtoN(m: Int, n: Int) extends XSModule {
val io = IO(new Bundle() {
val in = Vec(m, Flipped(DecoupledIO(new ExuOutput)))
val out = Vec(n, ValidIO(new ExuOutput))
})
// TODO: arbiter logic
for (i <- 0 until m) {
io.in(i).ready := false.B
}
io.out <> DontCare
for (i <- 0 until 4) {
io.out(i).valid := io.in(i+1).valid
io.out(i).bits := io.in(i+1).bits
io.in(i+1).ready := true.B
}
}
......
......@@ -8,9 +8,6 @@ import xiangshan.utils._
trait IQConst{
val iqSize = 8
val iqIdxWidth = log2Up(iqSize)
val layer1Size = iqSize
val layer2Size = iqSize/2
val debug = false
}
sealed abstract class IQBundle extends XSBundle with IQConst
......@@ -109,14 +106,14 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
//Tag Queue
val ctrlFlow = Mem(iqSize,new CtrlFlow)
val ctrlSig = Mem(iqSize,new CtrlSignals)
val brMask = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrqSize.W))))
val brTag = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrTagWidth.W))))
val brMask = Reg(Vec(iqSize, UInt(BrqSize.W)))
val brTag = Reg(Vec(iqSize, UInt(BrTagWidth.W)))
val validReg = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
val validWillFalse= WireInit(VecInit(Seq.fill(iqSize)(false.B)))
val valid = validReg.asUInt & ~validWillFalse.asUInt
val src1Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
val src2Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
val src3Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
val src1Rdy = Reg(Vec(iqSize, Bool()))
val src2Rdy = Reg(Vec(iqSize, Bool()))
val src3Rdy = Reg(Vec(iqSize, Bool()))
val prfSrc1 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
val prfSrc2 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
val prfSrc3 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
......@@ -143,7 +140,9 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcEnqRdy(0) := Mux(io.enqCtrl.bits.ctrl.src1Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src1State === SrcState.rdy)
srcEnqRdy(1) := Mux(io.enqCtrl.bits.ctrl.src2Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src2State === SrcState.rdy)
srcEnqRdy(2) := Mux(io.enqCtrl.bits.ctrl.src3Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src3State === SrcState.rdy)
//TODO:
if(fuTypeInt != FuType.fmac.litValue()){ srcEnqRdy(2) := true.B}
else{srcEnqRdy(2) := Mux(io.enqCtrl.bits.ctrl.src3Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src3State === SrcState.rdy)}
when (io.enqCtrl.fire()) {
ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf
......@@ -161,10 +160,10 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest
freelistAllocPtr(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr
roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx
if(debug) {XSDebug("[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n",enqueueSelect.asUInt,
XSDebug("[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n",enqueueSelect.asUInt,
(io.enqCtrl.bits.src1State === SrcState.rdy),
(io.enqCtrl.bits.src2State === SrcState.rdy),
(io.enqCtrl.bits.src3State === SrcState.rdy))}
(io.enqCtrl.bits.src3State === SrcState.rdy))
}
......@@ -184,19 +183,24 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
when(src2Rdy(enqSelNext)){src2Data(enqSelNext) := io.enqData.bits.src2}
when(src3Rdy(enqSelNext)){src3Data(enqSelNext) := io.enqData.bits.src3}
}
if(debug) {
XSDebug("[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n",enqSelNext,enqFireNext)
XSDebug("[IQ content] valid vr vf| pc insruction | src1rdy src1 | src2Rdy src2 pdest \n")
for(i <- 0 to (iqSize -1)){
val ins = ctrlFlow(i).instr
val pc = ctrlFlow(i).pc
when(valid(i)){XSDebug("[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d valid|\n",i.asUInt, valid(i), validReg(i), validWillFalse(i), pc,ins,src1Rdy(i), src1Data(i), src2Rdy(i), src2Data(i),prfDest(i))}
.elsewhen(validReg(i) && validWillFalse(i)){XSDebug("[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d valid will be False|\n",i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i), src2Rdy(i), src2Data(i),prfDest(i))}
.otherwise {XSDebug("[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d\n",i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i), src2Rdy(i), src2Data(i),prfDest(i))}
}
XSDebug("[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n",enqSelNext,enqFireNext)
XSDebug("[IQ content] valid vr vf| pc insruction | src1rdy src1 | src2Rdy src2 | src3Rdy src3 | pdest \n")
for(i <- 0 to (iqSize -1)) {
val ins = ctrlFlow(i).instr
val pc = ctrlFlow(i).pc
XSDebug(valid(i),
"[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %x %x | %d valid|\n",
i.asUInt, valid(i), validReg(i), validWillFalse(i), pc,ins,src1Rdy(i), src1Data(i),
src2Rdy(i), src2Data(i),src3Rdy(i), src3Data(i),prfDest(i))
XSDebug(validReg(i) && validWillFalse(i),
"[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %x %x | %d valid will be False|\n",
i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i),
src2Rdy(i), src2Data(i),src3Rdy(i), src3Data(i),prfDest(i))
XSDebug("[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %x %x | %d\n",
i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i),
src2Rdy(i), src2Data(i),src3Rdy(i), src3Data(i),prfDest(i))
}
// From Common Data Bus(wakeUpPort)
// chisel claims that firrtl will optimize Mux1H to and/or tree
......@@ -286,9 +290,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
Wire(new CmpInputBundle).apply(instRdy(i),roqIdx(i),i.U)
}
val selResult = ParallelSel(selVec)
if(debug) {
XSDebug("[Sel Result] ResReady:%d || ResultId:%d\n",selResult.instRdy,selResult.iqIdx.asUInt)
}
XSDebug("[Sel Result] ResReady:%d || ResultId:%d\n",selResult.instRdy,selResult.iqIdx.asUInt)
//---------------------------------------------------------
// Redirect Logic
//---------------------------------------------------------
......@@ -340,14 +342,12 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
io.deq.bits.src1 := src1Data(dequeueSelect)
io.deq.bits.src2 := src2Data(dequeueSelect)
io.deq.bits.src3 := src3Data(dequeueSelect)
if(debug) {
XSDebug("[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n",selInstRdy,selInstIdx.asUInt)
XSDebug(IQreadyGo,"[IQ dequeue] **dequeue fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n", io.deq.fire(), io.deq.bits.uop.roqIdx, dequeueSelect.asUInt,
(io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1,
(io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2
)
}
XSDebug("[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n",selInstRdy,selInstIdx.asUInt)
XSDebug(IQreadyGo,"[IQ dequeue] **dequeue fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n", io.deq.fire(), io.deq.bits.uop.roqIdx, dequeueSelect.asUInt,
(io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1,
(io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2
)
//update the index register of instruction that can be issue, unless function unit not allow in
//then the issue will be stopped to wait the function unit
......
......@@ -3,7 +3,7 @@ package xiangshan.backend.rename
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils.ParallelOR
import xiangshan.utils.{ParallelOR, XSDebug}
class BusyTable extends XSModule {
val io = IO(new Bundle() {
......@@ -27,15 +27,21 @@ class BusyTable extends XSModule {
when(alloc.valid){
table(alloc.bits) := true.B
}
XSDebug(alloc.valid, "Allocate %d\n", alloc.bits)
}
for((wb, i) <- io.wbPregs.zipWithIndex){
when(wb.valid){
table(wb.bits) := false.B
}
XSDebug(wb.valid, "writeback %d\n", wb.bits)
}
when(io.flush){
table.foreach(_ := false.B)
}
for (i <- 0 until NRPhyRegs) {
XSDebug(table(i), "%d is busy\n", i.U)
}
}
......@@ -99,6 +99,14 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
// TODO: commit store
XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
XSInfo("")
XSInfo(){
printf("retired pcs are: ")
for(i <- 0 until CommitWidth){
when(io.commits(i).valid){ printf("%d:0x%x ", ringBufferTail+i.U, microOp(ringBufferTail+i.U).cf.pc) }
}
printf("\n")
}
val walkFinished = (0 until CommitWidth).map(i => (ringBufferWalk + i.U) === ringBufferWalkTarget).reduce(_||_)
......@@ -133,19 +141,30 @@ class Roq(implicit val p: XSConfig) extends XSModule {
}
printf("\n")
}
XSDebug(){
for(i <- 0 until RoqSize){
if(i % 4 == 0) XSDebug("")
printf("%x ", microOp(i).cf.pc)
when(!valid(i)){printf("- ")}
when(valid(i) && writebacked(i)){printf("w ")}
when(valid(i) && !writebacked(i)){printf("v ")}
if(i % 4 == 3) printf("\n")
}
}
//difftest signals
val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
val emptyCsr = WireInit(0.U(64.W))
if(!p.FPGAPlatform){
BoringUtils.addSink(RegNext(retireCounter), "difftestCommit")
BoringUtils.addSink(RegNext(microOp(firstValidCommit).cf.pc), "difftestThisPC")//first valid PC
BoringUtils.addSink(RegNext(microOp(firstValidCommit).cf.instr), "difftestThisINST")//first valid inst
BoringUtils.addSink(archRF, "difftestRegs")//arch RegFile
BoringUtils.addSink(RegNext(false.B), "difftestSkip")//SKIP
BoringUtils.addSink(RegNext(false.B), "difftestIsRVC")//FIXIT
BoringUtils.addSink(RegNext(0.U), "difftestIntrNO")
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(archRF, "difftestRegs")//arch RegFile
BoringUtils.addSource(RegNext(false.B), "difftestSkip")//SKIP
BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
//TODO: skip insts that commited in the same cycle ahead of exception
//csr debug signals
......
package xiangshan.frontend
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils._
class Ibuffer extends XSModule {
val io = IO(new Bundle() {
val flush = Input(Bool())
val in = Flipped(DecoupledIO(new FetchPacket))
val out = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
})
when(io.in.valid) {
XSDebug("cache data\n")
for (i <- 0 until FetchWidth) {
XSDebug("%b\n", io.in.bits.instrs(i))
}
}
// ignore
for(i <- 0 until DecodeWidth) {
io.out(i).bits.exceptionVec := DontCare
io.out(i).bits.intrVec := DontCare
io.out(i).bits.isBr := DontCare
}
//mask initial
// val mask = Wire(Vec(FetchWidth*2, false.B))
// (0 until 16).map(i => mask(i.U) := (io.in.bits.pc(4,1) <= i.U))
// ibuf define
val ibuf = RegInit(VecInit(Seq.fill(IBufSize*2)(0.U(16.W))))
val ibuf_pc = RegInit(VecInit(Seq.fill(IBufSize*2)(0.U(VAddrBits.W))))
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))
// true: Last operation is enqueue
// false: Last operation is deq_ueue
val last_enq = RegInit(false.B)
val full = head_ptr === tail_ptr && last_enq
val empty = head_ptr === tail_ptr && !last_enq
val enqValid = !io.flush && io.in.valid && !full && !ibuf_valid(tail_ptr + (FetchWidth*2).U)
val deqValid = !io.flush && !empty //&& io.out.map(_.ready).reduce(_||_)
XSWarn(empty, "Ibuffer is empty\n")
XSWarn(full, "Ibuffer is full\n")
io.in.ready := enqValid
// enque
when(enqValid) {
XSInfo("Enque start\n")
var enq_idx = 0.U(log2Up(FetchWidth*2+1).W)
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
ibuf_valid(tail_ptr + enq_idx) := true.B
XSDebug("Enque: %b\n", Mux(i.U(0), io.in.bits.instrs(i>>1)(31,16), io.in.bits.instrs(i>>1)(15,0)))
}
enq_idx = enq_idx + io.in.bits.mask(i)
}
tail_ptr := tail_ptr + enq_idx
last_enq := true.B
XSInfo("Enque finished, tail_ptr=%d\n", tail_ptr + enq_idx)
}
// deque
when(deqValid) {
XSInfo("Deque start\n")
var deq_idx = 0.U(log2Up(DecodeWidth*2+1).W)
for(i <- 0 until DecodeWidth) {
when(io.out(i).ready && ibuf_valid(head_ptr + deq_idx)) {
when(ibuf(head_ptr + deq_idx)(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)
XSDebug("%b[RVC] PC=%d\n", Cat(0.U(16.W), ibuf(head_ptr + deq_idx)), ibuf_pc(head_ptr + deq_idx))
io.out(i).bits.isRVC := true.B
io.out(i).valid := true.B
ibuf_valid(head_ptr + deq_idx) := false.B
}.elsewhen(ibuf_valid(head_ptr + 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)
XSDebug("%b[NORVC] PC=%d\n", Cat(ibuf(head_ptr + deq_idx+1.U), ibuf(head_ptr + deq_idx)), ibuf_pc(head_ptr + deq_idx))
io.out(i).bits.isRVC := false.B
io.out(i).valid := true.B
ibuf_valid(head_ptr + deq_idx) := false.B
ibuf_valid(head_ptr + deq_idx+1.U) := false.B
}.otherwise {
// half inst keep in buffer
io.out(i).bits.instr := 0.U(32.W)
XSWarn("This is half inst\n")
io.out(i).bits.pc := 0.U(VAddrBits.W)
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
}.otherwise {
XSWarn("This output is not ready, or buffer is empty\n")
io.out(i).bits.instr := 0.U
io.out(i).bits.pc := 0.U
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
// 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 +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && !(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) && ibuf_valid(head_ptr + deq_idx + 1.U)) +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && !(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) && ibuf_valid(head_ptr + deq_idx + 1.U))
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
))
}
head_ptr := head_ptr + deq_idx
XSInfo("Deque finished\n")
XSInfo("head_prt=%d, tail_ptr=%d\n", head_ptr + deq_idx, tail_ptr)
last_enq := false.B
}.otherwise {
for(i <- 0 until DecodeWidth) {
io.out(i).bits.instr := 0.U
io.out(i).bits.pc := 0.U
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
}
// flush
when(io.flush) {
XSInfo("Flush signal received, clear buffer\n")
for(i <- 0 until IBufSize) {
ibuf_valid(i) := false.B
head_ptr := 0.U
tail_ptr := 0.U
}
for(i <- 0 until DecodeWidth) {
io.out(i).valid := false.B
}
}
package xiangshan.frontend
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils._
class Ibuffer extends XSModule {
val io = IO(new Bundle() {
val flush = Input(Bool())
val in = Flipped(DecoupledIO(new FetchPacket))
val out = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
})
when(io.in.valid) {
XSDebug("cache data\n")
for (i <- 0 until FetchWidth) {
XSDebug("%b\n", io.in.bits.instrs(i))
}
}
// ignore
for(i <- 0 until DecodeWidth) {
io.out(i).bits.exceptionVec := DontCare
io.out(i).bits.intrVec := DontCare
io.out(i).bits.isBr := DontCare
}
//mask initial
// val mask = Wire(Vec(FetchWidth*2, false.B))
// (0 until 16).map(i => mask(i.U) := (io.in.bits.pc(4,1) <= i.U))
// ibuf define
val ibuf = RegInit(VecInit(Seq.fill(IBufSize*2)(0.U(16.W))))
val ibuf_pc = RegInit(VecInit(Seq.fill(IBufSize*2)(0.U(VAddrBits.W))))
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))
// true: Last operation is enqueue
// false: Last operation is deq_ueue
val last_enq = RegInit(false.B)
val full = head_ptr === tail_ptr && last_enq
val empty = head_ptr === tail_ptr && !last_enq
val enqValid = !io.flush && io.in.valid && !full && !ibuf_valid(tail_ptr + (FetchWidth*2).U)
val deqValid = !io.flush && !empty //&& io.out.map(_.ready).reduce(_||_)
XSWarn(empty, "Ibuffer is empty\n")
XSWarn(full, "Ibuffer is full\n")
io.in.ready := enqValid
// enque
when(enqValid) {
XSInfo("Enque start\n")
var enq_idx = 0.U(log2Up(FetchWidth*2+1).W)
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
ibuf_valid(tail_ptr + enq_idx) := true.B
XSDebug("Enque: %b\n", Mux(i.U(0), io.in.bits.instrs(i>>1)(31,16), io.in.bits.instrs(i>>1)(15,0)))
}
enq_idx = enq_idx + io.in.bits.mask(i)
}
tail_ptr := tail_ptr + enq_idx
last_enq := true.B
XSInfo("Enque finished, tail_ptr=%d\n", tail_ptr + enq_idx)
}
// deque
when(deqValid) {
XSInfo("Deque start\n")
var deq_idx = 0.U(log2Up(DecodeWidth*2+1).W)
for(i <- 0 until DecodeWidth) {
when(io.out(i).ready && ibuf_valid(head_ptr + deq_idx)) {
when(ibuf(head_ptr + deq_idx)(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)
XSDebug("%b[RVC] PC=%d\n", Cat(0.U(16.W), ibuf(head_ptr + deq_idx)), ibuf_pc(head_ptr + deq_idx))
io.out(i).bits.isRVC := true.B
io.out(i).valid := true.B
ibuf_valid(head_ptr + deq_idx) := false.B
}.elsewhen(ibuf_valid(head_ptr + 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)
XSDebug("%b[NORVC] PC=%d\n", Cat(ibuf(head_ptr + deq_idx+1.U), ibuf(head_ptr + deq_idx)), ibuf_pc(head_ptr + deq_idx))
io.out(i).bits.isRVC := false.B
io.out(i).valid := true.B
ibuf_valid(head_ptr + deq_idx) := false.B
ibuf_valid(head_ptr + deq_idx+1.U) := false.B
}.otherwise {
// half inst keep in buffer
io.out(i).bits.instr := 0.U(32.W)
XSWarn("This is half inst\n")
io.out(i).bits.pc := 0.U(VAddrBits.W)
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
}.otherwise {
XSWarn("This output is not ready, or buffer is empty\n")
io.out(i).bits.instr := 0.U
io.out(i).bits.pc := 0.U
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
// 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 +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && !(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) && ibuf_valid(head_ptr + deq_idx + 1.U)) +
// (io.out(i).ready && ibuf_valid(head_ptr + deq_idx) && !(ibuf(head_ptr + deq_idx)(1,0) =/= "b11".U) && ibuf_valid(head_ptr + deq_idx + 1.U))
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
))
}
head_ptr := head_ptr + deq_idx
XSInfo("Deque finished\n")
XSInfo("head_prt=%d, tail_ptr=%d\n", head_ptr + deq_idx, tail_ptr)
last_enq := false.B
}.otherwise {
for(i <- 0 until DecodeWidth) {
io.out(i).bits.instr := 0.U
io.out(i).bits.pc := 0.U
io.out(i).bits.isRVC := false.B
io.out(i).valid := false.B
}
}
// flush
when(io.flush) {
XSInfo("Flush signal received, clear buffer\n")
for(i <- 0 until IBufSize) {
ibuf_valid(i) := false.B
head_ptr := 0.U
tail_ptr := 0.U
}
for(i <- 0 until DecodeWidth) {
io.out(i).valid := false.B
}
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ import xiangshan.utils.XSLogLevel.XSLogLevel
object XSLogLevel extends Enumeration {
type XSLogLevel = Value
val ALL = Value("ALL ")
val ALL = Value(0, "ALL ")
val DEBUG = Value("DEBUG")
val INFO = Value("INFO ")
val WARN = Value("WARN ")
......@@ -16,9 +16,9 @@ object XSLogLevel extends Enumeration {
val OFF = Value("OFF ")
}
object XSLog extends HasXSParameter {
object XSLog {
def displayLog(): Bool = {
def displayLog: Bool = {
val disp_begin, disp_end = WireInit(0.U(64.W))
BoringUtils.addSink(disp_begin, "DISPALY_LOG_START")
BoringUtils.addSink(disp_end, "DISPLAY_LOG_END")
......@@ -26,14 +26,19 @@ object XSLog extends HasXSParameter {
(GTimer() >= disp_begin) && (GTimer() <= disp_end)
}
def xsLogLevel: UInt = {
val log_level = WireInit(0.U(64.W))
BoringUtils.addSink(log_level, "DISPLAY_LOG_LEVEL")
assert(log_level < XSLogLevel.maxId.U)
log_level
}
def apply(debugLevel: XSLogLevel)
(cond: Bool, pable: Printable)
(implicit m: Module): Any = {
if (debugLevel >= LogLevel) {
when (cond && displayLog()) {
val commonInfo = p"[$debugLevel][time=${GTimer()}] ${m.name}: "
printf(commonInfo + pable)
}
val commonInfo = p"[$debugLevel][time=${GTimer()}] ${m.name}: "
when (debugLevel.id.U >= xsLogLevel && cond && displayLog) {
printf(commonInfo + pable)
}
}
}
......@@ -49,7 +54,7 @@ sealed abstract class LogHelper(val logLevel: XSLogLevel) extends HasXSParameter
// Do not use that unless you have valid reasons
def apply(cond: Bool = true.B)(body: => Unit): Any =
if (logLevel >= LogLevel) { when (cond && XSLog.displayLog()) { body } }
when (logLevel.id.U >= XSLog.xsLogLevel && cond && XSLog.displayLog) { body }
}
object XSDebug extends LogHelper(XSLogLevel.DEBUG)
......
......@@ -42,6 +42,18 @@ void init_device(void);
bool is_finished(void);
int get_exit_code(void);
// log
enum {
LOG_ALL = 0,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_OFF
};
uint64_t getLogLevel(const char * str);
void app_error(const char *fmt, ...);
int monitor(void);
......
......@@ -25,7 +25,7 @@ class Emulator {
// emu control variable
uint32_t seed;
uint64_t max_cycles, cycles;
uint64_t log_begin, log_end;
uint64_t log_begin, log_end, log_level;
std::vector<const char *> parse_args(int argc, const char *argv[]);
......@@ -57,7 +57,7 @@ class Emulator {
image(nullptr),
dut_ptr(new std::remove_reference<decltype(*dut_ptr)>::type),
seed(0), max_cycles(-1), cycles(0),
log_begin(0), log_end(-1)
log_begin(0), log_end(-1), log_level(LOG_ALL)
{
// init emu
auto args = parse_args(argc, argv);
......@@ -67,9 +67,10 @@ class Emulator {
srand48(seed);
Verilated::randReset(2);
// set log time range
// set log time range and log level
dut_ptr->io_logCtrl_log_begin = log_begin;
dut_ptr->io_logCtrl_log_end = log_end;
dut_ptr->io_logCtrl_log_level = log_level;
// init ram
extern void init_ram(const char *img);
......@@ -141,6 +142,8 @@ class Emulator {
set_abort();
}
printf("xsstatus pc=%lx commit=%d\n", dut_ptr->io_difftest_thisPC, dut_ptr->io_difftest_commit);//FIXIT: delete me when dummy test is passed
if (!hascommit && dut_ptr->io_difftest_thisPC == 0x80000000u) {
hascommit = 1;
extern void init_difftest(uint64_t *reg);
......
#include <cstdio>
#include <cstring>
#include "common.h"
uint64_t getLogLevel(const char * str) {
if(!strcmp("ALL", str)){
return LOG_ALL;
} else if(!strcmp("DEBUG", str)){
return LOG_DEBUG;
} else if(!strcmp("INFO", str)){
return LOG_INFO;
} else if(!strcmp("WARN", str)){
return LOG_WARN;
} else if(!strcmp("ERROR", str)){
return LOG_ERROR;
} else if(!strcmp("OFF", str)){
return LOG_OFF;
} else {
printf("Unknown verbosity level!\n");
exit(-1);
}
}
......@@ -20,8 +20,9 @@ const struct option Emulator::long_options[] = {
{ "seed", 1, NULL, 's' },
{ "max-cycles", 1, NULL, 'C' },
{ "image", 1, NULL, 'i' },
{ "log-begin", 1, NULL, 'b'},
{ "log-end", 1, NULL, 'e'},
{ "log-begin", 1, NULL, 'b' },
{ "log-end", 1, NULL, 'e' },
{ "verbose", 1, NULL, 'v' },
{ "help", 0, NULL, 'h' },
{ 0, 0, NULL, 0 }
};
......@@ -34,6 +35,7 @@ void Emulator::print_help(const char *file) {
printf(" -i, --image=FILE run with this image file\n");
printf(" -b, --log-begin=NUM display log from NUM th cycle\n");
printf(" -e, --log-end=NUM stop display log at NUM th cycle\n");
printf(" -v, --verbose=STR verbosity level, can be one of [ALL, DEBUG, INFO, WARN, ERROR]\n");
printf(" -h, --help print program help info\n");
printf("\n");
}
......@@ -41,7 +43,7 @@ void Emulator::print_help(const char *file) {
std::vector<const char *> Emulator::parse_args(int argc, const char *argv[]) {
std::vector<const char *> args = { argv[0] };
int o;
while ( (o = getopt_long(argc, const_cast<char *const*>(argv), "-s:C:hi:m:b:e:", long_options, NULL)) != -1) {
while ( (o = getopt_long(argc, const_cast<char *const*>(argv), "-s:C:hi:m:b:e:l:", long_options, NULL)) != -1) {
switch (o) {
case 's':
if(std::string(optarg) != "NO_SEED") {
......@@ -56,6 +58,7 @@ std::vector<const char *> Emulator::parse_args(int argc, const char *argv[]) {
break;
case 'b': log_begin = atoll(optarg); break;
case 'e': log_end = atoll(optarg); break;
case 'v': log_level = getLogLevel(optarg); break;
default:
print_help(argv[0]);
exit(0);
......
......@@ -28,7 +28,8 @@ class DiffTestIO extends Bundle {
}
class LogCtrlIO extends Bundle {
val log_begin, log_end = Input(UInt(32.W))
val log_begin, log_end = Input(UInt(64.W))
val log_level = Input(UInt(64.W)) // a cpp uint
}
class XSSimTop extends Module {
......@@ -72,12 +73,14 @@ class XSSimTop extends Module {
BoringUtils.addSink(difftest.scause, "difftestScause")
io.difftest := difftest
val log_begin, log_end = Wire(UInt(32.W))
val log_begin, log_end, log_level = Wire(UInt(64.W))
log_begin := io.logCtrl.log_begin
log_end := io.logCtrl.log_end
log_level := io.logCtrl.log_level
BoringUtils.addSource(log_begin, "DISPALY_LOG_START")
BoringUtils.addSource(log_end, "DISPLAY_LOG_END")
BoringUtils.addSource(log_level, "DISPLAY_LOG_LEVEL")
}
object TestMain extends App {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册