未验证 提交 0be662e4 编写于 作者: J Jay 提交者: GitHub

Instr uncache: support instruction fecth from MMIO device ( flash ) (#1151)

* InstrUncache: change into 1 instruciton logic

* Frontend: add MMIO fetch port

* IFU: flush pipeline and only pass 1 instruction to backend when
finding the address is mmio

* BPU: set the resetVector to 10000000

* Frontend: connect ifu.uncache to instrUncache

* IFU: Fix conflict with master

* IFU: fix mmio instruction prediction problem

* IFU: fix tlb af only hold 1 cycle
上级 c3abb8b6
......@@ -28,13 +28,11 @@ import xiangshan.frontend._
class InsUncacheReq(implicit p: Parameters) extends ICacheBundle
{
val addr = UInt(PAddrBits.W)
val id = UInt(3.W)
}
class InsUncacheResp(implicit p: Parameters) extends ICacheBundle
{
val data = UInt((mmioBeats * mmioBusWidth).W)
val id = UInt(3.W)
val data = UInt(maxInstrLen.W)
}
// One miss entry deals with one mmio request
......@@ -58,9 +56,7 @@ class InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule w
val state = RegInit(s_invalid)
val req = Reg(new InsUncacheReq )
val respDataReg = Reg(Vec(mmioBeats,UInt(mmioBusWidth.W)))
val beatCounter = Counter(mmioBeats)
val respDataReg = Reg(UInt(mmioBusWidth.W))
// assign default values to output signals
io.req.ready := false.B
......@@ -74,14 +70,6 @@ class InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule w
val needFlush = RegInit(false.B)
XSDebug("[ICache MMIO]entry: %d state: %d needFlush%d flush:%d\n", io.id, state, needFlush,io.flush)
XSDebug("[ICache MMIO]req.addr: %x req.id \n", req.addr)
XSDebug("[ICache MMIO]mmio_acquire:(v:%d r:%d) mmio_grant:(v:%d r:%d)\n", io.mmio_acquire.valid, io.mmio_acquire.ready, io.mmio_grant.valid, io.mmio_grant.ready)
XSDebug("[ICache MMIO]mmio_acquire:(v:%d r:%d) mmio_grant:(v:%d r:%d)\n", io.mmio_acquire.valid, io.mmio_acquire.ready, io.mmio_grant.valid, io.mmio_grant.ready)
XSDebug("[ICache MMIO]respReg: %x\n",respDataReg.asUInt)
when(io.flush && (state =/= s_invalid) && (state =/= s_send_resp)){ needFlush := true.B }
.elsewhen((state=== s_send_resp) && needFlush){ needFlush := false.B }
......@@ -89,7 +77,6 @@ class InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule w
// s_invalid: receive requests
when (state === s_invalid) {
io.req.ready := true.B
beatCounter.value := 0.U
when (io.req.fire()) {
req := io.req.bits
......@@ -102,7 +89,7 @@ class InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule w
io.mmio_acquire.valid := true.B
io.mmio_acquire.bits := edge.Get(
fromSource = io.id,
toAddress = req.addr + (beatCounter.value << log2Ceil(mmioBusBytes).U),
toAddress = align(req.addr, mmioBusBytes),
lgSize = log2Ceil(mmioBusBytes).U
)._2
......@@ -117,29 +104,35 @@ class InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule w
io.mmio_grant.ready := true.B
when (io.mmio_grant.fire()) {
// val realAddr = packetAligned(req.addr) + (beatCounter.value << log2Ceil(mmioBusBytes).U)
// val start = realAddr(5,3)
respDataReg(beatCounter.value) := io.mmio_grant.bits.data
state :=Mux((beatCounter.value === (mmioBeats - 1).U) || needFlush || io.flush ,s_send_resp,s_refill_req)
beatCounter.inc()
respDataReg := io.mmio_grant.bits.data
state := s_send_resp
}
}
// --------------------------------------------
def getDataFromBus(pc: UInt) = {
val respData = Wire(UInt(maxInstrLen.W))
respData := Mux(pc(2,1) === "b00".U, respDataReg(31,0),
Mux(pc(2,1) === "b01".U, respDataReg(47,16),
Mux(pc(2,1) === "b10".U, respDataReg(63,32),
Cat(0.U, respDataReg(63,48))
)
)
)
respData
}
when (state === s_send_resp) {
io.resp.valid := !needFlush
io.resp.bits.data := respDataReg.asUInt
io.resp.bits.id := req.id
io.resp.valid := !needFlush
io.resp.bits.data := getDataFromBus(req.addr)
// meta data should go with the response
when (io.resp.fire() || needFlush) {
state := s_invalid
beatCounter.value := 0.U
}
}
}
class icacheUncacheIO(implicit p: Parameters) extends XSBundle {
val req = Flipped(DecoupledIO(new InsUncacheReq))
class InstrUncacheIO(implicit p: Parameters) extends DCacheBundle {
val req = Flipped(DecoupledIO(new InsUncacheReq ))
val resp = DecoupledIO(new InsUncacheResp)
val flush = Input(Bool())
}
......@@ -154,16 +147,16 @@ class InstrUncache()(implicit p: Parameters) extends LazyModule with HasICachePa
)
val clientNode = TLClientNode(Seq(clientParameters))
lazy val module = new icacheUncacheImp(this)
lazy val module = new InstrUncacheImp(this)
}
class icacheUncacheImp(outer: InstrUncache)
class InstrUncacheImp(outer: InstrUncache)
extends LazyModuleImp(outer)
with HasICacheParameters
with HasTLDump
{
val io = IO(new icacheUncacheIO)
val io = IO(new InstrUncacheIO)
val (bus, edge) = outer.clientNode.out.head
......
......@@ -39,7 +39,7 @@ trait HasBPUConst extends HasXSParameter with HasIFUConst {
val debug = true
val resetVector = 0x80000000L//TODO: set reset vec
val resetVector = 0x10000000L//TODO: set reset vec
// TODO: Replace log2Up by log2Ceil
}
......
......@@ -123,9 +123,9 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
ibuffer.io.flush := needFlush
io.backend.cfVec <> ibuffer.io.out
instrUncache.io.req <> DontCare
instrUncache.io.resp <> DontCare
instrUncache.io.flush <> DontCare
instrUncache.io.req <> ifu.io.uncacheInter.toUncache
ifu.io.uncacheInter.fromUncache <> instrUncache.io.resp
instrUncache.io.flush := icache.io.missQueue.flush
io.error <> DontCare
val frontendBubble = PopCount((0 until DecodeWidth).map(i => io.backend.cfVec(i).ready && !ibuffer.io.out(i).valid))
......
......@@ -29,9 +29,7 @@ import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
def mmioBusWidth = 64
def mmioBusBytes = mmioBusWidth /8
def mmioBeats = FetchWidth * 4 * 8 / mmioBusWidth
def mmioMask = VecInit(List.fill(PredictWidth)(true.B)).asUInt
def mmioBusAligned(pc :UInt): UInt = align(pc, mmioBusBytes)
def maxInstrLen = 32
}
trait HasIFUConst extends HasXSParameter {
......@@ -49,6 +47,11 @@ class FtqInterface(implicit p: Parameters) extends XSBundle {
val toFtq = new IfuToFtqIO
}
class UncacheInterface(implicit p: Parameters) extends XSBundle {
val fromUncache = Flipped(DecoupledIO(new InsUncacheResp))
val toUncache = DecoupledIO( new InsUncacheReq )
}
class ICacheInterface(implicit p: Parameters) extends XSBundle {
val toIMeta = Decoupled(new ICacheReadBundle)
val toIData = Decoupled(new ICacheReadBundle)
......@@ -63,6 +66,7 @@ class NewIFUIO(implicit p: Parameters) extends XSBundle {
val icacheInter = new ICacheInterface
val toIbuffer = Decoupled(new FetchToIBuffer)
val iTLBInter = Vec(2, new BlockTlbRequestIO)
val uncacheInter = new UncacheInterface
val pmp = Vec(2, new Bundle {
val req = Valid(new PMPReqBundle())
val resp = Input(new PMPRespBundle())
......@@ -90,6 +94,7 @@ class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
val instValid = Bool()
val lastHalfMatch = Bool()
val oversize = Bool()
val mmio = Bool()
}
class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
......@@ -99,6 +104,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val (toFtq, fromFtq) = (io.ftqInter.toFtq, io.ftqInter.fromFtq)
val (toMeta, toData, meta_resp, data_resp) = (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData)
val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue)
val (toUncache, fromUncache) = (io.uncacheInter.toUncache , io.uncacheInter.fromUncache)
val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp)))
val fromPMP = io.pmp.map(_.resp)
......@@ -218,6 +224,11 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val f1_bank_hit_vec = VecInit(Seq(bank0_hit_vec, bank1_hit_vec))
val f1_bank_hit = VecInit(Seq(bank0_hit, bank1_hit))
//MMIO
//MMIO only need 1 instruction
val f1_mmio = tlbRespMMIO(0) && f1_valid
val replacers = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2))
val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))})
......@@ -272,6 +283,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val pmpExcpAF = fromPMP.map(port => port.instr)
val f2_pAddrs = RegEnable(next = f1_pAddrs, enable = f1_fire)
val f2_hit = RegEnable(next = f1_hit , enable = f1_fire)
val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire)
......@@ -283,6 +295,12 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val f2_except_af = VecInit(RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire).zip(pmpExcpAF).map(a => a._1 || DataHoldBypass(a._2, RegNext(f1_fire)).asBool))
val f2_except = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)})
val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_))
//MMIO
val f2_mmio = RegInit(false.B)
when(f2_flush) {f2_mmio := false.B}
.elsewhen(f1_fire && f1_mmio && !f1_flush) {f2_mmio := true.B }
.elsewhen(f2_fire) {f2_mmio := false.B}
//
io.pmp.zipWithIndex.map { case (p, i) =>
p.req.valid := f2_fire
......@@ -292,7 +310,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
}
//instruction
val wait_idle :: wait_queue_ready :: wait_send_req :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: Nil = Enum(8)
val wait_idle :: wait_queue_ready :: wait_send_req :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: wait_send_mmio :: wait_mmio_resp ::Nil = Enum(10)
val wait_state = RegInit(wait_idle)
fromMissQueue.map{port => port.ready := true.B}
......@@ -300,12 +318,12 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire())
val (bank0_fix, bank1_fix) = (miss0_resp && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1))
val only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except
val only_0_hit = f2_valid && f2_hit && !f2_doubleLine
val hit_0_hit_1 = f2_valid && f2_hit && f2_doubleLine
val (hit_0_miss_1 , miss_0_hit_1, miss_0_miss_1) = ( (f2_valid && !f2_bank_hit(1) && f2_bank_hit(0) && f2_doubleLine && !f2_has_except),
(f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine && !f2_has_except),
(f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except),
val only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except && !f2_mmio
val only_0_hit = f2_valid && f2_hit && !f2_doubleLine && !f2_mmio
val hit_0_hit_1 = f2_valid && f2_hit && f2_doubleLine && !f2_mmio
val (hit_0_miss_1 , miss_0_hit_1, miss_0_miss_1) = ( (f2_valid && !f2_bank_hit(1) && f2_bank_hit(0) && f2_doubleLine && !f2_has_except && !f2_mmio),
(f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine && !f2_has_except && !f2_mmio),
(f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except && !f2_mmio),
)
val hit_0_except_1 = f2_valid && f2_doubleLine && !f2_except(0) && f2_except(1) && f2_bank_hit(0)
......@@ -314,13 +332,17 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val except_0 = f2_valid && f2_except(0)
val f2_mq_datas = Reg(Vec(2, UInt(blockBits.W)))
val f2_mmio_data = Reg(UInt(maxInstrLen.W))
when(fromMissQueue(0).fire) {f2_mq_datas(0) := fromMissQueue(0).bits.data}
when(fromMissQueue(1).fire) {f2_mq_datas(1) := fromMissQueue(1).bits.data}
when(fromUncache.fire()) {f2_mmio_data := fromUncache.bits.data}
switch(wait_state){
is(wait_idle){
when(miss_0_except_1){
when(f2_mmio && !f2_except_af(0) && !f2_except_pf(0)){
wait_state := wait_send_mmio
}.elsewhen(miss_0_except_1){
wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
}.elsewhen( only_0_miss || miss_0_hit_1){
wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
......@@ -331,6 +353,14 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
}
}
is(wait_send_mmio){
wait_state := Mux(toUncache.fire(), wait_mmio_resp,wait_send_mmio )
}
is(wait_mmio_resp){
wait_state := Mux(fromUncache.fire(), wait_finish, wait_mmio_resp)
}
//TODO: naive logic for wait icache response
is(wait_queue_ready){
wait_state := wait_send_req
......@@ -390,6 +420,12 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
toMissQueue(i).bits.clientID :=0.U
}
toUncache.valid := (wait_state === wait_send_mmio) && !f2_except_af(0)
//assert( (GTimer() < 5000.U && toUncache.fire()) || !toUncache.fire() )
toUncache.bits.addr := f2_ftq_req.startAddr
fromUncache.ready := true.B
val miss_all_fix = (wait_state === wait_finish)
f2_fetchFinish := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0)
......@@ -440,6 +476,10 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
}
val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr )
when(f2_mmio){
f2_cut_data(0) := f2_mmio_data(15, 0)
f2_cut_data(1) := f2_mmio_data(31, 16)
}
// deal with secondary miss in f1
val f2_0_f1_0 = ((f2_valid && !f2_bank_hit(0)) && f1_valid && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr)))
......@@ -494,6 +534,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val f3_except_pf = RegEnable(next = f2_except_pf, enable = f2_fire)
val f3_except_af = RegEnable(next = f2_except_af, enable = f2_fire)
val f3_hit = RegEnable(next = f2_hit , enable = f2_fire)
val f3_mmio = RegEnable(next = f2_mmio , enable = f2_fire)
val f3_lastHalf = RegInit(0.U.asTypeOf(new LastHalfInfo))
val f3_lastHalfMatch = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr)
......@@ -526,6 +567,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
preDecoderIn.lastHalfMatch := f3_lastHalfMatch
preDecoderIn.pageFault := f3_except_pf
preDecoderIn.accessFault := f3_except_af
preDecoderIn.mmio := f3_mmio
// TODO: What if next packet does not match?
......@@ -537,14 +579,15 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
}
val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
val f3_mmio_range = VecInit((0 until PredictWidth).map(i => if(i ==0) true.B else false.B))
io.toIbuffer.valid := f3_valid
io.toIbuffer.bits.instrs := preDecoderOut.instrs
io.toIbuffer.bits.valid := f3_predecode_range & preDecoderOut.instrRange.asUInt
io.toIbuffer.bits.valid := Mux(f3_mmio, f3_mmio_range.asUInt, f3_predecode_range & preDecoderOut.instrRange.asUInt)
io.toIbuffer.bits.pd := preDecoderOut.pd
io.toIbuffer.bits.ftqPtr := f3_ftq_req.ftqIdx
io.toIbuffer.bits.pc := preDecoderOut.pc
io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i)}
io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i) && !f3_mmio}
io.toIbuffer.bits.foldpc := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth))
io.toIbuffer.bits.ipf := preDecoderOut.pageFault
io.toIbuffer.bits.acf := preDecoderOut.accessFault
......@@ -553,19 +596,23 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
//Write back to Ftq
val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush))
val f3_mmio_missOffset = Wire(ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
f3_mmio_missOffset.valid := f3_mmio
f3_mmio_missOffset.bits := 0.U
toFtq.pdWb.valid := !finishFetchMaskReg && f3_valid
toFtq.pdWb.bits.pc := preDecoderOut.pc
toFtq.pdWb.bits.pd := preDecoderOut.pd
toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid := f3_predecode_range(i)}
toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid := Mux(f3_mmio, f3_mmio_range(i), f3_predecode_range(i))}
toFtq.pdWb.bits.ftqIdx := f3_ftq_req.ftqIdx
toFtq.pdWb.bits.ftqOffset := f3_ftq_req.ftqOffset.bits
toFtq.pdWb.bits.misOffset := preDecoderOut.misOffset
toFtq.pdWb.bits.misOffset := Mux(f3_mmio, f3_mmio_missOffset, preDecoderOut.misOffset)
toFtq.pdWb.bits.cfiOffset := preDecoderOut.cfiOffset
toFtq.pdWb.bits.target := preDecoderOut.target
toFtq.pdWb.bits.target := Mux(f3_mmio,Mux(toFtq.pdWb.bits.pd(0).isRVC, toFtq.pdWb.bits.pc(0) + 2.U , toFtq.pdWb.bits.pc(0)+4.U) ,preDecoderOut.target)
toFtq.pdWb.bits.jalTarget := preDecoderOut.jalTarget
toFtq.pdWb.bits.instrRange := preDecoderOut.instrRange
toFtq.pdWb.bits.instrRange := Mux(f3_mmio, f3_mmio_range, preDecoderOut.instrRange)
val predecodeFlush = preDecoderOut.misOffset.valid && f3_valid
val predecodeFlush = ((preDecoderOut.misOffset.valid || f3_mmio) && f3_valid)
val predecodeFlushReg = RegNext(predecodeFlush && !(f2_fire && !f2_flush))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册