fix ID mapper to disallow two in-flight requests with the same inner ID
This commit is contained in:
parent
af76837970
commit
b105076996
@ -6,8 +6,10 @@ import uncore.tilelink._
|
|||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import cde.Parameters
|
import cde.Parameters
|
||||||
|
|
||||||
class IdMapper(val inIdBits: Int, val outIdBits: Int)
|
class IdMapper(val inIdBits: Int, val outIdBits: Int,
|
||||||
|
val forceMapping: Boolean = false)
|
||||||
(implicit val p: Parameters) extends Module {
|
(implicit val p: Parameters) extends Module {
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val req = new Bundle {
|
val req = new Bundle {
|
||||||
val valid = Bool(INPUT)
|
val valid = Bool(INPUT)
|
||||||
@ -18,51 +20,44 @@ class IdMapper(val inIdBits: Int, val outIdBits: Int)
|
|||||||
val resp = new Bundle {
|
val resp = new Bundle {
|
||||||
val valid = Bool(INPUT)
|
val valid = Bool(INPUT)
|
||||||
val matches = Bool(OUTPUT)
|
val matches = Bool(OUTPUT)
|
||||||
val out_id = UInt(INPUT, inIdBits)
|
val out_id = UInt(INPUT, outIdBits)
|
||||||
val in_id = UInt(OUTPUT, outIdBits)
|
val in_id = UInt(OUTPUT, inIdBits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val maxInXacts = 1 << inIdBits
|
val maxInXacts = 1 << inIdBits
|
||||||
|
|
||||||
if (inIdBits <= outIdBits) {
|
if (inIdBits <= outIdBits && !forceMapping) {
|
||||||
io.req.ready := Bool(true)
|
io.req.ready := Bool(true)
|
||||||
io.req.out_id := io.req.in_id
|
io.req.out_id := io.req.in_id
|
||||||
io.resp.matches := Bool(true)
|
io.resp.matches := Bool(true)
|
||||||
io.resp.in_id := io.resp.out_id
|
io.resp.in_id := io.resp.out_id
|
||||||
} else if (outIdBits <= 2) {
|
|
||||||
val nQueues = 1 << outIdBits
|
|
||||||
val entriesPerQueue = (maxInXacts - 1) / nQueues + 1
|
|
||||||
val (req_out_id, req_out_flip) = Counter(io.req.valid && io.req.ready, nQueues)
|
|
||||||
io.req.ready := Bool(false)
|
|
||||||
io.resp.matches := Bool(false)
|
|
||||||
io.resp.in_id := UInt(0)
|
|
||||||
io.req.out_id := req_out_id
|
|
||||||
for (i <- 0 until nQueues) {
|
|
||||||
val queue = Module(new Queue(UInt(width = inIdBits), entriesPerQueue))
|
|
||||||
queue.io.enq.valid := io.req.valid && req_out_id === UInt(i)
|
|
||||||
queue.io.enq.bits := io.req.in_id
|
|
||||||
when (req_out_id === UInt(i)) { io.req.ready := queue.io.enq.ready }
|
|
||||||
|
|
||||||
queue.io.deq.ready := io.resp.valid && io.resp.out_id === UInt(i)
|
|
||||||
when (io.resp.out_id === UInt(i)) {
|
|
||||||
io.resp.matches := queue.io.deq.valid
|
|
||||||
io.resp.in_id := queue.io.deq.bits
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val maxOutId = 1 << outIdBits
|
val nInXacts = 1 << inIdBits
|
||||||
val (req_out_id, req_nasti_flip) = Counter(io.req.valid && io.req.ready, maxOutId)
|
val nOutXacts = 1 << outIdBits
|
||||||
val roq = Module(new ReorderQueue(
|
|
||||||
UInt(width = inIdBits), outIdBits, maxInXacts))
|
val out_id_free = Reg(init = Vec.fill(nOutXacts){Bool(true)})
|
||||||
roq.io.enq.valid := io.req.valid
|
val next_out_id = PriorityEncoder(out_id_free)
|
||||||
roq.io.enq.bits.data := io.req.in_id
|
val id_mapping = Reg(Vec(nInXacts, UInt(0, outIdBits)))
|
||||||
roq.io.enq.bits.tag := req_out_id
|
val id_valid = Reg(init = Vec.fill(nOutXacts){Bool(false)})
|
||||||
io.req.ready := roq.io.enq.ready
|
|
||||||
io.req.out_id := req_out_id
|
val req_fire = io.req.valid && io.req.ready
|
||||||
roq.io.deq.valid := io.resp.valid
|
when (req_fire) {
|
||||||
roq.io.deq.tag := io.resp.out_id
|
out_id_free(io.req.out_id) := Bool(false)
|
||||||
io.resp.in_id := roq.io.deq.data
|
id_valid(io.req.in_id) := Bool(true)
|
||||||
io.resp.matches := roq.io.deq.matches
|
id_mapping(io.req.in_id) := io.req.out_id
|
||||||
|
}
|
||||||
|
when (io.resp.valid) {
|
||||||
|
out_id_free(io.resp.out_id) := Bool(true)
|
||||||
|
id_valid(io.resp.in_id) := Bool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.req.ready := out_id_free.reduce(_ || _) && !id_valid(io.req.in_id)
|
||||||
|
io.req.out_id := next_out_id
|
||||||
|
|
||||||
|
val id_matches = id_mapping.map(_ === io.resp.out_id)
|
||||||
|
val id_matches_valid = id_matches.zip(id_valid).map { case (m, v) => m && v }
|
||||||
|
io.resp.matches := id_matches_valid.reduce(_ || _)
|
||||||
|
io.resp.in_id := PriorityEncoder(id_matches_valid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,8 +304,8 @@ class TileLinkIONastiIOConverter(implicit p: Parameters) extends TLModule()(p)
|
|||||||
"NASTI write transaction cannot convert to TileLInk")
|
"NASTI write transaction cannot convert to TileLInk")
|
||||||
|
|
||||||
val put_count = Reg(init = UInt(0, tlBeatAddrBits))
|
val put_count = Reg(init = UInt(0, tlBeatAddrBits))
|
||||||
val get_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits))
|
val get_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits, true))
|
||||||
val put_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits))
|
val put_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits, true))
|
||||||
|
|
||||||
when (io.nasti.aw.fire()) {
|
when (io.nasti.aw.fire()) {
|
||||||
aw_req := io.nasti.aw.bits
|
aw_req := io.nasti.aw.bits
|
||||||
|
Loading…
Reference in New Issue
Block a user