Skip to content

Commit 089e98a

Browse files
authored
feat: add handling for non-cache requests (#28)
* Non-cache requests are forwarded directly downstream without entering the slice
1 parent a4eb50e commit 089e98a

File tree

5 files changed

+201
-25
lines changed

5 files changed

+201
-25
lines changed

OpenLLC.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class OpenLLC(implicit p: Parameters) extends LLCModule with HasClientInfo {
4747
println(s"CHI DAT Flit Width: ${io.rn(0).rx.dat.flit.getWidth}")
4848
println(s"CHI Port Width: ${io.rn(0).getWidth}")
4949

50+
val mmioDiverger = Module(new MMIODiverger())
51+
val mmioMerger = Module(new MMIOMerger())
5052
val rnXbar = Module(new RNXbar())
5153
val snXbar = Module(new SNXbar())
5254
val snLinkMonitor = Module(new SNLinkMonitor())
@@ -56,17 +58,20 @@ class OpenLLC(implicit p: Parameters) extends LLCModule with HasClientInfo {
5658
rnLinkMonitor.io.out <> io.rn(i)
5759
rnLinkMonitor.io.entranceID := i.U
5860
rnLinkMonitor.io.nodeID := io.nodeID
59-
rnXbar.io.in(i) <> rnLinkMonitor.io.in
61+
mmioDiverger.io.in(i) <> rnLinkMonitor.io.in
62+
rnXbar.io.in(i) <> mmioDiverger.io.out.cache(i)
6063
}
6164

6265
for (j <- 0 until banks) {
6366
val slice = Module(new Slice())
6467
slice.io.in <> rnXbar.io.out(j)
65-
rnXbar.io.snpMasks(j) := slice.io.snpMask
68+
rnXbar.io.snpMasks(j) := slice.io.snpMask
6669
snXbar.io.in(j) <> slice.io.out
6770
}
68-
69-
snLinkMonitor.io.in <> snXbar.io.out
71+
72+
mmioMerger.io.in.cache <> snXbar.io.out
73+
mmioMerger.io.in.uncache <> mmioDiverger.io.out.uncache
74+
snLinkMonitor.io.in <> mmioMerger.io.out
7075
snLinkMonitor.io.nodeID := io.nodeID
7176

7277
io.sn <> snLinkMonitor.io.out

chi/LinkLayer.scala

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class RNLinkMonitor(implicit p: Parameters) extends LLCModule {
7474
val txState = RegInit(LinkStates.STOP)
7575
val rxState = RegInit(LinkStates.STOP)
7676

77+
// Record the upstream request node's ID
78+
val rnID = RegEnable(rxOut.req.flit.asTypeOf(new CHIREQ()).elements.filter(_._1 == "srcID").head._2,
79+
0.U(NODEID_WIDTH.W), rxOut.req.flitv)
80+
7781
Seq(txState, rxState).zip(MixedVecInit(Seq(txOut, rxOut))).foreach { case (state, link) =>
7882
state := MuxLookup(Cat(link.linkactivereq, link.linkactiveack), LinkStates.STOP)(Seq(
7983
Cat(true.B, false.B) -> LinkStates.ACTIVATE,
@@ -87,16 +91,10 @@ class RNLinkMonitor(implicit p: Parameters) extends LLCModule {
8791
val rxreqDeact, rxrspDeact, rxdatDeact = Wire(Bool())
8892
val rxDeact = rxreqDeact && rxrspDeact && rxdatDeact
8993
Decoupled2LCredit(setSrcID(txIn.snp, io.nodeID), txOut.snp, LinkState(txState), Some("txsnp"))
90-
Decoupled2LCredit(setSrcID(txIn.rsp, io.nodeID), txOut.rsp, LinkState(txState), Some("txrsp"))
91-
Decoupled2LCredit(setSrcID(txIn.dat, io.nodeID), txOut.dat, LinkState(txState), Some("txdat"))
92-
LCredit2Decoupled(
93-
setSrcID(
94-
setTgtID(rxOut.req, new CHIREQ(), rxOut.req.flit.asTypeOf(new CHIREQ()).srcID),
95-
new CHIREQ(),
96-
io.entranceID
97-
),
98-
rxIn.req, LinkState(rxState), rxreqDeact, Some("rxreq"), maxLCreditNum
99-
)
94+
Decoupled2LCredit(setTgtID(setSrcID(txIn.rsp, io.nodeID), rnID.asUInt), txOut.rsp, LinkState(txState), Some("txrsp"))
95+
Decoupled2LCredit(setTgtID(setSrcID(txIn.dat, io.nodeID), rnID.asUInt), txOut.dat, LinkState(txState), Some("txdat"))
96+
LCredit2Decoupled(setSrcID(setTgtID(rxOut.req, new CHIREQ(), rxOut.req.flit.asTypeOf(new CHIREQ()).srcID),
97+
new CHIREQ(), io.entranceID), rxIn.req, LinkState(rxState), rxreqDeact, Some("rxreq"), maxLCreditNum)
10098
LCredit2Decoupled(setSrcID(rxOut.rsp, new CHIRSP(), io.entranceID), rxIn.rsp,
10199
LinkState(rxState), rxrspDeact, Some("rxrsp"), maxLCreditNum)
102100
LCredit2Decoupled(setSrcID(rxOut.dat, new CHIRSP(), io.entranceID), rxIn.dat,
@@ -124,6 +122,13 @@ class RNLinkMonitor(implicit p: Parameters) extends LLCModule {
124122
out
125123
}
126124

125+
def setTgtID[T <: Bundle](in: DecoupledIO[T], tgtID: UInt): DecoupledIO[T] = {
126+
val out = Wire(in.cloneType)
127+
out <> in
128+
out.bits.elements.filter(_._1 == "tgtID").head._2 := tgtID
129+
out
130+
}
131+
127132
def setTgtID[T <: Bundle](in: ChannelIO[T], gen: T, tgtID: UInt): ChannelIO[T] = {
128133
val out = Wire(in.cloneType)
129134
out <> in
@@ -132,7 +137,7 @@ class RNLinkMonitor(implicit p: Parameters) extends LLCModule {
132137
}
133138
}
134139

135-
class SNLinkMonitor(implicit p: Parameters) extends LLCModule {
140+
class SNLinkMonitor(implicit p: Parameters) extends LLCModule with HasCHIOpcodes {
136141
private val maxLCreditNum = 15
137142

138143
val io = IO(new Bundle() {
@@ -141,6 +146,9 @@ class SNLinkMonitor(implicit p: Parameters) extends LLCModule {
141146
val nodeID = Input(UInt(NODEID_WIDTH.W))
142147
})
143148

149+
def reqFromMMIO(req: CHIREQ): Bool = req.txnID(TXNID_WIDTH - 1)
150+
def datFromMMIO(dat: CHIDAT): Bool = dat.opcode === NonCopyBackWrData
151+
144152
val txState = RegInit(LinkStates.STOP)
145153
val rxState = RegInit(LinkStates.STOP)
146154

@@ -156,8 +164,10 @@ class SNLinkMonitor(implicit p: Parameters) extends LLCModule {
156164
/* IO assignment */
157165
val rxrspDeact, rxdatDeact = Wire(Bool())
158166
val rxDeact = rxrspDeact && rxdatDeact
159-
Decoupled2LCredit(setSrcID(io.in.tx.req, io.nodeID), io.out.tx.req, LinkState(txState), Some("txreq"))
160-
Decoupled2LCredit(setSrcID(io.in.tx.dat, io.nodeID), io.out.tx.dat, LinkState(txState), Some("txdat"))
167+
Decoupled2LCredit(setSrcID(io.in.tx.req, Mux(reqFromMMIO(io.in.tx.req.bits), io.in.tx.req.bits.srcID, io.nodeID)),
168+
io.out.tx.req, LinkState(txState), Some("txreq"))
169+
Decoupled2LCredit(setSrcID(io.in.tx.dat, Mux(datFromMMIO(io.in.tx.dat.bits), io.in.tx.dat.bits.srcID, io.nodeID)),
170+
io.out.tx.dat, LinkState(txState), Some("txdat"))
161171
LCredit2Decoupled(io.out.rx.rsp, io.in.rx.rsp, LinkState(rxState), rxrspDeact, Some("rxrsp"), maxLCreditNum)
162172
LCredit2Decoupled(io.out.rx.dat, io.in.rx.dat, LinkState(rxState), rxdatDeact, Some("rxdat"), maxLCreditNum)
163173

chi/RXREQ.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,20 @@ class RXREQ (implicit p: Parameters) extends LLCModule {
2929
val task = DecoupledIO(new Task())
3030
})
3131

32-
val id_pool = RegInit(0.U((TXNID_WIDTH - bankBits).W))
32+
// Outer interface connection
33+
/**
34+
* TxnID space arrangement:
35+
* If this is a cacheable request:
36+
* +----------------+-----------+---------------+
37+
* | 0.U(1.W) | SliceID | Inner TxnID |
38+
* +----------------+-----------+---------------+
39+
* Otherwise this is an MMIO request:
40+
* +----------------+-----------+---------------+
41+
* | 1.U(1.W) | Inner TxnID |
42+
* +----------------+---------------------------+
43+
*
44+
*/
45+
val id_pool = RegInit(0.U((TXNID_WIDTH - bankBits - 1).W))
3346
when(io.task.fire) {
3447
id_pool := id_pool + 1.U // maybe fail if in-flight transactions exceed (256/banks) ?
3548
}
@@ -47,7 +60,7 @@ class RXREQ (implicit p: Parameters) extends LLCModule {
4760
task.off := off
4861
task.size := r.size
4962
task.refillTask := false.B
50-
task.reqID := Cat(bank, id_pool)
63+
task.reqID := Cat(0.U(1.W), bank, id_pool)
5164
// this follows coupledL2.tl2chi.TaskBundle.toCHIReqBundle
5265
task.tgtID := r.tgtID
5366
task.srcID := r.srcID

utils/CHIXbar.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class RNXbar(implicit p: Parameters) extends LLCModule {
5151

5252
txrspArbs(i).io.in.zip(io.in.map(_.tx.rsp)).foreach { case (in, e) =>
5353
in.valid := e.valid && { if (banks == 1) true.B else
54-
e.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
54+
e.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
5555
in.bits := e.bits
5656
}
5757
txrspArbs(i).io.out.ready := io.out(i).tx.rsp.ready
@@ -60,7 +60,7 @@ class RNXbar(implicit p: Parameters) extends LLCModule {
6060

6161
txdatArbs(i).io.in.zip(io.in.map(_.tx.dat)).foreach { case (in, e) =>
6262
in.valid := e.valid && { if (banks == 1) true.B else
63-
e.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
63+
e.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
6464
in.bits := e.bits
6565
}
6666
txdatArbs(i).io.out.ready := io.out(i).tx.dat.ready
@@ -132,10 +132,10 @@ class SNXbar(implicit p: Parameters) extends LLCModule {
132132
io.in(i).tx.req.ready := txreqArb.io.out.fire && txreqArb.io.chosen === i.U
133133
io.in(i).tx.dat.ready := txdatArb.io.out.fire && txdatArb.io.chosen === i.U
134134
io.in(i).rx.dat.valid := io.out.rx.dat.valid && { if (banks == 1) true.B else
135-
io.out.rx.dat.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
135+
io.out.rx.dat.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
136136
io.in(i).rx.dat.bits := io.out.rx.dat.bits
137137
io.in(i).rx.rsp.valid := io.out.rx.rsp.valid && { if (banks == 1) true.B else
138-
io.out.rx.rsp.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
138+
io.out.rx.rsp.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
139139
io.in(i).rx.rsp.bits := io.out.rx.rsp.bits
140140
}
141141

@@ -148,11 +148,11 @@ class SNXbar(implicit p: Parameters) extends LLCModule {
148148
io.out.tx.dat.bits := txdatArb.io.out.bits
149149
io.out.rx.dat.ready := Cat(io.in.zipWithIndex.map { case (e, i) =>
150150
e.rx.dat.fire && { if (banks == 1) true.B else
151-
io.out.rx.dat.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
151+
io.out.rx.dat.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
152152
}).orR
153153
io.out.rx.rsp.ready := Cat(io.in.zipWithIndex.map { case (e, i) =>
154154
e.rx.rsp.fire && { if (banks == 1) true.B else
155-
io.out.rx.rsp.bits.txnID(TXNID_WIDTH - 1, TXNID_WIDTH - bankBits) === i.U }
155+
io.out.rx.rsp.bits.txnID(TXNID_WIDTH - 2, TXNID_WIDTH - bankBits - 1) === i.U }
156156
}).orR
157157

158158
}

utils/MMIOBridge.scala

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/** *************************************************************************************
2+
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3+
* Copyright (c) 2020-2021 Peng Cheng Laboratory
4+
*
5+
* XiangShan is licensed under Mulan PSL v2.
6+
* You can use this software according to the terms and conditions of the Mulan PSL v2.
7+
* You may obtain a copy of Mulan PSL v2 at:
8+
* http://license.coscl.org.cn/MulanPSL2
9+
*
10+
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11+
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12+
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13+
*
14+
* See the Mulan PSL v2 for more details.
15+
* *************************************************************************************
16+
*/
17+
18+
package openLLC
19+
20+
import chisel3._
21+
import chisel3.util._
22+
import org.chipsalliance.cde.config.Parameters
23+
import coupledL2.tl2chi._
24+
import utility.{FastArbiter}
25+
26+
class MMIODiverger(implicit p: Parameters) extends LLCModule with HasCHIOpcodes {
27+
val io = IO(new Bundle() {
28+
val in = Vec(numRNs, Flipped(new DecoupledPortIO()))
29+
val out = new Bundle() {
30+
val cache = Vec(numRNs, new DecoupledPortIO())
31+
val uncache = new DecoupledNoSnpPortIO()
32+
}
33+
})
34+
35+
def reqFromMMIO(req: CHIREQ): Bool = req.txnID(TXNID_WIDTH - 1)
36+
def datFromMMIO(dat: CHIDAT): Bool = dat.opcode === NonCopyBackWrData
37+
38+
val mmioReqArb = Module(new FastArbiter(new CHIREQ(), numRNs))
39+
val mmioDatArb = Module(new FastArbiter(new CHIDAT(), numRNs))
40+
val receiptQueue = Module(new Queue(new CHIRSP(), entries = numRNs, pipe = true, flow = true))
41+
42+
receiptQueue.io.enq.valid := io.out.uncache.tx.req.fire && io.out.uncache.tx.req.bits.opcode === ReadNoSnp
43+
receiptQueue.io.enq.bits := {
44+
val receipt = WireInit(0.U.asTypeOf(new CHIRSP()))
45+
receipt.opcode := ReadReceipt
46+
receipt.txnID := io.out.uncache.tx.req.bits.txnID
47+
receipt.tgtID := io.out.uncache.tx.req.bits.srcID
48+
receipt
49+
}
50+
receiptQueue.io.deq.ready := Cat(io.in.zipWithIndex.map { case (in, i) =>
51+
in.rx.rsp.ready && receiptQueue.io.deq.bits.tgtID === i.U
52+
}).orR
53+
54+
mmioReqArb.io.in.zip(io.in.map(_.tx.req)).foreach { case (in, e) =>
55+
in.valid := e.valid && reqFromMMIO(e.bits)
56+
in.bits := e.bits
57+
}
58+
mmioReqArb.io.out.ready := io.out.uncache.tx.req.ready
59+
60+
mmioDatArb.io.in.zip(io.in.map(_.tx.dat)).foreach { case (in, e) =>
61+
in.valid := e.valid && datFromMMIO(e.bits)
62+
in.bits := e.bits
63+
}
64+
mmioDatArb.io.out.ready := io.out.uncache.tx.dat.ready
65+
66+
io.in.zip(io.out.cache).zipWithIndex.foreach { case ((in, out), i) =>
67+
out.tx.req.valid := in.tx.req.valid && !reqFromMMIO(in.tx.req.bits)
68+
out.tx.req.bits := in.tx.req.bits
69+
out.tx.dat.valid := in.tx.dat.valid && !datFromMMIO(in.tx.dat.bits)
70+
out.tx.dat.bits := in.tx.dat.bits
71+
out.tx.rsp <> in.tx.rsp
72+
73+
out.rx.rsp.ready := in.rx.rsp.ready && (!receiptQueue.io.deq.valid || receiptQueue.io.deq.bits.tgtID =/= i.U) &&
74+
(!io.out.uncache.rx.rsp.valid || io.out.uncache.rx.rsp.bits.tgtID =/= i.U)
75+
out.rx.dat.ready := in.rx.dat.ready && (!io.out.uncache.rx.dat.valid || io.out.uncache.rx.dat.bits.tgtID =/= i.U)
76+
77+
in.tx.req.ready := io.out.uncache.tx.req.fire && mmioReqArb.io.chosen === i.U || out.tx.req.fire
78+
in.tx.dat.ready := io.out.uncache.tx.dat.fire && mmioDatArb.io.chosen === i.U || out.tx.dat.fire
79+
80+
in.rx.rsp.valid := out.rx.rsp.valid || io.out.uncache.rx.rsp.valid && io.out.uncache.rx.rsp.bits.tgtID === i.U ||
81+
receiptQueue.io.deq.valid && receiptQueue.io.deq.bits.tgtID === i.U
82+
in.rx.rsp.bits := Mux(
83+
receiptQueue.io.deq.valid && receiptQueue.io.deq.bits.tgtID === i.U,
84+
receiptQueue.io.deq.bits,
85+
Mux(
86+
io.out.uncache.rx.rsp.valid && io.out.uncache.rx.rsp.bits.tgtID === i.U,
87+
io.out.uncache.rx.rsp.bits,
88+
out.rx.rsp.bits
89+
)
90+
)
91+
in.rx.dat.valid := out.rx.dat.valid || io.out.uncache.rx.dat.valid && io.out.uncache.rx.dat.bits.tgtID === i.U
92+
in.rx.dat.bits := Mux(
93+
io.out.uncache.rx.dat.valid && io.out.uncache.rx.dat.bits.tgtID === i.U,
94+
io.out.uncache.rx.dat.bits,
95+
out.rx.dat.bits
96+
)
97+
in.rx.snp <> out.rx.snp
98+
}
99+
100+
io.out.uncache.tx.req.valid := mmioReqArb.io.out.valid && receiptQueue.io.enq.ready
101+
io.out.uncache.tx.req.bits := mmioReqArb.io.out.bits
102+
io.out.uncache.tx.req.bits.order := OrderEncodings.None
103+
io.out.uncache.tx.dat.valid := mmioDatArb.io.out.valid
104+
io.out.uncache.tx.dat.bits := mmioDatArb.io.out.bits
105+
106+
io.out.uncache.rx.rsp.ready := Cat(io.in.zipWithIndex.map { case (in, i) =>
107+
in.rx.rsp.ready && io.out.uncache.rx.rsp.bits.tgtID === i.U &&
108+
(!receiptQueue.io.deq.valid || receiptQueue.io.deq.bits.tgtID =/= i.U)
109+
}).orR
110+
io.out.uncache.rx.dat.ready := Cat(io.in.zipWithIndex.map { case (in, i) =>
111+
in.rx.dat.ready && io.out.uncache.rx.dat.bits.tgtID === i.U }).orR
112+
}
113+
114+
class MMIOMerger(implicit p: Parameters) extends LLCModule {
115+
val io = IO(new Bundle() {
116+
val in = new Bundle() {
117+
val cache = Flipped(new DecoupledNoSnpPortIO())
118+
val uncache = Flipped(new DecoupledNoSnpPortIO())
119+
}
120+
val out = new DecoupledNoSnpPortIO()
121+
})
122+
123+
val in = io.in
124+
val out = io.out
125+
126+
def datToMMIO(dat: CHIDAT): Bool = dat.txnID(TXNID_WIDTH - 1)
127+
def rspToMMIO(rsp: CHIRSP): Bool = rsp.txnID(TXNID_WIDTH - 1)
128+
129+
out.tx.req.valid := in.cache.tx.req.valid || in.uncache.tx.req.valid
130+
out.tx.req.bits := Mux(in.uncache.tx.req.valid, in.uncache.tx.req.bits, in.cache.tx.req.bits)
131+
out.tx.dat.valid := in.cache.tx.dat.valid || in.uncache.tx.dat.valid
132+
out.tx.dat.bits := Mux(in.uncache.tx.dat.valid, in.uncache.tx.dat.bits, in.cache.tx.dat.bits)
133+
out.rx.rsp.ready := in.cache.rx.rsp.fire || in.uncache.rx.rsp.fire
134+
out.rx.dat.ready := in.cache.rx.dat.fire || in.uncache.rx.dat.fire
135+
in.cache.tx.req.ready := out.tx.req.ready && !in.uncache.tx.req.valid
136+
in.cache.tx.dat.ready := out.tx.dat.ready && !in.uncache.tx.dat.valid
137+
in.cache.rx.dat.valid := out.rx.dat.valid && !datToMMIO(out.rx.dat.bits)
138+
in.cache.rx.dat.bits := out.rx.dat.bits
139+
in.cache.rx.rsp.valid := out.rx.rsp.valid && !rspToMMIO(out.rx.rsp.bits)
140+
in.cache.rx.rsp.bits := out.rx.rsp.bits
141+
142+
in.uncache.tx.req.ready := out.tx.req.ready
143+
in.uncache.tx.dat.ready := out.tx.dat.ready
144+
in.uncache.rx.dat.valid := out.rx.dat.valid && datToMMIO(out.rx.dat.bits)
145+
in.uncache.rx.dat.bits := out.rx.dat.bits
146+
in.uncache.rx.rsp.valid := out.rx.rsp.valid && rspToMMIO(out.rx.rsp.bits)
147+
in.uncache.rx.rsp.bits := out.rx.rsp.bits
148+
}

0 commit comments

Comments
 (0)