提交 635253aa 编写于 作者: Z Zihao Yu

system,CoherenceInterconnect: break deadlock by splitting the probe state machine from xbar

上级 82fa99c9
......@@ -11,107 +11,73 @@ trait HasCoherenceParameter extends HasNOOPParameter {
val supportCoh = HasDcache
}
class CoherenceInterconnect extends Module with HasCoherenceParameter {
class CoherenceManager extends Module with HasCoherenceParameter {
val io = IO(new Bundle {
val in = Flipped(Vec(2, new SimpleBusC))
val out = new SimpleBusUC
val in = Flipped(new SimpleBusUC)
val out = new Bundle {
val mem = new SimpleBusUC
val coh = new SimpleBusUC
}
})
def anotherMaster(thisMaster: UInt) = Mux(thisMaster === 1.U, 0.U, 1.U)
def isDcache() = inputArb.io.chosen === 1.U
// state transition:
// write: s_idle -> s_memWriteResp -> s_idle
// read from Dcache: s_idle -> s_memResp -> s_idle
// read from Icache: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
// read: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
val s_idle :: s_probeResp :: s_probeForward :: s_memReadReq :: s_memReadResp :: s_memWriteResp :: Nil = Enum(6)
val state = RegInit(s_idle)
val inflight = state =/= s_idle
val inflight = RegInit(false.B)
val inflightSrc = Reg(UInt(1.W)) // 0 - icache, 1 - dcache
val lockWriteFun = ((x: SimpleBusReqBundle) => x.isWrite() && x.isBurst())
val inputArb = Module(new LockingArbiter(chiselTypeOf(io.in(0).mem.req.bits), 2, 8, Some(lockWriteFun)))
(inputArb.io.in zip io.in.map(_.mem.req)).map{ case (arb, in) => arb <> in }
val thisReq = inputArb.io.out
val thisReq = io.in.req
assert(!(thisReq.valid && !thisReq.bits.isRead() && !thisReq.bits.isWrite()))
// when read, we should first probe another master
// when read, we should first probe dcache
val reqLatch = RegEnable(thisReq.bits, !inflight && thisReq.bits.isRead())
io.in.map(_.coh).map { case c => {
io.out.coh match { case c => {
c.req.bits := thisReq.bits
c.req.bits.cmd := SimpleBusCmd.probe
c.resp.ready := true.B
}}
io.out.req.bits := thisReq.bits
io.out.mem.req.bits := thisReq.bits
// bind correct valid and ready signals
io.out.req.valid := false.B
io.out.mem.req.valid := false.B
thisReq.ready := false.B
io.in.map(_.coh.req.valid).map { _ := false.B }
when (if (supportCoh) (thisReq.bits.isWrite() || isDcache()) else true.B) {
io.out.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.req.ready && !inflight
io.out.coh.req.valid := false.B
when (if (supportCoh) thisReq.bits.isWrite() else true.B) {
io.out.mem.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.mem.req.ready && !inflight
} .elsewhen (thisReq.bits.isRead()) {
io.in(anotherMaster(inputArb.io.chosen)).coh.req.valid := thisReq.valid && !inflight
thisReq.ready := io.in(anotherMaster(inputArb.io.chosen)).coh.req.ready && !inflight
io.out.coh.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.coh.req.ready && !inflight
}
io.in.map(_.mem.resp.bits := io.out.resp.bits)
io.in.map(_.mem.resp.valid := false.B)
(io.in(inflightSrc).mem.resp, io.out.resp) match { case (l, r) => {
l.valid := r.valid
r.ready := l.ready
}}
io.in.resp <> io.out.mem.resp
switch (state) {
is (s_idle) {
when (thisReq.fire()) {
inflightSrc := inputArb.io.chosen
when (thisReq.bits.isRead()) {
inflight := true.B
state := Mux(if (supportCoh) isDcache() else true.B, s_memReadResp, s_probeResp)
} .elsewhen (thisReq.bits.isWriteLast()) {
inflight := true.B
state := s_memWriteResp
}
when (thisReq.bits.isRead()) { state := Mux(supportCoh.B, s_probeResp, s_memReadResp) }
.elsewhen (thisReq.bits.isWriteLast()) { state := s_memWriteResp }
}
}
is (s_probeResp) {
when (io.in(anotherMaster(inflightSrc)).coh.resp.fire()) {
state := Mux(io.in(anotherMaster(inflightSrc)).coh.resp.bits.isProbeHit(), s_probeForward, s_memReadReq)
when (io.out.coh.resp.fire()) {
state := Mux(io.out.coh.resp.bits.isProbeHit(), s_probeForward, s_memReadReq)
}
}
is (s_probeForward) {
val thisResp = io.in(inflightSrc).mem.resp
val anotherCohResp = io.in(anotherMaster(inflightSrc)).coh.resp
thisResp.bits := anotherCohResp.bits
thisResp.valid := anotherCohResp.valid
anotherCohResp.ready := thisResp.ready
when (thisResp.fire() && thisResp.bits.isReadLast()) {
inflight := false.B
state := s_idle
}
val thisResp = io.in.resp
thisResp <> io.out.coh.resp
when (thisResp.fire() && thisResp.bits.isReadLast()) { state := s_idle }
}
is (s_memReadReq) {
io.out.req.bits := reqLatch
io.out.req.valid := true.B
when (io.out.req.fire()) { state := s_memReadResp }
}
is (s_memReadResp) {
when (io.out.resp.fire() && io.out.resp.bits.isReadLast()) {
inflight := false.B
state := s_idle
}
}
is (s_memWriteResp) {
when (io.out.resp.fire()) {
inflight := false.B
state := s_idle
}
io.out.mem.req.bits := reqLatch
io.out.mem.req.valid := true.B
when (io.out.mem.req.fire()) { state := s_memReadResp }
}
is (s_memReadResp) { when (io.out.mem.resp.fire() && io.out.mem.resp.bits.isReadLast()) { state := s_idle } }
is (s_memWriteResp) { when (io.out.mem.resp.fire()) { state := s_idle } }
}
}
......@@ -16,10 +16,17 @@ class NOOPSoC(implicit val p: NOOPConfig) extends Module {
})
val noop = Module(new NOOP)
val cohMg = Module(new CoherenceInterconnect)
cohMg.io.in(0) <> noop.io.imem
cohMg.io.in(1) <> noop.io.dmem
io.mem <> cohMg.io.out.toAXI4()
val cohMg = Module(new CoherenceManager)
val xbar = Module(new SimpleBusCrossbarNto1(2))
cohMg.io.in <> noop.io.imem.mem
noop.io.dmem.coh <> cohMg.io.out.coh
xbar.io.in(0) <> cohMg.io.out.mem
xbar.io.in(1) <> noop.io.dmem.mem
io.mem <> xbar.io.out.toAXI4()
noop.io.imem.coh.resp.ready := true.B
noop.io.imem.coh.req.valid := false.B
noop.io.imem.coh.req.bits := DontCare
if (p.FPGAPlatform) io.mmio <> noop.io.mmio.toAXI4Lite()
else io.mmio <> noop.io.mmio
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册