Skip to content

Commit

Permalink
Merge pull request #435 from riscv-boom/clean_trace
Browse files Browse the repository at this point in the history
[core] Store insts in a SyncReadMem | regenerate PCs from the FTQ
  • Loading branch information
jerryz123 committed Jan 30, 2020
2 parents a88fe70 + 9883dc6 commit 1d4d0cd
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 14 deletions.
41 changes: 32 additions & 9 deletions src/main/scala/exu/core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import freechips.rocketchip.devices.tilelink.{PLICConsts, CLINTConsts}
import boom.common._
import boom.exu.FUConstants._
import boom.common.BoomTilesKey
import boom.util.{RobTypeToChars, BoolToChar, GetNewUopAndBrMask, Sext, WrapInc, BoomCoreStringPrefix, DromajoCosimBlackBox}
import boom.util.{RobTypeToChars, BoolToChar, GetNewUopAndBrMask, Sext, WrapInc, BoomCoreStringPrefix, DromajoCosimBlackBox, AlignPCToBoundary}

/**
* IO bundle for the BOOM Core. Connects the external components such as
Expand Down Expand Up @@ -426,6 +426,7 @@ class BoomCore(implicit p: Parameters) extends BoomModule
// Branch Unit Requests
bru_pc_req.valid := RegNext(iss_valids(brunit_idx))
bru_pc_req.bits := RegNext(iss_uops(brunit_idx).ftq_idx)
exe_units(brunit_idx).io.get_ftq_pc := DontCare
exe_units(brunit_idx).io.get_ftq_pc.fetch_pc := RegNext(io.ifu.get_pc.fetch_pc)
exe_units(brunit_idx).io.get_ftq_pc.next_val := RegNext(io.ifu.get_pc.next_val)
exe_units(brunit_idx).io.get_ftq_pc.next_pc := RegNext(io.ifu.get_pc.next_pc)
Expand Down Expand Up @@ -1429,20 +1430,42 @@ class BoomCore(implicit p: Parameters) extends BoomModule
for (w <- 0 until coreWidth) {
io.trace(w).clock := clock
io.trace(w).reset := reset
io.trace(w).valid := rob.io.commit.valids(w)
io.trace(w).iaddr := Sext(rob.io.commit.uops(w).debug_pc(vaddrBits-1,0), xLen)
io.trace(w).insn := rob.io.commit.uops(w).debug_inst

// Delay the trace so we have a cycle to pull PCs out of the FTQ
io.trace(w).valid := RegNext(rob.io.commit.valids(w))

// Recalculate the PC
io.ifu.get_pc.debug_ftq_idx(w) := rob.io.commit.uops(w).ftq_idx
io.trace(w).iaddr := RegNext(Sext(AlignPCToBoundary(io.ifu.get_pc.debug_fetch_pc(w), icBlockBytes)
+ rob.io.commit.uops(w).pc_lob
- Mux(rob.io.commit.uops(w).edge_inst, 2.U, 0.U), xLen))

// use debug_insts instead of uop.debug_inst to use the rob's debug_inst_mem
io.trace(w).insn := rob.io.commit.debug_insts(w)

// Comment out this assert because it blows up FPGA synth-asserts
// This tests correctedness of the debug_inst mem
// when (RegNext(rob.io.commit.valids(w))) {
// assert(rob.io.commit.debug_insts(w) === RegNext(rob.io.commit.uops(w).debug_inst))
// }
// This tests correctedness of recovering pcs through ftq debug ports
// when (RegNext(rob.io.commit.valids(w))) {
// assert(Sext(io.trace(w).iaddr, xLen) ===
// RegNext(Sext(rob.io.commit.uops(w).debug_pc(vaddrBits-1,0), xLen)))
// }

// These csr signals do not exactly match up with the ROB commit signals.
io.trace(w).priv := csr.io.status.prv
io.trace(w).priv := RegNext(csr.io.status.prv)
// Can determine if it is an interrupt or not based on the MSB of the cause
io.trace(w).exception := rob.io.com_xcpt.valid && !rob.io.com_xcpt.bits.cause(xLen - 1)
io.trace(w).interrupt := rob.io.com_xcpt.valid && rob.io.com_xcpt.bits.cause(xLen - 1)
io.trace(w).cause := rob.io.com_xcpt.bits.cause
io.trace(w).tval := csr.io.tval
io.trace(w).exception := RegNext(rob.io.com_xcpt.valid && !rob.io.com_xcpt.bits.cause(xLen - 1))
io.trace(w).interrupt := RegNext(rob.io.com_xcpt.valid && rob.io.com_xcpt.bits.cause(xLen - 1))
io.trace(w).cause := RegNext(rob.io.com_xcpt.bits.cause)
io.trace(w).tval := RegNext(csr.io.tval)
}
dontTouch(io.trace)
} else {
io.trace := DontCare
io.trace map (t => t.valid := false.B)
io.ifu.get_pc.debug_ftq_idx := DontCare
}
}
22 changes: 17 additions & 5 deletions src/main/scala/exu/rob.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ class CommitSignals(implicit p: Parameters) extends BoomBundle
val uops = Vec(retireWidth, new MicroOp())
val fflags = Valid(UInt(5.W))

// These come a cycle later
val debug_insts = Vec(retireWidth, UInt(32.W))

// Perform rollback of rename state (in conjuction with commit.uops).
val rbk_valids = Vec(retireWidth, Bool())
val rollback = Bool()
Expand Down Expand Up @@ -227,6 +230,9 @@ class Rob(
val rob_pnr_lsb = RegInit(0.U((1 max log2Ceil(coreWidth)).W))
val rob_pnr_idx = if (coreWidth == 1) rob_pnr else Cat(rob_pnr , rob_pnr_lsb)

val com_idx = Mux(rob_state === s_rollback, rob_tail, rob_head)


val maybe_full = RegInit(false.B)
val full = Wire(Bool())
val empty = Wire(Bool())
Expand Down Expand Up @@ -283,6 +289,13 @@ class Rob(
// Contains all information the PNR needs to find the oldest instruction which can't be safely speculated past.
val rob_unsafe_masked = WireInit(VecInit(Seq.fill(numRobRows << log2Ceil(coreWidth)){false.B}))

// Used for trace port, for debug purposes only
val rob_debug_inst_mem = SyncReadMem(numRobRows, Vec(coreWidth, UInt(32.W)))
val rob_debug_inst_wmask = WireInit(VecInit(0.U(coreWidth.W).asBools))
val rob_debug_inst_wdata = Wire(Vec(coreWidth, UInt(32.W)))
rob_debug_inst_mem.write(rob_tail, rob_debug_inst_wdata, rob_debug_inst_wmask)
val rob_debug_inst_rdata = rob_debug_inst_mem.read(rob_head, will_commit.reduce(_||_))

for (w <- 0 until coreWidth) {
def MatchBank(bank_idx: UInt): Bool = (bank_idx === w.U)

Expand All @@ -297,6 +310,9 @@ class Rob(
//-----------------------------------------------
// Dispatch: Add Entry to ROB

rob_debug_inst_wmask(w) := io.enq_valids(w)
rob_debug_inst_wdata(w) := io.enq_uops(w).debug_inst

when (io.enq_valids(w)) {
rob_val(rob_tail) := true.B
rob_bsy(rob_tail) := !(io.enq_uops(w).is_fence ||
Expand Down Expand Up @@ -401,16 +417,12 @@ class Rob(
// Can this instruction commit? (the check for exceptions/rob_state happens later).
can_commit(w) := rob_val(rob_head) && !(rob_bsy(rob_head)) && !io.csr_stall

val com_idx = Wire(UInt())
com_idx := rob_head
when (rob_state === s_rollback) {
com_idx := rob_tail
}

// use the same "com_uop" for both rollback AND commit
// Perform Commit
io.commit.valids(w) := will_commit(w)
io.commit.uops(w) := rob_uop(com_idx)
io.commit.debug_insts(w) := rob_debug_inst_rdata(w)

// Don't attempt to rollback the tail's row when the rob is full.
val rbk_row = rob_state === s_rollback && !full
Expand Down
9 changes: 9 additions & 0 deletions src/main/scala/ifu/fetch-target-queue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class GetPCFromFtqIO(implicit p: Parameters) extends BoomBundle
// the next_pc may not be valid (stalled or still being fetched)
val next_val = Output(Bool())
val next_pc = Output(UInt(vaddrBitsExtended.W))

// Used to regenerate PC for trace port stuff in FireSim
// Don't tape this out, this blows up the FTQ
val debug_ftq_idx = Input(Vec(coreWidth, UInt(log2Ceil(ftqSz).W)))
val debug_fetch_pc = Output(Vec(coreWidth, UInt(vaddrBitsExtended.W)))
}

/**
Expand Down Expand Up @@ -293,6 +298,10 @@ class FetchTargetQueue(num_entries: Int)(implicit p: Parameters) extends BoomMod
io.get_ftq_pc.next_pc := ram(WrapInc(curr_idx, num_entries)).fetch_pc
io.get_ftq_pc.next_val := WrapInc(curr_idx, num_entries) =/= enq_ptr.value

for (w <- 0 until coreWidth) {
io.get_ftq_pc.debug_fetch_pc(w) := ram(io.get_ftq_pc.debug_ftq_idx(w)).fetch_pc
}

//-------------------------------------------------------------
// **** Handle Flush/Pipeline Redirections ****
//-------------------------------------------------------------
Expand Down

0 comments on commit 1d4d0cd

Please sign in to comment.