Merge remote-tracking branch 'origin/master' into ss-frontend
Conflicts: src/main/scala/btb.scala src/main/scala/core.scala
This commit is contained in:
commit
99614e37aa
@ -41,35 +41,57 @@ class RAS(nras: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BHTResp extends Bundle with BTBParameters {
|
class BHTResp extends Bundle with BTBParameters {
|
||||||
val index = UInt(width = log2Up(nBHT).max(1))
|
val history = UInt(width = log2Up(nBHT).max(1))
|
||||||
val value = UInt(width = 2)
|
val value = UInt(width = 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BHT(nbht: Int) {
|
// BHT contains table of 2-bit counters and a global history register.
|
||||||
|
// The BHT only predicts and updates when there is a BTB hit.
|
||||||
|
// The global history:
|
||||||
|
// - updated speculatively in fetch (if there's a BTB hit).
|
||||||
|
// - on a mispredict, the history register is reset (again, only if BTB hit).
|
||||||
|
// The counter table:
|
||||||
|
// - each PC has its own counter, updated when a branch resolves (and BTB hit).
|
||||||
|
// - the BTB provides the predicted branch PC, allowing us to properly index
|
||||||
|
// the counter table and provide the prediction for that specific branch.
|
||||||
|
// Critical path concerns may require only providing a single counter for
|
||||||
|
// the entire fetch packet, but that complicates how multiple branches
|
||||||
|
// update that line.
|
||||||
|
class BHT(nbht: Int, fetchwidth: Int) {
|
||||||
val nbhtbits = log2Up(nbht)
|
val nbhtbits = log2Up(nbht)
|
||||||
def get(addr: UInt): BHTResp = {
|
private val logfw = if (fetchwidth == 1) 0 else log2Up(fetchwidth)
|
||||||
|
|
||||||
|
def get(fetch_addr: UInt, bridx: UInt, update: Bool): BHTResp = {
|
||||||
val res = new BHTResp
|
val res = new BHTResp
|
||||||
res.index := addr(nbhtbits+1,2) ^ history
|
val aligned_addr = fetch_addr >> UInt(logfw + 2)
|
||||||
res.value := table(res.index)
|
val index = aligned_addr ^ history
|
||||||
|
val counters = table(index)
|
||||||
|
res.value := (counters >> (bridx<<1)) & Bits(0x3)
|
||||||
|
res.history := history
|
||||||
|
val taken = res.value(0)
|
||||||
|
when (update) { history := Cat(taken, history(nbhtbits-1,1)) }
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
def update(d: BHTResp, taken: Bool): Unit = {
|
def update(addr: UInt, d: BHTResp, taken: Bool, mispredict: Bool): Unit = {
|
||||||
table(d.index) := Cat(taken, (d.value(1) & d.value(0)) | ((d.value(1) | d.value(0)) & taken))
|
val aligned_addr = addr >> UInt(logfw + 2)
|
||||||
history := Cat(taken, history(nbhtbits-1,1))
|
val index = aligned_addr ^ d.history
|
||||||
|
val new_cntr = Cat(taken, (d.value(1) & d.value(0)) | ((d.value(1) | d.value(0)) & taken))
|
||||||
|
var bridx: UInt = null
|
||||||
|
if (logfw == 0) bridx = UInt(0) else bridx = addr(logfw+1,2)
|
||||||
|
val mask = Bits(0x3) << (bridx<<1)
|
||||||
|
table.write(index, new_cntr, mask)
|
||||||
|
when (mispredict) { history := Cat(taken, d.history(nbhtbits-1,1)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val table = Mem(UInt(width = 2), nbht)
|
private val table = Mem(UInt(width = 2*fetchwidth), nbht)
|
||||||
val history = Reg(UInt(width = nbhtbits))
|
val history = Reg(UInt(width = nbhtbits))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BTB update occurs during branch resolution (i.e., PC redirection if a mispredict).
|
// BTB update occurs during branch resolution.
|
||||||
// - "pc" is what future fetch PCs will tag match against.
|
// - "pc" is what future fetch PCs will tag match against.
|
||||||
// - "br_pc" is the PC of the branch instruction.
|
// - "br_pc" is the PC of the branch instruction.
|
||||||
// - "resp.mask" provides a mask of valid instructions (instructions are
|
// - "resp.mask" provides a mask of valid instructions (instructions are
|
||||||
// masked off by the predicted, taken branch).
|
// masked off by the predicted taken branch).
|
||||||
// Assumption: superscalar commits are batched together into a single
|
|
||||||
// "taken" update ("history compression"), and correspond to the
|
|
||||||
// superscalar fetch 1:1.
|
|
||||||
class BTBUpdate extends Bundle with BTBParameters {
|
class BTBUpdate extends Bundle with BTBParameters {
|
||||||
val prediction = Valid(new BTBResp)
|
val prediction = Valid(new BTBResp)
|
||||||
val pc = UInt(width = vaddrBits)
|
val pc = UInt(width = vaddrBits)
|
||||||
@ -91,10 +113,14 @@ class BTBResp extends Bundle with BTBParameters {
|
|||||||
val bht = new BHTResp
|
val bht = new BHTResp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BTBReq extends Bundle with BTBParameters {
|
||||||
|
val addr = UInt(width = vaddrBits)
|
||||||
|
}
|
||||||
|
|
||||||
// fully-associative branch target buffer
|
// fully-associative branch target buffer
|
||||||
class BTB extends Module with BTBParameters {
|
class BTB extends Module with BTBParameters {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val req = UInt(INPUT, vaddrBits)
|
val req = Valid(new BTBReq).flip
|
||||||
val resp = Valid(new BTBResp)
|
val resp = Valid(new BTBResp)
|
||||||
val update = Valid(new BTBUpdate).flip
|
val update = Valid(new BTBUpdate).flip
|
||||||
val invalidate = Bool(INPUT)
|
val invalidate = Bool(INPUT)
|
||||||
@ -126,23 +152,23 @@ class BTB extends Module with BTBParameters {
|
|||||||
idxValid & idxMatch & idxPageMatch
|
idxValid & idxMatch & idxPageMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
val update = Pipe(io.update)
|
val r_update = Pipe(io.update)
|
||||||
val update_target = io.req
|
val update_target = io.req.bits.addr
|
||||||
|
|
||||||
val pageHit = pageMatch(io.req)
|
val pageHit = pageMatch(io.req.bits.addr)
|
||||||
val hits = tagMatch(io.req, pageHit)
|
val hits = tagMatch(io.req.bits.addr, pageHit)
|
||||||
val updatePageHit = pageMatch(update.bits.pc)
|
val updatePageHit = pageMatch(r_update.bits.pc)
|
||||||
val updateHits = tagMatch(update.bits.pc, updatePageHit)
|
val updateHits = tagMatch(r_update.bits.pc, updatePageHit)
|
||||||
|
|
||||||
private var lfsr = LFSR16(update.valid)
|
private var lfsr = LFSR16(r_update.valid)
|
||||||
def rand(width: Int) = {
|
def rand(width: Int) = {
|
||||||
lfsr = lfsr(lfsr.getWidth-1,1)
|
lfsr = lfsr(lfsr.getWidth-1,1)
|
||||||
Random.oneHot(width, lfsr)
|
Random.oneHot(width, lfsr)
|
||||||
}
|
}
|
||||||
|
|
||||||
val updateHit = update.bits.prediction.valid
|
val updateHit = r_update.bits.prediction.valid
|
||||||
val updateValid = update.bits.incorrectTarget || updateHit && Bool(nBHT > 0)
|
val updateValid = r_update.bits.incorrectTarget || updateHit && Bool(nBHT > 0)
|
||||||
val updateTarget = updateValid && update.bits.incorrectTarget
|
val updateTarget = updateValid && r_update.bits.incorrectTarget
|
||||||
|
|
||||||
val useUpdatePageHit = updatePageHit.orR
|
val useUpdatePageHit = updatePageHit.orR
|
||||||
val doIdxPageRepl = updateTarget && !useUpdatePageHit
|
val doIdxPageRepl = updateTarget && !useUpdatePageHit
|
||||||
@ -151,7 +177,7 @@ class BTB extends Module with BTBParameters {
|
|||||||
val idxPageUpdate = OHToUInt(idxPageUpdateOH)
|
val idxPageUpdate = OHToUInt(idxPageUpdateOH)
|
||||||
val idxPageReplEn = Mux(doIdxPageRepl, idxPageRepl, UInt(0))
|
val idxPageReplEn = Mux(doIdxPageRepl, idxPageRepl, UInt(0))
|
||||||
|
|
||||||
val samePage = page(update.bits.pc) === page(update_target)
|
val samePage = page(r_update.bits.pc) === page(update_target)
|
||||||
val usePageHit = (pageHit & ~idxPageReplEn).orR
|
val usePageHit = (pageHit & ~idxPageReplEn).orR
|
||||||
val doTgtPageRepl = updateTarget && !samePage && !usePageHit
|
val doTgtPageRepl = updateTarget && !samePage && !usePageHit
|
||||||
val tgtPageRepl = Mux(samePage, idxPageUpdateOH, idxPageUpdateOH(nPages-2,0) << 1 | idxPageUpdateOH(nPages-1))
|
val tgtPageRepl = Mux(samePage, idxPageUpdateOH, idxPageUpdateOH(nPages-2,0) << 1 | idxPageUpdateOH(nPages-1))
|
||||||
@ -160,25 +186,25 @@ class BTB extends Module with BTBParameters {
|
|||||||
val doPageRepl = doIdxPageRepl || doTgtPageRepl
|
val doPageRepl = doIdxPageRepl || doTgtPageRepl
|
||||||
|
|
||||||
val pageReplEn = idxPageReplEn | tgtPageReplEn
|
val pageReplEn = idxPageReplEn | tgtPageReplEn
|
||||||
idxPageRepl := UIntToOH(Counter(update.valid && doPageRepl, nPages)._1)
|
idxPageRepl := UIntToOH(Counter(r_update.valid && doPageRepl, nPages)._1)
|
||||||
|
|
||||||
when (update.valid && !(updateValid && !updateTarget)) {
|
when (r_update.valid && !(updateValid && !updateTarget)) {
|
||||||
val nextRepl = Counter(!updateHit && updateValid, entries)._1
|
val nextRepl = Counter(!updateHit && updateValid, entries)._1
|
||||||
val waddr = Mux(updateHit, update.bits.prediction.bits.entry, nextRepl)
|
val waddr = Mux(updateHit, r_update.bits.prediction.bits.entry, nextRepl)
|
||||||
|
|
||||||
// invalidate entries if we stomp on pages they depend upon
|
// invalidate entries if we stomp on pages they depend upon
|
||||||
idxValid := idxValid & ~Vec.tabulate(entries)(i => (pageReplEn & (idxPagesOH(i) | tgtPagesOH(i))).orR).toBits
|
idxValid := idxValid & ~Vec.tabulate(entries)(i => (pageReplEn & (idxPagesOH(i) | tgtPagesOH(i))).orR).toBits
|
||||||
|
|
||||||
idxValid(waddr) := updateValid
|
idxValid(waddr) := updateValid
|
||||||
when (updateTarget) {
|
when (updateTarget) {
|
||||||
assert(io.req === update.bits.target, "BTB request != I$ target")
|
assert(io.req.bits.addr === r_update.bits.target, "BTB request != I$ target")
|
||||||
idxs(waddr) := update.bits.pc
|
idxs(waddr) := r_update.bits.pc
|
||||||
tgts(waddr) := update_target
|
tgts(waddr) := update_target
|
||||||
idxPages(waddr) := idxPageUpdate
|
idxPages(waddr) := idxPageUpdate
|
||||||
tgtPages(waddr) := tgtPageUpdate
|
tgtPages(waddr) := tgtPageUpdate
|
||||||
useRAS(waddr) := update.bits.isReturn
|
useRAS(waddr) := r_update.bits.isReturn
|
||||||
isJump(waddr) := update.bits.isJump
|
isJump(waddr) := r_update.bits.isJump
|
||||||
brIdx(waddr) := update.bits.br_pc
|
brIdx(waddr) := r_update.bits.br_pc
|
||||||
}
|
}
|
||||||
|
|
||||||
require(nPages % 2 == 0)
|
require(nPages % 2 == 0)
|
||||||
@ -189,9 +215,9 @@ class BTB extends Module with BTBParameters {
|
|||||||
when (en && pageReplEn(i)) { pages(i) := data }
|
when (en && pageReplEn(i)) { pages(i) := data }
|
||||||
|
|
||||||
writeBank(0, 2, Mux(idxWritesEven, doIdxPageRepl, doTgtPageRepl),
|
writeBank(0, 2, Mux(idxWritesEven, doIdxPageRepl, doTgtPageRepl),
|
||||||
Mux(idxWritesEven, page(update.bits.pc), page(update_target)))
|
Mux(idxWritesEven, page(r_update.bits.pc), page(update_target)))
|
||||||
writeBank(1, 2, Mux(idxWritesEven, doTgtPageRepl, doIdxPageRepl),
|
writeBank(1, 2, Mux(idxWritesEven, doTgtPageRepl, doIdxPageRepl),
|
||||||
Mux(idxWritesEven, page(update_target), page(update.bits.pc)))
|
Mux(idxWritesEven, page(update_target), page(r_update.bits.pc)))
|
||||||
|
|
||||||
when (doPageRepl) { pageValid := pageValid | pageReplEn }
|
when (doPageRepl) { pageValid := pageValid | pageReplEn }
|
||||||
}
|
}
|
||||||
@ -208,9 +234,13 @@ class BTB extends Module with BTBParameters {
|
|||||||
io.resp.bits.mask := Cat((UInt(1) << brIdx(io.resp.bits.entry))-1, UInt(1))
|
io.resp.bits.mask := Cat((UInt(1) << brIdx(io.resp.bits.entry))-1, UInt(1))
|
||||||
|
|
||||||
if (nBHT > 0) {
|
if (nBHT > 0) {
|
||||||
val bht = new BHT(nBHT)
|
val bht = new BHT(nBHT, params(FetchWidth))
|
||||||
val res = bht.get(io.req)
|
val res = bht.get(io.req.bits.addr, brIdx(io.resp.bits.entry), io.req.valid && hits.orR && !Mux1H(hits, isJump))
|
||||||
when (update.valid && updateHit && !update.bits.isJump) { bht.update(update.bits.prediction.bits.bht, update.bits.taken) }
|
val update_btb_hit = io.update.bits.prediction.valid
|
||||||
|
when (io.update.valid && update_btb_hit && !io.update.bits.isJump) {
|
||||||
|
bht.update(io.update.bits.br_pc, io.update.bits.prediction.bits.bht,
|
||||||
|
io.update.bits.taken, io.update.bits.incorrectTarget)
|
||||||
|
}
|
||||||
when (!res.value(0) && !Mux1H(hits, isJump)) { io.resp.bits.taken := false }
|
when (!res.value(0) && !Mux1H(hits, isJump)) { io.resp.bits.taken := false }
|
||||||
io.resp.bits.bht := res
|
io.resp.bits.bht := res
|
||||||
}
|
}
|
||||||
|
@ -61,28 +61,3 @@ trait ScalarOpConstants {
|
|||||||
|
|
||||||
val RA = UInt(1, 5)
|
val RA = UInt(1, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VectorOpConstants {
|
|
||||||
val VEC_X = Bits("b??", 2).toUInt
|
|
||||||
val VEC_FN_N = UInt(0, 2)
|
|
||||||
val VEC_VL = UInt(1, 2)
|
|
||||||
val VEC_CFG = UInt(2, 2)
|
|
||||||
val VEC_CFGVL = UInt(3, 2)
|
|
||||||
|
|
||||||
val VCMD_I = UInt(0, 3)
|
|
||||||
val VCMD_F = UInt(1, 3)
|
|
||||||
val VCMD_TX = UInt(2, 3)
|
|
||||||
val VCMD_TF = UInt(3, 3)
|
|
||||||
val VCMD_MX = UInt(4, 3)
|
|
||||||
val VCMD_MF = UInt(5, 3)
|
|
||||||
val VCMD_A = UInt(6, 3)
|
|
||||||
val VCMD_X = UInt(0, 3)
|
|
||||||
|
|
||||||
val VIMM_VLEN = UInt(0, 1)
|
|
||||||
val VIMM_ALU = UInt(1, 1)
|
|
||||||
val VIMM_X = UInt(0, 1)
|
|
||||||
|
|
||||||
val VIMM2_RS2 = UInt(0, 1)
|
|
||||||
val VIMM2_ALU = UInt(1, 1)
|
|
||||||
val VIMM2_X = UInt(0, 1)
|
|
||||||
}
|
|
||||||
|
@ -30,9 +30,14 @@ abstract trait CoreParameters extends UsesParameters {
|
|||||||
val coreMaxAddrBits = math.max(params(PPNBits),params(VPNBits)+1) + params(PgIdxBits)
|
val coreMaxAddrBits = math.max(params(PPNBits),params(VPNBits)+1) + params(PgIdxBits)
|
||||||
|
|
||||||
if(params(FastLoadByte)) require(params(FastLoadWord))
|
if(params(FastLoadByte)) require(params(FastLoadWord))
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract trait RocketCoreParameters extends CoreParameters
|
||||||
|
{
|
||||||
require(params(FetchWidth) == 1) // for now...
|
require(params(FetchWidth) == 1) // for now...
|
||||||
require(params(RetireWidth) == 1) // for now...
|
require(params(RetireWidth) == 1) // for now...
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CoreBundle extends Bundle with CoreParameters
|
abstract class CoreBundle extends Bundle with CoreParameters
|
||||||
abstract class CoreModule extends Module with CoreParameters
|
abstract class CoreModule extends Module with CoreParameters
|
||||||
|
|
||||||
|
@ -287,6 +287,7 @@ class Datapath extends Module
|
|||||||
io.imem.btb_update.bits.pc := mem_reg_pc
|
io.imem.btb_update.bits.pc := mem_reg_pc
|
||||||
io.imem.btb_update.bits.target := io.imem.req.bits.pc
|
io.imem.btb_update.bits.target := io.imem.req.bits.pc
|
||||||
io.imem.btb_update.bits.returnAddr := mem_int_wdata
|
io.imem.btb_update.bits.returnAddr := mem_int_wdata
|
||||||
|
io.imem.btb_update.bits.br_pc := mem_reg_pc
|
||||||
|
|
||||||
// for hazard/bypass opportunity detection
|
// for hazard/bypass opportunity detection
|
||||||
io.ctrl.ex_waddr := ex_reg_inst(11,7)
|
io.ctrl.ex_waddr := ex_reg_inst(11,7)
|
||||||
|
@ -84,7 +84,8 @@ class Frontend extends FrontendModule
|
|||||||
s2_valid := Bool(false)
|
s2_valid := Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
btb.io.req := s1_pc & SInt(-coreInstBytes)
|
btb.io.req.valid := !stall && !icmiss
|
||||||
|
btb.io.req.bits.addr := s1_pc & SInt(-coreInstBytes)
|
||||||
btb.io.update := io.cpu.btb_update
|
btb.io.update := io.cpu.btb_update
|
||||||
btb.io.invalidate := io.cpu.invalidate || io.cpu.ptw.invalidate
|
btb.io.invalidate := io.cpu.invalidate || io.cpu.ptw.invalidate
|
||||||
|
|
||||||
|
@ -817,7 +817,7 @@ class HellaCache extends L1HellaCacheModule {
|
|||||||
val regs = Vec.fill(rowWords){Reg(Bits(width = encDataBits))}
|
val regs = Vec.fill(rowWords){Reg(Bits(width = encDataBits))}
|
||||||
val en1 = s1_clk_en && s1_tag_eq_way(w)
|
val en1 = s1_clk_en && s1_tag_eq_way(w)
|
||||||
for (i <- 0 until regs.size) {
|
for (i <- 0 until regs.size) {
|
||||||
val en = en1 && (Bool(i == 0 || !doNarrowRead) || s1_writeback)
|
val en = en1 && ((Bool(i == 0) || !Bool(doNarrowRead)) || s1_writeback)
|
||||||
when (en) { regs(i) := data.io.resp(w) >> encDataBits*i }
|
when (en) { regs(i) := data.io.resp(w) >> encDataBits*i }
|
||||||
}
|
}
|
||||||
s2_data(w) := regs.toBits
|
s2_data(w) := regs.toBits
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
|
|
||||||
package object rocket extends
|
package object rocket extends
|
||||||
rocket.constants.ScalarOpConstants with
|
rocket.constants.ScalarOpConstants
|
||||||
rocket.constants.VectorOpConstants
|
|
||||||
{
|
{
|
||||||
val START_ADDR = 0x2000
|
val START_ADDR = 0x2000
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,14 @@ case object NTilePorts extends Field[Int]
|
|||||||
case object NPTWPorts extends Field[Int]
|
case object NPTWPorts extends Field[Int]
|
||||||
case object BuildRoCC extends Field[Option[() => RoCC]]
|
case object BuildRoCC extends Field[Option[() => RoCC]]
|
||||||
|
|
||||||
class Tile(resetSignal: Bool = null) extends Module(_reset = resetSignal) {
|
abstract class Tile(resetSignal: Bool = null) extends Module(_reset = resetSignal) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val tilelink = new TileLinkIO
|
val tilelink = new TileLinkIO
|
||||||
val host = new HTIFIO
|
val host = new HTIFIO
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RocketTile(resetSignal: Bool = null) extends Tile(resetSignal) {
|
||||||
|
|
||||||
val icache = Module(new Frontend, { case CacheName => "L1I"; case CoreName => "Rocket" })
|
val icache = Module(new Frontend, { case CacheName => "L1I"; case CoreName => "Rocket" })
|
||||||
val dcache = Module(new HellaCache, { case CacheName => "L1D" })
|
val dcache = Module(new HellaCache, { case CacheName => "L1D" })
|
||||||
|
Loading…
Reference in New Issue
Block a user